Search code examples
javasocketsconnectionjax-wspooling

Disable SSL socket connection pooling in JAX-WS?


I was wondering if it was possible to disable socket connection pooling in JAX-WS?

I am making calls to a webservice from within Jetty. The webservice is designed to have at most two connections to the server at any given time. One of the connections is a blocking connection that's used to do a pub/sub poll with the server. The other connection is used to make standard SOAP requests. Once a connection polls, no other connections can be used to poll, or the server returns an error.

To do this, I create two SOAP ports, one of which I use to poll and the other to make requests. This works great until the poller returns some data and the SOAP request connection is sitting there idle. When that happens, the next time I try to poll with the same SOAP port, it picks one of the connections out of the connection pool and reuses it. If it happens to get the SOAP request connection, the server returns an error. From that point on, the poller's dead in the water, since any new SOAP ports I create end up reusing one of those two connections, both of which have been deemed invalid for polling.

A possible solution would be to disable connection pooling, which means that each time I create a new SOAP port, it would establish a new connection. Either that, or a way to get at the socket itself, which I could forcefully close.

It might also be worth mentioning that the connection to the server is a mutually authenticated SSL connection.

FYI, here's the spec for the server that I'm trying to connect to:

http://www.trustedcomputinggroup.org/files/resource_files/93C23F2A-1A4B-B294-D0A36CCD8A9E7BD3/TNC_IFMAP_v2_0R0_47.pdf

Any help would be appreciated! Thanks, Marshall


Solution

  • I discovered a work-around solution to my problem after trying lots of different things. Unfortunately, I wasn't able to figure out how to disable connection pooling. If anyone knows how to do that, I'd like to hear the solution.

    I ended up creating my own custom SSL socket factory that acts as a pass-through to the default SSL socket factory, which I set on the HttpsURLConnection class:

    SSLContext context = SSLContext.getInstance("TLS");
    context.init(new KeyManager[] { new ClientKeyManager() }, 
        new TrustManager[] { new ClientTrustManager() }, 
        new SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(new ManagedSSLSocketFactory(context.getSocketFactory()));
    

    Note that I pass in the default socket factory from the SSLContext class. The code for the ManagedSSLSocketFactory looks like this:

    private class ManagedSSLSocketFactory extends SSLSocketFactory
    {
        private SSLSocketFactory m_socketFactory;
    
        public ManagedSSLSocketFactory(SSLSocketFactory socketFactory)
        {
            m_socketFactory = socketFactory;
        }
    
        @Override
        public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException
        {
            Socket socket = m_socketFactory.createSocket(s, host, port, autoClose);
    
            //Note that m_arcThread, m_arcSocket, etc are defined in the containing class
            if(Thread.currentThread() == m_arcThread)
            {
                if(m_arcSocketInvalid || (socket == m_ssrcSocket))
                {
                    closeSocketQuietly(socket);
                    return createSocket(s, host, port, autoClose);
                }
                m_arcSocketInvalid = false;
            }
    
            ... omitted some convoluted code that deals with edge cases
    
            return socket;
        }
    
        ... rest of implementation
    
    }