【发布时间】:2015-12-16 01:52:24
【问题描述】:
我目前正在开发一个 JAX-RS Servlet,然后我想将其部署在 Glassfish 4.1 服务器中(因此 JAX-RS 运行时是 Jersey 2.x)。
我不想使用 Spring 来进行配置和 DI 的东西,而是想尝试 Java EE 的方式来做这件事。但是,CDI 和我在 Glassfish 服务器中配置的数据源的注入都不起作用。但首先这里是关于 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>
Service.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 依赖项 - 但没有成功。我还尝试了来自 Oracle 的 solution,它发布在 this post 的某个地方。但这对我也不起作用。
我还看到了一个解决方案,您可以在 this post 中为 HK2 运行时指定从类型到实例的绑定。我承认我没有尝试过,因为我认为必须以编程方式注册要注入的实例,这完全是 DI 背后的想法。
但还有另一个问题。如果我将Service类中DataProvider的声明修改为如下
private DataProvider dataProvider = new SQLDataProvider();
CDI 的问题消失了,但抛出了 NPE,因为我试图从 JNDI 获取的 DataSource 没有注入到 SQLDataProvider 的实例中。因此,Java EE 的资源注入似乎在 JAX-RS Container 中也不起作用。对于这个问题,我在研究过程中没有找到任何可能的解决方案。
我希望有人可以告诉我我需要在配置中进行哪些更改才能使 CDI 和资源注入与 JAX-RS 一起使用,因为目前这对我来说似乎是不可能的。
亲切的问候 帕斯卡
【问题讨论】:
-
实际上在 JNDI 中是
jdbc/db_1。我假设您在 GlassFish 上设置了 DataSource。您是否通过 GlassFish JNDI 浏览器验证了这是正确的 JNDI 地址?我对@Path注释SQLDataProvider有点困惑。另外,@ApplicationScoped和@Singleton似乎有点多余。 -
是的,DataSource 在该名称下可用。我刚刚在 JDBC 资源下的管理控制台中检查了它。在相应的列表中出现了我的 DataSource,它指出它在 JNDI 名称 jdbc/db_1 下可用。我还使用“asadmin list-jndi-entries --context jdbc”命令对其进行了检查。 @Path 注解来自 Oracle 在此链接下发布的解决方案 docs.oracle.com/javaee/7/tutorial/jaxrs-advanced004.htm
标签: java jakarta-ee glassfish jax-rs cdi