2014-10-07 3 views
6

Для жизни меня я не могу получить Джерси с hk2, чтобы автоматически обнаружить @Service аннотированные классы и ввести их. Я старался следовать всем советам по переполнению стека, джерси и документации на hk2 и до сих пор не повезло. Я пытаюсь ввести простое эхо-сервис в ресурс Джерси. Скелет создается из простого архетипа webapp maven для Джерси, который я пытался расширить. Это то, что я до сих пор:Джерси Hk2 инъекции @Service аннотированные классы

pom.xml

<build> 
    <finalName>sandbox</finalName> 
    <plugins> 
    <plugin> 
     <groupId>org.glassfish.hk2</groupId> 
     <artifactId>hk2-inhabitant-generator</artifactId> 
     <version>2.3.0</version> 
     <executions> 
     <execution> 
      <configuration> 
      <verbose>true</verbose> 
      </configuration> 
      <goals> 
      <goal>generate-inhabitants</goal> 
      </goals> 
     </execution> 
     </executions> 
    </plugin> 
    </plugins> 
</build> 
... 
<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>org.glassfish.jersey.containers</groupId> 
    <artifactId>jersey-container-servlet-core</artifactId> 
    </dependency> 
    <dependency> 
    <groupId>org.glassfish.hk2</groupId> 
    <artifactId>hk2</artifactId> 
    <version>2.3.0</version> 
    </dependency> 
</dependencies> 

web.xml

<servlet> 
    <servlet-name>Jersey Web Application</servlet-name> 
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> 
    <init-param> 
     <param-name>jersey.config.server.provider.packages</param-name> 
     <param-value>my.package.jerseytest</param-value> 
    </init-param> 
    <init-param> 
     <param-name>javax.ws.rs.Application</param-name> 
     <param-value>my.package.jerseytest.application.Application</param-value> 
    </init-param>  

    <load-on-startup>1</load-on-startup> 
</servlet> 

my.package.jerseytest.application.Application

public class Application extends ResourceConfig { 
    public Application() { 
     ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator(); 
    } 
} 

мой. package.jerseytest.service.EchoService

@Service 
public class EchoService { 
    public String generateResponse(String echo) { 
     return echo; 
    } 
} 

my.package.jerseytest.resource.MyResource

@Path("myresource") 
public class MyResource { 

    @Inject 
    EchoService echoService; 

    @GET 
    @Produces(MediaType.TEXT_PLAIN) 
    public String getIt() { 
     return echoService.generateResponse("Got it!"); 
    } 
} 

Я проверил, что inhibitant-генератор делает на самом деле запуска и производить свою продукцию, но при запуске сервера Tomcat ПРИСТУПАЯ http://localhost:8080/sandbox/webapi/myresource я получаю

SEVERE: Servlet.service() for servlet [Jersey Web Application] in context with path [/sandbox] threw exception [A MultiException has 3 exceptions. They are: 
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=EchoService,parent=MyResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,932014249) 
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of my.package.jerseytest.resource.MyResource errors were found 
3. java.lang.IllegalStateException: Unable to perform operation: resolve on my.package.jerseytest.resource.MyResource 
] with root cause 
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at SystemInjecteeImpl(requiredType=EchoService,parent=MyResource,qualifiers={},position=-1,optional=false,self=false,unqualified=null,932014249) 

Любые идеи, что мне не хватает? Я был бы признателен за любую помощь :(

NB! Я знаю о

, но они мне не помогли ...

+1

ЛЮБЫХ удач на этом? –

+1

Нет, сдался. Было что-то примерно в двух разных версиях аннотации @Inject, но проект прошел мимо, и мы решили использовать пружинный мост трикотажа и контейнер Spring DI. –

+0

Просто любопытно, почему бы не просто CDI? – ymajoros

ответ

0

Попробуйте добавить пакеты, которые необходимо отсканировать в вашем конструкторе Application. «Истинный» параметр на упаковке означает, что сканировать пакет рекурсивно:

public class Application extends ResourceConfig { 
    public Application() { 
     packages(true, "my.package.jerseytest"); 
     ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator(); 
    } 
} 
+0

Пробовал, извините, я все равно получаю то же исключение. Просто интересно: если имена классов, которые должны быть введены, собираются в файле генератором-обитателем, то зачем мне сканировать пакеты? –

0

Использование packages(true, "my.package.jerseytest"); И использовать org.glassfish.jersey.spi.Contract не org.jvnet.hk2.annotations.Contract аннотацию. И используйте простые интерфейсы без дженериков.

+0

Пробовал с и без соответствия @Contract аннотированный интерфейс к сервису, не помог. Если я правильно понял документацию, нет необходимости иметь интерфейс для службы (хотя я понимаю, что с чистой кодовой точки зрения приятно иметь) –

0

@Stateless Попробуйте добавить

@Path("myresource") 
@Stateless 
public class MyResource { 
    @Inject 
    EchoService echoService; 
... 
} 
+0

Привет, спасибо за ответ ... у нас есть перешел к проекту и в итоге отказался от hk2; вместо этого мы полагаемся на пружинный мост и пружину для DI. –

+0

Как было принято решение использовать весенний мост и весну DI? Любые сожаления? – Raf

+0

Одним из преимуществ использования пружины является независимость от контейнера. Например, вы не увидите различия в использовании Glassfish, Wildfly или Tomcat. –

1

Я комбинируя понимание я получил от этих двух вопросов:

Во-первых, используйте HK2 Metadata Generator (или жителя ator) в вашей цепочке сборки (как вы уже делали). Это сканирует ваш источник и создает META-INF/hk2-locator/default.

Во-вторых, создать новый ServiceLocator, населенную услугами из метаданных:

ServiceLocator locator = ServiceLocatorUtilities.createAndPopulateServiceLocator(); 

Теперь передать его в Grizzly. Цитирование @peeskillet:

У Джерси есть свой собственный ServiceLocator, и нелегко попытаться получить ссылку на него. Мы могли бы предоставить Джерси наш ServiceLocator, но Джерси в конечном счете все еще создает собственный локатор и заполняет его нашим локатором.

ResourceConfig config = new MyApplicationConfig(); 
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(
    URI.create(BASE_URI), 
    config, 
    serviceLocator 
); 
1

я решил мою проблему совсем как этот, используя класс, расширяющий AbstractBinder, инстанцировании его и зарегистрировать его с приложением.

resourceConfig.register(new DependencyBinder()); 

Кроме того,

/** 
* dependency injection bindings. 
* Jersey requires that service implementations are bound to their contracts this way. 
*/ 
public final class DependencyBinder extends AbstractBinder { 

    @Override 
    protected final void configure() { 
     bind(StatusServiceImpl.class).to(StatusService.class); 
    } 
} 
+2

Внимание! Любой, кто использует это решение, не должен пытаться сделать его общим. Мы попытались это сделать и добавили 2 параметра конструктора к этому виду связующего. Результат был ужасным. Джерси только зарегистрировал первый экземпляр, основанный на типе класса.Таким образом, первый DependencyBinder будет вводиться, но что-то после этого отклоняется, потому что он уже добавлен в соответствии с трикотажем. – JSONStatham

Смежные вопросы