JBoss Web Services inherits full WS-Reliable Messaging capabilities from the underlying Apache CXF implementation. At the time of writing, Apache CXF provides support for the WS-Reliable Messaging 1.0 (February 2005) version of the specification.
Enabling WS-Reliable Messaging
WS-Reliable Messaging is implemented internally in Apache CXF through a set of interceptors that deal with the low level requirements of the reliable messaging protocol. In order for enabling WS-Reliable Messaging, users need to either:
-
consume a WSDL contract that specifies proper WS-Reliable Messaging policies / assertions
-
manually add / configure the reliable messaging interceptors
-
specify the reliable messaging policies in an optional CXF Spring XML descriptor
-
specify the Apache CXF reliable messaging feature in an optional CXF Spring XML descriptor
The former approach relies on the Apache CXF WS-Policy engine and is the only portable one. The other approaches are Apache CXF proprietary ones, however they allow for fine-grained configuration of protocol aspects that are not covered by the WS-Reliable Messaging Policy. More details are available in the Apache CXF documentation.
Example
In this example we configure WS-Reliable Messaging endpoint and client through the WS-Policy support.
Endpoint
We go with a contract-first approach, so we start by creating a proper WSDL contract, containing the WS-Reliable Messaging and WS-Addressing policies (the latter is a requirement of the former):
<?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">
<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">
<wsp:Policy>
<!-- WS-Addressing and basic WS-Reliable Messaging policy assertions -->
<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>
<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:8080/jaxws-samples-wsrm-api"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Then we use the wsconsume tool to generate both standard JAX-WS client and endpoint.
We provide a basic JAX-WS implementation for the endpoint, nothing special in it:
package org.jboss.test.ws.jaxws.samples.wsrm.service;
import javax.jws.Oneway;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
(
name = "SimpleService",
serviceName = "SimpleService",
wsdlLocation = "WEB-INF/wsdl/SimpleService.wsdl",
targetNamespace = "http://www.jboss.org/jbossws/ws-extensions/wsrm"
)
public class SimpleServiceImpl
{
@Oneway
@WebMethod
public void ping()
{
System.out.println("ping()");
}
@WebMethod
public String echo(String s)
{
System.out.println("echo(" + s + ")");
return s;
}
}
Finally we package the generated POJO endpoint together with a basic web.xml the usual way and deploy to the application server. The webservices stack automatically detects the policies and enables WS-Reliable Messaging.
Client
The endpoint advertises his RM capabilities (and requirements) through the published WSDL and the client is required to also enable WS-RM for successfully exchanging messages with the server.
So a regular JAX WS client is enough if the user does not need to tune any specific detail of the RM subsystem.
QName serviceName = new QName("http://www.jboss.org/jbossws/ws-extensions/wsrm", "SimpleService");
URL wsdlURL = new URL("http://localhost:8080/jaxws-samples-wsrm-api?wsdl");
Service service = Service.create(wsdlURL, serviceName);
proxy = (SimpleService)service.getPort(SimpleService.class);
proxy.echo("Hello World!");
Additional configuration
Fine-grained tuning of WS-Reliable Messaging engine requires setting up proper RM features in the Bus using a Spring XML descriptor; here is an example:
<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
The client needs to pick up the bus configuration such as below:
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.jboss.wsf.stack.cxf.client.configuration.JBossWSBusFactory;
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
{
URL cxfConfig = new File("resources/jaxws/samples/wsrm/cxf.xml").toURL();
Bus bus = new JBossWSBusFactory().createBus(cxfConfig);
try
{
BusFactory.setThreadDefaultBus(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.echo("Hello World!");
}
finally
{
// shutdown bus
bus.shutdown(true);
}
}
}