2013-04-10 8 views
5

組み込みJettyセットアップでJersey用にLoggingFilterを設定しようとしています。Jerseyと埋め込みJettyでLoggingFilterは無視されます

ServletContainer servletContainer = new ServletContainer(application); 
ServletHolder servletHolder = new ServletHolder(servletContainer); 
servletHolder.setInitParameter("com.sun.jersey.config.feature.Debug", "true"); 
servletHolder.setInitParameter("com.sun.jersey.config.feature.Trace", "true"); 
servletHolder.setInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters", 
    "com.sun.jersey.api.container.filter.LoggingFilter"); 
servletHolder.setInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters", 
    "com.sun.jersey.api.container.filter.LoggingFilter"); 

実際にはログフィルタは無視され、コンソールに関連するログは表示されません。これどうやってするの? Jersey 1.xと2.xでテスト済み。

relevant answerは、web.xmlを使用してこれを達成する方法を説明しています。

+0

あなたのコードは、サーブレット名とクラスという1つの詳細を除いて、XMLサーブレットの設定と同等に見えます。多分あなたはちょうどその部分をここに貼り付けなかったでしょう。 XML設定ソリューションを試してみたことがありますか? – Cebence

+0

JDKロギングを適切に設定しましたか? – skirsch

+0

@Cebence 'ServletHolder'は' web.xml'として機能します。アプリケーションが実行され、動作します。 – nobeh

答えて

4

私はそれが完全にバグではありませんならば、これはServletContainerの文書化行動の非常に微妙なニュアンスだと思います。初期化パラメータの対象となるServletContainer docsは、

となります。すべての初期化パラメータは、作成されたResourceConfigのプロパティとして追加されます。

回答はそこに隠されています。具体的には、ServletContainerによってResourceConfigインスタンスが作成されない場合、サーブレットのinitパラメータはプロパティとして追加されないため、アプリケーションの構成には影響しません。

あなたのコードは、あなたのApplicationインスタンスに次ServletContainerコンストラクタを呼び出します:

public ServletContainer(Application app) { 
    this.app = app; 
} 

コンテナはあなたのServletContainerなどを初期化し、あなた自身のApplicationインスタンスを提供する場合、あなたがnew ServletContainer(application)で行ったように、初期化は大体この経過をたどります

protected void init(WebConfig webConfig) throws ServletException { 
    webComponent = (app == null) 
      ? new InternalWebComponent() 
      : new InternalWebComponent(app); 
    webComponent.init(webConfig); 
} 

あなたのはそこに行く:典型的なServletライフサイクルの一部インスタンスをInternalWebComponentコンストラクタに挿入します。

InternalWebComponent(Application app) { 
    super(app); 
} 

呼び出し:

public WebComponent(Application app) { 
    if (app == null) 
     throw new IllegalArgumentException(); 

    if (app instanceof ResourceConfig) { 
     resourceConfig = (ResourceConfig) app; 
    } else { 
     resourceConfig = new ApplicationAdapter(app); 
    } 
} 

これは、あなたが直接Applicationインスタンスを提供するので、ResourceConfigのいずれかであなたのために構築され、あるInternalWebComponentはちょうどわずかなのでWebComponentのカスタマイズ、ありますその2番目の枝if。構築直後に、新しいコンポーネントに対してWebComponent.init()が呼び出されます(上記のServletContainer.init()呼び出しを参照してください)。このinit()の中には、ドキュメントによって参照される "作成されたResourceConfig"がに作成されますが、あなたのケースでは、私たちがここにたどるトレイルに示すように、既に存在します。すなわち、resourceConfigはnullではないので、以下の重要な行は実行されません:

public void init(WebConfig webConfig) throws ServletException { 
    ... 
    if (resourceConfig == null) 
     resourceConfig = createResourceConfig(config); 
    ... 
} 

それcreateResourceConfig()方法を(まだWebComponentに)として読み込む:あなたはそのコールに見ることができます

