在Rest Service中使用CDI时存在一些问题:
使用以下文件TestRessource.java
创建了一个J2EE 7动态Web项目:
@Path("/testpath")
public class TestRessource{
@Inject IDataBase db;
@GET
@Produces("text/html")
public Response getElements() {
return Response.status(200).entity("Items").build();
}
如果我包括行'@Inject IDataBase db'
,该行应注入一个虚拟数据库类,则无法在浏览器中调用页面localhost:8080/testpath
。它最终出现在几个异常堆栈中。第一个是:
org.glassfish.hk2.api.UnsatisfiedDependencyException:在处没有可用于注入的对象 SystemInjecteeImpl(requiredType = IDataBase,parent = TestRessource,qualifiers = {},position = -1,optional = false,self = false,unqualified = null,1686223016)
看来,他找不到应注入的文件。
DataBase.java看起来像:
public class Database implements IDataBase {
private Map<String, Long> numbers; // Dummy data
public Database() {
numbers = new HashMap<>();
}
public String getItems() {
return (new Gson()).toJson(numbers);
}
}
IDataBase.java看起来像:
public interface IDataBase {
String getItems();
}
我的pom.xml看起来像:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>en.testpackage</groupId>
<artifactId>mytestproject</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>mytestprojectMavenWebapp</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.bundles</groupId>
<artifactId>jaxrs-ri</artifactId>
<version>2.13</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers.glassfish</groupId>
<artifactId>jersey-gf-cdi</artifactId>
<version>2.14</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>2.4.7.Final</version>
</dependency>
</dependencies>
<build>
<finalName>mytestproject</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<path>/</path>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>exec-war-only</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
以下是异常堆栈:
type Exception report
message A MultiException has 3 exceptions. They are:
description The server encountered an internal error that prevented it from fulfilling this request.
exception
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=IDataBase,parent=TestRessource,qualifiers={@javax.inject.Named(value=db)},position=-1,optional=false,self=false,unqualified=null,256127442)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of en.testpackage.resource.TestRessource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on en.testpackage.resource.TestRessource
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:393)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
root cause
A MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=IDataBase,parent=TestRessource,qualifiers={@javax.inject.Named(value=db)},position=-1,optional=false,self=false,unqualified=null,256127442)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of en.testpackage.resource.TestRessource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on en.testpackage.resource.TestRessource
org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:88)
org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:252)
org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:360)
org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:461)
org.glassfish.jersey.process.internal.RequestScope.findOrCreate(RequestScope.java:160)
org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2268)
org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:690)
org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:655)
org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:169)
org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:185)
org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:74)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:115)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:115)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:115)
org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:94)
org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:63)
org.glassfish.jersey.process.internal.Stages.process(Stages.java:197)
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:263)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
org.glassfish.jersey.internal.Errors.process(Errors.java:315)
org.glassfish.jersey.internal.Errors.process(Errors.java:297)
org.glassfish.jersey.internal.Errors.process(Errors.java:267)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:254)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1030)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
root cause
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=IDataBase,parent=TestRessource,qualifiers={@javax.inject.Named(value=db)},position=-1,optional=false,self=false,unqualified=null,256127442)
org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)
org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:214)
org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:237)
org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:360)
org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:461)
org.glassfish.jersey.process.internal.RequestScope.findOrCreate(RequestScope.java:160)
org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2268)
org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:690)
org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:655)
org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:169)
org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:185)
org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:74)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:115)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:115)
org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:115)
org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:94)
org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:63)
org.glassfish.jersey.process.internal.Stages.process(Stages.java:197)
org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:263)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
org.glassfish.jersey.internal.Errors.process(Errors.java:315)
org.glassfish.jersey.internal.Errors.process(Errors.java:297)
org.glassfish.jersey.internal.Errors.process(Errors.java:267)
org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:254)
org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1030)
org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.37 logs.
因此,如果我删除@Inject行,则其余服务工作正常,并且我能够通过浏览器加载此页面(但当然不会注入对象db)
我已经在webapp / WEB-INF中添加了一个空的beans.xml。
这里缺少能够使用CDI的任何东西吗?还是在CDI + RestService上下文中没有提及的其他内容?
答案 0 :(得分:0)
因此,经过数小时的实验,我找到了一个可行的解决方案:
我的pom.xml现在看起来像:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>en.testpackage</groupId>
<artifactId>mytestproject</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>mytestprojectMavenWebapp</name>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.jboss.weld.servlet</groupId>
<artifactId>weld-servlet</artifactId>
<version>2.4.7.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext.cdi</groupId>
<artifactId>jersey-cdi1x</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.27</version>
</dependency>
</dependencies>
<build>
<finalName>mytestproject</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<path>/</path>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>exec-war-only</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- more plugins e.g. shade plugin for my purpose -->
</plugins>
</build>
</project>
我的src / main / webapp / WEB-INF / 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>JerseyRESTService</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.testpackage.resource</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>JerseyRESTService</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
<resource-env-ref>
<resource-env-ref-name>BeanManager</resource-env-ref-name>
<resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
</resource-env-ref>
</web-app>
在src / main / resources / META-INF / beans.xml中,我有:
<?xml version="1.0" encoding="UTF-8"?>
<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"
bean-discovery-mode="all">
</beans>
在src / main / webapp / META-INF / context.xml中,我有:
<Context>
<Resource name="BeanManager"
auth="Container"
type="javax.enterprise.inject.spi.BeanManager"
factory="org.jboss.weld.resources.ManagerObjectFactory"/>
</Context>
通过这种组合,我能够避免异常堆栈,并且我基于依赖jersey-cdi1x HK2和Weld能够相互“通信”。
在com.testpackage.resource中,我有多个包含REST方法的类。
我希望我将为所有具有所有这些异常问题的其他用户提供一个可行的(最新的)解决方案。
目的是创建一个包含Tomcat7的uber-jar文件,该文件提供REST服务并使用基于Weld的CDI。