8.3.  Turning on WS-RM 1.0

Four steps are necessary to turn on WS-RM in JBossWS-CXF. They are outline below.
  • Extend WSDL with WS-Policy containing both WSRM and WS-Addressing policy.
  • Provide jbossws-cxf.xml endpoint configuration file.
  • Provide client CXF configuration.
  • Update client code to read CXF configuration file.
Extending WSDL Using WS-Policy

To activate WSRM we need to extend WSDL with WSRM and addressing policy. Here is how it looks:

 
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="SimpleService" targetNamespace="http://www.jboss.org/jbossws/ws-extensions/wsrm" xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/wsrm" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsp="http://www.w3.org/2006/07/ws-policy">

  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - -->
  <!-- Created WS-Policy with WSRM addressing assertions -->
  <!-- - - - - - - - - - - - - - - - - - - - - - - - - - -->
  <wsp:UsingPolicy/>
  <wsp:Policy wsu:Id="wsrm10policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <wswa:UsingAddressing xmlns:wswa="http://www.w3.org/2006/05/addressing/wsdl">
      <wsp:Policy/>
    <wswa:UsingAddressing>
    <wsrmp:RMAssertion xmlns:wsrmp="http://schemas.xmlsoap.org/ws/2005/02/rm/policy"/>
  </wsp:Policy>
  
  <wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/wsrm" attributeFormDefault="unqualified" elementFormDefault="unqualified" targetNamespace="http://www.jboss.org/jbossws/ws-extensions/wsrm">
<xsd:element name="ping" type="tns:ping"/>
<xsd:complexType name="ping">
<xsd:sequence/>
</xsd:complexType>
<xsd:element name="echo" type="tns:echo"/>
<xsd:complexType name="echo">
<xsd:sequence>
<xsd:element minOccurs="0" name="arg0" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="echoResponse" type="tns:echoResponse"/>
<xsd:complexType name="echoResponse">
<xsd:sequence>
<xsd:element minOccurs="0" name="return" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
  </wsdl:types>
  <wsdl:message name="echoResponse">
    <wsdl:part name="parameters" element="tns:echoResponse">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="echo">
    <wsdl:part name="parameters" element="tns:echo">
    </wsdl:part>
  </wsdl:message>
  <wsdl:message name="ping">
    <wsdl:part name="parameters" element="tns:ping">
    </wsdl:part>
  </wsdl:message>
  <wsdl:portType name="SimpleService">
    <wsdl:operation name="ping">
      <wsdl:input name="ping" message="tns:ping">
    </wsdl:input>
    </wsdl:operation>
    <wsdl:operation name="echo">
      <wsdl:input name="echo" message="tns:echo">
    </wsdl:input>
      <wsdl:output name="echoResponse" message="tns:echoResponse">
    </wsdl:output>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="SimpleServiceSoapBinding" type="tns:SimpleService">
    <!-- - - - - - - - - - - - - - - - - - - - -->
    <!-- Associated WS-Policy with the binding -->
    <!-- - - - - - - - - - - - - - - - - - - - -->
    <wsp:PolicyReference URI="#wsrm10policy"/>
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="ping">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="ping">
        <soap:body use="literal"/>
      </wsdl:input>
    </wsdl:operation>
    <wsdl:operation name="echo">
      <soap:operation soapAction="" style="document"/>
      <wsdl:input name="echo">
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="echoResponse">
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="SimpleService">
    <wsdl:port name="SimpleServicePort" binding="tns:SimpleServiceSoapBinding">
      <soap:address location="http://localhost:9090/hello"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

We added wsp:UsingPolicy;wsp:Policy and wsp:PolicyReference elements to WSDL.
Providing jbossws-cxf.xml Endpoint Configuration File

This is the JBossWS CXF integration extension file: Chapter 3, Server Side Integration Customization . In our case, the relevant content is as follows:

  
<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:jaxws='http://cxf.apache.org/jaxws'
  xmlns:wsp='http://www.w3.org/2006/07/ws-policy'
  xmlns:p='http://cxf.apache.org/policy'
  xsi:schemaLocation='http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
    http://cxf.apache.org/policy
    http://cxf.apache.org/schemas/policy.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'>
  
  <wsp:Policy wsu:Id="wsrm10policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <wswa:UsingAddressing xmlns:wswa="http://www.w3.org/2006/05/addressing/wsdl"/>
    <wsrmp:RMAssertion xmlns:wsrmp="http://schemas.xmlsoap.org/ws/2005/02/rm/policy"/>
  </wsp:Policy>
  
  <jaxws:endpoint
    id='SimpleServiceImpl'
    address='http://localhost:8080/jaxws-samples-wsrm'
    implementor='org.jboss.test.ws.jaxws.samples.wsrm.service.SimpleServiceImpl'>
    <jaxws:invoker>
      <bean class='org.jboss.wsf.stack.cxf.InvokerJSE'/>
    </jaxws:invoker>
    <jaxws:features>
      <p:policies>
        <wsp:PolicyReference URI="#wsrm10policy" xmlns:wsp="http://www.w3.org/2006/07/ws-policy"/>
      </p:policies>
    </jaxws:features>
  </jaxws:endpoint>
  
</beans>

