Using the Tasks
Using schema2java and both2bind ant tasks.
To use the schema2java and both2bind ant tasks, you will need to follow these steps:
Set up the Ant Classpath
First, xbean.jar and jsr173_api.jar will need to be on the classpath you use to run ant. I use the following trick within a build.xml file to recursively spawn ant on a test-build.xml file, in another process with the additional JARs on the classpath:
{{{ <target name="test-build-with-xbeans">
<java classname="org.apache.tools.ant.Main" fork="true">
<arg value="-f"/> <arg value="test-build.xml"/> <classpath>
<pathelement path="${java.class.path}"/> <pathelement location="${env.XMLBEANS_HOME}/build/lib/xbean.jar"/> <pathelement location="${env.XMLBEANS_HOME}/build/lib/jaxen.jar"/> <pathelement location="${env.XMLBEANS_HOME}/build/lib/jsr173_api.jar"/> <pathelement location="${env.XMLBEANS_HOME}/build/lib/jsr173_ri.jar"/>
</classpath>
</java>
</target> }}}
Of course there are a bunch of other ways to set up the ant classpath; the cleanest is to just modify the shell script you use to launch ant.
Set up the Ant Taskdefs
Next you will need to set up the taskdefs for the tasks. Here are the relevant classnames:
{{{ <taskdef name='java2schema'
classname='org.apache.xmlbeans.impl.binding.compile.Java2SchemaTask'/>
<taskdef name='schema2java'
classname='org.apache.xmlbeans.impl.binding.compile.Schema2JavaTask'/>
<taskdef name='both2bind'
classname='org.apache.xmlbeans.impl.binding.compile.Both2BindTask'/> }}}
Use
Here is an example of simple usage of the schema2java and both2bind tasks. Both tasks operate by transforming sources (schema or java or both) from a "src" directory into sources (schema or java and/or just a binding file) into a "dest" directory.
{{{ <target name='default'>
<mkdir dir='s2j/dest'/> <schema2java srcdir='s2j/src' destdir='s2j/dest'/> <mkdir dir='b2b/dest'/> <both2bind srcdir='b2b/src' destdir='b2b/dest'/>
</target> }}}
File Layout
Source schema files can be organized in an arbitrary way, but all schema files must be saved with the extension *.xsd to be picked up by either the schema2java or both2bind tasks.
Similarly source java files can be organized in any way (it is not strictly necessary to organize java files in directories according to their pacakage names), but all Java files must be saved with the extension *.java.
Task Options
Both schema2java and both2bind tasks inherit from the ant MatchingTask, so they inherit the properties that MatchingTask permits. In particular, they both support the "includes", "includesfile", "excludes", and "excludesfile" properties that the builtin Javac, Jar, and Zip tasks use.
In addition, they permit multiple src directories, by following the pattern of Javac. For example, you should be able to write
{{{ <schema2java destdir="build/gensrc">
<src path="local/accounting"/> <src path="corporate/common"/> <include name="schemas/**"/> <include name="public/xsd/**"/> <exclude name="private/**"/>
</schema2java> }}}
Finally, you should be able to set the classpath to be used while building, using the "classpath" attribute. A classpath should be able to contain:
- Existing java class binaries used to resolved undefined Java classes.
- An existing binding-config.xml file which is used to resolve existing bindings.
- Compiled schema files (.xsb files) to resolve undefined schema types.
schema2java behavior
Schema2java should do the following:
- It should validate and process the given schemas. If there are any compilation problems in the given schemas, it should output error messages with filenames and line numbers of the problem.
- It should produce Java source code, organized in subdirectories of the desintation directory, according to package name.
schema2java should be able to produce Java for any valid schema, as long as there are no name collisions.
And it should be able to recognize the following patterns:
Simple types, and complex types that derive from simple types, should be treated as the "nearest" Java atomic type. (E.g., int, float, double, BigInteger, Calendar, and so on.)
- Ordinary complex types should be treated as Java classes with property names that are derived from the element or attribute names in the complex types. If there are name collisions, an error should be produced.
- SOAP arrays should be converted to arrays.
Document-literal style arrays ("ArrayOfString") should be converted to arrays.
Example: single simple structure
For example, given the following schema which contains a single type definition:
{{{ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://myco.com/test">
<xs:complexType name="test">
<xs:sequence>
<xs:element name="i" type="xs:int"/> <xs:element name="f" type="xs:float"/> <xs:element name="bi" type="xs:integer"/> <xs:element name="bd" type="xs:decimal"/> <xs:element name="s" type="xs:string"/> <xs:element name="q" type="xs:QName"/>
</xs:sequence>
</xs:complexType>
</xs:schema> }}}
The following Java should be generated:
package com.myco.test;
{{{ /**
Generated from schema type t=test@http://myco.com/test
- /
- class Test {
- private int i; private float f;
private java.math.BigInteger bi; private java.math.BigDecimal bd; private java.lang.String s; private javax.xml.namespace.QName q; public int getI() { return i; } public void setI(int i) { this.i = i; } public float getF() { return f; } public void setF(float f) { this.f = f; } public java.lang.String getS() { return s; } public void setS(java.lang.String s) { this.s = s; } public java.math.BigInteger getBi() { return bi; } public void setBi(java.math.BigInteger bi) { this.bi = bi; } public java.math.BigDecimal getBd() { return bd; } public void setBd(java.math.BigDecimal bd) { this.bd = bd; } public javax.xml.namespace.QName getQ() { return q; } public void setQ(javax.xml.namespace.QName q) { this.q = q; } }}}
- private int i; private float f;
And futhermore - and this is important - a binding-config.xml file should be generated which specifies how the Java properties line up with Schema element and attribute names.
both2bind behavior
both2bind should do the following:
- It should match up type names in the Java and the schema. The default name matching algorithm probes four times for:
- An exact match
- A case-insensitive name match
- An exact match for a JAXB respelled version of the XML name
- A case-insensitive match for the JAXB respelling
- It should match up properties in individual Java and schema types, using the same default name matching algorithm.
- If a Java and schema type do not match (because a required XML element or attribute cannot be bound to Java, or because a property type doesn't match), then an error should be produced indicating the location of the mismatched Java and schema types.
- If any global schema types are left unmapped at the end of the process, an error should be indicated.
- Finally, a binding-config.xml file should be generated that correctly describes how the schema and Java types line up with each other.
For example, given the following schema _and_ Java files:
{{{ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://myco.com/test" xmlns:tns="http://myco.com/test">
<xs:complexType name="test">
<xs:sequence>
<xs:element name="i" type="xs:int"/> <xs:element name="f" type="xs:float"/> <xs:element name="bi" type="xs:integer"/> <xs:element name="bd" type="xs:decimal"/> <xs:element name="s" type="tns:mystring"/> <xs:element name="q" type="xs:QName"/> <xs:element name="nested">
<xs:complexType>
<xs:sequence>
<xs:element name="i" type="xs:int"/> <xs:element name="s" type="tns:mystring"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType> <xs:simpleType name="mystring">
<xs:restriction base="xs:string"/>
</xs:simpleType> </xs:schema>
- class Test {
- private int i; private float f;
private java.math.BigInteger bi; private java.math.BigDecimal bd; private java.lang.String s; private javax.xml.namespace.QName q; private Hm hm; public static class Hm {
- private int i; private java.lang.String s; public int getI() { return i; } public void setI(int i) { this.i = i; } public java.lang.String getS() { return s; } public void setS(java.lang.String s) { this.s = s; }
public java.math.BigInteger getBi() { return bi; } public void setBi(java.math.BigInteger bi) { this.bi = bi; } public java.math.BigDecimal getBd() { return bd; } public void setBd(java.math.BigDecimal bd) { this.bd = bd; } public javax.xml.namespace.QName getQ() { return q; } public void setQ(javax.xml.namespace.QName q) { this.q = q; } public Hm getNested() { return hm; } public void setNested(Hm hm) { this.hm = hm; }
- private int i; private float f;
Given the above input, only a binding-config.xml should be generated which specifies how the Java properties line up with Schema element and attribute names.