Jax-rs初始化子资源没有可用于注入的对象

Jax-rs initialize subresource There was no object available for injection

我有一个子资源 class,它必须使用路径中的参数进行初始化,并且还包含对必须注入的 EJB 的引用。

资源class:

@Path("widgets")
public class MasterResource{
    @Inject
    WidgetBean widgets;

    @Context
    ResourceContext rc;

    @Path("{year}")
    public WidgetArchives wArchives(@PathParam("year") String year){
        return rc.initResource(new WidgetArchiveResource(year));
    }
}

子资源 class

public class WidgetArchiveResource{
    @Inject
    WidgetBean widgets;

    public WidgetArchiveResource(String year){
        ....code
    }

    @GET
    public String doGet(){
        ....code using WidgetBean
    }
}

当我使用年份调用 get 时,我看到以下错误:

org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=WidgetBean,parent=WidgetArchiveResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,542790913)

我是 Java EE 的新手。我做错了什么?

方法 rc.initResource 仅当您需要将一些依赖项注入资源时才有意义(例如,由 @Inject 注释)。这是将依赖项注入 bean 的 JAX-RS 特定方法。它在完整的 JavaEE 环境中已被弃用,其中注入依赖项的首选方式是通过 CDI。 rc.initResource 不会注入所有 CDI bean(例如,@EJB 可以工作,但 @Inject 不行)。

因此,在 JavaEE 中,实现您想要实现的目标的首选方法是将 WidgetArchiveResource 注入父 MasterResource。 CDI bean 必须具有不带参数的构造函数,但您可以使用 setter 传递年份。如果您将您的主资源放在请求范围内,它将为每个请求重新创建,从而使其对于并发请求是安全的:

@Path("widgets")
@RequestScoped
public class MasterResource{
    @Inject
    Instance<WidgetArchiveResource> waResources;

    @Path("{year}")
    public WidgetArchives wArchives(@PathParam("year") String year){
        WidgetArchiveResource waResource = waResources.get();
        waResource.setYear(year);
        return waResource;
    }
}

此外,您应该在 bean-discovery-mode="all" 的 WEB-INF 文件夹中包含 beans.xml,或者在 WidgetArchiveResource 上明确添加依赖范围以使其符合 CDI 条件:

@Dependent
public class WidgetArchiveResource {
    public WidgetArchiveResource() {} // optional no arg constructor
}