[[WS-Reliable_Messaging]]
= WS-Reliable Messaging
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
http://schemas.xmlsoap.org/ws/2005/02/rm/[WS-Reliable Messaging 1.0]
(February 2005) version of the specification.
[[enabling-ws-reliable-messaging]]
== 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
http://cxf.apache.org/docs/wsrmconfiguration.html[Apache CXF
documentation].
[[example]]
== Example
In this example we configure WS-Reliable Messaging endpoint and client
through the WS-Policy support.
[[endpoint]]
=== 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):
[source, xml]
----
----
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:
[source, java]
----
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]]
=== 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.
[source, java]
----
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]]
=== Additional configuration
Fine-grained tuning of WS-Reliable Messaging engine requires setting up
proper RM features and attach them for instance to the client proxy.
Here is an example:
[source, java]
----
package org.jboss.test.ws.jaxws.samples.wsrm.client;
//...
import javax.xml.ws.Service;
import org.apache.cxf.ws.rm.feature.RMFeature;
import org.apache.cxf.ws.rm.manager.AcksPolicyType;
import org.apache.cxf.ws.rm.manager.DestinationPolicyType;
import org.jboss.test.ws.jaxws.samples.wsrm.generated.SimpleService;
// ...
Service service = Service.create(wsdlURL, serviceName);
RMFeature feature = new RMFeature();
RMAssertion rma = new RMAssertion();
RMAssertion.BaseRetransmissionInterval bri = new RMAssertion.BaseRetransmissionInterval();
bri.setMilliseconds(4000L);
rma.setBaseRetransmissionInterval(bri);
AcknowledgementInterval ai = new AcknowledgementInterval();
ai.setMilliseconds(2000L);
rma.setAcknowledgementInterval(ai);
feature.setRMAssertion(rma);
DestinationPolicyType dp = new DestinationPolicyType();
AcksPolicyType ap = new AcksPolicyType();
ap.setIntraMessageThreshold(0);
dp.setAcksPolicy(ap);
feature.setDestinationPolicy(dp);
SimpleService proxy = (SimpleService)service.getPort(SimpleService.class, feature);
proxy.echo("Hello World");
----
The same can of course be achieved by factoring the feature into a
custom pojo extending `org.apache.cxf.ws.rm.feature.RMFeature` and
setting the obtained property in a client configuration:
[source, java]
----
package org.jboss.test.ws.jaxws.samples.wsrm.client;
import org.apache.cxf.ws.rm.feature.RMFeature;
import org.apache.cxf.ws.rm.manager.AcksPolicyType;
import org.apache.cxf.ws.rm.manager.DestinationPolicyType;
import org.apache.cxf.ws.rmp.v200502.RMAssertion;
import org.apache.cxf.ws.rmp.v200502.RMAssertion.AcknowledgementInterval;
public class CustomRMFeature extends RMFeature
{
public CustomRMFeature() {
super();
RMAssertion rma = new RMAssertion();
RMAssertion.BaseRetransmissionInterval bri = new RMAssertion.BaseRetransmissionInterval();
bri.setMilliseconds(4000L);
rma.setBaseRetransmissionInterval(bri);
AcknowledgementInterval ai = new AcknowledgementInterval();
ai.setMilliseconds(2000L);
rma.setAcknowledgementInterval(ai);
super.setRMAssertion(rma);
DestinationPolicyType dp = new DestinationPolicyType();
AcksPolicyType ap = new AcksPolicyType();
ap.setIntraMessageThreshold(0);
dp.setAcksPolicy(ap);
super.setDestinationPolicy(dp);
}
}
----
... this is how the `jaxws-client-config.xml` descriptor would look:
[source,xml]
----
Custom Client Config
cxf.features
org.jboss.test.ws.jaxws.samples.wsrm.client.CustomRMFeature
----
... and this is how the client would set the configuration:
[source, java]
----
import org.jboss.ws.api.configuration.ClientConfigUtil;
import org.jboss.ws.api.configuration.ClientConfigurer;
//...
Service service = Service.create(wsdlURL, serviceName);
SimpleService proxy = (SimpleService)service.getPort(SimpleService.class);
ClientConfigurer configurer = ClientConfigUtil.resolveClientConfigurer();
configurer.setConfigProperties(proxy, "META-INF/jaxws-client-config.xml", "Custom Client Config");
proxy.echo("Hello World!");
----