我正在编写一个使用异步EJB 3.1方法来并行执行许多任务的企业Java应用程序。为了支持取消长时间运行的任务,我一直在尝试使用Future接口(interface)。
不幸的是,尽管取消调用返回future.cancel(true)
,从客户端应用程序调用true
似乎对执行任务的bean的 session 上下文没有影响。
我有一个简单的界面:
public interface AsyncInterface
{
Future<Integer> run() throws Exception;
}
使用如下的bean实现:
@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的输出是无尽的“工作”流;它永远不会检测到取消。
如果相关,我将在JBoss Application Server 6.0.0上运行该应用程序。我没有使用Future接口(interface)的取消功能找到很多示例代码,所以我想知道我是否正确使用Future。这种用法看起来正确吗?是否有更好的选项来取消异步EJB方法调用?
最佳答案
回答我自己的问题-我发现JBoss AS 6.0.0不支持可异步调用的调用。
作为替代方案,我将代码重构为使用JMS请求/响应样式消息传递。
消息驱动的bean用于执行异步操作。消息驱动的Bean创建一个临时队列,并通过JMS将队列返回给调用方。这是通过利用JMS消息的ReplyTo字段实现的。
然后,消息驱动bean定期检查临时队列中是否有取消消息。
这比@Asynchronous版本要复杂得多,但是它可以在JBoss AS 6.0.0上运行。