I'm involved in a banking project involving difficult synchronous to asynchronous problems.
Therefore I think turning to the experts, you, is a good idea.
Here's a scenario:
1. A web client places an order (buy fund) to the application server (WLS 6.0 - J2EE 1.3). Since the web client by default is a synchronous call we need to hide that functionality below is using asynchronous calls.
2. A stateless bean receives the call and should now call x number of backend systems with MQ (note that this should not be done in sequence - but in parallel):
-> MQ to OS/390 to check customer data.
-> MQ to another OS/390 to change the amount of the account.
-> MQ to a Windows NT box to place the order (buy fund).
3. Depending on the outcome (i.e. wait for all calls to return):
-> If everything went ok, then produce a 'OK' response.
-> If something went wrong, then we need to send 'UNDO' to the called backend systems.
The transaction handling will have the following scheme (all calls from WLS to backend systems should be parallel):
WLS -> Change amount of account (OS/390)
OS/390 -> Begin Tran
OS/390 -> Change amount of account
OS/390 -> Commit
WLS -> Place order (Win NT)
Win NT -> Begin Tran
Win NT -> Buy Fund
Win NT -> Commit
And so on...
When all calls have returned it is time to evaluate if everything went ok.
If not we need to produce 'UNDO' messages to the concerned backend systems.
How do we achieve this functionality with hiding the asynchronous calls from the web clients?
1. Use a Servlet and let it produce threads of all calls, i.e. create asynchronous behaviour.
Wait for the outcome and take proper response.
2. Use a Resource Adapter (since you are allowed to use threading in these objects) and
let it encapsulate the asynchronous behaviour.
3. Ignore the non-threading ban and let a stateless EJB handle the asynchronous behaviour.
We are encouraged to use the latest in J2EE and JMS is one of the techniques that will be used.
Any input on our problem would be highly appreciated.
I think a relatively standard and stable solution for your problem is to put up a message queue in each of the three boxes that you need to delegate processing to. A sinlge thread (running a session bean for instance) could put a message in each of these queues and return. The other boxes can pick up these messages, do whatever processing is involed, and put in a "finished" message in some queue (or topic, in JMS terminology). The hard part here is that you will need to assign "transaction ids" that will be passed to the participants and back to you, and somehow keep track of these IDs and the responses you got for them.
This sort of book-keeping is time-consuming, but if you choose to do the two-phase commit yourself instead of use a transaction manager you can't help it. If you use an XA transaction manager you won't be able to use JMS as a solution for communication (transaction contexts don't flow with messages) and you'll have to make sure your transaction manager supports multi-threaded transactions.
Of course we could use a single thread for putting messages into the different queues. The problem is, though, that the caller (in this case a web client) is expecting to see the result synchronously. Therefore we cannot terminate the single thread before we know the outcome of the different calls...
One way of doing this could be using ResourceAdapters, since they are allowed to use threads in the app. server which is something EJBs are not.
Ohh, now I understand... You want to wait for the calculations to finish before returning.
In that case, you can have the session bean send out the messages and then block on a queue until all the components place their reply there. For the queue you have two options:
1. If your JMS provider supports temporary queues, that's probably the cleanest sultion. Just make a temporary for the replies to go into.
2. If it doesn't, you can use a single static queue and filter messages for each session bean using some unique ID. For this purpose, an IP+time+random(32bit is good) would probably be unique enogth.
Have you considered this approach?
BTW - Check out the MDB chapter review from Mastering EJB II. It lists some common problems with using such an approach, most have to due with passivation as I remember.
Thanx Gal. I'll look into Mastering EJB II for more information.