Sunday, July 31, 2011

How to get best use of AXIS2 Object support.


Axis2 web service framework offers number of development approaches to match various user requirements instead of limiting to support one or two specifications. This is a one distinct feature that Axis2 go beyond from some other web service frameworks. If someone want to deploy a web service very quickly using POJOs without touching XML or SOAP, AXIS2 ADB is the ideal solution for him. ADB Object support is a one of the great feature and we have done some nice set of recent improvements too. I will discuss few tips within this post that users should know in order to get best use of Axis2 ADB Object support.

 Public Object objectService(Object obj){  
 System.out.println(obj)  
 return obj;  
 }  

Since above method takes Object type as an argument and return type it should possible to send any java primitive or POJO as a parameter value. As an example for a sample String massage it is possible to have following payload.

 <ns2:obj   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
           xmlns:xs="http://www.w3.org/2001/XMLSchema"   
           xsi:type="xs:string">  
        Hello World  
 </ns2:obj>  


In case of POJO message it is possible to have following payload.

 <ns2:obj xmlns:ns1="http://sample/xsd"   
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
                 xsi:type="ns1:Student">  
             <ns1:age>20</ns1:age>  
             <ns1:id>200</ns1:id>  
             <ns1:name>saman</ns1:name>  
            </ns2:obj>  


In above messages “xsi:type” attribute carries type system information that is required in marshalling and unmarshalling. When you send a POJO value server need to aware with the schema information associate with that particular POJO type otherwise marshalling/unmarshalling process will not possible. Typically Axis2 run-time only aware with the types associate with a particular service method, if you send above second message you will get an exception something similar to below because server can’t identify type system associate with incoming message.
 Exception in thread "main" org.apache.axis2.AxisFault: Unknow type {http://sample/xsd}Student  

the solution here is use a parameter called “extraClass” within your services.xml file.

e.g -

 <parameter name="extraClass">sample.Item,sample.Student</parameter>  

The above parameter will instruct run-time to register type details of give classes and generate schema as well . Without schema generation it is not possible to write WS clients that capable of send and receive messages with above POJOs. That is what you all need in server side now you can test your service using a tool like SoapUI.


In client side easiest and quickest way to write a client is generate code using WSDL2JAVA tool , again by default WSDL2JAVA tool also ignore extra sachem type available on WSDL file when generating codes. But it is possible to change this behaviour by adding option
“-g” that instruct to generate codes for all the schema types available . You can use following command to generate client side codes for sample application .

 axis2-1.7.0-SNAPSHOT/bin/wsdl2java.sh -uri http://localhost:8080/services/SimpleObjectService?wsdl -g   

Now you have generated POJOs in your client side you can use them with your Object service as follows.
 Student student = new Student();  
 student.setName("saman");  
 student.setId(200);  
 student.setAge(20);  
 req.setObj(student);  
 ObjectServiceResponse res = stub.objectService(req );  
 System.out.println(res.get_return());  

Tuesday, July 26, 2011

W3C Document support in Axis2



Recently we have implemented W3C Document  support for Axis2 ADB data binding. Now it is possible to use W3C Dom Document  as a input parameter , return type or as a field of a java bean. 
Let’s consider following web service method as an example. 
 public Document simpleDomService(Document doc) {  
    printInCommingDocument(doc);  
    return doc;  
  }  
It takes W3C DOM Document  as a parameter and return the same value. In order to support this method Axis2 run time should construct DOM Document from incoming payload and need to be serialized into out going payload in both server and client sides. 
In server side  based on Java refection Axis2 run-time identify parameters and return type of DOM Document and perform required conventions. But in client side this become bit of a complex task because they is no standard  way  to represent DOM Document in a WSDL. Axis2  generate xs:any type for DOM Document and this is represented as a OMElement  in generated code.
With above limitation if you have a Dom Document first you need to convert into a OMElement , you could use following code segment to convert DOM to OM. 

 OMFactory fac = OMAbstractFactory.getOMFactory();  
 OMElement domDoc = BeanUtil.convertDOMtoOM(fac, getDomDocument()); 
 
The other option is without constructing a DOM Document, directly construct a OMElement and pass it to the server side. If the server side method parameter type is DOM Document  Axis2 run-time can construct  a DOM Document for that particular service. As an example following code segment use String to construct OMElement. Refer Axiom user guide to find out other options.  
 public static OMElement getOmDocument() throws XMLStreamException {  
    return AXIOMUtil  
        .stringToOM("sample content using Axiom");  
  }  
After a successful invocation you receive a OMElement as the return value , sometimes you may want to convert this incoming value in to a DOM back . In such scenarios following code segment can be used. 

 public static org.w3c.dom.Document getDomDocument(OMElement element){  
    OMFactory doomFactory = DOOMAbstractFactory.getOMFactory();  
    StAXOMBuilder doomBuilder = new StAXOMBuilder(doomFactory,  
        element.getXMLStreamReader());  
    return (org.w3c.dom.Document) doomBuilder.getDocument();  
  }  

Here is the complete  client side code 

     // create a OMElement using Axiom tools.  
     OMFactory fac = OMAbstractFactory.getOMFactory();  
     OMElement domDoc = BeanUtil.convertDOMtoOM(fac, getDomDocument());  
     // create a pure Axiom based document  
     OMElement omDoc = getOmDocument();      
     SimpleDomServiceStub stub = new SimpleDomServiceStub();  
     SimpleDomService req = new SimpleDomService();  
     Document doc = new Document();  
     req.setDoc(doc);  
     //1st call  
     doc.setExtraElement(domDoc);  
     SimpleDomServiceResponse res = stub.simpleDomService(req);  
     res.get_return().getExtraElement().serialize(System.out);  
     //2nd call  
     System.out.println();  
     doc.setExtraElement(omDoc);  
     res = stub.simpleDomService(req);  
     res.get_return().getExtraElement().serialize(System.out);  

Note : 
1.) Some of above features based on Axiom based DOM API implementation called DOOM. But DOOM is not a complete implementation of W3C DOM and you may find some limitation. 
2.) Above features available with  upcoming   Axis2 1.7.0 release and right now you can try with 1.7.0-SNAPSHOT.
3.) Download sample project from here.  You can run “mvn jetty:run “ to start embedded Jetty server and WSDL content can be found here http://localhost:8080/services/SimpleDomService?wsdl.