Search code examples
javacxfonvifcxf-client

CXF client - TCP connection is closed between each request


I am implementing one SOAP client, the general working is fine, but I have spotted one pitfall because on each request the TCP connection is closed (by me).

This is sub-optimal, and it's worse when HTTPS is used because the certificates are exchanged are each request.

The creation of the httpconduit and the call of SOAP service

public static void test(final String destination) {
        System.setProperty("javax.xml.soap.SAAJMetaFactory", "com.sun.xml.messaging.saaj.soap.SAAJMetaFactoryImpl");

        TLSClientParametersFactory tlsClientParametersFactory = new TLSClientParametersFactory
            .Builder()
            .acceptAllCerts()
            .build();

        JAXRSClientFactoryBean clientFactoryBean = new JAXRSClientFactoryBean();
        clientFactoryBean.setAddress(destination);

        WebClient webClient = clientFactoryBean.createWebClient();
        ClientConfiguration config = WebClient.getConfig(webClient);
        HTTPConduit conduit = config.getHttpConduit();

        HTTPClientPolicy client = conduit.getClient();
        client.setConnection(ConnectionType.KEEP_ALIVE);
        client.setConnectionTimeout(TimeUnit.MINUTES.toMillis(60));

        conduit.setTlsClientParameters(tlsClientParametersFactory.createTlsClient());

        Media media = createFactory(Media.class, conduit, tlsClientParametersFactory, destination);

        // The call of the soap service, with the expectation to have the same TCP connection used.
        List<Profile> profiles = media.getProfiles();
        List<Profile> profiles2 = media.getProfiles();
        List<Profile> profiles3 = media.getProfiles();
        List<Profile> profiles4 = media.getProfiles();
        List<Profile> profiles5 = media.getProfiles();

The creation of the SOAP port

private static <T> T createFactory(final Class<T> clazz,
                                   final Conduit conduit,
                                   final TLSClientParametersFactory factory,
                                   final String destination)  {

    Map<String, Object> props = new HashMap<>();
    props.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
    props.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_DIGEST);
    props.put(WSHandlerConstants.PW_CALLBACK_CLASS, PasswordCallback.class.getName());
    props.put(WSHandlerConstants.USER, "test");
    WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(props);

    JaxWsProxyFactoryBean proxyFactory = new JaxWsProxyFactoryBean();
    proxyFactory.setAddress(destination);
    proxyFactory.setServiceClass(clazz);

    SoapBindingConfiguration config = new SoapBindingConfiguration();
    config.setVersion(Soap12.getInstance());
    proxyFactory.setBindingConfig(config);
    proxyFactory.setConduitSelector(new PreexistingConduitSelector(conduit));
    Map<String, Object> properties = proxyFactory.getProperties();
    if (properties == null) {
        properties = Maps.newHashMap();
    }
    properties.put(Client.KEEP_CONDUIT_ALIVE, true);
    proxyFactory.setProperties(properties);
    T t = proxyFactory.create(clazz);
    TLSClientParametersFactory.setSsClientParametersToPort(factory, t);
    return t;
}

What did I do wrong ??

Note : The connection is closed when a new request is done. Otherwise the TCP connection stay alive.

Another input The problem is not present with all the destinations target. For example if I use the device "AXIS A1001 Network Door Controller" the system work without recreate the tcp socket (the tcp conversation is colorized)

Axis A1001 same socket

But I use the "AXIS P5534 Network Camera", the socket is recreated.

Multiples request against network camera

And it's my pc (10.110.0.106) who'is closing the connection enter image description here

The version used :

  • cxf-rt-ws-security version 3.3.6
  • cxf-rt-rs-client version 3.3.6

Solution

  • Finally, I have found the problem, the code is not the faulty system. The problem come from the Axis device.

    The tricks is that the remote device close the TCP stream directly in the SOAP response (HTTP message) and in this case wireshark doesn't display the [FIN, ACK]. But If we look directly in the TCP layer, we can see the "TCP FIN" flags was set :

    TCP FIN is SOAP response