I have a java application with Apache ServiceMix and Apache Camel.
Here is my Camel Spring XML configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
xmlns:ctx="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<osgix:cm-properties id="portalEsbSERVICEProps" persistent-id="portal.esb.SERVICE">
<prop key="SERVICE-protocol">http</prop>
<prop key="SERVICE-endpoint">localhost:8880/mockSERVICE</prop>
<prop key="SERVICE-timeout">15000</prop>
</osgix:cm-properties>
<ctx:property-placeholder properties-ref="portalEsbSERVICEProps" />
<camelContext xmlns="http://camel.apache.org/schema/spring">
<endpoint id="toUri" uri="${SERVICE-protocol}4://${SERVICE-endpoint}?httpClient.socketTimeout=${SERVICE-timeout}&bridgeEndpoint=true&disableStreamCache=true&throwExceptionOnFailure=false"/>
<route>
<from uri="jetty:http://0.0.0.0:9200/SERVICE" />
<log message="Connecting to SERVICE" />
<to uri="ref:toUri" />
</route>
</camelContext>
</beans>
I send request to external service. When the await time for the external service exceeded limit (currently I simulate it on mock), Camel throws SocketTimeoutException. Then we get Internal Server Error (code 500) in the browser, because application expect valid SOAP response, instead of this get exception and can't parse it. Error:
Caused by: javax.xml.ws.WebServiceException: Could not receive Message.
at org.apache.cxf.jaxws.JaxWsClientProxy.mapException(JaxWsClientProxy.java:183)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:145)
at com.sun.proxy.$Proxy1053.komunikat(Unknown Source)
at pl.com.profidata.pp.otago.mint.ws.MintWsClient.sendMessage(MintWsClient.java:105)
... 193 more
Caused by: java.net.SocketTimeoutException: SocketTimeoutException invoking http://localhost:8880/mock1: Read timed out
at sun.reflect.GeneratedConstructorAccessor2422.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.mapException(HTTPConduit.java:1402)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1386)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:673)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:63)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:537)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:446)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:361)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:319)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140)
... 195 more
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:735)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:678)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1587)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream$2.run(URLConnectionHTTPConduit.java:377)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream$2.run(URLConnectionHTTPConduit.java:373)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.getResponseCode(URLConnectionHTTPConduit.java:373)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.doProcessResponseCode(HTTPConduit.java:1599)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1627)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1572)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1373)
... 205 more
What I would like to achieve is:
- catch SocketTimeoutException on the Camel site
- then send some SOAP fault response back to application
I have try so far to catch SocketTimeoutException using onException and doCatch, but without success.
EDIT My final Camel Spring XML configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:osgix="http://www.springframework.org/schema/osgi-compendium"
xmlns:ctx="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
http://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<osgix:cm-properties id="portalEsbSERVICEProps" persistent-id="portal.esb.SERVICE">
<prop key="SERVICE-protocol">http</prop>
<prop key="SERVICE-endpoint">localhost:8880/mockSERVICE</prop>
<prop key="SERVICE-timeout">15000</prop>
</osgix:cm-properties>
<ctx:property-placeholder properties-ref="portalEsbSERVICEProps" />
<bean id="faultHandler" class="my.class.FaultHandler"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<endpoint id="toUri" uri="${SERVICE-protocol}4://${SERVICE-endpoint}?httpClient.socketTimeout=${SERVICE-timeout}&bridgeEndpoint=true&disableStreamCache=true&throwExceptionOnFailure=false"/>
<route>
<from uri="jetty:http://0.0.0.0:9200/SERVICE" />
<log message="Connecting to SERVICE" />
<doTry>
<to uri="ref:toUri" />
<doCatch>
<exception>java.net.SocketTimeoutException</exception>
<setFaultBody>
<method ref="faultHandler" method="timeoutExceptionMessage"/>
</setFaultBody>
</doCatch>
</doTry>
</route>
</camelContext>
</beans>
And FaultHandler:
public class FaultHandler {
//SOAP response for timeout
public String timeoutExceptionMessage() {
String message = "mySoapMessage";
return message;
}
}