Search code examples
javajettycxfjax-ws

Issue with SSL listener for CXF/Jetty/Jax-WS - Port is configured with wrong protocol "http" for "https://0.0.0.0:9227/v1"


Trying to modify an existing application that used CXF 2.2.10/Jetty 6 & 8 to CXF 3.3.2/Jetty 9 and I'm encountering an issue setting up the SSL Listener. Unfortunately, I have very little experience with CXF and I'm running into issues.

This is running on Linux, using Java 1.8, and the error we are seeing is:

java.lang.IllegalStateException: Port 9227 is configured with wrong protocol "http" for "https://0.0.0.0:9227/v1"

This is our cxf.xml file:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sec="http://cxf.apache.org/configuration/security"
       xmlns:http="http://cxf.apache.org/transports/http/configuration"
       xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
       xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
       xsi:schemaLocation="http://cxf.apache.org/configuration/security
                      http://cxf.apache.org/schemas/configuration/security.xsd
            http://cxf.apache.org/transports/http/configuration
            http://cxf.apache.org/schemas/configuration/http-conf.xsd
            http://cxf.apache.org/transports/http-jetty/configuration
            http://cxf.apache.org/schemas/configuration/http-jetty.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <beans:bean name="connectorThreadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool">
        <beans:constructor-arg value="72"/>
    </beans:bean>

    <beans:bean name="server" class="org.eclipse.jetty.server.Server">
        <constructor-arg ref="connectorThreadPool" />
    </beans:bean>

    <beans:bean name="sslConnectionFactory" class="org.eclipse.jetty.server.SslConnectionFactory" />

    <httpj:engine-factory bus="cxf">
        <httpj:engine port="9127">
            <httpj:threadingParameters minThreads="5" maxThreads="200"/>
            <httpj:connector>
                <beans:bean class="org.eclipse.jetty.server.ServerConnector">
                    <constructor-arg ref="server" />
                    <beans:property name="port" value="9127"/>
                </beans:bean>
            </httpj:connector>
        </httpj:engine>
    </httpj:engine-factory>

    <httpj:engine-factory bus="cxf">
        <httpj:identifiedTLSServerParameters id="secure">
            <httpj:tlsServerParameters secureSocketProtocol="TLSv1">
                <sec:keyManagers keyPassword="keyPassword">
                    <sec:keyStore type="JKS" password="keyPassword" file="keystore-lab.jks"/>
                </sec:keyManagers>
                <sec:trustManagers>
                    <sec:keyStore type="JKS" password="password" file="cacerts.jks"/>
                </sec:trustManagers>
                <sec:cipherSuitesFilter>
                    <sec:include>.*_EXPORT_.*</sec:include>
                    <sec:include>.*_EXPORT1024_.*</sec:include>
                    <sec:include>.*_WITH_DES_.*</sec:include>
                    <sec:include>.*_WITH_DES40_.*</sec:include>
                    <sec:include>.*_WITH_AES_.*</sec:include>
                    <sec:exclude>.*_DH_anon_.*</sec:exclude>
                </sec:cipherSuitesFilter>
            </httpj:tlsServerParameters>
        </httpj:identifiedTLSServerParameters>
        <httpj:engine port="9227">
            <httpj:tlsServerParametersRef id="secure" />
            <httpj:threadingParameters minThreads="5" maxThreads="200"/>
            <httpj:connector>
                <beans:bean class="org.eclipse.jetty.server.ServerConnector">
                    <constructor-arg ref="server" />
                    <constructor-arg ref="sslConnectionFactory" />
                    <beans:property name="port" value="9227"/>
                </beans:bean>
            </httpj:connector>
        </httpj:engine>
    </httpj:engine-factory>
</beans>

One thing I've noticed is that CXF's SslConnectionFactory calls it's superclass constructor with "SSL" as the protocol, while JettyHTTPServerEngine checks for the value of "https" as the protocol value. I can't imagine this hasn't been found before, so I feel I must be missing something.

But when I extended SslConnectionFactory and modified that constructor to pass "https" instead of "SSL" as the protocol, it didn't throw this exception. It did end up throwing another one later upon connection attempt:

java.lang.NullPointerException
        at com.mypackage.util.CustomSslConnectionFactory.newConnection(CustomSslConnectionFactory.java:108)
        at org.eclipse.jetty.server.ServerConnector$ServerConnectorManager.newConnection(ServerConnector.java:550)
        at org.eclipse.jetty.io.ManagedSelector.createEndPoint(ManagedSelector.java:263)
        at org.eclipse.jetty.io.ManagedSelector.access$1900(ManagedSelector.java:61)
        at org.eclipse.jetty.io.ManagedSelector$Accept.run(ManagedSelector.java:747)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:698)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:804)
        at java.lang.Thread.run(Thread.java:748)

