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); } }