Wednesday, October 12, 2011

Web Service Style Types

Service Styles - RPC, Document, Wrapped, and Message

http://ws.apache.org/axis/java/user-guide.html#ServiceStylesRPCDocumentWrappedAndMessage

There are four "styles" of service in Axis. RPC services use the SOAP RPC conventions, and also the SOAP "section 5" encoding. Document services do not use any encoding (so in particular, you won't see multiref object serialization or SOAP-style arrays on the wire) but DO still do XML<->Java databinding. Wrapped services are just like document services, except that rather than binding the entire SOAP body into one big structure, they "unwrap" it into individual parameters. Message services receive and return arbitrary XML in the SOAP Envelope without any type mapping / data binding. If you want to work with the raw XML of the incoming and outgoing SOAP Envelopes, write a message service.
RPC services
RPC services are the default in Axis. They are what you get when you deploy services with <service ... provider="java:RPC"> or <service ... style="RPC">. RPC services follow the SOAP RPC and encoding rules, which means that the XML for an RPC service will look like the "echoString" example above - each RPC invocation is modeled as an outer element which matches the operation name, containing inner elements each of which maps to a parameter of the operation. Axis will deserialize XML into Java objects which can be fed to your service, and will serialize the returned Java object(s) from your service back into XML. Since RPC services default to the soap section 5 encoding rules, objects will be encoded via "multi-ref" serialization, which allows object graphs to be encoded. (See the SOAP spec for more on multi-ref serialization.)
Document / Wrapped services
Document services and wrapped services are similar in that neither uses the SOAP encoding for data; it's just plain old XML schema. In both cases, however, Axis still "binds" Java representations to the XML (see the databinding section for more), so you end up dealing with Java objects, not directly with XML constructs.
A good place to start in describing the difference between document and wrapped services is with a sample SOAP message containing a purchase order:
<soap:Envelope xmlns="http://xml.apache.org/axis/wsdd/"
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  <soap:Body>
    <myNS:PurchaseOrder xmlns:myNS="http://commerce.com/PO">
      <item>SK001</item>
      <quantity>1</quantity>
      <description>Sushi Knife</description>
    </myNS:PurchaseOrder>
  </soap:Body>
</soap:Envelope>
The relevant schema for the PurchaseOrder looks like this:
<schema targetNamespace="http://commerce.com/PO">
  <complexType name="POType">
    <sequence>
      <element name="item" type="xsd:string"/>
      <element name="quantity" type="xsd:int"/>
      <element name="description" type="xsd:string"/>
    </sequence>
  </complexType>
  <element name="PurchaseOrder" type="POType"/>
</schema>
For a document style service, this would map to a method like this:
public void method(PurchaseOrder po)
In other words, the ENTIRE <PurchaseOrder> element would be handed to your method as a single bean with three fields inside it. On the other hand, for a wrapped style service, it would map to a method like this:
public void purchaseOrder(String item, int quantity, String description)
Note that in the "wrapped" case, the <PurchaseOrder> element is a "wrapper" (hence the name) which only serves to indicate the correct operation. The arguments to our method are what we find when we "unwrap" the outer element and take each of the inner ones as a parameter.
The document or wrapped style is indicated in WSDD as follows:
<service ... style="document"> for document style
<service ... style="wrapped"> for wrapped style
In most cases you won't need to worry about document or wrapped services if you are starting from a WSDL document (see below).
Message services
Finally, we arrive at "Message" style services, which should be used when you want Axis to step back and let your code at the actual XML instead of turning it into Java objects. There are four valid signatures for your message-style service methods:
public Element [] method(Element [] bodies);
public SOAPBodyElement [] method (SOAPBodyElement [] bodies);
public Document method(Document body);
public void method(SOAPEnvelope req, SOAPEnvelope resp);
The first two will pass your method arrays of either DOM Elements or SOAPBodyElements - the arrays will contain one element for each XML element inside the <soap:body> in the envelope.
The third signature will pass you a DOM Document representing the <soap:body>, and expects the same in return.
The fourth signature passes you two SOAPEnvelope objects representing the request and response messages. This is the signature to use if you need to look at or modify headers in your service method. Whatever you put into the response envelope will automatically be sent back to the caller when you return. Note that the response envelope may already contain headers which have been inserted by other Handlers.
Message Example
A sample message service can be found in samples/message/MessageService.java. The service class, MessageService, has one public method, echoElements, which matches the first of the three method signatures above:
public Element[] echoElements(Element [] elems)
The MsgProvider handler calls the method with an array of org.w3c.dom.Element objects that correspond to the immediate children of the incoming message's SOAP Body. Often, this array will contain a single Element (perhaps the root element of some XML document conforming to some agreed-upon schema), but the SOAP Body can handle any number of children. The method returns an Element[] array to be returned in the SOAP body of the response message.
Message services must be deployed with a WSDD file. Here is the full WSDD for the MessageService class:
<deployment name="test" xmlns="http://xml.apache.org/axis/wsdd/"
    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
    xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
  <service name="MessageService" style="message">
    <parameter name="className" value="samples.message.MessageService"/>
    <parameter name="allowedMethods" value="echoElements"/>
  </service>
</deployment>
Note that the "style" attribute is different from the RPC deployment example. The "message" style tells Axis that this service is to be handled by org.apache.axis.providers.java.MsgProvider rather than org.apache.axis.providers.java.RPCProvider.
You can test this service by deploying it, then running samples.message.TestMsg (look at the source to see what the test driver does).

No comments:

Post a Comment

Blog Archive