5 Replies Latest reply on Aug 29, 2011 9:51 AM by rjbaty

    Support for SOAP Header elements on JBossAS 7.0.1

    rjbaty

      Been further getting into the JBossWS-CXF implementation contained in the JBossAS 7 stack.  We have a couple endpoints that make use of a SOAP Header element in their WSDL definition.  To test this out on JBossAS 7 I created a sample service to ensure this was still supported.  The sections of my example WSDL file for this are shown below:

       

        <message name="register">
          <part name="parameters" element="tns:register"/>
          <part name="RJBHeader" element="tns:RJBHeader"/>
        </message>
        <message name="registerResponse">
          <part name="result" element="tns:registerResponse"/>
        </message>
        <portType name="AutoRegister">
          <operation name="register" parameterOrder="parameters RJBHeader">
            <input message="tns:register"/>
            <output message="tns:registerResponse"/>
          </operation>
        </portType>
        <binding name="AutoRegisterBinding" type="tns:AutoRegister">
          <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
          <operation name="register">
            <soap:operation soapAction=""/>
            <input>
              <soap:body use="literal" parts="parameters"/>
              <soap:header message="tns:register" part="RJBHeader" use="literal"/>
            </input>
            <output>
              <soap:body use="literal"/>
            </output>
          </operation>
        </binding>
      

       

      The RJBHeader is the POJO that gets sent in the SOAP Header section, nothing complex so I didn't include it here.  When this WSDL is generated using CXF it creates what I believe is referred to as a Doc/Lit Bare endpoint like this.

       

       

      /**
       * This class was generated by Apache CXF 2.4.1
       * 2011-08-25T10:09:59.082-05:00
       * Generated source version: 2.4.1
       * 
       */
      @WebService(targetNamespace = "http://header.ws4.rjb", name = "AutoRegister")
      @XmlSeeAlso({ObjectFactory.class})
      @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
      public interface AutoRegister {
      
          @WebResult(name = "registerResponse", targetNamespace = "http://header.ws4.rjb", partName = "result")
          @WebMethod
          public RegisterResponse register(
              @WebParam(partName = "parameters", name = "register", targetNamespace = "http://header.ws4.rjb")
              Register parameters,
              @WebParam(partName = "RJBHeader", name = "RJBHeader", targetNamespace = "http://header.ws4.rjb", header = true)
              RjbHeader rjbHeader
          );
      }
      

       

      I think the generation does this because of the Header element but I am not sure.  At any rate, this endpoint deploys fine and things are good.

       

      Taking this WSDL, generating a servlet client and running it I seem to be getting an issue when trying to create the Servcie and Port classes.

       

      15:55:15,473 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/rjbWS4Client].[AutoRegisterClientServlet]] (http--0.0.0.0-8080-2) Servlet.service() for servlet AutoRegisterClientServlet threw exception: java.lang.NoClassDefFoundError: javax.wsdl.extensions.soap12.SOAP12HeaderFault from [Module "deployment.RJBatyWebServiceEAR-4.1.ear.RJBatyWebService4Client-4.1.war:main" from Service Module Loader]
          at $Proxy99.<clinit>(Unknown Source)    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [:1.6.0_21]
          at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) [:1.6.0_21]
          at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) [:1.6.0_21]
          at java.lang.reflect.Constructor.newInstance(Unknown Source) [:1.6.0_21]
          at java.lang.reflect.Proxy.newProxyInstance(Unknown Source) [:1.6.0_21]
          at org.apache.cxf.tools.util.SOAPBindingUtil.getProxy(SOAPBindingUtil.java:89) [cxf-tools-common-2.4.1.jar:2.4.1]
          at org.apache.cxf.tools.util.SOAPBindingUtil.getSoapHeader(SOAPBindingUtil.java:229) [cxf-tools-common-2.4.1.jar:2.4.1]
          at org.apache.cxf.binding.soap.SoapBindingFactory.addMessageFromBinding(SoapBindingFactory.java:444) [cxf-rt-bindings-soap-2.4.1.jar:2.4.1]
          at org.apache.cxf.binding.AbstractBindingFactory.copyExtensors(AbstractBindingFactory.java:120) [cxf-rt-core-2.4.1.jar:2.4.1]
          at org.apache.cxf.binding.AbstractBindingFactory.initializeBindingInfo(AbstractBindingFactory.java:99) [cxf-rt-core-2.4.1.jar:2.4.1]
          at org.apache.cxf.binding.soap.SoapBindingFactory.createBindingInfo(SoapBindingFactory.java:625) [cxf-rt-bindings-soap-2.4.1.jar:2.4.1]
          at org.apache.cxf.wsdl11.WSDLServiceBuilder.buildBinding(WSDLServiceBuilder.java:487) [cxf-rt-core-2.4.1.jar:2.4.1]
          at org.apache.cxf.wsdl11.WSDLServiceBuilder.buildServices(WSDLServiceBuilder.java:349) [cxf-rt-core-2.4.1.jar:2.4.1]
          at org.apache.cxf.wsdl11.WSDLServiceBuilder.buildServices(WSDLServiceBuilder.java:198) [cxf-rt-core-2.4.1.jar:2.4.1]
          at org.apache.cxf.wsdl11.WSDLServiceFactory.create(WSDLServiceFactory.java:142) [cxf-rt-core-2.4.1.jar:2.4.1]
          at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFromWSDL(ReflectionServiceFactoryBean.java:382) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
          at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:499) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
          at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:241) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
          at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:202) [cxf-rt-frontend-jaxws-2.4.1.jar:2.4.1]
          at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:101) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
          at org.apache.cxf.frontend.ClientFactoryBean.create(ClientFactoryBean.java:90) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
          at org.apache.cxf.frontend.ClientProxyFactoryBean.create(ClientProxyFactoryBean.java:152) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
          at org.apache.cxf.jaxws.JaxWsProxyFactoryBean.create(JaxWsProxyFactoryBean.java:142) [cxf-rt-frontend-jaxws-2.4.1.jar:2.4.1]
          at org.apache.cxf.jaxws.ServiceImpl.createPort(ServiceImpl.java:464) [cxf-rt-frontend-jaxws-2.4.1.jar:2.4.1]
          at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:331) [cxf-rt-frontend-jaxws-2.4.1.jar:2.4.1]
          at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:318) [cxf-rt-frontend-jaxws-2.4.1.jar:2.4.1]
          at javax.xml.ws.Service.getPort(Service.java:99) [jboss-jaxws-api_2.2_spec-2.0.0.Final.jar:2.0.0.Final]
          at rjb.ws4.header.AutoRegisterService.getAutoRegisterPort(AutoRegisterService.java:78) [classes:]
      

       

      Do these type of endpoints require the WSDL12 jar libraries?  I tried to add this to my MANIFEST.MF file

       

      Dependencies: org.apache.ws.security, org.jboss.ws.cxf.jbossws-cxf-client, javax.wsdl4j.api services

       

      To get access to the javax WSDL4J classes but that seemed to screw up other service types I have.  Wondering which way to go for this.

       

      Robert

        • 1. Re: Support for SOAP Header elements on JBossAS 7.0.1
          asoldano

          If you didn't already, please try adding the services and export flag to the jbossws-cxf-client moule

           

          Dependencies: org.apache.ws.security,org.jboss.ws.cxf.jbossws-cxf-client services export, foo.bar

           

          The import of javax.wsdl4j.api module should only be required if you actually use its classes in your own code. The org.apache.cxf module already has a dependency on it, so the classloader for it should be able to see it.

          Form the stack trace above, it's not really clear to me which classloader is being used to load the wsdl4j class. Is that the full stacktrace ?

          Do you perhaps have the wsdl4j lib somewhere in your deployment(s) too?

          • 2. Re: Support for SOAP Header elements on JBossAS 7.0.1
            rjbaty

            Alessio,

            I tried the

             

            Dependencies: org.apache.ws.security,org.jboss.ws.cxf.jbossws-cxf-client services export

             

            setting in this WAR as you requested, the issue still remains.  This brings up a related question though around what the "services" and "export" flags actually mean but perhaps this is a question for the JBossAS modules team.  I thought when a WAR lists these flags in Dependencies it means the following.

             

            services - Include the listed module on my classpath as well as any of its dependent modules from the modules.xml file.

             

            export - Make this module available to other modules in JBossAS.

             

            So to me export would be used if you want to make a WAR or JAR module in your JEE deployment available to another JEE deployment but I may be completely wrong on this.  Since my JEE apps don't need this I never add "export" to my Dependency listings.

             

            But back to this wsdl4j issue.

             

            I checked my projects for wsdl4j somewhere.  This project is being built by Maven so I am seeing the wsdl4j-1.6.2.jar on the build time classpath from this dependency in the WAR.

             

            <dependency>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-api</artifactId>
                <version>2.4.1</version>
                <scope>provided</scope>
            </dependency>
            

             

            but since that is a "provided" scope I don't see the wsdl4j-1.6.2.jar in any EAR/lib or WAR/WEB-INF/lib directories of the built JEE app that gets deployed.  I also looked at the code and I don't reference a wsdl4j class anywhere.

             

            The full stack is provided below:

             

            09:10:33,814 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/rjbWS4Client].[AutoRegisterClientServlet]] (http--0.0.0.0-8080-1) Servlet.service() for servlet AutoRegisterClientServlet threw exception: java.lang.NoClassDefFoundError: javax.wsdl.extensions.soap12.SOAP12HeaderFault from [Module "deployment.RJBatyWebServiceEAR-4.1.ear.RJBatyWebService4Client-4.1.war:main" from Service Module Loader]
                at $Proxy52.<clinit>(Unknown Source)    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [:1.6.0_21]
                at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) [:1.6.0_21]
                at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) [:1.6.0_21]
                at java.lang.reflect.Constructor.newInstance(Unknown Source) [:1.6.0_21]
                at java.lang.reflect.Proxy.newProxyInstance(Unknown Source) [:1.6.0_21]
                at org.apache.cxf.tools.util.SOAPBindingUtil.getProxy(SOAPBindingUtil.java:89) [cxf-tools-common-2.4.1.jar:2.4.1]
                at org.apache.cxf.tools.util.SOAPBindingUtil.getSoapHeader(SOAPBindingUtil.java:229) [cxf-tools-common-2.4.1.jar:2.4.1]
                at org.apache.cxf.binding.soap.SoapBindingFactory.addMessageFromBinding(SoapBindingFactory.java:444) [cxf-rt-bindings-soap-2.4.1.jar:2.4.1]
                at org.apache.cxf.binding.AbstractBindingFactory.copyExtensors(AbstractBindingFactory.java:120) [cxf-rt-core-2.4.1.jar:2.4.1]
                at org.apache.cxf.binding.AbstractBindingFactory.initializeBindingInfo(AbstractBindingFactory.java:99) [cxf-rt-core-2.4.1.jar:2.4.1]
                at org.apache.cxf.binding.soap.SoapBindingFactory.createBindingInfo(SoapBindingFactory.java:625) [cxf-rt-bindings-soap-2.4.1.jar:2.4.1]
                at org.apache.cxf.wsdl11.WSDLServiceBuilder.buildBinding(WSDLServiceBuilder.java:487) [cxf-rt-core-2.4.1.jar:2.4.1]
                at org.apache.cxf.wsdl11.WSDLServiceBuilder.buildServices(WSDLServiceBuilder.java:349) [cxf-rt-core-2.4.1.jar:2.4.1]
                at org.apache.cxf.wsdl11.WSDLServiceBuilder.buildServices(WSDLServiceBuilder.java:198) [cxf-rt-core-2.4.1.jar:2.4.1]
                at org.apache.cxf.wsdl11.WSDLServiceFactory.create(WSDLServiceFactory.java:142) [cxf-rt-core-2.4.1.jar:2.4.1]
                at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFromWSDL(ReflectionServiceFactoryBean.java:382) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
                at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:499) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
                at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:241) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
                at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:202) [cxf-rt-frontend-jaxws-2.4.1.jar:2.4.1]
                at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:101) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
                at org.apache.cxf.frontend.ClientFactoryBean.create(ClientFactoryBean.java:90) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
                at org.apache.cxf.frontend.ClientProxyFactoryBean.create(ClientProxyFactoryBean.java:152) [cxf-rt-frontend-simple-2.4.1.jar:2.4.1]
                at org.apache.cxf.jaxws.JaxWsProxyFactoryBean.create(JaxWsProxyFactoryBean.java:142) [cxf-rt-frontend-jaxws-2.4.1.jar:2.4.1]
                at org.apache.cxf.jaxws.ServiceImpl.createPort(ServiceImpl.java:464) [cxf-rt-frontend-jaxws-2.4.1.jar:2.4.1]
                at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:331) [cxf-rt-frontend-jaxws-2.4.1.jar:2.4.1]
                at org.apache.cxf.jaxws.ServiceImpl.getPort(ServiceImpl.java:318) [cxf-rt-frontend-jaxws-2.4.1.jar:2.4.1]
                at javax.xml.ws.Service.getPort(Service.java:99) [jboss-jaxws-api_2.2_spec-2.0.0.Final.jar:2.0.0.Final]
                at rjb.ws4.header.AutoRegisterService.getAutoRegisterPort(AutoRegisterService.java:78) [classes:]
                at rjb.ws4.header.client.AutoRegisterClientServlet.doPost(AutoRegisterClientServlet.java:141) [classes:]
                at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
                at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) [jboss-servlet-api_3.0_spec-1.0.0.Final.jar:1.0.0.Final]
                at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:139) [jboss-as-web-7.0.1.Final.jar:7.0.1.Final]
                at org.jboss.as.web.NamingValve.invoke(NamingValve.java:57) [jboss-as-web-7.0.1.Final.jar:7.0.1.Final]
                at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:154) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:667) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:952) [jbossweb-7.0.1.Final.jar:7.0.1.Final]
                at java.lang.Thread.run(Unknown Source) [:1.6.0_21]
            
            • 3. Re: Support for SOAP Header elements on JBossAS 7.0.1
              johnbailey

              I took a little bit of time to look at this with Robert (we used to work together).  The SoapBindingUtil is attempting to load "org.apache.cxf.tools.common.extensions.soap.SoapHeader" using the TCCL, which happens to be his WAR's module in this case.  

               

              He has a dependency on "org.jboss.ws.cxf.jbossws-cxf-client" with the export flag.  So in order for it to be able to properly load that class from the WAR the "jbossws-cxf-client" would need a fully exported path to "javax.wsdl4j.api". 

               

              The only modules "org.jboss.ws.cxf.jbossws-cxf-client" exports are as follows:

                javax.xml.bind.api -- Not going to help

                com.sun.xml.bind -- Not going to help

                org.jboss.ws.api -- No exported modules

                org.jboss.ws.jaxws-client -- No exported modules

                org.apache.cxf -- No exported modules

                org.jboss.ws.cxf.jbossws-cxf-transports-httpserver  -- No exported modules

                org.jboss.jaxbintro -- Not going to help

               

               

              So I had Robert run a couple tests for me.

               

              1.  Add an exporting dependency on "javax.wsdl4j.api" modules in his WAR

                        This resolved the issue, but is not a good long term solution.  Ideally we don't want there to be an explosion of required deps in user

              2.  Add an exporting dependency on "javax.wsdl4j.api" modules in the "org.jboss.ws.cxf.jbossws-cxf-client" module

                        This resolved the issue, and is a better long term solution.

               

              I think the client module just needs to include the internal deps and make sure we can limit the users to including at most one dep.  Ideally it would be great to automatically discover they are using WS and add the client dep for them. 

              • 4. Re: Support for SOAP Header elements on JBossAS 7.0.1
                asoldano

                OK,  previously I was a bit misled by the fact the exception is generated by cxf, so I thought the cxf module classloader should have been involved in resolving the wsdlj classes. However, the cxf module classloader is not set into the TCCL when getting a port from the service (we do control the TCCL configuration from the jaxws spi Provider implementation, which is not part of the game when getting the port). Sorry about this.

                This said, I pretty much agree with John's analysis:

                 

                 

                So I had Robert run a couple tests for me.

                 

                1.  Add an exporting dependency on "javax.wsdl4j.api" modules in his WAR

                          This resolved the issue, but is not a good long term solution.  Ideally we don't want there to be an explosion of required deps in user

                Right, considering javax.wsdl4j.api is actually a pretty common one.

                 

                2.  Add an exporting dependency on "javax.wsdl4j.api" modules in the "org.jboss.ws.cxf.jbossws-cxf-client" module

                          This resolved the issue, and is a better long term solution.

                Sure, just created https://issues.jboss.org/browse/JBWS-3341

                 

                I think the client module just needs to include the internal deps and make sure we can limit the users to including at most one dep.  Ideally it would be great to automatically discover they are using WS and add the client dep for them. 

                Automatically discovering client side WS usage at deploy time is simply not doable (a ws client can be everywhere). To be honest, the real fix here would probably be to look at overwriting the Apache CXF ServiceImpl for being able to to control the TCCL during the getPort (the SOAPBindingUtil is actually fine in using TCCL there). I'll evaluate the feasibility of that. In the mean time fixing the jbossws-cxf-client module is for sure a good solution, as that's there exactly for providing a shortcut to users looking for which module dependencies to add to their deployments.

                • 5. Re: Support for SOAP Header elements on JBossAS 7.0.1
                  rjbaty

                  John and Alessio,

                  Thanks for the help on this one.  I'll track the JIRA for this resolution.

                   

                  Robert