17

What might be the cause of:

org.apache.cxf.interceptor.Fault: Could not send Message.

Caused by: java.net.SocketTimeoutException: SocketTimeoutException invoking https://xxx.xxx.xxx.xxx:8443/services/test: Read timed out

It usually occurs after I send a soap request to the ws. I'm using apache cxf. I'm completely sure that the ws is up and running because before the time out occur the client will send 2 more request. The timeout happens in the third soap request.

Paul R
  • 208,748
  • 37
  • 389
  • 560
irumi
  • 211
  • 2
  • 3
  • 4

4 Answers4

17

I have encountered this error as well for my webservice client. The solution that worked for me is to configure the http client in the CXF config file (cxf.xml).

As documented in Apache CXF document:

1.Add the http-conduit namespace and xsd:

<beans ...
       xmlns:http-conf="http://cxf.apache.org/transports/http/configuration
       ...
       xsi:schemaLocation="...
           http://cxf.apache.org/transports/http/configuration
           http://cxf.apache.org/schemas/configuration/http-conf.xsd
       ...">

2.Add the http-conduit tag/element and set the ReceiveTimeout/ConnectionTimeout to 300000 ms:

<http-conf:conduit name="*.http-conduit">
      <http-conf:client 
                      ConnectionTimeout="300000"
                      ReceiveTimeout="300000"/>       
</http-conf:conduit>
maxxyme
  • 2,164
  • 5
  • 31
  • 48
Carlos Jaime C. De Leon
  • 2,476
  • 2
  • 37
  • 53
14

The error message means that your web service client was trying to receive data from a remote web service over the network, but no data was received for a specific period of time, so the web service client stopped waiting for the data to be received.

One of the possible causes might be that the timeout property is too low. Defaults to cxf default values of 30000 and 60000 ms respectively. These can be changed depending how you are creating your client.

If you are creating a client using java code you can use:

//1 minute for connection
((BindingProvider) wsPort).getRequestContext().put("com.sun.xml.ws.connect.timeout", 1 * 60 * 1000); 

//3 minutes for request
((BindingProvider) wsPort).getRequestContext().put("com.sun.xml.ws.request.timeout", 3 * 60 * 1000); 

If you are using Spring, you can use a map like this:

<util:map id="jaxwsProperties">
    <entry key="com.sun.xml.internal.ws.request.timeout">
        <value type="java.lang.Integer">120000</value>
    </entry>
    <entry key="com.sun.xml.internal.ws.connect.timeout">
        <value type="java.lang.Integer">60000</value>
    </entry>
</util:map>

Then set that map into your <jaxws:client.../> configuration.

Paulius Matulionis
  • 23,085
  • 22
  • 103
  • 143
  • okay ill try that :) anyway can wrong soap request format can also the culprit of the error??,, i accidentally sent a soap request with null values/ "" values then i suddenly received the ws soap response .. – irumi Feb 01 '13 at 16:21
  • 2
    The properties have changed names to `javax.xml.ws.client.connectionTimeout` and `javax.xml.ws.client.receiveTimeout` respectively. – Anders R. Bystrup Aug 16 '16 at 09:13
  • The use of `BindingProviderProperties.CONNECT_TIMEOUT`and `BindingProviderProperties.REQUEST_TIMEOUT`as keys should prevent problems of name change. – Manur Dec 13 '19 at 09:37
  • @Manur this class is deprecated and it points to old property names – Kirill Apr 08 '21 at 10:13
4

Another approche to config timeouts (programmatically):

JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
Object serviceClass = factory.create();
defineTimeouts(serviceClass);

static void defineTimeouts(Object serviceClass) {
    Client cxfClient = ClientProxy.getClient(serviceClass);
    HTTPConduit httpConduit = (HTTPConduit) cxfClient.getConduit();

    HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
    httpClientPolicy.setConnectionTimeout(DEFAULT_CLIENT_CONNECTION_TIMEOUT);
    httpClientPolicy.setReceiveTimeout(DEFAULT_CLIENT_RECEIVE_TIMEOUT);
    httpConduit.setClient(httpClientPolicy);
}
Bob Rivers
  • 5,261
  • 6
  • 47
  • 59
0

You might want to change the receiveTimeout setting from Apache CXF src and replace the existing cxf-rt-transports-http-version.jar in your server.

Brief instructions: (Got the instructions from Wildfly 8.2/undertow read time out)

  1. Download CXF2.7.16 src from apache
  2. Add maven/bin to PATH
  3. Export MAVEN_OPTS=-Xmx512m to fix permgen errors
  4. Open ./rt/transports/http/src/main/resources/schemas/wsdl/http-conf.xsd and change ReceiveTimeout from 60000 to whatever needed for eg. 600000 (10 minutes)
  5. Run mvn -Pfastinstall
  6. Get the "patched" cxf-rt-transports-http-2.7.16.jar from ./rt/transports/http/target folder
  7. Replace cxf-rt-transports-http-2.7.16.jar in your server. For example, with wildfly8.2, it is in .//modules/system/layers/base/org/apache/cxf/impl/main folder and remember to update module.xml inside the same folder to use this patched cxf-rt-transports-http-2.7.16.jar.

This should resolve the SocketTimeoutException caused by the underlying Apache CXF used in the server.

Community
  • 1
  • 1
Henry Neo
  • 2,357
  • 1
  • 24
  • 27