为什么 javax.ejb.AsyncResult.isDone 总是抛出异常?

Ole*_*leg 5 java asynchronous future jakarta-ee

我想我误解了java ee异步方法调用。我遵循这个官方教程的想法。对于 void 方法来说没问题,但我希望我的异步方法返回一个值:

@Asynchronous
public Future<String> processPayment(Order order) {
    ...
    String status = ...;
    return new AsyncResult<String>(status);
}
Run Code Online (Sandbox Code Playgroud)

我在后台有很多这样长时间运行的任务,因此我收集List<Future<String>>并循环它们以检查任务是否完成。我做这个检查

for(Future<String> future: listOfFutures) {
    if(future.isDone())
       // do something
}
Run Code Online (Sandbox Code Playgroud)

但是当调用IllegalStateException:"Object does not represent an acutal Future"该方法时,代码会失败。AsyncResult.isDone()

好吧,然后我读到了这篇文章,这让我很困惑:官方教程说“使用 AsyncResult.isDone()”来检查异步方法的状态,而官方 javadoc 说“不敢使用 AsyncResult.isDone()”

我知道我可以FutureTask<T>与 一起使用Callable<T>,但这是 java se 部分。

您能否解释一下是否可以使用java ee 异步方法调用

谢谢你!

PS 我正在使用 Glassfish 3.1.2 和 EJB 3.1

小智 3

所以,你的问题是“是否可以使用java ee异步方法调用?” 答案是肯定的。你问题中的两点代码是正确的。然而,为了完全诊断您的情况出了什么问题,我们可能需要查看更多代码。

一种可能是您没有“正确”使用注释。可以在此处阅读有关如何使用的超短代码示例: https: //tomee.apache.org/examples-trunk/async-methods/README.html

该示例的重要信息是,您的异步方法必须声明为SingletonStateless bean(我们称之为容器 bean),并且在不同的 bean(或 Servlet 或 POJO 中,可以访问正确的 JNDI 上下文,就像在上面的链接)我们可以调用您对容器 bean进行调用的客户端。所以要清楚,你的for循环是在client中。然后你的意志就会按照你想要的方式行事。AsyncResult

如果您仔细阅读链接到的 javadoc,它会显示:

构造函数中指定的值将由容器检索并可供客户端使用。

应用程序不应调用其任何实例方法

这意味着该类AsyncResult是一种“愚蠢的包装器”,可以让您轻松实现接口,但不应该“真正”使用。

请注意,当您未实现 EJB 或位于 EJB 容器外部时,使用ExecutorService是执行异步调用的方法。事实上,对你有用的事实让我觉得你可以直接引用容器类,而不是通过注释或 JNDI 查找。@EJB