blob: f6d100cda926182e6247104ceb29394744a90c24 [file] [log] [blame]
<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>&lt;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"&gt;
&lt;import namespace="http://schemas.xmlsoap.org/soap/encoding/"/&gt;
&lt;complexType name="SOAPStruct"&gt;
&lt;sequence&gt;
&lt;element name="varString" type="xsd:string"/&gt;
&lt;element name="varInt" type="xsd:int"/&gt;
&lt;element name="varFloat" type="xsd:float"/&gt;
&lt;/sequence&gt;
&lt;/complexType&gt;
&lt;element name="myElement" type="tns:SOAPStruct"/&gt;
&lt;/schema&gt;</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>&lt;myElement&gt;
&lt;varInt&gt;5&lt;/varInt&gt;
&lt;varString&gt;Hello&lt;/varString&gt;
&lt;varFloat&gt;3.3&lt;/varFloat&gt;
&lt;/myElement&gt;</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>