Невозможно внедрить зависимости @Service и @Contract в мой класс ресурсов - PullRequest
3 голосов
/ 18 марта 2020

На основе руководства из этого блога Скатайте свое собственное автообнаружение с Джерси и 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 имеет версию 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>

В Чтобы Джерси сканировал классы @Service и @Contract автоматически , я использовал плагин inhabitant-generator с версией 2.5.0-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 класс:

@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)
...

Вопрос: Кто-нибудь знает, почему класс @Service нельзя внедрить? Я использую сервер Tomcat

1 Ответ

2 голосов
/ 20 марта 2020

После нескольких дней тщательного изучения исходного кода inhabitat-generator я выяснил, что в случае пакета веб-приложения war файл locator не создается в META-INF/hk2-locator как показано на сайте HK2 Inhabitant Generator в случае использования jar в качестве пакета развертывания Исходный код AbstractInhabitantsGeneratorMojo. java говорит, что в случае war, locator файлы создаются в hk2-locator, и это не упоминается на сайте офиса HK2 Inhabitant Generator

Однако при построении ClasspathDescriptorFileFinder без аргумента имен каталогов в классе bootstrap, AutoServiceDiscovery, он совместим только с jar в качестве пакета развертывания, то есть он находит файлы только в META-INF/hk2-locator.

Таким образом, лучшим решением было бы не использовать плагин inhabitant-generator, а зависимость metadata-generator, которая является процессором аннотаций во время компиляции, и это доказано вне -the-box .

Если кто-то настойчиво использует этот плагин, он / она может создать свой собственный ClasspathDescriptorFileFinder, чтобы он мог найти locator файлы из hk2-locator

И последнее, но не менее важное: я также пытался использовать опции плагина inhabitants-generator для генерации файлов locator в hk2-locator, но это кажется почти невозможным а также

...