9 Replies Latest reply on May 15, 2013 9:49 AM by asoldano

    Creating a JBossWS CXF client using HTTPS WSDL url triggers "Failed to create service." exception

    slbanal

      Hi,

       

      I am currently developing a web service which uses HTTPS with WS-Security (Authentication/Signing) support. The client works using normal HTTP wsdl URL while using https causes the client to throw exception below.

       

      I was able to test service https WSDL URL by using a browser and by using JaxWsProxyFactoryBean API to create the client (essentially just to avoid the Service.create(...) call), setting TLSClientParameters in http-conduit and it works fine. But, when https is used as WSDL url in the client it throws an exception.

       

      • HTTPS tests works using a browser. Firefox prompts me to add the certificate in exception list when I browse HTTPS WSDL url. i believe because I am using a self-signed certificate. So, I assumed it is working fine.
      • HTTPS works using JaxWsProxyFactoryBean but without WS-Security policy in WSDL. Fails to work if WS-Security (Authentication/Signing) is enabled since client is not adding the appropriate headers/certificate tokens in the SOAP request.
      • WS-Security without HTTPS works using Service.create(wsdlUrl, serviceQName). Integration of HTTPS doesn't work due to exception thrown during create call. Stack trace below.

       

      Is there a configuration i have to enable/code for the CXF Bus for this to work? I saw a similar issue posted here: http://stackoverflow.com/questions/15755293/apache-cxf-wsdl-download-via-ssl-tls?rq=1 but I am somewhat hesitant on using such a solution that adds a custom ResourceResolver in ResourceManager of CXF Bus.

       

      Stacktrace exception:

       

      javax.xml.ws.WebServiceException: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.

          at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:149)

          at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:98)

          at javax.xml.ws.Service.<init>(Service.java:56)

          at javax.xml.ws.Service.create(Service.java:680)

         ...

          at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

          at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

          at java.lang.reflect.Method.invoke(Method.java:597)

          at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)

          at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)

          at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)

          at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)

          at org.junit.runners.ParentRunner.run(ParentRunner.java:300)

          at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)

          at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)

          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)

          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)

          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)

          at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

      Caused by: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.

          at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:94)

          at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:203)

          at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:147)

          ... 22 more

      ..... handshake error

        • 1. Re: Creating a JBossWS CXF client using HTTPS WSDL url triggers "Failed to create service." exception
          asoldano

          I *think* the problem here is that the httpconduit ends up not being configured properly when going the JAXWS Service.create(..) approach. Can you share a bit more of what you set in it when using the JaxWsProxyFactoryBean approach (which afaiu is working for you) ? Can you also past the full stracktrace, including the actual handshare error exception?

          Btw, you can get a handle to the http conduit by doing something like:

           

          import org.apache.cxf.endpoint.Client;

          import org.apache.cxf.frontend.ClientProxy;

          import org.apache.cxf.transport.http.HTTPConduit;

          ...

                Service service = Service.create(wsdlURL, serviceName);

                port = service.getPort(..., ...);

                Client client = ClientProxy.getClient(port);

                HTTPConduit conduit = (HTTPConduit)client.getConduit();

          ...

          • 2. Re: Creating a JBossWS CXF client using HTTPS WSDL url triggers "Failed to create service." exception
            slbanal

            Hi Allesio,

             

            The exception is actually thrown when Service.create(...) is called. Thus, even the line where my code should have called client.getConduit() and set the TLS parameters is not called.

            Is there a way to delay the retrieval of the WSDL definition through HTTPS (from the specified WSDL URL)? Such that I can create the Service then set the conduit TLS parameters and only after that will the client retrieve the WSDL definition from the HTTPS url.

             

            Continuation of stack trace I posted:

             

            Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: Problem parsing 'https://myserver.com:8443/myservice?wsdl'.: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

                at com.ibm.wsdl.xml.WSDLReaderImpl.getDocument(Unknown Source)

                at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)

                at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)

                at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:249)

                at org.apache.cxf.wsdl11.WSDLManagerImpl.getDefinition(WSDLManagerImpl.java:192)

                at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:92)

                ... 24 more

            Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

                at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)

                at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)

                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1806)

                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:986)

                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1170)

                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1197)

                at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1181)

                at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)

                at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)

                at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1172)

                at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)

                at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:675)

                at com.sun.org.apache.xerces.internal.impl.XMLVersionDetector.determineDocVersion(XMLVersionDetector.java:186)

                at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:772)

                at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)

                at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)

                at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:232)

                at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:284)

                ... 30 more

            • 3. Re: Creating a JBossWS CXF client using HTTPS WSDL url triggers "Failed to create service." exception
              slbanal

              Hi Allesio,

               

              I also tried this article from CXF site  http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html#ClientHTTPTransport%28includingSSLsupport%29-ConfiguringSSLSupport which requires a <http:conduit/> entry in a spring configuration file to override Client SSL paramaters. It seems based on CXF logs the configuration is read but the same exception is thrown. Is this type of CXF configuration works with JBossWS CXF?

               

              Thanks,

              Stephen

              • 4. Re: Creating a JBossWS CXF client using HTTPS WSDL url triggers "Failed to create service." exception
                slbanal

                Finally fixed this issue. Fix is setting secureSocketProtocol="TLSv1" in <http-conduit/> in my cxf.xml file. I have to specify TLSv1 since In my JBoss standalone.xml <connector/><ssl/> entry i specified that value in the protocol attribute.

                 

                <http:conduit name="*.http-conduit">

                 

                    <http:tlsClientParameters secureSocketProtocol="TLSv1">

                      <sec:keyManagers keyPassword="password">

                        <sec:keyStore type="JKS" password="password" file="client.jks"/>

                      </sec:keyManagers>

                      <sec:trustManagers>

                        <sec:keyStore type="JKS" password="password" file="truststore.jks"/>

                      </sec:trustManagers>

                      <sec:cipherSuitesFilter>

                        <!-- these filters ensure that a ciphersuite with

                             export-suitable or null encryption is used,

                             but exclude anonymous Diffie-Hellman key change as

                             this is vulnerable to man-in-the-middle attacks -->

                        <sec:include>.*_EXPORT_.*</sec:include>

                        <sec:include>.*_EXPORT1024_.*</sec:include>

                        <sec:include>.*_WITH_DES_.*</sec:include>

                        <sec:include>.*_WITH_AES_.*</sec:include>

                        <sec:include>.*_WITH_NULL_.*</sec:include>

                        <sec:exclude>.*_DH_anon_.*</sec:exclude>

                      </sec:cipherSuitesFilter>

                    </http:tlsClientParameters>

                  </http:conduit>


                • 5. Re: Creating a JBossWS CXF client using HTTPS WSDL url triggers "Failed to create service." exception
                  asoldano

                  Thanks for the feedback. That for sure works, basically you build up the client bus from a cxf.xml descriptor with a custom http-conduit.

                   

                  Sorry, for the late reply, but I've been thinking about this anyway and there's most probably also a fully programmatic (non spring) approach, should you need or prefer it (it's a bit complicated though atm). Basically, the problem here is that you need to configure the conduit in the bus before it's used to get the endpoint wsdl, which happens during Service.create(...), that is before you can get the port and cast it to ClientProxy to get a handle to the conduit. So, you need to build up the client bus explicitely and get the configurer extension from it:

                   

                  import org.apache.cxf.configuration.Configurer;

                  import org.jboss.wsf.stack.cxf.client.configuration.BeanCustomizer;

                  import org.jboss.wsf.stack.cxf.client.configuration.JBossWSConfigurer;

                  ...

                  Bus bus = BusFactory.newInstance().createBus();

                  JBossWSConfigurer configurer = (JBossWSConfigurer)bus.getExtension(Configurer.class);

                  BeanCustomizer customizer = configurer.getCustomizer();

                   

                  this all assumes the jbossws-cxf integration is available on client. Then you should replace the customizer with an extension overriding its configureHTTPConduit method [1] to setup the conduit as you need.

                  Once that's done, you set the bus as thread default bus and start building up the jaxws client.

                   

                  Alternatively, you might keep a local copy of the wsdl on the client side and parse that instead (that is often a suggested approach to reduce network traffic btw).

                   

                   

                  [1] http://anonsvn.jboss.org/repos/jbossws/stack/cxf/tags/jbossws-cxf-4.1.1.Final/modules/client/src/main/java/org/jboss/wsf/stack/cxf/client/configuration/BeanCustomizer.java

                  • 6. Re: Creating a JBossWS CXF client using HTTPS WSDL url triggers "Failed to create service." exception
                    slbanal

                    Hi Alessio,

                     

                    Actually I prefer to use bean configuration to make it simpler, it's only meant for testing anyway. I just have one additional question. What maven depenencies should I add for the client to work when using CXF + HTTPS + WS-Security/SecurityPolicy? I am getting a successful response from service when I use my Eclipse IDE with "Apache CXF Library" (from jbossws-cxf-bin-dist) referenced in an Eclipse project. But when I build my code using CXF libraries from Maven repo (without the Apache CXF Library reference from jbossws-cxf-bin-dist) I am getting a handshake problem. It seems like some jars are not initialized or wrong jars are used (just my hunch). Dependencies I have are as follows where cxf.version value is 2.4.6. I also have the logs below during initialization.

                     

                    <dependency>

                                <groupId>org.apache.ws.security</groupId>

                                <artifactId>wss4j</artifactId>

                                <version>1.6.9</version>

                                <scope>provided</scope>

                    </dependency>

                    <dependency>

                                 <groupId>org.jboss.ws</groupId>

                                  <artifactId>jbossws-api</artifactId>

                                  <version>1.0.1.Final</version>

                                  <scope>provided</scope>

                    </dependency>

                    <dependency>

                        <groupId>org.apache.cxf</groupId>

                        <artifactId>cxf-rt-ws-policy</artifactId>

                        <version>${cxf.version}</version>

                        <scope>test</scope>

                    </dependency>

                    <dependency>

                        <groupId>org.apache.cxf</groupId>

                        <artifactId>cxf-rt-ws-security</artifactId>

                        <version>${cxf.version}</version>

                        <scope>test</scope>

                    </dependency>

                    <dependency>

                        <groupId>org.apache.cxf</groupId>

                        <artifactId>cxf-rt-frontend-jaxws</artifactId>

                        <version>${cxf.version}</version>

                        <scope>test</scope>

                    </dependency>

                    <dependency>

                        <groupId>org.apache.cxf</groupId>

                        <artifactId>cxf-rt-transports-http</artifactId>

                        <version>${cxf.version}</version>

                        <scope>test</scope>

                    </dependency>

                    <dependency>

                         <groupId>org.bouncycastle</groupId>

                         <artifactId>bcprov-jdk16</artifactId>

                         <version>1.46</version>

                         <scope>test</scope>

                    </dependency>  

                     

                     

                    Thanks,

                    Stephen

                    • 7. Re: Creating a JBossWS CXF client using HTTPS WSDL url triggers "Failed to create service." exception
                      asoldano

                      Stephen,

                      you can either set a maven dependency to the org.jboss.ws.cxf:jbossws-cxf-client artifact (which will transitively pull in the same dependencies included in the jbwscxf bin dist) or generate a dependency tree for your current maven project (mvn dependency:tree) and compare what you get with the list of jars in the bin dist.

                      • 8. Re: Creating a JBossWS CXF client using HTTPS WSDL url triggers "Failed to create service." exception
                        slbanal

                        Hi Alessio,

                         

                        Thanks a lot that works. I actually tried org.jboss.ws.cxf:jbossws-cxf-client artifact 4.1.1.Final earlier but did not remove the existing CXF dependencis. After i removed them and only left org.jboss.ws.cxf:jbossws-cxf-client artifact its working fine now.

                         

                        Thanks for the help.

                         

                        Stephen

                        • 9. Re: Creating a JBossWS CXF client using HTTPS WSDL url triggers "Failed to create service." exception
                          asoldano

                          good. Btw, I've just remembered that I wrote a section in the doc on this (client dependencies setup) some months ago, adding a link just in case someone else is having similar doubts: https://docs.jboss.org/author/display/JBWS/Quick+Start#QuickStart-Resolvingdependenciesandrunningtheclient