[[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!"); ----