我认为我误解了java ee异步方法调用。我正在遵循这位官员tutorial的想法。对于void方法,它很好,但我希望我的异步方法返回一个值:
@Asynchronous
public Future<String> processPayment(Order order) {
...
String status = ...;
return new AsyncResult<String>(status);
}
我在后台有很多这样长时间运行的任务,所以我收集List<Future<String>>
并循环遍历它们以检查任务是否完成。我按
for(Future<String> future: listOfFutures) {
if(future.isDone())
// do something
}
但是当调用方法IllegalStateException:"Object does not represent an acutal Future"
时,代码会因AsyncResult.isDone()
而失败。
那么,我读了this,这让我非常困惑:官方教程说“使用AsyncResult.isDone()”检查异步方法的状态,而官方的javadoc说< strong>“不敢使用AsyncResult.isDone()”。
我知道我可以将FutureTask<T>
与Callable<T>
一起使用,但这是java se部分。
如果可以使用 java ee异步方法调用,你能解释一下吗?
谢谢!
P.S。我正在使用Glassfish 3.1.2和EJB 3.1
答案 0 :(得分:1)
所以,你的问题是“是否可以使用java ee异步方法调用?” 答案是是。你问题中的两小部分代码是正确的。但是,要完全诊断出您的情况出了什么问题,我们可能需要查看更多代码。
可能是您没有正确使用注释。可以在这里阅读如何使用的超短代码示例: https://tomee.apache.org/examples-trunk/async-methods/README.html
该示例的重要信息是您的异步方法必须声明为 Singleton 或无状态 bean(让我们称之为容器bean ),以及我们可以调用客户端的另一个bean(或Servlet,或POJO,可以访问正确的JNDI上下文,如上面的链接)调用容器bean 。所以要明确的是, for 循环位于客户端中。那么你的AsyncResult
就会表现得像你想要的那样。
如果您仔细阅读了链接的javadoc,则说:
容器将检索构造函数中指定的值,并使其可供客户端使用。
和
应用程序
不应调用任何实例方法
这意味着AsyncResult
类是一种“哑包装”,可以让你轻松实现界面,但不应该用于“真实”。
请注意,当您不实现EJB或位于EJB容器之外时,使用ExecutorService
是执行异步调用的方法。对您有用的事实使我直接引用容器类,而不是通过@EJB
注释或JNDI查找。
答案 1 :(得分:0)
如果使用Spring Framework,请使用
org.springframework.scheduling.annotation.AsyncResult
代替
javax.ejb.AsyncResult
答案 2 :(得分:-1)
@Holger在某种意义上指出了正确的方向:在这种情况下,我的问题是Future
,AsyncResult
的实施。事实证明这很有趣。我查看了AsyncResult
类代码,这就是我所看到的:
public boolean cancel(boolean mayInterruptIfRunning)
{
throw new IllegalStateException("Object does not represent an acutal Future");
}
public boolean isCancelled()
{
throw new IllegalStateException("Object does not represent an acutal Future");
}
public boolean isDone()
{
throw new IllegalStateException("Object does not represent an acutal Future");
}
所以它解释了为什么我一直都有这个例外。
我的解决方法是将java.util.concurrent.ExecutorService.submit(new MyCallable<MyClass>(myClassInstance))
作为java.util.concurrent.Future<MyClass>
实施返回。在按预期工作后。