112

以前のジャージー 1.x の知識なしでゼロから始めたので、ジャージー 2.0 プロジェクトで依存性注入をセットアップする方法を理解するのに苦労しています。

また、HK2 が Jersey 2.0 で使用できることも理解していますが、Jersey 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

4

8 に答える 8

57

最初に、受け入れ回答のコメントに回答するだけです。

「バインドは何をしますか?インターフェースと実装がある場合はどうなりますか?」

それは単に読みますbind( implementation ).to( contract )。チェーンを代替できます.in( scope )。のデフォルト スコープPerLookup。したがって、シングルトンが必要な場合は、次のことができます

bind( implementation ).to( contract ).in( Singleton.class );

RequestScopedご用意しております

また、 の代わりにbind(Class).to(Class)も使用できますbind(Instance).to(Class)。これは自動的にシングルトンになります。


受け入れられた回答への追加

AbstractBinder実装を web.xmlに登録する方法を理解しようとしている(つまり、 を使用していないResourceConfig) 人にとっては、パッケージ スキャンによってバインダーが検出されないようです。

<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
    <param-name>jersey.config.server.provider.packages</param-name>
    <param-value>
        your.packages.to.scan
    </param-value>
</init-param>

それともこれか

<init-param>
    <param-name>jersey.config.server.provider.classnames</param-name>
    <param-value>
        com.foo.YourBinderImpl
    </param-value>
</init-param>

それを機能させるには、Feature次のものを実装する必要がありました。

import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;

@Provider
public class Hk2Feature implements Feature {

    @Override
    public boolean configure(FeatureContext context) {
        context.register(new AppBinder());
        return true;
    }
}

@Provider注釈Featureにより、パッケージ スキャンで を取得できるようにする必要があります。または、パッケージ スキャンなしで、明示的Featureweb.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.classnames</param-name>
        <param-value>
            com.foo.Hk2Feature
        </param-value>
    </init-param>
    ...
    <load-on-startup>1</load-on-startup>
</servlet>

関連項目:

およびジャージーのドキュメントからの一般的な情報については


アップデート

工場

受け入れられた回答の基本的なバインディングとは別に、より複雑な作成ロジックを持ち、リクエストのコンテキスト情報にアクセスできるファクトリもあります。例えば

public class MyServiceFactory implements Factory<MyService> {
    @Context
    private HttpHeaders headers;

    @Override
    public MyService provide() {
        return new MyService(headers.getHeaderString("X-Header"));
    }

    @Override
    public void dispose(MyService service) { /* noop */ }
}

register(new AbstractBinder() {
    @Override
    public void configure() {
        bindFactory(MyServiceFactory.class).to(MyService.class)
                .in(RequestScoped.class);
    }
});

MyService次に、リソース クラスに挿入できます。

于 2015-03-26T10:07:13.580 に答える
13

選択された回答は、しばらく前のものです。カスタム HK2 バインダーですべてのバインディングを宣言するのは現実的ではありません。私は Tomcat を使用していますが、依存関係を 1 つ追加するだけで済みました。Glassfish 用に設計されていますが、他のコンテナに完全に適合します。

   <dependency>
        <groupId>org.glassfish.jersey.containers.glassfish</groupId>
        <artifactId>jersey-gf-cdi</artifactId>
        <version>${jersey.version}</version>
    </dependency>

コンテナーも適切に構成されていることを確認してください (ドキュメントを参照してください)。

于 2015-01-08T19:49:19.903 に答える
5

遅くなりましたが、これが誰かの役に立てば幸いです。

JAX RS を次のように定義しています。

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

次に、最終的に私のコードに挿入できます:

@Inject
SomeManagedBean bean;

私の場合、これSomeManagedBeanは ApplicationScoped Bean です。

これが誰にでも役立つことを願っています。

于 2016-10-06T07:51:52.143 に答える
3

オラクルは、JAX-RS と CDI を組み合わせるときに、注入されるすべてのタイプに @Path アノテーションを追加することをお勧めします : http://docs.oracle.com/javaee/7/tutorial/jaxrs-advanced004.htmたとえば、起動時に Jersey から警告が表示されます)、この方法を取ることにしました。これにより、サポートされているすべての型をバインダー内で維持する必要がなくなりました。

例:

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

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

  @GET
  public Object get() {..}
}
于 2014-06-02T13:52:43.330 に答える
0

Guice を使用したいが、すべてのバインディングを宣言したくない場合は、次のアダプターを試すこともできます。

guice-bridge-jit-インジェクター

于 2014-07-03T20:18:36.773 に答える