I would do a combination of your so called "bad solution" and the "j2ee solution":
- The original UI thread sends a asynchronous JMS message to the "backend" and returns.
- The backend receives the asynchronous request and processes it.
- When a result (or error) is reached in the backend, it is returned to the controller layer.
- The UI, still doing AJAX polling or using Bayeux/Cometed, receives and displays the result.
The trick is to match the request / response pair. I would do it like this:
- Create a "AsyncManagerService" (AMS) that has SESSION, maybe even APPLICATION wide scope so all threads talk to the same instance.
- The AMS holds a map with an id as key and any object as value.
- When creating the request JMS message, generate a unique, random key and put it into the jmsCorrelationId of the message as well as into the map, with
NULL as a value. Also pass that id to the UI.
- Let the UI thread poll the AMS with the previously generated id as long as the value in the map is
NULL.
- When the result is ready, let your JMS receiver put it into the AMS' map at the given id.
- Next time the UI thread polls the map, it will receive the answer and stop polling.
This is clean and well abstracted from any concrete domain. A purely technical solution.
Even if you don't like polling, HTTP is stateless by design and I think this way polling only happens at well defined intervals.
Anyway, I implemented a system with exactly this pattern and it runs just fine...