问题描述
我有一个JAX-RS资源类,它使用@Context ResourceContext为子资源类提供路径路由,为每种资源类型创建子资源实例。在此示例中,我将实例化报告子资源。
I have a JAX-RS resource class that provides path routing to sub resource classes using @Context ResourceContext to create sub resource instances for each resource type. In this example I am instantiating a reporting sub resource.
资源
@Context
ResourceContext rc;
@Path("reports")
public ReportsResource reportsResource() {
return rc.initResource(new ReportsResource());
}
子资源需要一个ReportService类的实例(使用@Stateless定义注释),自然的解决方案是@Inject it ...
The sub resource needs an instance of a ReportService class (defined with the @Stateless annotation), the natural solution would be to @Inject it ...
报告SubResource
@Inject
ReportsService rs;
@GET
@Path("{rptno}")
@Produces(MediaType.APPLICATION_XML)
public Report report(@PathParam("rptno") int rptNumber) throws Exception {
return rs.getReport(rptNumber);
}
我将Glass EE7与Glassfish和WAS Liberty Profile一起使用的经验
是没有注入ReportService rs的实例,将rs保留为null并导致NPE。
My experience using Java EE7 with both Glassfish and WAS Liberty Profile is that an instance of ReportService rs is not injected, leaving rs as null and causing a NPE.
我的假设是因为资源类正在执行new ReportsResource( ),CDI无法查看ReportsResource实例,因此ReportsResource不是容器管理的。
这似乎与这个问题的情况相同
My assumption is that because the resource class is doing a "new ReportsResource()", CDI has no visibility to the ReportsResource instance and so ReportsResource is not container managed.This seems to be the same situation as this question Inject EJB into JAX-RS 2.0 subresource when subresource is got via ResourceContext
我的解决方案有些不同,我选择在Resource类中的@Inject ReportService,然后在ReportsResource构造函数上传递实例。
My solution is somewhat different, I chose to @Inject ReportService in the Resource class, then pass the instance on the ReportsResource constructor.
修改后的资源
@Inject
ReportsSerivce rs;
@Context
ResourceContext rc;
@Path("reports")
public ReportsResource reportsResource() {
return rc.initResource(new ReportsResource(rs));
}
修改后的报告子资源
public class ReportsResource {
private ReportsSerivce rs;
public ReportsResource(ReportsSerivce rs) {
this.rs = rs;
}
@Context
HttpHeaders headers;
@GET
@Path("{rptno}")
@Produces(MediaType.APPLICATION_XML)
public Report report(@PathParam("rptno") int rptNumber) throws Exception {
return rs.getReport(rptNumber);
}
所以我的问题
- 我对@Inject失败原因的假设是什么?
- 有没有办法让@Inject在子资源中工作?
- 是否有更好的解决办法将ReportService实例从Resource传递给SubResource那更像是CDI / Java EE吗?
推荐答案
如果你想注入CDI bean进入JAX-RS资源,我不建议使用。所有这一切都是将字段注入现有对象,但它使用JAX-RS特定机制,类似于当CDI不可用时JavaEE5中EJB的注入工作方式。
If you want to inject CDI beans into JAX-RS resources, I don't recommend using rc.initResource. All it does is injection of fields into existing object, but it uses JAX-RS specific mechanism, similar to how injection worked for EJBs in JavaEE5, when CDI was not available.
最好使用CDI并从代码中删除 ResourceContext
。
It is better to use CDI and remove ResourceContext
from your code.
示例:
资源
@Inject
private ReportsResource reportsResource;
@Path("reports")
public ReportsResource reportsResource() {
return reportsResource;
}
主资源应为 @RequestScoped
以便为每个请求重新创建它。或者您可以使用注入新内容每个方法调用的实例:
The master resource should be @RequestScoped
so that it gets recreated for each request. Or you may inject using Intance to get new instance for every method call:
@Inject
private Instance<ReportsResource> reportsResources;
@Path("reports")
public ReportsResource reportsResource() {
return reportsResources.get();
}
这篇关于在ResourceContext initResource创建的JAX-RS子资源实例中无法进行CDI注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!