java - Инъекционная инъекция с Джерси 2.0




dependency-injection jersey (4)

Oracle рекомендует добавлять аннотацию @Path ко всем типам, которые нужно вводить при объединении JAX-RS с CDI: http://docs.oracle.com/javaee/7/tutorial/jaxrs-advanced004.htm Хотя это далеко не идеально ( например, вы получите предупреждение от Джерси при запуске), я решил пойти по этому маршруту, что избавит меня от поддержки всех поддерживаемых типов внутри связующего.

Пример:

@Singleton
@Path("singleton-configuration-service")
public class ConfigurationService {
  .. 
}

@Path("my-path")
class MyProvider {
  @Inject ConfigurationService _configuration;

  @GET
  public Object get() {..}
}

Начиная с нуля, без каких-либо предыдущих знаний Джерси 1.x, мне трудно понять, как настроить инъекцию зависимостей в проекте Jersey 2.0.

Я также понимаю, что HK2 доступен в Джерси 2.0, но я не могу найти документы, которые помогают интеграции с Джерси 2.0.

@ManagedBean
@Path("myresource")
public class MyResource {

    @Inject
    MyService myService;

    /**
     * Method handling HTTP GET requests. The returned object will be sent
     * to the client as "text/plain" media type.
     *
     * @return String that will be returned as a text/plain response.
     */
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/getit")
    public String getIt() {
        return "Got it {" + myService + "}";
    }
}

@Resource
@ManagedBean
public class MyService {
    void serviceCall() {
        System.out.print("Service calls");
    }
}

pom.xml

<properties>
    <jersey.version>2.0-rc1</jersey.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<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.core</groupId>
        <artifactId>jersey-common</artifactId>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.core</groupId>
        <artifactId>jersey-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey</groupId>
        <artifactId>jax-rs-ri</artifactId>
    </dependency>
</dependencies>

Я могу заставить контейнер запускать и обслуживать мой ресурс, но как только я добавлю @Inject в MyService, фреймворк выдает исключение:

SEVERE: Servlet.service() for servlet [com.noip.MyApplication] in context with path [/jaxrs] threw exception [A MultiException has 3 exceptions.  They are:
1. org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=MyService,parent=MyResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,1039471128)
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of com.noip.MyResource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on com.noip.MyResource
] with root cause
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=MyService,parent=MyResource,qualifiers={}),position=-1,optional=false,self=false,unqualified=null,1039471128)
    at org.jvnet.hk2.internal.ThreeThirtyResolver.resolve(ThreeThirtyResolver.java:74)


Мой стартовый проект доступен в GitHub: https://github.com/donaldjarmstrong/jaxrs


Вам необходимо определить AbstractBinder и зарегистрировать его в приложении JAX-RS. Связующее определяет, как инъекция зависимости должна создавать ваши классы.

public class MyApplicationBinder extends AbstractBinder {
    @Override
    protected void configure() {
        bind(MyService.class).to(MyService.class);
    }
}

Когда @Inject обнаружен в параметре или поле типа MyService.class он MyService.class с использованием класса MyService . Чтобы использовать это связующее, его необходимо зарегистрировать в приложении JAX-RS. В вашем web.xml определите приложение JAX-RS следующим образом:

<servlet>
  <servlet-name>MyApplication</servlet-name>
  <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
  <init-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value>com.mypackage.MyApplication</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>MyApplication</servlet-name>
  <url-pattern>/*</url-pattern>
</servlet-mapping>

MyApplication класс MyApplication (указанный выше в init-param ).

public class MyApplication extends ResourceConfig {
    public MyApplication() {
        register(new MyApplicationBinder());
        packages(true, "com.mypackage.rest");
    }
}

Связующее, определяющее инъекцию зависимостей, регистрируется в конструкторе класса, и мы также сообщаем приложению, где найти ресурсы REST (в вашем случае MyResource ), используя метод метода методов packages() .


Если вы предпочитаете использовать Guice и не хотите объявлять все привязки, вы также можете попробовать этот адаптер:

guice-bridge-jit-injector


Поздно, но я надеюсь, что это поможет кому-то.

У меня JAX RS определяется следующим образом:

@Path("/examplepath")
@RequestScoped //this make the diference
public class ExampleResource {

Затем в моем коде, наконец, я могу ввести:

@Inject
SomeManagedBean bean;

В моем случае SomeManagedBean является компонентом ApplicationScoped.

Надеюсь, это поможет кому угодно.







hk2