private ResourceConfig createResourceConfig(WebConfig webConfig) 
     throws ServletException { 
    final Map<String, Object> props = getInitParams(webConfig); 
    final ResourceConfig rc = createResourceConfig(webConfig, props); 
    rc.setPropertiesAndFeatures(props); 
    return rc; 
} 

setPropertiesAndFeatures()を使用してサーブレットのinitパラメータをResourceConfigインスタンスにコピーします。残念ながら、これはの呼び出しが行われた場所であり、デフォルトではServletContainerのコンストラクタを使用しているため、実際には実行されません。

元の作者は、この動作が導入されていることを知らないうちに、Servlet 3.0コンテナでの使いやすさのために、後で追加された1つの引数のないコンストラクタを使用してServletContainerを書きました。さもなければ、私はの一部をと言います。

だから、長い話を短く:デフォルトServletContainerコンストラクタを使用するか、この部分のことは自分を世話をする方法を見つけるのいずれか:

Map<String, Object> props = getInitParams(webConfig); 
rc.setPropertiesAndFeatures(props); 

最初の方法は、おそらく最も簡単です。たとえば、次のような、限り、事前にそれをインスタンス化するためにあなたを必要とする何もないとして、あまりにも、初期化パラメータとしてごApplicationクラスを指定することができます、

servletHolder.setInitParameter("javax.ws.rs.Application", "org.foo.MyApplication"); 

「ノーマル」の初期化パスをそのようになりますWebComponentResourceConfigを作成し、initパラメータを正しく適用することを意味します。

+0

この 'ServletContainer> Servlet'の振舞いは、基本的に制御のインバースですIoC)と同じように、SpringのDependency Injectionに似ています。豆をオートワイヤーにしたい場合は、 'new'で自分で作成してはいけません。同じことがサーブレットに適用されます。 – Cebence

+0

@Cebence:私はその比較に同意するとは思わない。最近、[新しいコンストラクタ]を持っているSpringの[DispatcherServlet](http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/DispatcherServlet.html)を参照してください( http://static.springsource.org/spring/docs/current/javadoc-api/org/springframework/web/servlet/DispatcherServlet.html#DispatcherServlet(org.springframework.web.context.WebApplicationContext))を使用すると、 Servlet 3.0環境で使用するための既存のSpringコンテキスト。それは期待通りに機能します。これはありません。 –

+0

はい、私は「3.0」とは言いませんでした。 1つは4-5年後に成熟したと思うでしょう。 – Cebence

0

私はあなたが間違っているかもしれないと思います。あなたが行うように

// Creating an instance of Jersey servlet, right? 
ServletContainer servletContainer = new ServletContainer(application); 

// Putting it in a container by reference. 
ServletHolder servletHolder = new ServletHolder(servletContainer); 

This pageは、サーブレットを作成しません:

ServletHolder sh = new ServletHolder(WicketServlet.class); 

突堤は、インスタンスを作成し、サーブレットのinit()を呼び出します。この道を。 あなたの場合、init()に電話する必要があるかもしれませんが、ServletConfigurationインスタンスを取得するかどうかはわかりません。

UPDATE: あなたはこのようにそれを試してみてください:

ServletHolder servletHolder = new ServletHolder(ServletContainer.class); 
    servletHolder.setInitParameter("javax.ws.rs.Application", "MyRESTApplication"); 
    servletHolder.setInitParameter("com.sun.jersey.config.feature.Debug", "true"); 
    servletHolder.setInitParameter("com.sun.jersey.config.feature.Trace", "true"); 
    servletHolder.setInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters", 
     "com.sun.jersey.api.container.filter.LoggingFilter"); 
    servletHolder.setInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters", 
     "com.sun.jersey.api.container.filter.LoggingFilter"); 

    ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); 
    contextHandler.addServlet(servletHolder, "/services/*"); 
    server.setHandler(contextHandler); 
関連する問題