Sandeep,

This problem bit us not too long ago and I figured out why.  Since
ServiceMix makes use of of an InputStream (see:
http://cwiki.apache.org/SM/javaioioexception-stream-closed.html) by mulitple
components, it requires that the InputStream being returned can be read
multiple times if the message is being used (i.e. parsed for logic, etc.) by
multiple components.  This is the reason the wiki page says to make use of
the StringSource so that a String buffer is stored in memory to allow for
multiple reads of the response.  The reason your input stream cannot be read
multiple times is because the returned server objects is of the type 
http://commons.apache.org/io/api-release/org/apache/commons/io/input/AutoCloseInputStream.html
org.apache.commons.io.input.AutoCloseInputStream . 

from the AutoCloseInputStream Javadoc:


> Proxy stream that closes and discards the underlying stream as soon as the
> end of input has been reached or when the stream is explicitly closed. Not
> even a reference to the underlying stream is kept after it has been
> closed, so any allocated in-memory buffers can be freed even if the client
> application still keeps a reference to the proxy stream. 
> 

There are 2 reasons the AutoCloseInputStream is being used to wrap the HTTP
server response:

1) The HTTP API being used is the Apache HTTP Commons Client and it has
special rules to wrap the server responses in different input streams
depending on the response headers.

2) The HTTP response coming from the Server is most likely using the 
http://en.wikipedia.org/wiki/Chunked_transfer_encoding 'Transfer-Encoding:
chunked'  header.  Use a program like  http://www.wireshark.org Wireshark 
or  https://tcpmon.dev.java.net/ tcpmon  to monitor the response to see if
this is the case.  I have a high degree of confidence that it is.  When the
server responds with a chunked encoding the HTTP Commons client wraps the
response with a 
http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/ChunkedInputStream.html
ChunkedInputStream  enclosed in an AutoCloseInputStream object.

There are a few ways this can be fixed:

1) Change your server to respond using the normal 'Content-Length: XXX'
header instead of 'Transfer-Encoding: chunked'.  This will cause the HTTP
commons client to return a different InputStream type which can be read from
multiple times.

2) Modify the internal Camel/ServiceMix API's to use the 
http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/HttpMethodBase.html#getResponseBody()
HttpMethodBase.getResponseBody()  instead of 
http://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/HttpMethodBase.html#getResponseBodyAsStream()
HttpMethodBase#getResponseBodyAsStream() .  You will most likely need to
wrap the HttpMethodBase.getResponseBody() call in a 
http://java.sun.com/j2se/1.5.0/docs/api/java/io/ByteArrayInputStream.html
java.io.ByteArrayInputStream  if you do not want to modify the source code
too much.

Example API replacement:


> replace HttpMethodBase.getResponseBodyAsStream()
> with new ByteArrayInputStream(HttpMethodBase.getResponse())
> 

I also found these threads and JIRA tickets which may be related to the
server sending a chunked response.
Fuse JIRA  http://open.iona.com/issues/browse/ESB-73 ESB-73 
http://www.nabble.com/simple-http-soap-gateway-tp16543790p16543790.html
http://cwiki.apache.org/SM/discussion-forums.html#nabble-td5412079|a5709913

Hope this helps and good luck!

Thanks,
Trevor


sandeep reddy wrote:
> 
> Hi,
>    I am still facing this same problem and I am not able to resolve it.
> Please provide some advice on how to solve this or at least a workaround.
>    This is very important so please help us.
> 
> Thanks,
> Sandeep 
> 
> 
> sandeep reddy wrote:
>> 
>>>Can you pinpoint the messages that are causing this error? 
>>   
>> This is the response message from External application:
>> when it is success:
>>     <?xml version='1.0' encoding='UTF-8'?>
>> 
>>         <response>
>>             <message>password changed</message>
>>             <status>0</status>
>>         </response>
>> when it is error:
>>     <?xml version='1.0' encoding='UTF-8'?><response><message>Internal
>> Server Error: failed to change
>> password</message><status>1000</status></response>
>> 
>>>Is there anything special to them? 
>> 
>>     There is nothing special with response message.And we are pretty sure
>> that message is not creating any sought of problem because if message is
>> not proper it should fail for each time. And it works fine having DEBUG
>> level in log4j.xml file.
>> 
>>>BTW, I see you are using the Camel dead
>>>letter channel.  Make sure you configure that properly (not related to
>>>your current question, but the default configuration just writes a
>>>message to the log when things go wrong without information the JBI
>>>endpoint).
>> 
>>     Yes we are using Dead letter channel, and it is configured
>> properly.This is camel configure method:
>> public void configure() {
>> 
>>         exception(java.lang.Throwable.class)
>>         .setBody(constant("<response><status>"+
>> ErrorConstants.SYSTEM_ERROR +"</status><message>System
>> Error</message></response>"))
>>        
>> .to("jbi:service:http://servicemix.in2m.com/operations/changepassword/ResponseGeneratorService?mep=in-out";);
>>        
>>         exception(java.net.SocketException.class)
>>         .setBody(constant("<response><status>"+
>> ErrorConstants.SOCKET_ERROR +"</status><message>Connection
>> Error</message></response>"))
>>        
>> .to("jbi:service:http://servicemix.in2m.com/operations/changepassword/ResponseGeneratorService?mep=in-out";);
>>        
>>        
>> from("jbi:service:http://servicemix.in2m.com/operations/changepassword/RoutingService";)
>>         .convertBodyTo(DOMSource.class)    //added here
>>         .choice()
>>         .when(header("userPrincipals").contains("director"))       
>>            
>> .to("jbi:service:http://servicemix.in2m.com/operations/changepassword/PortalService?mep=in-out";)
>>             .convertBodyTo(DOMSource.class)   //added here
>>         .when(header("userPrincipals").contains("portal"))
>>            
>> .to("jbi:service:http://servicemix.in2m.com/operations/changepassword/DirectorService?mep=in-out";)
>>             .convertBodyTo(DOMSource.class);   //added here
>> } 
>> 
> 
> 

-- 
View this message in context: 
http://www.nabble.com/RuntimeCamelException%3A-java.io.IOException%3AAttempted-read-on-closed-stream-tp18869452p19314190.html
Sent from the ServiceMix - User mailing list archive at Nabble.com.

Reply via email to