001: /*
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: Sender1_2SF.java 5995 2004-12-17 15:08:36Z joaninh $
023: * --------------------------------------------------------------------------
024: */
025:
026: // SenderSF1_1.java
027: // Stateful Session Bean
028: package org.objectweb.jonas.jtests.beans.message;
029:
030: import java.rmi.RemoteException;
031: import java.util.Collection;
032: import java.util.Iterator;
033:
034: import javax.ejb.CreateException;
035: import javax.ejb.EJBException;
036: import javax.ejb.FinderException;
037: import javax.ejb.SessionBean;
038: import javax.ejb.SessionContext;
039: import javax.jms.ConnectionFactory;
040: import javax.jms.Destination;
041: import javax.jms.JMSException;
042: import javax.jms.MapMessage;
043: import javax.jms.MessageProducer;
044: import javax.jms.Session;
045: import javax.naming.InitialContext;
046: import javax.naming.NamingException;
047: import javax.rmi.PortableRemoteObject;
048: import javax.transaction.UserTransaction;
049: import javax.transaction.NotSupportedException;
050: import javax.transaction.SystemException;
051:
052: import org.objectweb.jonas.common.Log;
053: import org.objectweb.jonas.jtests.util.Env;
054: import org.objectweb.util.monolog.api.BasicLevel;
055: import org.objectweb.util.monolog.api.Logger;
056:
057: /**
058: * This Session Bean is equivalent to the Sender1_1SF bean
059: * the only difference is it is bean managed transaction
060: * it is using ConnectionFactory, Connection, Session and MessageProducer
061: */
062: public class Sender1_2SF implements SessionBean {
063:
064: static protected Logger logger = null;
065: SessionContext ejbContext;
066: private transient InitialContext ictx = null;
067: private transient ConnectionFactory cf = null;
068: private transient javax.jms.Connection c = null;
069: private transient MRecordHome ehome = null;
070: private static int count = 1;
071: private static UserTransaction utx = null;
072:
073: // ------------------------------------------------------------------
074: // SessionBean implementation
075: // ------------------------------------------------------------------
076:
077: /**
078: * Set the associated session context. The container calls this method
079: * after the instance creation.
080: * The enterprise Bean instance should store the reference to the context
081: * object in an instance variable.
082: * This method is called with no transaction context.
083: *
084: * @param sessionContext A SessionContext interface for the instance.
085: * @throws EJBException Thrown by the method to indicate a failure caused by
086: * a system-level error.
087: */
088: public void setSessionContext(SessionContext ctx) {
089: if (logger == null)
090: logger = Log.getLogger(Log.JONAS_TESTS_PREFIX);
091: logger.log(BasicLevel.DEBUG, "");
092: ejbContext = ctx;
093: }
094:
095: /**
096: * A container invokes this method before it ends the life of the session object.
097: * This happens as a result of a client's invoking a remove operation, or when a
098: * container decides to terminate the session object after a timeout.
099: * This method is called with no transaction context.
100: *
101: * @throws EJBException Thrown by the method to indicate a failure caused by
102: * a system-level error.
103: */
104: public void ejbRemove() {
105: logger.log(BasicLevel.DEBUG, "");
106: try {
107: c.close();
108: } catch (Exception e) {
109: logger.log(BasicLevel.ERROR, "Exception on close:" + e);
110: }
111: }
112:
113: /**
114: * The Session bean must define 1 or more ejbCreate methods.
115: *
116: * @throws CreateException Failure to create a session EJB object.
117: */
118: public void ejbCreate() throws CreateException {
119: logger.log(BasicLevel.DEBUG, "");
120: // Lookup Connection Factories
121: try {
122: ictx = new InitialContext();
123: cf = (ConnectionFactory) ictx.lookup("CF");
124: } catch (NamingException e) {
125: logger.log(BasicLevel.ERROR,
126: "SenderSF : Cannot lookup Connection Factories: "
127: + e);
128: throw new CreateException(
129: "SenderSF: Cannot lookup Connection Factories");
130: }
131:
132: // Create Connections
133: try {
134:
135: c = cf.createConnection();
136: } catch (JMSException e) {
137: logger.log(BasicLevel.ERROR,
138: "SenderSF : Cannot create connections: " + e);
139: throw new CreateException(
140: "SenderSF: Cannot create connections");
141: }
142:
143: // Lookup Entity Home for checking
144: String BEAN_HOME = "messageMRecordECHome";
145: try {
146: ehome = (MRecordHome) PortableRemoteObject.narrow(ictx
147: .lookup(BEAN_HOME), MRecordHome.class);
148: } catch (NamingException e) {
149: logger.log(BasicLevel.ERROR,
150: "SenderSF ejbCreate: Cannot get entity home: " + e);
151: throw new CreateException(
152: "SenderSF: Cannot get entity home");
153: }
154: }
155:
156: /**
157: * A container invokes this method on an instance before the instance
158: * becomes disassociated with a specific EJB object.
159: */
160: public void ejbPassivate() {
161: logger.log(BasicLevel.DEBUG, "");
162: }
163:
164: /**
165: * A container invokes this method when the instance is taken out of
166: * the pool of available instances to become associated with a specific
167: * EJB object.
168: */
169: public void ejbActivate() {
170: logger.log(BasicLevel.DEBUG, "");
171: }
172:
173: // ------------------------------------------------------------------
174: // private methods
175: // ------------------------------------------------------------------
176:
177: /**
178: * return a unique identifier
179: */
180: private String getUUID() {
181: long uuid;
182: synchronized (getClass()) {
183: uuid = System.currentTimeMillis() * 256 + count;
184: count++;
185: }
186: return String.valueOf(uuid);
187: }
188:
189: // ------------------------------------------------------------------
190: // Sender implementation
191: // ------------------------------------------------------------------
192:
193: /**
194: * send a message on destination (topic or queue)
195: * @param Session session
196: * @param String destination
197: * @param int value set in message
198: * @param int nb of messages sent
199: * @param boolean commit transaction if true
200: */
201: public void sendOnDestination(Session ss, String dst, int val,
202: int nb) {
203:
204: // Lookup destinations
205: Destination dest = null;
206: try {
207: dest = (Destination) ictx.lookup(dst);
208: } catch (NamingException e) {
209: throw new EJBException("sendOnDestination: Cannot lookup "
210: + dest);
211: }
212:
213: // Create the MessageProducer for destination
214: MessageProducer producer = null;
215: try {
216: producer = ss.createProducer(dest);
217: } catch (JMSException e) {
218: throw new EJBException("Cannot create MessageProducer: "
219: + e);
220: }
221:
222: // Send messages on the destination
223: try {
224: for (int i = 0; i < nb; i++) {
225: MapMessage mess = ss.createMapMessage();
226: mess.setString("Id", getUUID());
227: mess.setString("Text", dst);
228: mess.setInt("Value", val);
229: producer.send(mess);
230: }
231: } catch (JMSException e) {
232: throw new EJBException("Cannot send message: " + e);
233: }
234:
235: }
236:
237: /**
238: * send a message on destination (topic or queue)
239: * the transaction is demarcated before the session creation
240: * @param String destination
241: * @param int value set in message
242: * @param int nb of messages sent
243: * @param boolean commit transaction if true
244: */
245: public void sendOnDestinationWithTxBeforeSession(String dst,
246: int val, int nb, boolean commit) throws RemoteException {
247: logger.log(BasicLevel.DEBUG, "");
248:
249: // Obtain the UserTransaction interface
250: try {
251: utx = ejbContext.getUserTransaction();
252: } catch (IllegalStateException e) {
253: logger.log(BasicLevel.ERROR, "Can't get UserTransaction");
254: throw new RemoteException("Can't get UserTransaction:", e);
255: }
256:
257: // Start a global transaction
258: try {
259: utx.begin();
260: } catch (NotSupportedException e) {
261: logger.log(BasicLevel.ERROR, "Can't start Transaction");
262: throw new RemoteException("Can't start Transaction:", e);
263: } catch (SystemException e) {
264: logger.log(BasicLevel.ERROR, "Can't start Transaction");
265: throw new RemoteException("Can't start Transaction:", e);
266: }
267:
268: // Create Session
269: // Create Session at each request : Avoids the bug in JMS
270: // about Session not enlisted in transactions if open first.
271: Session ss = null;
272: try {
273: // (true, 0) are the recommanded args, although they are not taken
274: // in account by the container.
275: ss = c.createSession(true, 0);
276: } catch (JMSException e) {
277: throw new EJBException("Cannot create Session: " + e);
278: }
279: sendOnDestination(ss, dst, val, nb);
280:
281: // Close Session: This is mandatory for the correct behaviour of
282: // XA protocol. An XA END must be sent before commit or rollback.
283: try {
284: ss.close();
285: } catch (JMSException e) {
286: throw new EJBException("Cannot close session: " + e);
287: }
288:
289: try {
290: // commit or rollback the transaction depending on commit parameter
291: if (commit) {
292: utx.commit();
293: } else {
294: utx.rollback();
295: }
296:
297: } catch (Exception e) {
298: logger.log(BasicLevel.ERROR, "Can't rollback Transaction");
299: throw new RemoteException("Can't rollback Transaction:", e);
300: }
301: }
302:
303: /**
304: * send messages on destination (topic or queue)
305: * the transaction is demarcated after the session creation
306: * @param String destination
307: * @param int value set in message
308: * @param int nb of messages sent
309: * @param boolean commit transaction if true
310: */
311: public void sendOnDestinationWithTxAfterSession(String dst,
312: int val, int nb, boolean commit) throws RemoteException {
313:
314: // Obtain the UserTransaction interface
315: try {
316: utx = ejbContext.getUserTransaction();
317: } catch (IllegalStateException e) {
318: logger.log(BasicLevel.ERROR, "Can't get UserTransaction");
319: throw new RemoteException("Can't get UserTransaction:", e);
320: }
321:
322: Session ss = null;
323: try {
324:
325: ss = c.createSession(false, 0);
326: } catch (JMSException e) {
327: throw new EJBException("Cannot create Session: " + e);
328: }
329:
330: // Start a global transaction
331: try {
332: utx.begin();
333: } catch (NotSupportedException e) {
334: logger.log(BasicLevel.ERROR, "Can't start Transaction");
335: throw new RemoteException("Can't start Transaction:", e);
336: } catch (SystemException e) {
337: logger.log(BasicLevel.ERROR, "Can't start Transaction");
338: throw new RemoteException("Can't start Transaction:", e);
339: }
340: sendOnDestination(ss, dst, val, nb);
341: // Close Session: This is mandatory for the correct behaviour of
342: // XA protocol. An XA END must be sent before commit or rollback.
343: try {
344: ss.close();
345: } catch (JMSException e) {
346: throw new EJBException("Cannot close session: " + e);
347: }
348:
349: try {
350: // commit or rollback the transaction depending on commit parameter
351: if (commit) {
352: utx.commit();
353: } else {
354: utx.rollback();
355: }
356:
357: } catch (Exception e) {
358: logger.log(BasicLevel.ERROR, "Can't rollback Transaction");
359: throw new RemoteException("Can't rollback Transaction:", e);
360: }
361: }
362:
363: /**
364: * Checking send methods
365: * @param int value looked in messages received
366: * @param int nb of messages that could be received
367: * @param int nb of seconds max to wait for all messages
368: * @return actual nb of messages received
369: */
370: public int check(int val, int nb, int sec) {
371: Collection elist = null;
372: int retval = 0;
373: for (int i = 0; i <= sec; i++) {
374: logger.log(BasicLevel.DEBUG, "sec : " + i + "/" + sec);
375: try {
376: elist = ehome.findByValue(val);
377: retval = elist.size();
378: if (retval >= nb) {
379: // clean database before returning
380: Iterator it = elist.iterator();
381: while (it.hasNext()) {
382: MRecord ent = (MRecord) PortableRemoteObject
383: .narrow(it.next(), MRecord.class);
384: try {
385: ent.remove();
386: } catch (Exception e) {
387: throw new EJBException("Error on remove");
388: }
389: }
390: return retval;
391: }
392: } catch (FinderException e) {
393: } catch (RemoteException e) {
394: return retval;
395: }
396: try {
397: Thread.sleep(1000);
398: } catch (InterruptedException e) {
399: }
400: }
401: return retval;
402: }
403:
404: /**
405: * Clean all entity beans for this value
406: */
407: public void clean(int val) {
408: logger.log(BasicLevel.DEBUG, "");
409: Collection elist = null;
410: try {
411: elist = ehome.findByValue(val);
412: } catch (FinderException e) {
413: return;
414: } catch (Exception e) {
415: throw new EJBException("Error on find");
416: }
417: Iterator it = elist.iterator();
418: while (it.hasNext()) {
419: MRecord ent = (MRecord) PortableRemoteObject.narrow(it
420: .next(), MRecord.class);
421: try {
422: ent.remove();
423: } catch (Exception e) {
424: throw new EJBException("Error on remove");
425: }
426: }
427: }
428:
429: }
|