【问题标题】:Exception when sending big soap request发送大肥皂请求时出现异常
【发布时间】:2011-07-15 20:15:17
【问题描述】:

在 tomcat 6 上部署了一个 Web 服务,并通过 apache-cxf 2.3.3 公开。使用 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]

这里是某种最大请求长度,我完全被它所困扰。

【问题讨论】:

    标签: exception soap wsdl cxf wsdl2java


    【解决方案1】:

    Vladimir's suggestion 工作。下面的代码将帮助其他人了解将 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());
            */
        }       
    
    
    } 
    

    【讨论】:

      【解决方案2】:

      我知道出了什么问题。实际上这是拦截器代码中的错误:

      CachedOutputStream requestStream = new CachedOutputStream()
      

      当我用

      替换它时
       CachedOutputStream requestStream = new CachedOutputStream(1000000);
      

      一切都开始正常了。

      所以请求只是在复制流期间被中继。

      【讨论】:

      • 你在哪里添加了这个 CachedOutputStream requestStream = new CachedOutputStream(1000000);看看我也面临同样的问题
      【解决方案3】:

      我在使用 CachedOutputStream 类时遇到了同样的问题,即“com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog”。

      查看 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
      

      在 tmpInputStream 上调用 close() 时临时文件被删除,并且没有其他对其的引用,请参阅 CachedOutputStream.maybeDeleteTempFile() 的源代码

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多