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())
| .lookup(ServiceConstants.USER_TRANSACTION_JNDI);
|
| userTransaction.begin();
|
| for(...every number in from request content...){
| 1. parse number
| 2. save number to DB
| 3. send message with number
| }
|
| userTransaction.commit();
|
| }
|
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.
P.S
Sorry for my English - learning still in progress.
View the original post :
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4249245#...
Reply to the post :
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&a...