Is Webservice Reliable Messaging (WS-RM) the ugly duck of the WS-* story ?

The Webservice Reliable Messaging (WS-RM) specification has been designed a couple of years ago (2005) but few projects used it. Different reasons could explain this situation, the complexity of the specification, the cost to implement it and the lack of use cases. Personally, I think that developers and architects adopt a low profile when designing a solution and spend times developing alternative solutions providing functionality similar to what WS-RM propose.

WS-RM is not the ugly duck of the story and need more attention from community because it allows you to design solutions where you will be able to

  • Guaranty message (= web services) delivery, which is required by example in financial order processing, alarm monitoring systems, …
  • Control the communication between the client and the server (retransmission, …)
  • Implement asynchronous solution by decoupling the request from the reply

Well, what I have presented could be assimilated to a style exercise or a faith act and you will adhere or not. To convince you about the interests to use WS-RM, I will show you How easy it is to design such a solution using Apache CXF framework. This process can be achieved in three simple steps

STEP 1 : Turn on your WSDL contract into a WS-addressing

WS-addressing needs to be used because the communication between the client and server will be governed by the Reliable Message Server which is running on a different port address number. This decoupling is required to allow to retransmit message, acknowledge the messages received and guaranty the delivery

Here is one way that you can adopt :

<!-- Service definition -->
<wsdl:service name="ReportIncidentEndpointService">
  <wsdl:port name="ReportIncidentPort" binding="tns:ReportIncidentBinding">
    <soap:address location="http://localhost:8080/cxf/camel-example/incident">
      <!-- <wswa:usingaddressing wswa="http://www.w3.org/2005/02/addressing/wsdl"> -->
      <wswa:usingaddressing wswa="http://www.w3.org/2005/02/addressing/wsdl"></wswa:usingaddressing>
    </soap:address>
  </wsdl:port>
</wsdl:service>

the other consists in to use a Policy Rule (= WS-Policy)

<wsp:policy wsp="http://www.w3.org/2006/07/ws-policy">
  <wsam:addressing wsam="http://www.w3.org/2007/02/addressing/metadata">
    <wsp:policy></wsp:policy>
  </wsam:addressing>
</wsp:policy>

STEP 2 : Activate the Reliable Server

Now that the WSDL contract is modified, we need to add the Reliable Server to the configuration of our platform. I will show you using a spring xml configuration file but you can use the Apache CXF classes in your java code if you want

To activate the RM server, you simply needs to add the tags wsa:addressing and wsrm-mgr in the bus definition of Apache CXF. Different parameters are available like retransmission interval, acknowledge interval. I will not digg into these ones and if you need information, I invite you to check Apache CXF javadoc and specifications.

By example< it is possible to activate also the persistence manager of the RM server ;-)

<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:acknowledgementinterval>
              <wsrm-mgr:destinationpolicy>
                <wsrm-mgr:ackspolicy intramessagethreshold="0"></wsrm-mgr:ackspolicy>
              </wsrm-mgr:destinationpolicy>
            </wsrm-policy:baseretransmissioninterval>
          </wsrm-policy:rmassertion>
        </wsrm-mgr:reliablemessaging>
      </wsa:addressing>
    </cxf:logging>
  </cxf:features>
</cxf:bus>

If you use CXF in combination with the Routing engine Apache Camel, you don’t need to do additional things as the Apache CXF endpoint who will consume the web servicesmessages will be drived by the RM server of CXF.

Here is an example of Camel integration with CXF

<!-- webservice endpoint -->
<cxfcamel:cxfendpoint id="reportIncident" address="http://localhost:8080/cxf/camel-example/incident" serviceclass="org.apache.camel.example.reportincident.ReportIncidentEndpoint" s="http://reportincident.example.camel.apache.org"></cxfcamel:cxfendpoint>
<!-- Camel route -->
<camel:camelcontext trace="true" xmlns="http://camel.apache.org/schema/osgi">
  <route>
    <from uri="cxf:bean:reportIncident">// messages are consumed from CXF endpoint
      <convertbodyto type="org.apache.camel.example.reportincident.InputReportIncident">// the body of the WS message is converted directly into a POJOI
        <to uri="bean:webservice">// We call a POJO to save the reportincident in a DB
          <inOnly uri="osgiqueuingservice:queue:in">
          // We put the object in a queue
          <transform>
            <method bean="feedback" method="setOk">// We provide a feedback message as the WS is of type request/replyt</method>
          </transform>
        </to>
      </to>
    </convertbodyto>
  </from>
</route>
</camel:camelcontext> 

STEP : Verify

If you use a java client using Apache CXF java classes, you can easily enable the logging of the IN/OUT WS messages exchanged with the RM server and the application.

The following trace shows that :

  • a sequence has been started
  • each message is identified ‘’ with a UID
  • Within a sequence, the messages send receive a messageID
  • The server acknowledge the reception (= processing) of the messages

Conclusion

Awesome, isn’it. Even, if you continue to doubt about this specification, I’m pretty sure that in the future you will take it into account into your decision process regarding to what has been developed here.