CDI 注入在使用 Jersey 作为 JAX-RS 实现的 WAS Liberty 中的 REST 资源中不起作用

CDI injection not working in REST Resource in WAS Liberty with Jersey as JAX-RS implementation

我正在使用 websphere liberty 19.0.0.8,我想使用 Jersey 而不是默认的 CXF 来实现 jax-rs。我从服务器 xml 中删除了 jaxrs-2.1 功能,并在我的 webapp 中打包了 jersey 实现 jar。war。

<featureManager>
    <feature>servlet-4.0</feature>
    <feature>jndi-1.0</feature>
    <feature>requestTiming-1.0</feature>
    <feature>monitor-1.0</feature>
    <feature>localConnector-1.0</feature>
    <feature>restConnector-2.0</feature>

<!-- Do not add enabled webProfile-8.0 because we want to disable default 
    REST implementation (Apache-CXF) provided by Liberty. We want to use Jersey 
    as our REST implementation because it better support multi-part streaming, -->
    <!-- <feature>webProfile-8.0</feature> -->
    <feature>jsp-2.3</feature>
    <feature>cdi-2.0</feature>
    <feature>managedBeans-1.0</feature>
    <feature>jdbc-4.2</feature>
    <!-- <feature>jaxrs-2.1</feature> -->
</featureManager>

Gradle 构建包括球衣实现

//JxRS Jersey implementation    
compile group: 'org.glassfish.jersey.containers', name: 'jersey-container-servlet', version: '2.25.1'       
compile group: 'org.glassfish.jersey.media', name: 'jersey-media-json-jackson', version: '2.25.1'
compile group: 'org.glassfish.jersey.media', name: 'jersey-media-multipart', version: '2.25.1'
compile group: 'com.fasterxml.jackson.jaxrs', name: 'jackson-jaxrs-json-provider', version: '2.9.0'

扩展球衣的 ResourceConfig 来配置我的 RestApplication

@ApplicationPath("/")
public class RestApplicationConfig extends ResourceConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(RestApplicationConfig.class);

    public RestApplicationConfig() {
        super();
        configureResourcesAndFeatures();
    }

    private void configureResourcesAndFeatures() {
        packages(RestApplicationConfig.class.getPackage().getName());
        register(MultiPartFeature.class);
    }
}

通过所有这些设置,我的其余部分 api 可以正常工作,并且我可以在我的代码中使用 Jersey 的多个相关 classes。

现在问题出在 CDI 上。在我的资源 class 中,我能够注入托管的 CDI resource/classes 例如

@ApplicationScoped
@Path("/ping")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class PingResource {

    private static final Logger LOGGER = LoggerFactory.getLogger(PingResource.class);

    @Resource(lookup = "jndi_dpa_iss_rest_url")
    private String issRestBaseUrlInResource;

    @Inject
    private DocumentService documentService;
}

在上面 class @Resource 和 @Inject 无法解析 JNDI 资源和托管 bean。只要我在 server.xml 中启用 jaxrs-2.1 功能,CDI 注入就可以工作,但随后我松开球衣,它使用 CXF。

DocumentService 及其实现 class 定义如下。一切都在与 RestApplicationConfig class 或其子包相同的包下。

@ApplicationScoped
@Transactional(value = Transactional.TxType.NOT_SUPPORTED)
public class DocumentServiceImpl implements DocumentService {
    // some code here
}

在我的休息资源 classes 中使用 CDI 需要什么?

因为目前没有 CDI 2.0 的球衣扩展,我必须找到解决方法。解决方法是手动向 CDI 容器查询我们感兴趣的 bean 类型。这样我们在我们的资源中手动注入 CDI bean class 但注入的 bean 是托管 bean 实例,因此 CDI 已经满足所有需求它的依赖项。

我们仅在资源层中进行手动注入,但 CDI 应该可以正常工作。

工作代码。

@ApplicationScoped
@Path("/ping")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class PingResource {

    private DocumentService documentService = CDI.current().select(DocumentService.class).get();

}

基本上不用@Inject 手动查询CDI容器。