Re: How do i handle long-running background tasks in J2EE?
On 15-09-2010 13:36, Tom Anderson wrote:
By 'long-running', i mean 'up to ten seconds'.
The context is a bog-standard e-commerce site. The task in question is
carrying out a credit card authentication and then submitting an order
to a backend system; most of the up-to-ten seconds is spent waiting for
the remote systems to respond. The page flow we want is:
1. User is on the order review page and clicks 'confirm'
2. User goes quickly to a 'were processing ur order lol' page, and waits
for it to sponteneously occur that ...
3. User arrives at the order confirmation page
The idea is that when the confirmation is submitted, we kick off the
authentication and submission as a background task, then serve the
processing page. That page then polls the server (currently by
periodically refreshing itself, in the near future perhaps with some
AJAX) to see if the order has been processed. When it has, the request
picks up the results of the processing and serves the confirmation page
(well, or an error page, etc).
Is there a standard or best-practice way to do this in pure J2EE? If
not, how about in the greater J2EE ecosystem (eg Quartz or something)?
Specifically, when running on JBoss?
As it happens, we know we can do this by spawning a thread. I know that
the J2EE spec contains dire injunctions against doing that, and that
it's not portable, but on our platform, it happens that it works. Our
current implementation is thus to set up a global ExecutorService, and
pass the order processing tasks to it as Callables to be run; we
communicate completion to the request-handling threads via a Future
which eventually delivers a sort of OrderProcessingResult object.
I'd like to know if there is a better way of doing it, though.
The one thing i've come up with is using JMS. We could set up a queue,
have the request threads post orders onto it, then use a message-driven
bean to pull them off and deal with them. I have no idea how we'd make
that multithreaded, nor how we'd communicate completion back to the
request threads. In any case, i lean away from it, because we aren't
currently using JMS or EJB, and i fear they would be a bit of a pain to
incorporate into our architecture. It might be the way to go, but i'm
more interested in hearing about other ideas.
Creating threads are fully supported in Java EE - it is explicit
forbidden in EJB and a bad idea in servlet but it is a core
feature of JCA.
That said then in this context I think the message queue (via JMS)
and a MDB is a much better solution. The first servlet/Strust Action/
JSF Backing Bean/whatever puts the request in one queue, the MDB
processes and put the response in the other queue, the second
whatever simply checks if the response are in the queue using
message selector.
Arne