Отмена @Asynchronous EJB-вызова - PullRequest
       33

Отмена @Asynchronous EJB-вызова

7 голосов
/ 24 января 2011

Я пишу корпоративное Java-приложение, которое использует асинхронные методы EJB 3.1 для параллельного выполнения ряда задач. Чтобы поддержать отмену длительной задачи, я пытался использовать интерфейс Future.

К сожалению, вызов future.cancel(true) из клиентского приложения, похоже, не влияет на контекст сеанса компонента, выполняющего задачу, несмотря на то, что вызов отмены возвращает true.

У меня простой интерфейс:

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

С реализацией компонента следующим образом:

@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);
     }
}

Код клиента прост:

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");
}

Выход из bean-компонента - это бесконечный поток «Working»; никогда не обнаруживает отмену.

Если это актуально, я запускаю приложение на сервере приложений JBoss 6.0.0. Я не нашел много примеров кода с помощью функции отмены интерфейса Future, поэтому мне интересно, правильно ли я использую Future. Это использование выглядит правильно? Есть ли лучшие варианты для отмены асинхронного вызова метода EJB?

Ответы [ 2 ]

3 голосов
/ 16 февраля 2011

Отвечая на мой собственный вопрос - я обнаружил, что в JBoss AS 6.0.0 не поддерживается канкаляция асинхронных запросов.

В качестве альтернативы я реорганизовал код для использования обмена сообщениями в стиле запроса / ответа JMS.

Бин, управляемый сообщениями, используется для выполнения асинхронной операции. Управляемый сообщениями компонент создает временную очередь и возвращает очередь вызывающей стороне через JMS. Это достигается путем использования поля replyTo сообщений JMS.

Затем управляемый сообщениями компонент периодически проверяет временную очередь на предмет сообщения об отмене.

Это сложнее, чем @Asynchronous версия, но она работает на JBoss AS 6.0.0.

2 голосов
/ 24 января 2011

Вы должны return тип объекта Future вместо null.Кстати, ты не получаешь NPE?Я ожидаю, что с вашим кодом.

Кроме того, cancel() не должен вызываться. См. Документы здесь .Между прочим, это не просто метод cancel(), который не должен вызываться, не должен вызываться метод экземпляра, в соответствии с документами .В связи с этим возникает вопрос, почему, черт возьми, метод должен вернуть AsyncResult.Я просто понятия не имею, может быть, его там для будущего использования.Но комментарии уровня класса предполагают, что все методы существуют для удобства для предоставления результата контейнеру.

Следовательно, я не уверен, возможно ли отмена асинхронного вызова EJB ввсе или еще нет.

[Отредактировано после небольшого исследования]

Попробуйте эту реализацию,

@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;
     }
}
...