views:

255

answers:

2

We use axis2 for building our webservices and a Jboss server to run the logic of all of our applications. We were asked to build a webservice that talks to a bean that could take up to 1 hour to respond (depending on the size of the request) so we would not be able to keep the connection with the consumers opened during that time.

We could use an asynchronous webservice but that hasn't come out all that well so we decided we could implement a bean that will do the logic behind the webservice and have the service invoke that bean asynchronously. The webservice will generate a token that will pass to the consumer and the consumer can use it to query the status of the request.

The questions I have are:

  1. How to I query the status of the bean on the Jboss server once I have returned from the method in the service that created that bean. Do I need to use stateful beans?
  2. Can I use stateful beans if I want to do asynchronous calls from the webservice side?
A: 

I don't think stateful session beans are the answer to your problem, they're designed for long-running conversational sessions, which isn't your scenario.

My recommendation would be to use a Java5-style ExecutorService thread pool, created using the Executors factory class:

  1. When the web service server initializes, create an ExecutorService instance.
  2. Web service call comes in, the handler creates an instance of Callable. The Callable.call() method would make the actual invocation on the business logic bean, in whatever form that takes.
  3. This Callable is passed to ExecutorService.submit(), which immediately returns a Future object representing the eventual result of the call. The Executor will start to invoke your Callable in a separate thread.
  4. Generate a random token, store the Future in a Map with the token as the key.
  5. Return the token to the web service client (steps 1 to 4 should happen immediately)
  6. Later, he web service client makes another call asking for the result, passing in the token
  7. The server looks up the Future using the token, and calls get() on the Future, with a timeout value so that it only waits a short time for the answer. The get() call will return the execution result of whatever the Callable invoked.
    • If the answer is available, return it to the client, and remove the Future from the `Map.
    • Otherwise, tell the client to come back later.

It's a pretty robust approach. You can even configure the ExecutorService to limit the number of calls that can be in execution at the same time, if you so desire.

skaffman
It seems like a new Thread is created when I use this interface. I tried creating a simple Thread and also tried Timer and then I came across a different problem. When the child thread executes it doesn't seem to have access to the datatypes defined in the .aar file. None of my custom datatypes are recognized and I had to put them on a separated jar in the tomcat lib folder for it to work. I assume the same will happen here... Do you know if there is a way around it so I don't have to put this jar in the tomcat lib directory?Thanks
poijoi
Also how do I save the token in a Map? The object will die when the method returns the response to the webservice client... no?
poijoi
+3  A: 

Another approach you could take is to make use of JMS and a DB.

The process would be

  1. In web service call, put a message on a JMS Queue
  2. Insert a record into a DB table, and return a unique id for that record to the client
  3. In an MDB that listens to the Queue, call the bean
  4. When the bean returns, update the DB record with a "Done" status
  5. When the client calls for status, read the DB record, return "Not Done" or "Done" depending on the record.
  6. When the client calls and the record indicates "Done", return "Done" and delete the record

This process is a bit heavier on resource usage, but has some advantages

  • A Durable JMS Queue will redeliver if your bean method throws an Exception
  • A Durable JMS Queue will redeliver if your server restarts
  • By using a DB table instead of some static data, you can support a clustered or load balanced environment
karoberts