-
1. Re: Use JMS integration classes for MessageListener
tomjenkinson Apr 26, 2016 10:09 AM (in response to sewatech)This sounds like a good one for gytis to provide input on. Can you can express a little more in pseudocode what you are proposing, it would help to understand where it would be best placed to add your work. [JBTM-2616] Implement JMS integration classes - JBoss Issue Tracker was added so that when getConnection is called the connection can be enlisted in an XA transaction, rather that to add JMS-like functionality to JSE.
I guess you are wanting the onMessage to be within the same XA transaction as a DB update maybe? From my recollection that is predominantly the role of the container and requires a lot of code. Perhaps something like WildFly swarm would be more appropriate for that: wildfly-swarm-examples/messaging/messaging-mdb at master · wildfly-swarm/wildfly-swarm-examples · GitHub
-
2. Re: Use JMS integration classes for MessageListener
sewatech Apr 26, 2016 10:30 AM (in response to tomjenkinson)I've asked my client to share the source code. I hope I'll be allowed to very soon. If not, I'll make a separate example.
As you guess it, my onMessage method access to a database. Something like this :
public void onMessage(Message jmsMessage) { try (MessageDbAccess dao = new MessageDbAccess()) { dao.save(fromJMS(jmsMessage)); } catch (JMSException e) { throw new FailException(e); } }
I want that onMessage to be in a XA transaction. For this aim, I've put the MessageListener object in a MessageListenerProxy :
public void onMessage(Message jmsMessage) { try { transactionManager.begin(); Transaction transaction = transactionManager.getTransaction(); transaction.enlistResource(xaSession.getXAResource()); messageListener.onMessage(jmsMessage); transactionManager.commit(); } catch (Exception e) { transactionManager.rollback(); ... } }
-
3. Re: Use JMS integration classes for MessageListener
sewatech Apr 26, 2016 10:37 AM (in response to sewatech)In the meanwhile, I'm authorized to share the example. It's on bitbucket : sewatech / efluid-jta — Bitbucket
My own support proxies are in the fr.sewatech.jta.jms package, in the tx-jta-utils module (see https://bitbucket.org/sewatech/efluid-jta/src/8db792aeacd3/tx-jta-utils/src/main/java/fr/sewatech/jta/jms/).
-
4. Re: Use JMS integration classes for MessageListener
tomjenkinson Apr 27, 2016 7:36 AM (in response to sewatech)We did do some Spring Boot integration work (its actually where the JMS work came from) and that has some kind of message listener abstraction. We have a quickstart that shows that: quickstart/MessagesService.java at master-JBTM-2634-spring-boot · gytis/quickstart · GitHub
-
5. Re: Use JMS integration classes for MessageListener
sewatech Apr 27, 2016 9:46 AM (in response to tomjenkinson)Is the onMessage method transactional in your quickstart example ?
-
6. Re: Use JMS integration classes for MessageListener
tomjenkinson Apr 27, 2016 10:05 AM (in response to sewatech)A good question, I assumed so but perhaps its not. gytis will know as he wrote the original example.
-
7. Re: Use JMS integration classes for MessageListener
zhfeng Apr 28, 2016 1:24 AM (in response to tomjenkinson)I think the current quickstart example does not use transaction in the MessageListerner. But it could be easy to add this
@Component @Transactional public class MessagesListener { @Autowired private EntriesService entriesService; public static final String QUEUE_NAME = "quickstart-messages"; @JmsListener(destination = QUEUE_NAME) public void onMessage(String message) throws Exception { System.out.println("Message received: " + message); entriesService.create(message); if (message.contains("rollback")) { throw new RuntimeException(message); // This could cause the spring to rollback the transaction } } }
I just update gytis example in GitHub - zhfeng/quickstart at spring-boot and hope it is helpful.
Amos
-
8. Re: Use JMS integration classes for MessageListener
gytis Apr 28, 2016 3:08 AM (in response to sewatech)First of all, I need to point out that currently org.jboss.narayana.jta.jms package only contains functionality which was needed to integrate Narayana to Spring Boot. Which is to enlist XAResource to the transaction when a session is created and to make sure that the session is closed when the transaction is completed.
As for MessageListener, I think that if you only implement the MessageListener interface there isn't much we can do in standalone, because some middleware would be required to wrap it into the transaction and we don't have such functionality at the moment. However, if you're using our current ConnectionProxy to create a session, it might work if you use Session.setMessageListener method on the returned session (I haven't have a chance to try this yet).
Finally, the quickstart that was mentioned here a couple of times is not completed yet. For now, only the one in Spring Boot repository works correctly: https://github.com/spring-projects/spring-boot/blob/v1.4.0.M2/spring-boot-samples/spring-boot-sample-jta-narayana. However, that quickstart uses Spring JmsListener annotation rather than the JMS interface (https://github.com/spring-projects/spring-boot/blob/v1.4.0.M2/spring-boot-samples/spring-boot-sample-jta-narayana/src/main/java/sample/narayana/Messages.java#L25).
-
9. Re: Use JMS integration classes for MessageListener
sewatech Apr 28, 2016 9:08 AM (in response to zhfeng)zhfeng Thanks Amos. It would be nice to have something similar without Java EE and without Spring. I could add the support of the JTA @Transactional annotation in my example.
-
10. Re: Use JMS integration classes for MessageListener
sewatech Apr 28, 2016 9:07 AM (in response to gytis)Oh, I thought that this jms package aimed to be used in a JavaSE environment, just like the jdbc package. It mainly works in my example without Spring, except for the MessageListener.
some middleware would be required to wrap it into the transaction...
Couldn't this middleware stuff be replace by a proxy of MessageListener ? That's what I've done in my example. Is there anything wrong in my own proxy : sewatech / efluid-jta / source / tx-jta-utils / src / main / java / fr / sewatech / jta / jms / MessageListenerProxy.… ?
-
11. Re: Use JMS integration classes for MessageListener
gytis Apr 28, 2016 9:22 AM (in response to sewatech)I wrote it to integrate Narayana with Spring, but I tried to write it in a way that it could be used standalone too. However, it doesn't have the complete functionality, because at the time of the implementation all we needed were the proxies for factory, connection, and session in order to integrate with Spring Boot.
Of course there is room for extension, if there is a need. E.g. Spring Boot doesn't use JMS 2.0, so proxies for that are also not implemented.
I'm sure we could provide an integration for MessageListener too. Either with proxy or not is the question of usability, because user would have to wrap his listeners manually.
Feel free to raise a JIRA at System Dashboard - JBoss Issue Tracker with JBTM project.
-
12. Re: Use JMS integration classes for MessageListener
tomjenkinson Apr 28, 2016 9:24 AM (in response to sewatech)The JMS integration code should not require Spring and should be able to be used outside of that for synchronous use cases and I understand from your initial message that this is the case.
However, it will be JMS provider implementation specific how setMessageListener on an XAConnection will work. From my recollection of implementing a provider typically the transaction management is handled by an external container (contemporarily something like JEE or Spring).
-
13. Re: Use JMS integration classes for MessageListener
tomjenkinson Apr 28, 2016 9:34 AM (in response to gytis)To the point about building something XA aware for message listener it is a question of the suitability for such a project within the scope of Narayana. The point I am making is that building a container for "MDBs" is already done by both Spring and WFLY (boot or swarm I guess) and so I don't believe we can add considerable value here over what a user can do using the synchronous JMS API. A simple pseudo code would be to put this in a thread pool:
public void run() {
getXAConnection()
while (true) {
tx.begin();
getXASession
createMessageConsumer()
receive()
doDbWork()
tx.commit()
}
}
-
14. Re: Use JMS integration classes for MessageListener
sewatech Apr 28, 2016 9:43 AM (in response to tomjenkinson)Are you saying that async is useless in Java SE ???
MDB is not the only place for async, and MessageListener is not only for MDB. If my JMS client make the job with threads and such low level things, it's better for my own code.
Once again, I don't understand why a simple proxy wouldn't do the job here, and why a full container is needed.