4

最近、2 フェーズ インジェクションに切り替えたところ、サーブレット バインディングでエラーが発生しました。現在、2 つのエラー モードを切り替えていますが、どちらの方向に進むのが最適かわかりません。

最初に遭遇したエラーは次のとおりです。

com.sun.jersey.api.container.ContainerException: ResourceConfig インスタンスにルート リソース クラスが含まれていません。

私のサーブレットモジュールは次のようになりました:

public class MyServletModule extends JerseyServletModule {
    @Override
    protected void configureServlets() {
        bind(MyServlet.class).asEagerSingleton();

        serve("/*").with(GuiceContainer.class);
    }
}

com.sun.jersey.config.property.packages パラメータを明示的に指定することで、このエラーを取り除くことができました。

public class MyServletModule extends JerseyServletModule {

    @Override
    protected void configureServlets() {
        bind(MyServlet.class).asEagerSingleton();

        Map<String,String> parameters = new HashMap<String, String>();
        parameters.put(PackagesResourceConfig.PROPERTY_PACKAGES, MyServlet.class.getPackage().getName());
        serve("/*").with(GuiceContainer.class, parameters);
    }
}

しかし、これを行うと、Guice は、サーブレット コンストラクターで @Inject を尊重しないジャスト イン タイム バインディングを試みます。

com.google.inject.ConfigurationException: Guice 構成エラー:

1) MyServlet のバインドを作成できません。MyServletModule.configureServlets(MyServletModule.java:44) でバインドされた 1 つ以上の子インジェクターまたはプライベート モジュールで既に構成されていました。それが PrivateModule にあった場合、バインドを公開するのを忘れましたか? MyServlet の検索中

com.google.inject.internal.InjectorImpl.getBinding(InjectorImpl.java:150) で 1 エラー

私のサーブレットには、引数のジャスト イン バインドができない @Inject コンストラクターがあります。InjectorImpl にデバッグした後、これが PROPERTY_PACKAGES を使用すると失敗する理由だと思います。

PROPERTY_PACKAGES の使用が正しいかどうかわからないので、いくつかのバインディングを修正する必要がありますか? または、それが間違った方向であり、元の ResourceConfig エラーを別の方法で修正する必要がある場合。

ヘルプまたは正しい方向へのプッシュを歓迎します。

4

3 に答える 3

8

bind-parameters を使用せずに (com.sun.jersey.config.property.packages パラメーターを明示的に指定せずに)、リソースを個別にバインドすることで、Jersey リソースを Guice にバインドできました。

public class BindJerseyResources extends ServletModule {

    @Override
    protected void configureServlets() {
        // excplictly bind GuiceContainer before binding Jersey resources
        // otherwise resource won't be available for GuiceContainer
        // when using two-phased injection
        bind(GuiceContainer.class);

        // bind Jersey resources
        PackagesResourceConfig resourceConfig = new PackagesResourceConfig("jersey.resources.package");
        for (Class<?> resource : resourceConfig.getClasses()) {
            bind(resource);
        }

        // Serve resources with Jerseys GuiceContainer
        serve("/*").with(GuiceContainer.class);
    }
}

リソースは次のようなものです

@Path("/")
@RequestScoped
public class Resource {

    private Storage storage;

    @Inject
    public Resource(Storage storage) {
        this.storage = storage;
    }

    @GET
    @Path("get/{name}")
    @Produces(MediaType.TEXT_PLAIN)
    public String getGuid(@PathParam("name") String name) {
        return storage.get(name);
    }
}

おそらくこれは、後者の問題のあるバインディングを回避するのに役立ちます。


二段階注入で動作するように回答を更新しました。

于 2013-09-24T04:50:07.840 に答える
0

バインディングの方法に関する記事 (完全なソース コードを含む) は次のとおりです。

于 2014-10-02T01:57:32.360 に答える
0

Java 部分

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import com.google.inject.persist.jpa.JpaPersistModule;
import com.google.inject.servlet.GuiceServletContextListener;
import com.sun.jersey.guice.JerseyServletModule;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import com.thjug.apipublic.Echo;

public class ServletContextListener extends GuiceServletContextListener {

    @Override
    protected Injector getInjector() {
        final Injector injector = Guice.createInjector(new JerseyServletModule() {
            @Override
            protected void configureServlets() {
                bind(Echo.class);
                bind(ServletContainer.class).in(Singleton.class);
                serve("/*").with(GuiceContainer.class);
            }
        }, new JpaPersistModule("dbUnit"), new LoggingModule());

        injector.getInstance(JPAInitializer.class);
        return injector;
    }
}

web.xml

    <distributable />

    <display-name>API</display-name>

    <filter>
            <filter-name>guiceFilter</filter-name>
            <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
    </filter>
    <filter-mapping>
            <filter-name>guiceFilter</filter-name>
            <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
            <description>Guice Initiate</description>
            <listener-class>com.thjug.base.ServletContextListener</listener-class>
    </listener>

以下は、Guice を使用して REST を作成する方法に関する私の基調講演です http://www.slideshare.net/nuboat/lightweight-javaee

于 2013-09-24T04:10:35.587 に答える