4 Replies Latest reply on Aug 13, 2009 6:46 AM by Damian Sinczak

    Messaging and transactions together

    Damian Sinczak Newbie

      I have a great problem with understanding transactions along with messaging. What I have to do is to write a Servlet that will receive a lot of data, e.g. POST request with 100000 numbers in content, I have to parse those numbers and do both:
      - Save them into database (I'm using JPA with Hibernate below)
      - For every number I have to send message on queue with it.
      On the other site there are Message Driven Beans (MDB) that consumes messages, takes numbers from them and do something with those numbers (e.g. send them to another system).

      What My problem is that I want it to happen in two steps
      1 - Numbers parsing, persisting into database and sending messages with them (in one transaction, because if any of the numbers in content is corrupted I have to roll back both saving data to database and sending messages)
      2 - After everything have been saved and send (there was a transaction commit) MDBs start to consume messages and process them and reding also the same numbers from database (in second separate transaction managed by EJB container, because if anything during processing message goes wrong I want it to go back on queue), the same numbers that were saved in previous transaction.

      What I can't do is that I can not force QueueSession (Even tried XAQueueSession) to work with JTA user transaction. This is what I do:

      protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
       IOException {
       UserTransaction userTransaction = null;
       QueueConnectionFactory jmsConnectionFactory = null;
       MessageProducer jmsProducer = null;
       QueueSession jmsSession = null;
       QueueConnection jmsConnection = null;
       Queue jmsSingleNumberQueue = null;
       QueueConnectionFactory jmsConnectionFactory =(QueueConnectionFactory) initialContext.lookup(ServiceConstants.CONNECTION_FACTORY_JNDI);
       jmsConnection = jmsConnectionFactory.createQueueConnection();
       jmsSingleMsisdnQueue = (Queue) initialContext.lookup(ServiceConstants.SINGLE_NUMBER_QUEUE_JNDI);
       jmsSession = jmsConnection.createQueueSession(true, Session.SessionTransacted);
       jmsProducer = jmsSession.createProducer(jmsSingleNumberQueue);
       userTransaction = (UserTransaction) (new InitialContext())
       for(...every number in from request content...){
       1. parse number
       2. save number to DB
       3. send message with number

      This is only sketch so if something is not clear please tell.

      When I wrote this code I noticed that JMS session is not a part of user transaction. In other words, when I put some messages on queue they are instantly consumed by MDB. Also in this case where there is jmsSession = jmsConnection.createQueueSession(true, Session.SessionTransacted); I have to commit JMS session by my self. It seams that JMS session do not see or event cooperate with user transaction.
      When I used XAQueueSession, commit was made by session but there was other problem, this commit also didn't care about user transaction and messages were consumed instantly after sending, that brought another problem, because User transaction in many cases didn't commit and numbers that were persisted (2. save number to DB) are not visible to MDB and I'm getting NoResultException when I'm trying to retrieve those numbers from DB (they are just not commited yet and MDB (with transaction attribute required) works in another transaction so those numbers are not visible for him).

      Maybe I'm misunderstood the concept of JMS and JBoss messaging so please correct me. I would appreciate if you have any ideas how to solve my problem.

      Sorry for my English - learning still in progress.