Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cancelling an @Asynchronous EJB call

I am writing an enterprise Java application that uses asynchronous EJB 3.1 methods to execute a number of tasks in parallel. To support cancelling a long running task I have been attempting to use the Future interface.

Unfortunately calling future.cancel(true) from the client application appears to have no effect on the session context of the bean executing the task, despite the fact that the cancel call is returning true.

I have a simple interface:

public interface AsyncInterface
{
    Future<Integer> run() throws Exception;
}

With a bean implementation as follows:

@Stateless
@Remote(AsyncInterface.class)
public class AsyncBean
{
    @Resource SessionContext myContext;

    @Asynchronous
    public Future<Integer> run() throws Exception
    {
        Integer result = 0;

        System.out.println("Running AsyncBean");

        while(myContext.wasCancelCalled() == false)
        {
            Thread.sleep(2000);
            System.out.println("Working");
        }      

        System.out.println("AsyncBean cancelled");

        return new AsyncResult<Integer>(result);
     }
}

The client code is straight forward:

InitialContext ctx = new InitialContext();
AsyncInterface async = (AsyncInterface)ctx.lookup("AsyncBean/remote");
Future<Integer> future = async.run();

if( future.cancel(true) )
{
     System.out.println("future.cancel() returned true");
}
else
{
     System.out.println("future.cancel() returned false");
}

The output from the bean is an endless stream of "Working"; it never detects the cancellation.

In case it's relevant, I'm running the application on JBoss Application Server 6.0.0. I haven't located much sample code using the cancel feature of the Future interface, so I'm wondering if I am using Future correctly. Does this usage look correct? Are there better options for cancelling an asynchronous EJB method call?

like image 868
malloc Avatar asked Jan 24 '11 03:01

malloc


2 Answers

Answering my own question - I've found out that cancallation of asynchronous requests is not supported in JBoss AS 6.0.0.

As an alternative I've refactored the code to use JMS request/response style messaging.

A message driven bean is used to execute an asynchronous operation. The message driven bean creates a temporary queue and returns the queue to the caller via JMS. This is achieved by utilising the replyTo field of JMS messages.

The message driven bean then periodically checks the temporary queue for a cancellation message.

This is more complicated than the @Asynchronous version but it works on JBoss AS 6.0.0.

like image 82
malloc Avatar answered Oct 17 '22 11:10

malloc


You must return a Future type of object, instead of null. By the way, are you not getting a NPE? I would expect one, with your code in question.

Furthermore, cancel() should not be called. See the docs here. By the way, its not just cancel() method which should not be called, no instance method should be called, according to the docs. Which begs the question that why the heck then a method should return AsyncResult. I simply have no idea, may be its there for future use. But the class level comments are suggesting that all the methods are there for convenience to provide the result to the container.

Hence, I am not sure whether cancelling the asynchronous EJB call is possible at all or not yet.

[Edited after a little research]

Try this implementation,

@Stateless
@Remote(AsyncInterface.class)
public class AsyncBean
{
    @Resource SessionContext myContext;

    @Asynchronous
    public Integer run() throws Exception
    {
        Integer result = 0;

        System.out.println("Running AsyncBean");

        while(myContext.wasCancelCalled() == false)
        {
            Thread.sleep(2000);
            System.out.println("Working");
        }      

        System.out.println("AsyncBean cancelled");

        return result;
     }
}
like image 2
Adeel Ansari Avatar answered Oct 17 '22 12:10

Adeel Ansari