We need to include this jbossws-cxf.xml CXF configuration file in the WEB-INF directory of the endpoint archive because we are creating a POJO deployment.
jar -tvf jaxws-samples-wsrm.war 
     0 Wed Apr 16 19:05:38 CEST 2008 META-INF/
   106 Wed Apr 16 19:05:36 CEST 2008 META-INF/MANIFEST.MF
     0 Wed Apr 16 19:05:38 CEST 2008 WEB-INF/
   591 Wed Apr 16 19:05:36 CEST 2008 WEB-INF/web.xml
     0 Wed Apr 16 19:05:38 CEST 2008 WEB-INF/classes/
     0 Wed Apr 16 19:05:32 CEST 2008 WEB-INF/classes/org/
     0 Wed Apr 16 19:05:32 CEST 2008 WEB-INF/classes/org/jboss/
     0 Wed Apr 16 19:05:32 CEST 2008 WEB-INF/classes/org/jboss/test/
     0 Wed Apr 16 19:05:32 CEST 2008 WEB-INF/classes/org/jboss/test/ws/
     0 Wed Apr 16 19:05:34 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/
     0 Wed Apr 16 19:05:34 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/
     0 Wed Apr 16 19:05:34 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/
     0 Wed Apr 16 19:05:34 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/
     0 Wed Apr 16 19:05:34 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/
  1235 Wed Apr 16 19:05:34 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/SimpleServiceImpl.class
   997 Wed Apr 16 19:05:34 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/Echo.class
  1050 Wed Apr 16 19:05:34 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/EchoResponse.class
   679 Wed Apr 16 19:05:34 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsrm/service/jaxws/Ping.class
  1554 Wed Apr 16 19:05:36 CEST 2008 WEB-INF/jbossws-cxf.xml
     0 Wed Apr 16 19:05:38 CEST 2008 WEB-INF/wsdl/
  3237 Wed Apr 16 19:05:36 CEST 2008 WEB-INF/wsdl/SimpleService.wsdl
The next step is to create the client CXF configuration file that will be used by the client. It activates the WS-RM protocol for the CXF client. We will name this file cxf.xml in our sample. The content of this file is as follows:
     
<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:cxf="http://cxf.apache.org/core"
  xmlns:wsa="http://cxf.apache.org/ws/addressing"
  xmlns:http="http://cxf.apache.org/transports/http/configuration"
  xmlns:wsrm-policy="http://schemas.xmlsoap.org/ws/2005/02/rm/policy"
  xmlns:wsrm-mgr="http://cxf.apache.org/ws/rm/manager"
  xsi:schemaLocation="
    http://cxf.apache.org/core
    http://cxf.apache.org/schemas/core.xsd
    http://cxf.apache.org/transports/http/configuration
    http://cxf.apache.org/schemas/configuration/http-conf.xsd
    http://schemas.xmlsoap.org/ws/2005/02/rm/policy
    http://schemas.xmlsoap.org/ws/2005/02/rm/wsrm-policy.xsd
    http://cxf.apache.org/ws/rm/manager
    http://cxf.apache.org/schemas/configuration/wsrm-manager.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">
 
  <cxf:bus>
    <cxf:features>
      <cxf:logging/>
      <wsa:addressing/>
      <wsrm-mgr:reliableMessaging>
        <wsrm-policy:RMAssertion>
          <wsrm-policy:BaseRetransmissionInterval Milliseconds="4000"/>           
          <wsrm-policy:AcknowledgementInterval Milliseconds="2000"/>          
        </wsrm-policy:RMAssertion>
        <wsrm-mgr:destinationPolicy>
          <wsrm-mgr:acksPolicy intraMessageThreshold="0" />
        </wsrm-mgr:destinationPolicy>
      </wsrm-mgr:reliableMessaging>
    </cxf:features>
  </cxf:bus>
    
</beans>

We are almost done. The client configuration needs to be picked up by the client classloader. In order to achieve that the cxf.xml has to be put in the META-INF directory of client jar. That jar should then be provided when setting the class loader.
Alternatively you can read the bus configuration programmatically.
Updating Client Code to Read Bus Configuration File

Here's the last piece of the updated CXF client:

  
package org.jboss.test.ws.jaxws.samples.wsrm.client;
 
import java.net.URL;
import java.io.File;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.bus.spring.SpringBusFactory;
import org.jboss.test.ws.jaxws.samples.wsrm.generated.SimpleService;
 
public final class SimpleServiceTestCase
{
 
   private static final String serviceURL = "http://localhost:8080/jaxws-samples-wsrm/SimpleService";
   
   public static void main(String[] args) throws Exception
   {
      // create bus
      SpringBusFactory busFactory = new SpringBusFactory();
      URL cxfConfig = new File("resources/jaxws/samples/wsrm/cxf.xml").toURL();
      Bus bus = busFactory.createBus(cxfConfig);
      busFactory.setDefaultBus(bus);
 
      // create service
      QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/wsrm", "SimpleService");
      URL wsdlURL = new URL(serviceURL + "?wsdl");
      Service service = Service.create(wsdlURL, serviceName);
      SimpleService proxy = (SimpleService)service.getPort(SimpleService.class);
      
      // invoke methods
      proxy.ping(); // one way call
      proxy.echo("Hello World!"); // request responce call
 
      // shutdown bus
      bus.shutdown(true);
   }
   
}