| <html> |
| <head> |
| <meta http-equiv="content-type" content=""> |
| <meta content=""> |
| <meta content=""> |
| <meta content=""> |
| <meta content=""> |
| <meta content=""> |
| <meta content=""> |
| <title>ADB - Howto</title> |
| </head> |
| |
| <body> |
| <h1>Axis2 Databinding Framework</h1> |
| |
| <h2>Introduction</h2> |
| |
| <p>The objective of the Axis2Databinding framework is to provide a |
| lightweight and simple schema compiler/ Java bean generator for Axis2. By no |
| means it's to be a fully functional schema compiler like XMLBeans. This |
| document aims to provide the architectural overview of the Axis2 Databinding |
| Framework (referred to as ADB from here onwards) and be a guide to anyone who |
| wants to use and modify ADB. Note that ADB is written in a fashion that |
| allows it to be used as a standalone schema compiler and also to be extended |
| to generate code for other languages.</p> |
| |
| <h2>Architectural Overview</h2> |
| |
| <p>ADB is built on a modular architecture that allows it to utilize a pre |
| configured writer depending on the configuration.The 'big block diagram' for |
| the code generator architecture is depicted below</p> |
| |
| <p><img src="images/ADB.jpg"/></p> |
| |
| <p>ADB utilizes the WS-commons XmlSchema library for reading the Schema. The |
| object model for the schema comes in the form of a XmlSchema object. The |
| schema compiler keeps an instance of the writer (in the default case it's the |
| JavaBeanWriter) which actually writes the classes. The writers may use |
| whatever the technique they prefer, as in the case of the JavaBeanWriter, |
| they use an XSLT template. The SchemaCompiler also uses a typemapper object |
| that tells it what classnames to be used for the QNames that it encounters. |
| This type mapper is also part of the configuration and the users can override |
| the default type mapper by overriding the property setting.</p> |
| |
| <h2>Code and Dependencies</h2> |
| |
| <p>As explained in the previous section, the schema compiler depends on the |
| WS-Commons XmlSchema library. The XSLT transformations are dependent on the |
| JVM's DOMimplementation (either crimson or xerces) which means that the |
| underlying JVM should be 1.4 or higher. Apart from that ADB has no special |
| dependencies on any other special jar files. The code for the schema compiler |
| is completely in the <strong>org.apache.axis2.databinding.schema.*</strong> |
| package. This package resides in the codegen module of the Axis2 source |
| tree.</p> |
| |
| <p>Following are the important classes and files</p> |
| <ol> |
| <li>SchemaCompiler - The work horse that really compiles the schema into |
| classes.</li> |
| <li>BeanWriter - BeanWriter represents the kind of interface the |
| SchemaCompiler accepts as a writer. The writer needs to handle the actual |
| writing of the clasess</li> |
| <li>JavaBeanWriter - The default implementation of the BeanWriter |
| interface.</li> |
| <li>TypeMap - represents the interface that the schema compiler looks |
| towards to find classes</li> |
| <li>JavaTypeMap - the default implementation of the TypeMap</li> |
| <li>BeanTemplate.xsl - the XSLtemplate the JavaBeanWriter uses.</li> |
| <li>Schema-compile.properties - The property file for the schema |
| compiler</li> |
| </ol> |
| |
| <p>The easiest way to obtain the ADB binaries is to run the maven build for |
| the codegen module. This will generate the codegen-{$version}.jar inside the |
| target folder which is directly usable when the ADB schema compiler is |
| required.</p> |
| |
| <h2>Invoking the ADB Code Generator</h2> |
| |
| <h3>As a standalone schema compiler</h3> |
| |
| <p>ADB comes with a mainclass XSD2Java that allows the schemas to be compiled |
| just by giving the schema file reference.This main class is pretty much |
| primitive and does not provide much control over the code generation process. |
| This is bound to improve in the near future.</p> |
| |
| <p>Code generator accepts the follwing parameters</p> |
| <ol> |
| <li>The Schema file name - This should be a complete file name pointing to |
| the local file system</li> |
| <li>The output folder name - This should be the name of a folder within the |
| local fileSystem</li> |
| </ol> |
| |
| <p>Since the main class has no validations built in, the compiler is likely |
| to cough up an unexpected error message if these parameters are not supplied |
| properly.</p> |
| |
| <h3>Through the API</h3> |
| |
| <p>This is the only way to harness the full potential of the schema compiler. |
| The current Axis2 integration of ADB happens through this API. The most |
| important classes and methods of the Schema compiler are as follows.</p> |
| <ul> |
| <li>SchemaCompiler - Constructor |
| <p>The constructor of the schema compiler expects a CompilerOptions |
| object. This compilerOptions object is more of a holder for the |
| parameters that are passed to the SchemaCompiler. The only mandatory |
| parameter in the CompilerOptions is the output directory</p> |
| </li> |
| <li>SchemaCompiler - Compile(XMLSchema schema) |
| <p>The compile method to call for a single schema. The expected object is |
| a XMLSchema which is part of the XmlSchema library.</p> |
| </li> |
| <li>SchemaCompiler - Compile(List schemaList) |
| <p>Similar to the previous method but accepts a list of schemas instead |
| of one.</p> |
| </li> |
| </ul> |
| |
| <p>For a comprehensive code sample in invoking the schema compiler throught |
| the API, the following classes would be helpful</p> |
| <ul> |
| <li><strong>org.apache.axis2.databinding.schema.XSD2Java</strong></li> |
| <li><strong>org.apache.axis2.wsdl.codegen.extension.SimpleDBExtension</strong></li> |
| </ul> |
| |
| <h2>Deep into the Generated Code</h2> |
| |
| <p>When the schema compiler is invoked (oneway or another) it generates code |
| depending on the following rules</p> |
| <ol> |
| <li>All named complex types become bean classes. Any attribute or element |
| encapsulated in this complex type will become a field in the generated |
| class. Note that the support for constructs other than the sequence and |
| all is not yet implemented.</li> |
| <li>All top level elements become classes. This is rather a questioning |
| feature but unless classes are generated for the top level elements the |
| handling of elements become difficult and messy!</li> |
| <li>SimpleType restrictions are handled by replacing the relevant type with |
| the basetype</li> |
| </ol> |
| |
| <p>Once the code is generated according to the rules it looks like the |
| following. Consider the follwing piece of schema</p> |
| <pre><schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
| xmlns:tns="http://soapinterop.org/types" targetNamespace="http://soapinterop.org/types"> |
| <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/> |
| <complexType name="SOAPStruct"> |
| <sequence> |
| <element name="varString" type="xsd:string"/> |
| <element name="varInt" type="xsd:int"/> |
| <element name="varFloat" type="xsd:float"/> |
| </sequence> |
| </complexType> |
| <element name="myElement" type="tns:SOAPStruct"/> |
| </schema></pre> |
| |
| <p>This particular schema generates the following two classes in the |
| designated package. This package is derived from the target Namespace of the |
| schema.</p> |
| <ol> |
| <li>myElement.java</li> |
| <li>SOAPStruct.java</li> |
| </ol> |
| |
| <p>As explained earlier, SOAPStruct refers to the complexType. MyElement is |
| the class that refers to the element.Just as expected, the SOAPStruct bean |
| has getters and Setters for varString,varInt and varFloat which are a |
| String,an int and a float respectively.myElement on the other hand has a |
| single field representing the SOAPStruct object that it encapsulates.</p> |
| |
| <p>The most important aspect of the generated code is that it encapsulates |
| two methods for creation and serializing the beans.Note that to make this |
| work, the generated beans implement the |
| <strong>org.apache.axis2.databinding.ADBBean</strong> interface</p> |
| |
| <p>The creator and reader methods look like the following</p> |
| <ul> |
| <li><pre>public javax.xml.stream.XMLStreamReader |
| getPullParser(javax.xml.namespace.QName qName)</pre> |
| <p>This method returns a pull parser that throws the right events for |
| this particular object. However there is a subtle difference between |
| element based classes and complexType based classes</p> |
| <ol> |
| <li>An element based bean class (like myElement.java in the example) |
| will ignore the passed in QName. instead of using the passed in QName |
| it'll utilize it's own QName which is embedded in the class under the |
| constant MY_QNAME,during the code generation.</li> |
| <li>A ComplexType based bean class(like SOAPStruct.java in the example) |
| will use the passed on QName to return an instance of the |
| ADBpullparser. This will effectively wrap the elements inside with an |
| element having the passed QName</li> |
| </ol> |
| </li> |
| <li><pre> public static [Object] |
| parse(javax.xml.stream.XMLStreamReader reader) |
| throws java.lang.Exception </pre> |
| <p>This method returns a populated instance of the class in |
| question.(Note that</p> |
| <pre>[Object]</pre> |
| will be replaced by the actual class that contains this method. Say for |
| SOAPStruct the method looks like |
| <pre>public static SOAPStruct |
| parse(javax.xml.stream.XMLStreamReader reader) |
| throws java.lang.Exception </pre> |
| </li> |
| </ul> |
| |
| <h3>An Example!</h3> |
| |
| <p>Consider the follwing XML fragment</p> |
| <pre><myElement> |
| <varInt>5</varInt> |
| <varString>Hello</varString> |
| <varFloat>3.3</varFloat> |
| </myElement></pre> |
| |
| <p>Enthusiastic readers might already have figured out that this piece of XML |
| complies to the Schema mentioned above. The following piece of code shows how |
| to build a populated instance of myElement with this fragment of XML</p> |
| |
| <p></p> |
| <pre>XMLStreamReader reader = XMLInputFactory.newInstance(). |
| createXMLStreamReader( |
| new ByteArrayInputStream(xmlString.getBytes())); |
| myElement elt = myElement.parse(reader);</pre> |
| |
| <p>Although this example takes on the tedious effort of creating a reader out |
| of the String, inside the Axis2 environment an XMLStreamReader can be |
| direclty asked from the OMElement! Hence the parse method becomes a hugh |
| advantage for hassle free object creation.</p> |
| |
| <p>Similarly the reader obtained from the object can also be utilized as |
| needed. The following code fragment shows how to utilize the getPullParser |
| method to create an OMElement</p> |
| |
| <p></p> |
| <pre>XMLStreamReader reader = elt.getPullParser(null); |
| OMElement omElt = new StAXOMBuilder(reader).getDocumentElement();</pre> |
| |
| <p>That's all to it! If you are interested in learning more on ADB the |
| following documents may also be helpful</p> |
| |
| <p></p> |
| <ul> |
| <li><a href="adb-tweaking.html">Tweaking the ADB code generator</a></li> |
| <li><a href="adb-codegen-integration.html">ADB and Axis2 |
| Integration</a></li> |
| </ul> |
| |
| <h2>Known Limitations</h2> |
| ADB is meant to be a 'Simple' databinding framework and was not meant to |
| compile all types of schemas. The following limitations are the most |
| highlighted. |
| <ol> |
| <li>Complex Extensions and Restrictions are not supported.</li> |
| <li>Choice (Particle) is not supported</li> |
| <li>SimpleType Unions are not supported</li> |
| </ol> |
| <hr> |
| </body> |
| </html> |