Version 6
    Since 3.2.1 (CXF)

    JBossWS-CXF supports JMS Transport to transfer SOAP messages. There is a testcase in the codebase to demonstrate this ability, available here. In this tutorial, we will use a wsdl first web service example to show you how to enable this feature in JBossWS.

     

    WSDL

    <wsdl:definitions name="OrganizationJMSEndpointService" targetNamespace="http://org.jboss.ws/samples/jmstransport" xmlns:jms="http://cxf.apache.org/transports/jms" xmlns:ns1="http://schemas.xmlsoap.org/wsdl/soap/http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://org.jboss.ws/samples/jmstransport" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <wsdl:message name="getContactInfoResponse">
        <wsdl:part name="return" type="xsd:string">
        </wsdl:part>
      </wsdl:message>
      <wsdl:message name="getContactInfo">
        <wsdl:part name="arg0" type="xsd:string">
        </wsdl:part>
      </wsdl:message>
      <wsdl:portType name="Organization">
        <wsdl:operation name="getContactInfo">
          <wsdl:input message="tns:getContactInfo" name="getContactInfo">
        </wsdl:input>
          <wsdl:output message="tns:getContactInfoResponse" name="getContactInfoResponse">
        </wsdl:output>
        </wsdl:operation>
      </wsdl:portType>
      <wsdl:binding name="HTTPSoapBinding" type="tns:Organization">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="getContactInfo">
          <soap:operation soapAction="" style="rpc"/>
          <wsdl:input name="getContactInfo">
            <soap:body namespace="http://org.jboss.ws/samples/jmstransport" use="literal"/>
          </wsdl:input>
          <wsdl:output name="getContactInfoResponse">
            <soap:body namespace="http://org.jboss.ws/samples/jmstransport" use="literal"/>
          </wsdl:output>
        </wsdl:operation>
      </wsdl:binding>
    
      <wsdl:binding name="JMSSoapBinding" type="tns:Organization">
        <soap:binding style="rpc" transport="http://cxf.apache.org/transports/jms"/>
        <wsdl:operation name="getContactInfo">
          <soap:operation soapAction="" style="rpc"/>
          <wsdl:input name="getContactInfo">
            <soap:body namespace="http://org.jboss.ws/samples/jmstransport" use="literal"/>
          </wsdl:input>
          <wsdl:output name="getContactInfoResponse">
            <soap:body namespace="http://org.jboss.ws/samples/jmstransport" use="literal"/>
          </wsdl:output>
        </wsdl:operation>
      </wsdl:binding>
    
    
      <wsdl:service name="OrganizationService">
        <wsdl:port binding='tns:HTTPSoapBinding' name='HttpEndpointPort'>
          <soap:address location='http://@jboss.bind.address@:8080/jaxws-samples-jmstransport'/>
        </wsdl:port>
        <wsdl:port binding="tns:JMSSoapBinding" name="JmsEndpointPort">
               <jms:address
                       destinationStyle="queue"
                       jndiConnectionFactoryName="ConnectionFactory" 
                       jndiDestinationName="queue/RequestQueue"
                       jndiReplyDestinationName="queue/ResponseQueue">
                       >                   
                    </jms:address>    
            </wsdl:port>
      </wsdl:service>
    </wsdl:definitions>
    
    
    
    

     

    Apache CXF defines the jms wsdl extension, so the jms queue name or other information about jms in wsdl port can be parsed to send or receive jms message. Check this wiki page to see what jms attributes you can defined in WSDL.  In this wsdl, we define two queues to send and receive the soap message. CXF uses JNDI to look up the jms ConnectionFactory, so we may also need to provide the JNDI properties as the following example :

     

    <jms:address
        destinationStyle="queue"
        jndiConnectionFactoryName="ConnectionFactory" 
        jndiDestinationName="queue/RequestQueue"
        jndiReplyDestinationName="queue/ResponseQueue"
        >
        <jms:JMSNamingProperty name="java.naming.factory.initial"
                               value="org.jnp.interfaces.NamingContextFactory"/>
        <jms:JMSNamingProperty name="java.naming.provider.url"
                               value="jnp://localhost:1099"/>
    </jms:address>
    

     

    Service Implementation

     

    After generated code from this wsdl , we wrote two class to implement this interface for this two ports . We annotate the portName in annotation to tell web service stack
    which transport this service uses :

     

    @WebService (serviceName="OrganizationService", portName="HttpEndpointPort",wsdlLocation = "WEB-INF/wsdl/jmstransport.wsdl",targetNamespace = "http://org.jboss.ws/samples/jmstransport", endpointInterface="org.jboss.test.ws.jaxws.samples.jmstransport.Organization")
    @SOAPBinding(style = SOAPBinding.Style.RPC)
    
    public class OrganizationHttpEndpoint implements Organization
    { 
       @WebMethod
       public String getContactInfo(String organization)
       {
          return "The '" + organization + "' boss is currently out of office, please call again.";
       }
    }
    
    
    
    

     

     

     

    @WebService (serviceName="OrganizationService",portName="JmsEndpointPort", wsdlLocation = "WEB-INF/wsdl/jmstransport.wsdl", targetNamespace = "http://org.jboss.ws/samples/jmstransport", endpointInterface="org.jboss.test.ws.jaxws.samples.jmstransport.Organization")
    @SOAPBinding(style = SOAPBinding.Style.RPC)
    
    public class OrganizationJmsEndpoint implements Organization
    { 
       @WebMethod
       public String getContactInfo(String organization)
       {
          return "The '" + organization + "' boss is currently out of office, please call again.";
       }
    }
    
    
    
    

     

    web.xml

     

    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
      version="2.4">
    
      <servlet>
        <servlet-name>OrganizationService</servlet-name>
        <servlet-class>org.jboss.test.ws.jaxws.samples.jmstransport.OrganizationHttpEndpoint</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
    
      <servlet-mapping>
        <servlet-name>OrganizationService</servlet-name>
        <url-pattern>/*</url-pattern>
      </servlet-mapping>
    
    </web-app>
    
    
    
    

     

    It is almost the same as the usual web.xml to deploy a web service except the <load-on-startup> servlet initialize
    parameter. This is for jms service start ready when deployment, no need to wait until the first servlet request to
    start the jms endpoint.

     

    jbossws-cxf.xml

    In addition to web.xml,  the jbossws-cxf.xml is needed to actually pass in cxf to start this two port.

     

    <beans xmlns='http://www.springframework.org/schema/beans'
        xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:beans='http://www.springframework.org/schema/beans'
            xmlns:jms="http://cxf.apache.org/transports/jms"
        xmlns:jaxws='http://cxf.apache.org/jaxws'
        xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
      http://www.w3.org/2006/07/ws-policy http://www.w3.org/2006/07/ws-policy.xsd 
      http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
      http://cxf.apache.org/transports/jms http://cxf.apache.org/schemas/configuration/jms.xsd'>
    
            <import resource="classpath:META-INF/cxf/cxf-extension-jms.xml"/>    
        <jaxws:endpoint id='SOAPQueryService'
            implementor='org.jboss.test.ws.jaxws.samples.jmstransport.OrganizationHttpEndpoint'
                    >
            <jaxws:invoker>
                <bean class='org.jboss.wsf.stack.cxf.InvokerJSE'/>
            </jaxws:invoker>
        </jaxws:endpoint>
    
        <jaxws:endpoint id='JMSQueryService'
            implementor='org.jboss.test.ws.jaxws.samples.jmstransport.OrganizationJmsEndpoint'
                    transportId="http://cxf.apache.org/transports/jms">
        </jaxws:endpoint>
    </beans> 
    
    
    
    

     

    Note: the import resource is the JmsTransportFactory configuration . It is required to jms transport enablement .

     

    Below gives the war file directory structure to make it more clear what inside :

    |-- jmstransport-sample.war 
    `-- WEB-INF
        |-- classes
        |   `-- org
        |       `-- jboss
        |           `-- test
        |               `-- ws
        |                   `-- jaxws
        |                       `-- samples
        |                           `-- jmstransport
        |                               |-- JMSTransportTestCase$ResponseListener.class
        |                               |-- JMSTransportTestCase.class
        |                               |-- Organization.class
        |                               |-- OrganizationHttpEndpoint.class
        |                               `-- OrganizationJmsEndpoint.class
        |-- jboss-web.xml
        |-- jbossws-cxf.xml
        |-- web.xml
        `-- wsdl
            `-- jmstransport.wsdl