0

tomcat 6にデプロイされ、apache-cxf2.3.3を介して公開されるWebサービスがあります。このサービスを呼び出すことができるようにwsdl2javaを使用して生成されたソーススタブ。

大きなリクエスト(〜1Mb)を送信するまでは問題ないようでした。このリクエストは処理されず、例外を除いて失敗しました。

Interceptor for {http://localhost/}ResourceAllocationServiceSoapService has thrown      
exception, unwinding now org.apache.cxf.binding.soap.SoapFault:
Error reading XMLStreamReader.
...
com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog 
at [row,col {unknown-source}]: [1,0]

ここでは、ある種の最大リクエスト長ですが、私は完全にそれに固執しています。

4

3 に答える 3

3

ウラジミールの提案はうまくいきました。以下のこのコードは、他の人が 1000000 をどこに置くべきかを理解するのに役立ちます。

public void handleMessage(SoapMessage message) throws Fault { 
        // Get message content for dirty editing...

    InputStream inputStream = message.getContent(InputStream.class);

    if (inputStream != null)
    {
        String processedSoapEnv = "";
        // Cache InputStream so it can be read independently
        CachedOutputStream cachedInputStream = new CachedOutputStream(1000000);
        try {
            IOUtils.copy(inputStream,cachedInputStream);
            inputStream.close();
            cachedInputStream.close();

            InputStream tmpInputStream = cachedInputStream.getInputStream();
            try{
                String inputBuffer = "";
                int data;
                while((data = tmpInputStream.read()) != -1){
                    byte x = (byte)data;
                    inputBuffer += (char)x;
                }
                /**
                  * At this point you can choose to reformat the SOAP
                  * envelope or simply view it just make sure you put
                  * an InputStream back when you done (see below)
                  * otherwise CXF will complain.
                  */
                processedSoapEnv = fixSoapEnvelope(inputBuffer);
            }
            catch(IOException e){

            }
        }
        catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        // Re-set the SOAP InputStream with the new envelope

        message.setContent(InputStream.class,new ByteArrayInputStream( processedSoapEnv.getBytes()));

        /**
         * If you just want to read the InputStream and not
         * modify it then you just need to put it back where
         * it was using the CXF cached inputstream
         *
         * message.setContent(InputStream.class,cachedInputStream.getInputStream());
        */
    }       


} 
于 2012-04-25T00:32:56.387 に答える
2

私は何が悪いのかを理解しました。実際、それはインターセプターのコード内のバグでした:

CachedOutputStream requestStream = new CachedOutputStream()

これを置き換えたとき

 CachedOutputStream requestStream = new CachedOutputStream(1000000);

物事はうまく働き始めます。

そのため、ストリームのコピー中にリクエストがトランク化されました。

于 2011-03-17T06:28:53.333 に答える
2

CachedOutputStream クラスを使用すると、「com.ctc.wstx.exc.WstxEOFException: プロローグで予期しない EOF」が発生するという同じ問題が発生します。

CachedOutputStream クラスのソースを見ると、しきい値を使用して、ストリームのデータを「メモリ内」から「ファイル」に格納します。
ストリームがしきい値を超えるデータで動作すると仮定すると、ファイルに保存されるため、次のコードは壊れます

IOUtils.copy(inputStream,cachedInputStream);
inputStream.close();
cachedInputStream.close(); //closes the stream, the file on disk gets deleted
InputStream tmpInputStream = cachedInputStream.getInputStream(); //returned tmpInputStream is brand *empty* one
// ... reading tmpInputStream here will produce WstxEOFException 

「しきい値」を大きくすると、すべてのストリーム データがメモリに格納され、そのようなシナリオで cachedInputStream.close() を呼び出しても基になるストリーム実装が実際には閉じられないため、後で読み取ることができます。

これが上記のコードの「修正済み」バージョンです(少なくとも、私にとっては例外なく機能しました)

IOUtils.copy(inputStream,cachedInputStream);
inputStream.close();
InputStream tmpInputStream = cachedInputStream.getInputStream();
cachedInputStream.close();
// reading from tmpInputStream here works fine

close() が tmpInputStream で呼び出され、それに対する他の参照がなくなると、一時ファイルが削除されます。CachedOutputStream.maybeDeleteTempFile() のソース コードを参照してください。

于 2012-07-26T12:54:20.453 に答える