Исключение при отправке большого запроса на мыло - PullRequest
0 голосов
/ 15 марта 2011

Существует веб-сервис, развернутый на tomcat 6 и предоставляемый через 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]

Это какая-то максимальная длина запроса, я полностью застрял с ней.

Ответы [ 3 ]

3 голосов
/ 25 апреля 2012

Предложение Владимира сработало. Этот код ниже поможет другим понять, где поставить 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 голосов
/ 26 июля 2012

Я сталкиваюсь с той же проблемой получения «com.ctc.wstx.exc.WstxEOFException: неожиданный EOF в прологе» при использовании класса CachedOutputStream.

Глядя на источники класса 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 ()

2 голосов
/ 17 марта 2011

Я понял, что случилось. На самом деле это была ошибка внутри кода перехватчика:

CachedOutputStream requestStream = new CachedOutputStream()

Когда я заменил это на

 CachedOutputStream requestStream = new CachedOutputStream(1000000);

все начинает работать нормально.

Таким образом, запрос был скопирован во время копирования потоков.

...