2011-12-15 20 views
14

このコードでは、要求入力ストリームから入力を読み込み、JacksonMapperを使用してPOJOに変換します。 guiceをサポートするjetty 7コンテナで動作します。HttpServletRequestの入力ストリームが空白なのはなぜですか?

@Override 
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 

    try { 
     RequestType requestType = mapper.readValue(req.getInputStream(), RequestType.class); 
    } Catch(Exception ex) { 
     .... 
    } 
} 

ただし、ロード時に次の例外がスローされます。私はクライアントをチェックして、有効なjson文字列を送信していると確信しています。何がうまくいかないのですか?負荷のあるJetty 7の動作が期待されていますか?

java.io.EOFException: No content to map to Object due to end of input 
    at org.codehaus.jackson.map.ObjectMapper._initForReading(ObjectMapper.java:2433) 
    at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2385) 
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1637) 
    at com.ea.wsop.user.LoginServlet.processRequest(LoginServlet.java:69) 
    at com.ea.wsop.user.LoginServlet.doPost(LoginServlet.java:63) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.CGLIB$doPost$0(<generated>) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd$$FastClassByGuice$$c6f479ee.invoke(<generated>) 
    at com.google.inject.internal.cglib.proxy.$MethodProxy.invokeSuper(MethodProxy.java:228) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.ea.monitor.MethodExecutionTimer.invoke(MethodExecutionTimer.java:130) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:52) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.doPost(<generated>) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:727) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.CGLIB$service$8(<generated>) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd$$FastClassByGuice$$c6f479ee.invoke(<generated>) 
    at com.google.inject.internal.cglib.proxy.$MethodProxy.invokeSuper(MethodProxy.java:228) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.ea.monitor.MethodExecutionTimer.invoke(MethodExecutionTimer.java:130) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:52) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.service(<generated>) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.CGLIB$service$9(<generated>) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd$$FastClassByGuice$$c6f479ee.invoke(<generated>) 
    at com.google.inject.internal.cglib.proxy.$MethodProxy.invokeSuper(MethodProxy.java:228) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.ea.monitor.MethodExecutionTimer.invoke(MethodExecutionTimer.java:130) 
    at com.google.inject.internal.InterceptorStackCallback$InterceptedMethodInvocation.proceed(InterceptorStackCallback.java:72) 
    at com.google.inject.internal.InterceptorStackCallback.intercept(InterceptorStackCallback.java:52) 
    at com.ea.wsop.user.LoginServlet$$EnhancerByGuice$$a91c2ebd.service(<generated>) 
    at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:263) 

答えて

12

既に消費されている場合は空になります。これは、getParameter(),getParameterValues()getParameterMap()getReader()などHttpServletRequestに電話するたびに暗黙のうちに実行されます。 getInputStream()に電話をかける前に、依頼主から情報を収集する必要のある方法を呼び出さないように注意してください。サーブレットがそれをしていない場合は、同じURLパターンにマップされているサーブレット・フィルターの検査を開始します。


更新:これはGAE 1.5特異的であるように思われます。参照してください

私は、彼らはそれが固定されるまで、何の解決策/回避策はありませんことを恐れています。 を利用してFilterの中にあるかどうかを確認し、そうであればコピーしてリクエスト属性として保存してください。しかし、このかもしれないは、いくつかのGAEサーブレットによるさらなる処理に影響します。

+0

私のコードには何もありませんが、Guiceは何かをボンネットの下でやっているかもしれません。 –

+0

代わりに 'getQueryString()'を使用することもできますが、GAEが "構文的に無効な"クエリ文字列でどのように動作するかはわかりません。 – BalusC

+0

その投稿要求と私はそこからデータを引き出しています。 –

6

リクエストのInputStreamがJetty 6.1.15で常に空であり、「Content-Type」ヘッダーが見つからないか間違っていることが原因であることがわかりました。

HttpUrlConnectionを使用して別のJavaプログラムで要求を生成します。 Content-Typeヘッダーを明示的に設定しなかった場合、受信プログラムのrequest.getInputStream()によって返されたInputStreamは常に空でした。コンテンツタイプを「バイナリ/オクテットストリーム」に設定すると、リクエストのInputStreamに正しいデータが含まれていました。

getInputStream()の前に要求オブジェクトに対して呼び出される唯一のメソッドはgetContentLength()です。

0

私はmod_jk 1.2.39を使用していましたが、この問題の原因となったバグがありました。 1.2.40に更新された後、動作を開始しました。

10

私は、Spring Bootアプリケーションを実行するのと同様の問題がありました。 My Spring Bootアプリは、単純なDispatcherサーブレットで、リクエスト本体を読み込んで処理します。私の場合

カールコマンドライン-d {some-data}を使用し-Hcontent-type=some-other-media-typeを介して特定のコンテンツタイプヘッダを設定しない場合、クライアント(curl)は、アプリケーション/ x-www-form-urlencodedでのコンテンツタイプヘッダを設定します。春ブーツが実行Apacheのカタリナサーブレット・エンジン内部

Requestクラスが行われ、他のcontent-type値、ここではRequestリターンについては、parseParameters()

 if (!("application/x-www-form-urlencoded".equals(contentType))) { 
      success = true; 
      return; 
     } 

で次のテストを行います。

しかしながら、コンテンツタイプマッチapplication/x-www-form-urlencoded場合、Requestが続く:

try { 
     if (readPostBody(formData, len) != len) {   
      parameters.setParseFailedReason(FailReason.REQUEST_BODY_INCOMPLETE); 
      return; 
     } 
    } catch (....) 

を消費するであろう。したがって、私のケースでは、私のサーブレットはrequest.getInputStream()を呼び出す以外は何もしませんし、read()から試してみてください。すでに遅すぎます - ランタイムRequestは既に入力を読み込み、それをバッファしたり未読にしません。唯一の回避策は別のContent-Typeを設定することです。

犯人は"_method"クエリパラメータを探している OrderedHiddenHttpMethodFilter(HiddenHttpMethodFilter).doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain)ライン70

です。

私は(another problemを解決するために使用された)

@Bean 
public FilterRegistrationBean registration(HiddenHttpMethodFilter filter) { 
    FilterRegistrationBean registration = new FilterRegistrationBean(filter); 
    registration.setEnabled(false); 
    return registration; 
} 

を追加することにより、フィルタを無効にすることができました

+1

これは素晴らしい発見です。そうでなければ、コントローラーのPostハンドラーのHttpServletRequestは常に理由がなく空を返します。 –

+0

これは難しいものでした。なぜなら、ポストエンティティが空であった理由を調べようとする2時間です。どうもありがとう! – emerino

0

私はポストでこの問題を持っていました。私は、入力ストリームを読み込んでそれをキャッシュに入れ、パラメータを読み込むことで解決しました。それはトリックをするように見えた

関連する問題