java - 使用 JAX-RS 和 Glassfish 进行 CDI 和资源注入(inject)

标签 java jakarta-ee glassfish jax-rs cdi

我目前正在开发一个 JAX-RS Servlet,然后我想将其部署在 Glassfish 4.1 服务器中(因此 JAX-RS 运行时是 Jersey 2.x)。

我不想使用 Spring 进行配置和 DI 工作,而是想尝试使用 Java EE 方法来完成此操作。但是,CDI 和我在 Glassfish Server 中配置的数据源注入(inject)都不起作用。但首先这里是有关 servlet 的相关内容。

依赖项(在父 pom 中声明版本和范围 - 这不是您在此处看到的):

<dependencies>
    <!-- Java EE API -->
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
    </dependency>

    <!-- Jersey CDI support -->
    <dependency>
        <groupId>org.glassfish.jersey.ext.cdi</groupId>
        <artifactId>jersey-cdi1x</artifactId>
    </dependency>

    <dependency>
        <groupId>org.glassfish.jersey.ext.cdi</groupId>
        <artifactId>jersey-cdi1x-ban-custom-hk2-binding</artifactId>
    </dependency>

    <!-- Logging dependencies -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
    </dependency>
</dependencies>

web.xml:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
     version="3.1">

<servlet>
    <servlet-name>Backend</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

    <!-- Disable Moxy JSON -->
    <init-param>
        <param-name>jersey.config.disableMoxyJson</param-name>
        <param-value>true</param-value>
    </init-param>

    <!-- Register resource classes -->
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>org.test.Service</param-value>
    </init-param>
</servlet>

<servlet-mapping>
    <servlet-name>Backend</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

</web-app>

beans.xml:

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
   version="1.1" bean-discovery-mode="all">
</beans>

服务.java:

@Path("/")
@RequestScoped
public class Service {

    @Inject
    private DataProvider dataProvider;

    @Path("test")
    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public Response test(){
        return Response.ok(dataProvider.getArticles()).build();
    }

}

SQLDataProvider.java:

@Default
@ApplicationScoped
@Singleton
@Path("singleton-bean")
public class SQLDataProvider implements DataProvider {

    @Resource(name = "jdbc/db_1")
    private DataSource dataSource;

    private SQLQueryFactory factory;

    @Override
    public List<Article> getArticles() {
        if(factory == null){
            factory = new SQLQueryFactory(new Configuration(new MySQLTemplates()), dataSource);
        }

        QArtikel artikel = QArtikel.artikel;
        List<String> names = factory.select(artikel.artikeltyp).from(artikel).fetch();

        return names.stream().map(Article::new).collect(Collectors.toList());
    }
}

如果我在 Glassfish 服务器中部署此 servlet 并执行请求,则会引发以下异常:

javax.servlet.ServletException: A MultiException has 3 exceptions.  They are:
    1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=DataProvider,parent=SkiBazaarService,qualifiers={},position=-1,optional=false,self=false,unqualified=null,158365417)
    2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of org.skiclub.service.SkiBazaarService errors were found
    3. java.lang.IllegalStateException: Unable to perform operation: resolve on org.skiclub.service.SkiBazaarService

正如你所看到的,我已经尝试了来自 this post 的用户 G. Demecki 的解决方案。通过在我的 servlet 中包含两个 Jersey 依赖项 - 但没有成功。我也尝试了solution来自 Oracle,发布于 this post 中的某处。但这对我来说也不起作用。

我还看到了一个解决方案,您可以在 this post 中为 HK2 运行时指定从类型到实例的绑定(bind)。 。我承认我还没有尝试过,因为我认为必须以编程方式注册要注入(inject)的实例使得 DI 背后的想法绝对是无意义的。

但是还有另一个问题。如果我将Service类中DataProvider的声明修改为以下

private DataProvider dataProvider = new SQLDataProvider();

CDI 的问题消失了,但是抛出了 NPE,因为我尝试从 JNDI 获取的 DataSource 没有注入(inject)到 SQLDataProvider 的实例中。看来Java EE的资源注入(inject)在JAX-RS容器中也不起作用。对于这个问题我在研究过程中没有找到任何可能的解决方案。

我希望有人可以向我展示我需要在配置中进行哪些更改,以便使 CDI 和资源注入(inject)与 JAX-RS 一起工作,因为目前这对我来说似乎是不可能的。

亲切的问候 帕斯卡

最佳答案

请参阅这个问题:

Recource injection doesn't work with glassfish 4 while lookup works

尝试在不同的属性中查找您的Resource,例如上述问题所建议的mappedName

 @Resource(mappedName = "jdbc/db_1")
 private DataSource dataSource;

关于java - 使用 JAX-RS 和 Glassfish 进行 CDI 和资源注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32660066/

相关文章:

java - 在 Java Swing/Awt 中实现图像加载器

java - 以多态方式将 Java 枚举值转换为字符串列表

java - 将 Primefaces 从 3.2 更新到 3.4 会抛出 java.lang.NoSuchFieldError : SKIP_ITERATION

java - 使用 Maven、Glassfish 和 JRebel 开发 servlet 的最快方法是什么?

java - 独立的 Java Glasshfish 客户端。引用 gf-client.jar

java - 如何在 java 中为 Neo4j 节点设置节点的属性

java - Spring MVC,为什么我会收到 404 错误?

java - J2EE 实用项目的 Maven GroupID 和 ArtifactID

java - 如何在 Java 中监控外部文件

java - 带有 JPA : Illegal mix of collations (utf8mb4_general_ci, IMPLICIT 的 MySQL 和 (utf8_general_ci,COERCIBLE)