Transacted web service
simondelfab Apr 23, 2013 4:43 AMOriginally posted on webservices forum (https://community.jboss.org/thread/224013) with minor modification.
Hi,
I have a web service method which reads off a JMS message off from websphere MQ and the client writes the response to a database. I want the reading of the message from the queue and the writing of the data to database to be performed as a single transaction. So I set about achieving this with WS-Atomic (and I also tried WS-BusinessActivity). I followed the samples [1] and got something working (minus the integration with Websphere) in my dev environment. When I tested in an environment which simulates the live environment, it failed to work because the server on which web service was being invoked couldn't communciate to the JBoss instance ("the client") calling the web service because the client was behind a firewall. On debugging and a bit research, I realise that (obviously) sychronous communication is necessary [2] for participant registration and coordination.
So my first question is, is it possible to enable the communication back to the client to be performed over the connection established by the client to the server i.e. duplex communication like Web sockets? I doubt whether this would be possible given that HttpURLConnection that is probably being used by the client to make the call would not support Web sockets. I have considered creating a SSL tunnel from the "client" machine to the server, but this is not feasible at all deployments.
Another question I wanted to ask is whether the client calling a transacted web service needs to be performed from within JBoss? I assume it has to because of the participant registration and coordination stuff.
As an alternative solution to using WS-*, I implemented 2 web service methods (commit, rollback) which the client calls after writing the response to the database. On the server side, the read message web service method created a (transacted) session, read the message, spawned a thread (which had a reference to the JMS session), created a UUID as a transaction id and returned both the tx id and message back to the client. The spawned thread blocked (with timeout) and on receipt of either the commit and rollback web service methods, the thread was woken up and the JMS session was either committed or rolled back. Not exactly atomic, but it meant messages from the queue weren't lost and the possibility of duplicates was acceptable. I tested this with Hornet as the JMS implementation and it worked fine. But once I tried it with Websphere it didn't work because 1. the connection obtained from the factory was not transacted (despite using QueueConnection.createQueueSession(true, Session.AUTO_ACKNOWLEDGE)) and 2. if I created a UserTransaction, it is bound to the current thread.
I then looked into a solution where the transactional context is contained in a separate thread and I thought I came across the solution with javax.resource.spi.work.WorkManager, but this not available for general use in JBoss 7.1.1 [3].
I have looked at using an EJB (3.1) asynchronous method [4] in conjunction with the above solution I have outlined, but I don't think that will work either.
The situation I have encountered doesn't sound like a unique problem and I am certain there is solution or a practical work around this problem. I don't particularly want to reinvent something that is most likely solved. I would appreciate some advice/feedback. Thanks.
Regards,
Simon
[1] https://github.com/jboss-jdf/jboss-as-quickstart/tree/jdf-2.0.0.Final/wsat-simple
[2] http://docs.jboss.org/jbosstm/5.0.0.M1/guides/xts-administration_and_development_guide/ch04.html
[3] https://community.jboss.org/message/798227
[4] http://satishgopal.wordpress.com/2011/04/24/ejb-3-1-asynchronous-methods/