无法在我的资源中注入 @Service 和 @Contract 依赖项 class
Not able to inject @Service and @Contract dependency in my resource class
基于此博客的指南,Roll your own Auto Discovery with Jersey and HK2,我有以下 资源 POJO:
@Path("Test")
public class TestResource {
@Inject
private TestService service;
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Set<Test> getTests() {
return service.getAllTests();
}
}
TestService
:
@Contract
public interface TestService {
public Set<Test> getAllTests();
}
TestServiceImpl
@Service
public class TestServiceImpl implements TestService {
@Override
public Set<Test> getAllTests() {
Set<Test> tests = new HashSet<>();
Test c = new Test();
c.setName("test");
tests.add(c);
return tests;
}
}
pom.xml
中的 Jersey 依赖项是版本 2.25.1
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<dependency>
<groupId>org.glassfish.jersey.bundles</groupId>
<artifactId>jaxrs-ri</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>hk2</artifactId>
<version>2.5.0-b36</version>
</dependency>
为了让 Jersey 扫描 @Service 和 @Contract classes 自动,我使用了 2.5.0 版本的 inhabitant-generator
插件- b36:
<plugin>
<groupId>org.glassfish.hk2</groupId>
<artifactId>hk2-inhabitant-generator</artifactId>
<version>2.5.0-b36</version>
<executions>
<execution>
<goals>
<goal>generate-inhabitants</goal>
</goals>
</execution>
</executions>
</plugin>
有对应的Feature
实现:
public class AutoServiceDiscovery implements Feature {
@Override
public boolean configure(FeatureContext context) {
ServiceLocator locator = ServiceLocatorProvider.getServiceLocator(context);
DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class);
Populator populator = dcs.getPopulator();
try {
populator.populate(new ClasspathDescriptorFileFinder(this.getClass().getClassLoader()),
new DuplicatePostProcessor());
} catch (IOException | MultiException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
}
return true;
}
}
而且确实是通过我ResourceConfig
class注册的:
@ApplicationPath("/*")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
packages("resources");
register(new AutoServiceDiscovery());
}
}
但是,我向 /test
发送请求,得到以下错误:
MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for
injection at SystemInjecteeImpl(requiredType=TestService,parent=TestResource,qualifiers=
{},position=-1,optional=false,self=false,unqualified=null,1947073589)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of
rx.practice.ee.jaxrs.resources.TestResource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on
rx.practice.ee.jaxrs.resources.TestResource
org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:89)
org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:250)
org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:358)
org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:487)
org.glassfish.jersey.process.internal.RequestScope.findOrCreate(RequestScope.java:162)
...
问题:谁知道@Serviceclass为什么不能注入?我正在使用 Tomcat 服务器
经过几天研究 inhabitat-generator
的源代码后,我发现在 Web 应用程序包的情况下,war
, locator 文件未在 META-INF/hk2-locator
中生成,如 HK2 Inhabitant Generator office site in case of using jar
as deployment package. The source code of AbstractInhabitantsGeneratorMojo.java told that in case of war
, locator files are generated in hk2-locator
, and this is not mentioned in the HK2 Inhabitant Generator office site.
中所示
但是,在 bootstrap class、AutoServiceDiscovery
中构造不带目录名参数的 ClasspathDescriptorFileFinder 时,它仅与 jar
兼容,因为部署包,这意味着它只在 META-INF/hk2-locator
.
中查找文件
所以更好的解决方案是不使用 inhabitant-generator
插件,而是使用 metadata-generator
依赖项,它是编译时的 annotation processor 并且,它已证明 开箱即用。
如果有人坚持使用这个插件,he/she 可以创建 his/her 自己的 ClasspathDescriptorFileFinder
以便能够找到 locator来自 hk2-locator
的文件
最后但同样重要的是,我还尝试使用 inhabitants-generator
插件的选项在 hk2-locator
中生成 locator 文件,但这似乎是几乎不可能
基于此博客的指南,Roll your own Auto Discovery with Jersey and HK2,我有以下 资源 POJO:
@Path("Test")
public class TestResource {
@Inject
private TestService service;
@GET
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public Set<Test> getTests() {
return service.getAllTests();
}
}
TestService
:
@Contract
public interface TestService {
public Set<Test> getAllTests();
}
TestServiceImpl
@Service
public class TestServiceImpl implements TestService {
@Override
public Set<Test> getAllTests() {
Set<Test> tests = new HashSet<>();
Test c = new Test();
c.setName("test");
tests.add(c);
return tests;
}
}
pom.xml
中的 Jersey 依赖项是版本 2.25.1
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>${jersey.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<!-- use the following artifactId if you don't need servlet 2.x compatibility -->
<!-- artifactId>jersey-container-servlet</artifactId -->
</dependency>
<dependency>
<groupId>org.glassfish.jersey.bundles</groupId>
<artifactId>jaxrs-ri</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.hk2</groupId>
<artifactId>hk2</artifactId>
<version>2.5.0-b36</version>
</dependency>
为了让 Jersey 扫描 @Service 和 @Contract classes 自动,我使用了 2.5.0 版本的 inhabitant-generator
插件- b36:
<plugin>
<groupId>org.glassfish.hk2</groupId>
<artifactId>hk2-inhabitant-generator</artifactId>
<version>2.5.0-b36</version>
<executions>
<execution>
<goals>
<goal>generate-inhabitants</goal>
</goals>
</execution>
</executions>
</plugin>
有对应的Feature
实现:
public class AutoServiceDiscovery implements Feature {
@Override
public boolean configure(FeatureContext context) {
ServiceLocator locator = ServiceLocatorProvider.getServiceLocator(context);
DynamicConfigurationService dcs = locator.getService(DynamicConfigurationService.class);
Populator populator = dcs.getPopulator();
try {
populator.populate(new ClasspathDescriptorFileFinder(this.getClass().getClassLoader()),
new DuplicatePostProcessor());
} catch (IOException | MultiException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
}
return true;
}
}
而且确实是通过我ResourceConfig
class注册的:
@ApplicationPath("/*")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
packages("resources");
register(new AutoServiceDiscovery());
}
}
但是,我向 /test
发送请求,得到以下错误:
MultiException has 3 exceptions. They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for
injection at SystemInjecteeImpl(requiredType=TestService,parent=TestResource,qualifiers=
{},position=-1,optional=false,self=false,unqualified=null,1947073589)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of
rx.practice.ee.jaxrs.resources.TestResource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on
rx.practice.ee.jaxrs.resources.TestResource
org.jvnet.hk2.internal.Collector.throwIfErrors(Collector.java:89)
org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:250)
org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:358)
org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:487)
org.glassfish.jersey.process.internal.RequestScope.findOrCreate(RequestScope.java:162)
...
问题:谁知道@Serviceclass为什么不能注入?我正在使用 Tomcat 服务器
经过几天研究 inhabitat-generator
的源代码后,我发现在 Web 应用程序包的情况下,war
, locator 文件未在 META-INF/hk2-locator
中生成,如 HK2 Inhabitant Generator office site in case of using jar
as deployment package. The source code of AbstractInhabitantsGeneratorMojo.java told that in case of war
, locator files are generated in hk2-locator
, and this is not mentioned in the HK2 Inhabitant Generator office site.
但是,在 bootstrap class、AutoServiceDiscovery
中构造不带目录名参数的 ClasspathDescriptorFileFinder 时,它仅与 jar
兼容,因为部署包,这意味着它只在 META-INF/hk2-locator
.
所以更好的解决方案是不使用 inhabitant-generator
插件,而是使用 metadata-generator
依赖项,它是编译时的 annotation processor 并且,它已证明 开箱即用。
如果有人坚持使用这个插件,he/she 可以创建 his/her 自己的 ClasspathDescriptorFileFinder
以便能够找到 locator来自 hk2-locator
最后但同样重要的是,我还尝试使用 inhabitants-generator
插件的选项在 hk2-locator
中生成 locator 文件,但这似乎是几乎不可能