which I believe has to do with the "nextProtocol" value. But not being able to find this, I feel like I'm heading down the wrong path with this method.

I'm really just hoping to get this upgrade working with both http (which does seem to work ok!) and SSL.

UPDATE:

Eddo's post got me in the right direction, but I needed server details instead of client.

I was also able to remove a lot of the extraneous junk I didn't need. Final cxf.xml based on http://cxf.apache.org/docs/standalone-http-transport.html :

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:sec="http://cxf.apache.org/configuration/security"
       xmlns:http="http://cxf.apache.org/transports/http/configuration"
       xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
       xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
       xsi:schemaLocation="http://cxf.apache.org/configuration/security
                      http://cxf.apache.org/schemas/configuration/security.xsd
            http://cxf.apache.org/transports/http/configuration
            http://cxf.apache.org/schemas/configuration/http-conf.xsd
            http://cxf.apache.org/transports/http-jetty/configuration
            http://cxf.apache.org/schemas/configuration/http-jetty.xsd
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

    <http:destination name="{http://WsdlHost}WsdlPort.http-destination">
    </http:destination>

    <httpj:engine-factory bus="cxf">
        <httpj:engine port="9127">
            <httpj:threadingParameters minThreads="5" maxThreads="200"/>
            <httpj:connector>
                <beans:bean class="org.eclipse.jetty.server.ServerConnector">
                    <constructor-arg ref="server" />
                    <beans:property name="port" value="9127"/>
                </beans:bean>
            </httpj:connector>
        </httpj:engine>
    </httpj:engine-factory>

    <httpj:engine-factory bus="cxf">
        <httpj:engine port="9227">
            <httpj:tlsServerParameters>
                <sec:keyManagers keyPassword="keyPassword">
                    <sec:keyStore type="JKS" password="keyPassword" file="keystore-lab.jks"/>
                </sec:keyManagers>
                <sec:trustManagers>
                    <sec:keyStore type="JKS" password="password" file="cacerts.jks"/>
                </sec:trustManagers>
                <sec:cipherSuitesFilter>
                    <sec:include>.*_EXPORT_.*</sec:include>
                    <sec:include>.*_EXPORT1024_.*</sec:include>
                    <sec:include>.*_WITH_DES_.*</sec:include>
                    <sec:include>.*_WITH_DES40_.*</sec:include>
                    <sec:include>.*_WITH_AES_.*</sec:include>
                    <sec:exclude>.*_DH_anon_.*</sec:exclude>
                </sec:cipherSuitesFilter>
            </httpj:tlsServerParameters>
        </httpj:engine>
    </httpj:engine-factory>
</beans>

Solution

  • Here is an example of how I set it up using https, so you can use this as a reference, just notice that I'm using blueprint (not spring DSL) and also JBoss but I know this approach works in spring DSL too so you can try it.

    <?xml version="1.0" encoding="UTF-8" ?>
    <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
        xmlns:bp="http://camel.apache.org/schema/blueprint"
        xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.1.0"
        xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf" 
        xmlns:http="http://cxf.apache.org/transports/http/configuration"
        xmlns:sec="http://cxf.apache.org/configuration/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
          http://camel.apache.org/schema/blueprint
             http://camel.apache.org/schema/blueprint/camel-blueprint-2.16.4.xsd
          http://www.osgi.org/xmlns/blueprint/v1.0.0
             https://osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
          http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.1.0
             http://aries.apache.org/schemas/blueprint-ext/blueprint-ext-1.1.xsd
          http://camel.apache.org/schema/blueprint/cxf
             http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd
          http://cxf.apache.org/transports/http/configuration 
             http://cxf.apache.org/schemas/configuration/http-conf.xsd
          http://cxf.apache.org/configuration/security 
             http://cxf.apache.org/schemas/configuration/security.xsd
          ">
    
        <cxf:cxfEndpoint id="myService"
            address="https://localhost:8443/MyWebService/"
            wsdlURL="https://localhost:8443/MyWebService?wsdl"
            loggingFeatureEnabled="true">
        </cxf:cxfEndpoint>
    
        <http:conduit name="*.http-conduit">
            <http:tlsClientParameters disableCNCheck="true">
                <sec:keyManagers keyPassword="$RF[trustStore.password]">
                    <sec:keyStore type="JKS" password="yourpassgoeshere"
                        file="/var/app/security/my-trust.jks" />
                </sec:keyManagers>
                <sec:trustManagers>
                    <sec:keyStore type="JKS" password="yourpassgoeshere"
                        file="/var/app/security/my-trust.jks" />
                </sec:trustManagers>
            </http:tlsClientParameters>
        </http:conduit>
    
    </blueprint>
    

    Along with this take a look at the documentation which is well explained so you can adapt it to your needs.

    http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html