Payara Micro中@Asynchronous注解未实现异步执行问题
问题原因
你的@Asynchronous注解未生效,核心原因是JAX-RS资源类默认不属于EJB容器管理的Bean,直接调用自身标注@Asynchronous的方法时,只是普通的同步方法调用,不会触发容器的异步代理逻辑,自然无法实现异步执行。
解决方案
方案一:将资源类转为无状态EJB
给FooResource添加@Stateless注解,让它成为EJB容器管理的Bean,此时容器会为其生成代理,调用异步方法时会触发异步逻辑:
@Path("foo") @Stateless public class FooResource { @GET public String get() { System.out.println("Request started"); this.doSomething(); // 现在会通过EJB代理实现异步 System.out.println("Request ended"); return "Hello world! "; } @Asynchronous public void doSomething() { try { System.out.println("Long task started"); Thread.sleep(2000); System.out.println("Long task ended"); } catch (InterruptedException e) { System.out.println("Long task failed"); } } }
方案二:将异步方法抽入独立EJB
如果不想修改资源类的类型,可以把异步方法单独放到一个EJB类中,再通过依赖注入调用:
- 创建异步业务EJB:
@Stateless public class AsyncService { @Asynchronous public void doSomething() { try { System.out.println("Long task started"); Thread.sleep(2000); System.out.println("Long task ended"); } catch (InterruptedException e) { System.out.println("Long task failed"); } } }
- 修改资源类注入并调用:
@Path("foo") public class FooResource { @Inject private AsyncService asyncService; @GET public String get() { System.out.println("Request started"); asyncService.doSomething(); // 通过注入的EJB触发异步执行 System.out.println("Request ended"); return "Hello world! "; } }
注意事项
- Payara Micro默认支持EJB与JAX-RS的集成,无需额外配置
domain.xml,但若你对domain.xml做过自定义修改,需确保ejb-container组件处于启用状态。 - 永远不要直接调用自身的异步方法,因为这种调用不会经过容器代理,容器无法识别并处理
@Asynchronous注解。
内容的提问来源于stack exchange,提问作者Calcimicium
相关产品推荐
相关产品推荐

