[jboss-user] [EJB 3.0] - Re: Stateful Bean and the database commit

elkner do-not-reply at jboss.com
Wed Jan 17 09:46:01 EST 2007


"konstantin.ermakov" wrote : Hi!
  | 
  | As far as I understood, after update() it is not guaranteed, that the data is in database and commit event already happened. So, as I have the fat clients it can be the case, that after update() was called, getObject() still returns the old entity.
  | 
  | My question is  - is it guarateed, that after the afterCompletion() method the database commit already happened, and it is safe to call getObject() to receive the new data?
  | 

I think yes, when you use TXed messages to notify your clients. E.g. here the meat (aka main things) how I use it:

  | public class MsgProducer {
  |     private static HashMap<String, AtomicLong> seq =
  |         new HashMap<String, AtomicLong>();
  | ...
  |     /**
  |      * Simple container for recording queue parameters.
  |      *
  |      * @author  Jens Elkner
  |      * @version $Revision$
  |      */
  |     public static class QueueParams {
  |         Connection con;
  |         Session session;
  |         MessageProducer producer;
  | 
  |         QueueParams(Connection con, Session session, MessageProducer producer) {            this.con = con;
  |             this.session = session;
  |             this.producer = producer;
  |         }
  | 
  |         void destroy() {
  |             if (con != null) {
  |                 try {
  |                     con.stop();
  |                 } catch (JMSException e) {
  |                     // ignore
  |                 }
  |             }
  |             if (session != null) {
  |                 try {
  |                     session.close();
  |                 } catch (JMSException e) {
  |                     // ignore
  |                 }
  |             }
  |             if (con != null) {
  |                 try {
  |                     con.close();
  |                 } catch (JMSException e) {
  |                     // ignore
  |                 }
  |             }
  |         }
  |     }
  | 
  |       /**
  |      * Create a message producer for the given destination.
  |      *
  |      * @param destination   topic to use
  |      * @param tx            whether to use a transaction scoped session
  |      * @return <code>null</code> on error, the message producer otherwise.
  |      */
  |     private static QueueParams createNewSession(String destination, boolean tx)
  | {
  |       try {
  |             ctx = new InitialContext();
  |             // we let the destination decide, whether it is a
  |             // Queue- or TopicConnectionFactory
  |             ConnectionFactory cf = (ConnectionFactory)
  |                 ctx.lookup("java:/JmsXA");
  |             // create a Connection using the ConnectionFactory (it is not
  |             // necessary to start the Connection if messages are only sent)
  |             Connection tc = cf.createConnection();
  |             // create a Session using the Connection: Transaction +
  |             // Auto Acknowledge of the Messages
  |             Session s = tc.createSession(tx,
  |                 tx ? Session.SESSION_TRANSACTED : Session.AUTO_ACKNOWLEDGE);
  |             // look up the Destination (either Queue or Topic) to which we want
  |             // to connect in JNDI
  |             Destination dst = (Destination) ctx.lookup(destination);
  |             // create a message producer by the session and destination acquired
  |             // above
  |             MessageProducer producer = s.createProducer(dst);
  |             if (producer != null) {
  |                 params = new QueueParams(tc, s, producer);
  |             }
  |         } catch (Exception e) {
  |             log.error(e.getLocalizedMessage());
  |             failed = true;
  |         }
  |         if (failed && params != null) {
  |             params.destroy();
  |             params = null;
  |         }
  |         return params;
  |     }
  | 
  |     /**
  |      * Send a message to the given destination.
  |      *
  |      * @param destination   name of the queue/topic - e.g. "topic/foo" or
  |      *      "queue/bar".
  |      * @param list  list of CRUD events
  |      */
  |     public static void send(String destination, CrudEventList list) {
  |         if (destination == null || list == null || list.getSize() == 0) {
  |             return;
  |         }
  |         QueueParams q = createNewSession(destination, true);
  |         if (q == null) {
  |             log.error("Unable to deliver message to '" + destination + "'");
  |             return;
  |         }
  |         try {
  |             ObjectMessage m = q.session.createObjectMessage(list);
  |             long msgId = getNextId(destination);
  |             m.setLongProperty("seq", msgId);
  |             if (log.isDebugEnabled()) {
  |                 log.debug("sending CRUD message " + msgId + " to " + destination);
  |             }
  |             q.producer.send(m);
  |         } catch (JMSException e) {
  |             log.error(e.getLocalizedMessage());
  |         }
  |         q.destroy();
  |     }
  | ...
  | }
  | 
So  if you append something like MsgProducer.send(bla, fahsel) at the end of your SLSB, the message would be sent only, if the TX succeeds, i.e. commit succeeded.
Never had any out of sync problems, after changed to this pattern, so it might be useful for you as well... ;-)

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4002813#4002813

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4002813



More information about the jboss-user mailing list