Generally we use wsimport to auto generated JAVA class for consuming WSDL base web service.
Many times it happens we use to see this specific type of error messages while auto generating code.
[ERROR] Two declarations cause a collision in the ObjectFactory class.
[ERROR] A class/interface with the same name “XXXClassName” is already in use. Use a class customization to resolve this conflict.
[ERROR] This error is caused because on Windows you cannot have both “XXXClassName.java” and “xxxClassname.java” in the same directory.
[ERROR] This error is caused because on Windows you cannot have both “xxxClassName.java” and “PersistentObjectOfInt.java” in the same directory.
This are the possible ways which I tried and able to get ride of these errr:
Option 1:- This is simple option which works 90% of times. Use –B-XautoNameResolution.
Option 2:- This error is created because your XSD or WSDL is forcing to wsimport command to create java class of same name in same package. So if we not so strict in creating the auto generated source file in our specific folder neglect –p option.
Option 3:- Create binding.xml to get ride of this error. Through this we can tell wsimport to create class with the name specified by us rather than auto generating class name. But as stated in this if we had more than one schema in WSDL then for all name conflict we have to do the same.
Make sure when we create binding.xml add it command prompt using –b option.
Example of binding.xml
<jaxws:bindings node=”wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace=’http://duke.example.org’%5D”>
jxb:bindings node=”//xs:element[@name=’cxml.payment’]/xs:complexType”>
<jxb:class name=”CxmlInnerPaymentType” />
</jxb:bindings>
</jaxws:bindings>
About shdhumale
• Having professional experience in development of various applications on different Web based Application and Client Server Application.
• Strong understanding of Spring,Spring LDAP, Spring Security, GWT(Google Web Tool), Ext- GWT, SOAP Technology (Apache Axis, Apache CXF RS,WS), Thrift, Java web Start,Hibernate, Ajax, Portal, Portlet, Jersey Restful Services, Java OSGI Frame, Shibboleth Single Sing on Architecture, Core Java, Struts, Swing, and J2EE Technologies like JSP, Servlet, JDBC and Java Beans, EJB (Both Sesssion and Entity Bean), Android Mobile Development, Apache Kafka. Service Mesh, Microservice Architecture, Docker, Kubernetes, Helm Charts, ELK EFK Stack, DaTree,
Hybrid Mobile development using Ionic Frame work.
• Sound knowledge of Front End Java frame work like Angular 6 and React.
• Sound knowledge of integrating SSO Circle Single Sign On, ADFS integration.
This entry was posted in Uncategorized. Bookmark the permalink.
Abstract
This document explains various interesting/complex/tricky
aspects of JAXB, based on questions posted on the JAXB
users forum and answers I provided. This is an ongoing
work-in-progress. Any feedback
appreciated.
1. Compiling XML Schema
1.1. Dealing with errors
1.1.1. Schema errors
Because XML Schema is so complicated, and because there are a
lot of tools out there do not implement the spec correctly, it is
often the case that a schema you are trying to compile has some real
errors in it. When this is the case, you’ll see XJC reporting somewhat
cryptic errors such as rcase-RecurseLax.2: There is not a
complete functional mapping between the particles.
The JAXB RI uses the schema correctness checker from the
underlying JAXP implementation, which is the JAXP RI in a typical
setup. The JAXP RI is one of the most conformant schema validators,
and therefore most likely correct. So the first course of action
usually is to fix problems in the schema.
However, in some situations, you might not have an authority to
make changes to the schema. If that is the case and you really need to
compile the schema, you can bypass the correctness check by using the
-nv
option in XJC. When you do this, keep in mind
that you are possibly feeding «garbage» in, so you may see XJC choke
with some random exception.
1.1.2. Property ‘fooBarZot’ is already defined
One of the typical errors you’ll see when compiling a complex
schema is:
Example 1. Multiple property definitions error
parsing a schema... [ERROR] Property "MiOrMoOrMn" is already defined. line 132 of file:/C:/kohsuke/Sun/JAXB/jaxb-unit/schemas/individual/MathML2/presentation/scripts.xsd [ERROR] The following location is relevant to the above error line 138 of file:/C:/kohsuke/Sun/JAXB/jaxb-unit/schemas/individual/MathML2/presentation/scripts.xsd
This is an actual example of the offending part of a schema,
taken from MathML. If you go to line 132 of
scripts.xsd
, you’ll see that it has a somewhat
complicated content model definition:
Example 2. Multiple property definitions in MathML
<xs:group name="mmultiscripts.content"> <xs:sequence> <xs:group ref="Presentation-expr.class"/> <xs:sequence minOccurs="0" maxOccurs="unbounded"> <xs:group ref="Presentation-expr-or-none.class"/> <xs:group ref="Presentation-expr-or-none.class"/> </xs:sequence> <xs:sequence minOccurs="0"> <xs:element ref="mprescripts"/> <xs:sequence maxOccurs="unbounded"> <xs:group ref="Presentation-expr-or-none.class"/> <xs:group ref="Presentation-expr-or-none.class"/> </xs:sequence> </xs:sequence> </xs:sequence> </xs:group>
This is a standard technique in designing a schema. When you
want to say «in this element, B
can occur arbitrary
times, but C
can occur only up to once», you write
this as B*,(C,B*)?
. This, however, confuses JAXB,
because it tries to bind the first B
to its own
property, then C
to its own property, then the
second B
to its own property, and so we end up
having a collision again.
In this particular case, B
isn’t a single
element but it’s a choice of large number of elements abstracted away
in <xs:group>
s, so they are hard to see. But
if you see the same content model referring to the same element/group
twice in a different place, you can suspect this.
In this case, you’d probably want the whole thing to map to a
single list so that you can retain the order those elements show up in
the document. You can do this by putting the same
<jaxb:property>
customization on the whole
«mmultiscripts.content
» model group, like this (or
you can do it externally with XPath):
Example 3. How to fix the problem?
<xs:groupname="mmultiscripts.content"> <xs:annotation> <xs:appinfo> <jaxb:propertyname="content"/> </xs:appinfo> </xs:annotation> <xs:sequence> <xs:groupref="Presentation-expr.class"/>
Another way to fix this problem is to use the
simpler and better binding mode in XJC, which is a JAXB RI
vendor extension.
1.1.3. Two declarations cause a collision in the ObjectFactory
class
When schemas contain similar looking element/type names, they
can result in «Two declarations cause a collision in the ObjectFactory
class» errors. To be more precise, for each of all types and many
elements (exactly what elements get a factory and what doesn’t is bit
tricky to explain), XJC produces one method on the
ObjectFactory
class in the same package. The
ObjectFactory
class is created for each package that XJC
generates some files into. The name of the method is derived from XML
element/type names, and the error is reported if two elements/types
try to generate the same method name.
There are two approaches to fix this problem. If the collision
is coming from two different schemas with different target namespaces,
then you can easily avoid the collision by compiling them into
different Java packages. To do this, use <schemabindings>
customization on two schemas and specify the package name.
Another way to fix this problem is to use <factoryMethod>
customization on two conflicting elements/types to specify different
factory method names. This can be used in all cases, but if you have a
large number of conflicts, you’ll have to specify this customization
one by one.
Notice that <class>
customization doesn’t affect the ObjectFactory
method
name by itself.
1.1.4. Customization errors
1.1.4.1. XPath evaluation of … results in empty target
node
External JAXB customizations are specified by using XPath
(or using SCD.)
This works by writing an XPath expression that matches a
particular element in the schema document. For example, given the
following schema and binding file:
Example 4. Schema and external binding file
test.xsd
.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:complexTypename="foo"/> </xs:schema>
test.xjb
.
<bindings version="2.0" xmlns="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <bindings schemaLocation="test.xsd"> <bindings node="//xs:complexType[@name='foo']"> <classname="Bar"/> </bindings> </bindings> </bindings>
will be interpreted as if the class customization is
attached to the complex type ‘foo
‘.
For this to work, the XPath expression needs to match one
and only one element in the schema document. When the XPath
expression is incorrect and it didn’t match anything, you get this
«XPath evaluation of … results in empty target node»
problem.
Common causes of this problem include typos, incorrect
namespace URI declarations, and misunderstanding of XPath.
1.2. Fixing broken references in schema
Sometimes a schema may refer to another schema document without
indicating where the schema file can be found, like this:
Example 5. Schema reference without location
<xs:import namespace="http://www.w3.org/1999/xlink" />
In other cases, a schema may refer to another schema on the network,
which often slows down your compilation process and makes it unreliable.
Yet in some other cases, a schema may reference another schema in relative
path, and that may not match your directory structure.
XJC bundles a catalog
resolver so that you can work around these situations without
changing the schema documents. The main idea behind the catalog is
«redirection» — when XJC is about to fetch resources, it will consult
the catalog resolver to see if it can find the resource elsewhere (which
is usually your local resources.)
1.2.1. Catalog format
The catalog resolver supports many different formats, but the
easiest one is a line based *.cat
format. Other than
comments and empty lines, the file mainly consists of two kinds of
declarations, SYSTEM
, and
PUBLIC
.
Example 6. sample-catalog.cat
-- sample catalog file. double hyphens are used to begin and end a comment section. -- SYSTEM "http://www.w3.org/2001/xml.xsd" "xml.xsd" PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "s4s/XMLSchema.dtd"
1.2.2. Resolve by system ID
The SYSTEM entry has the format of «SYSTEM
REFERENCE ACTUAL-LOCATION«,
which defines a simple redirection. Every time XJC loads any resource
(be it schemas, DTDs, any entities referenced within), it will first
resolve relative paths to absolute paths, then looks for a matching
REFERENCE line. If it is found, the specified
actual location is read instead. Otherwise XJC will attempt to resolve
the absolutepath.
ACTUAL-LOCATION above accepts relative
paths, and those are resolved against the catalog file itself (so in
the above example, xml.xsd
is assumed to be in the same
directory with sample-catalog.cat
.
What you need to be careful is the fact that the
REFERENCE portion must be absolute, and when XJC
finds a reference in schema, it will first convert that to the
absolute path before checking the catalog. So what this means is that
if your schema is written like this:
Example 7. Schema reference by relative path
<xs:import namespace="http://www.w3.org/1999/xlink" schemaLocation="xlink.xsd" />
Then your catalog entry would have to look like this:
Example 8. xlink.cat
-- this doesn't work because xlink.xsd will be turned into absolute path -- SYSTEM "xlink.xsd" "http://www.w3.org/2001/xlink.xsd" -- this will work, assuming that the above schema is in /path/to/my/test.xsd -- SYSTEM "/path/to/my/xlink.xsd" "http://www.w3.org/2001/xlink.xsd"
1.2.3. Resolve by public ID / namespace URI
Another kind of entry has the format of «PUBLIC
PUBLICID ACTUAL-LOCATION» or
«PUBLIC NAMESPACEURI
ACTUAL-LOCATION«.
The «PUBLICID
» version is used to resolve DTDs and entities in
DTDs. But this type of entry is also used to resolve <xs:import>
statements. XJC will match the value of the namespace attribute and
see if there’s any matching entry. So given a schema like this:
Example 9. Schema import
<xs:import namespace="http://www.w3.org/1999/xlink" schemaLocation="xlink.xsd" /> <xs:import namespace="http://www.w3.org/1998/Math/MathML" />
The following catalog entries will match them.
Example 10. by-publicid.cat
PUBLIC "http://www.w3.org/1999/xlink" "http://www.w3.org/2001/xlink.xsd" PUBLIC "http://www.w3.org/1998/Math/MathML" "/path/to/my/mathml.xsd"
As you can see, XJC will check the PUBLIC entries regardless of
whether <xs:import>
has the schemaLocation attribute or not. As
with the case with the SYSTEM entry, the ACTUAL-LOCATION part can be
relative to the location of the catalog file.
1.2.4. Specifying the catalog file
Once you write a catalog file, you’d need to specify that when
you invoke XJC.
- CLI
-
To do this from the CLI, use the
-catalog
option. See xjc
-help for more details. - Ant
-
Use the catalog attribute on the
<xjc>
task.
See XJC
ant task documentation for more details. - Maven
-
For the Maven
plugin, use the<catalog>
element in the
configuration:<plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <configuration> <!-- relative to the POM file --> <catalog>mycatalog.cat</catalog> </copnfiguration> </plugin>
1.2.5. Debugging catalog file
If you are trying to write a catalog file and banging your head
against a wall because it’s not working, you should enable the verbose
option of the catalog resolver. How you do this depends on what
interface you use:
- CLI
-
Specify export
XJC_OPTS=»-Dxml.catalog.verbosity=999″ then run
XJC. - Ant/Maven
-
Add
-Dxml.catalog.verbosity=999
as a
command line option to Ant/Maven.
If you are otherwise invoking XJC programmatically, you can set
the above system property before invoking XJC.
1.3. Mapping of <xs:any />
XJC binds <xs:any />
in the following ways:
1.3.1. processContents="skip"
<xs:any />
with processContents=skip
means
any well-formed XML elements can be placed. Therefore, XJC binds this
to DOM Element
interface.
Example 11. Any/Skip schema
<xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string" /> <xs:any processContents="skip" maxOccurs="unbounded" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element>
Example 12. Any/Skip binding
import org.w3c.dom.Element; @XmlRootElement class Person { public String getName(); public void setName(String); @XmlAnyElement public List<Element> getAny(); }
1.3.2. processContents="strict"
<xs:any />
with processContents=strict
(or
<xs:any />
without any processContents attribute, since it
defaults to «strict») means any XML elements placed here must have
corresponding schema definitions. This mode is not what people
typically expect as «wildcard
«, but this is the default. The following
shows this binding. (lax=true
is unintuitive, but it’s
not an error in this document):
Example 13. Any/Strict schema
<xs:element name="person"> <xs:complexType> <xs:sequence> <xs:element name="name" type="xs:string" /> <xs:any maxOccurs="unbounded" minOccurs="0" /> </xs:sequence> </xs:complexType> </xs:element>
Example 14. Any/Strict binding
@XmlRootElement class Person { public String getName(); public void setName(String); @XmlAnyElement(lax=true) public List<Object> getAny(); }
JAXB binds any such element to an Object
, and
during unmarshalling, all elements encountered are unmarshalled into
corresponding JAXB objects (including JAXBElement
s if
necessary) and placed in this field. If it encounters elements that
cannot be unmarshalled, DOM elements are produced instead.
At runtime, you can place either DOM elements or some JAXB
objects that map to elements. A typical mistake is to put a
String
that contains XML fragment, but this won’t work;
you’d have to first read that into a DOM.
1.3.3. processContents="lax"
<xs:any />
with processContents=lax
means any
XML elements can be placed here, but if their element names match
those defined in the schema, they have to be valid. XJC actually
handles this exactly like processContents=’strict’, since the strict
binding allows unknown elements anyway.
1.4. Mapping of <xs:element />
to JAXBElement
Sometimes XJC binds an element declaration to
JAXBElement
. Sometimes XJC binds an element declaration to a
Java class. What makes this difference?
1.5. How modularization of schema interacts with XJC
Over time schema authors have developed several techniques to
modularize large schemas. Some of those techniques have some noteworthy
interactions with XJC.
1.5.1. Chameleon schema
Chameleon
schema» (read
more, in particular this)
is a technique used to define multiple almost-identical sets of
definitions into multiple namespaces from a single schema
document.
For example, with this technique, you can write just one «foo»
complex type and define it into namespace X and Y. In this case, one
tends to hope that XJC will only give you one Foo
class
for this, but unfortunately because it’s actually defined in two
namespaces, JAXB needs two Java classes to distinguish X:foo
and
Y:foo
, so you’ll get multiple copies.
If you find this to be problematic, there are a few ways to work
around the problem.
-
If you are in control of the schema, see if you can
rewrite the schema to avoid using this technique. In some
cases, the schema doesn’t actually exploit the additional
power of this technique, so this translation can be done
without affecting XML instance documents. In some other cases,
the chameleon schema can be argued as a bad schema design, as
it duplicates definitions in many places. -
If you are not in control of the schema, see if you can
rewrite the schema nevertheless. This will only work if your
transformation doesn’t affect XML instance documents. -
Perhaps there can be a plugin that eases the pain of
this, such as by defining common interfaces among
copies.
1.6. Adding behaviors
Adding behaviors to the generated code is one area that
still needs improvement. Your feedback is appreciated.
Suppose if JAXB generated the following classes.
Example 15. Simple JAXB Generated Code
package org.acme.foo; @XmlRootElement class Person { private String name; public String getName() { return name; } public void setName(String) { this.name=name; } } @XmlRegistry class ObjectFactory { Person createPerson() { ... } }
To add a behavior, first write a class that extends from
Person
. You also need to extend ObjectFactory to return this
new class. Notice that neither classes have any JAXB annotation, and I put
them in a separate package. This is because we’d like
PersonEx
class to be used in place of Person
,
and we don’t want PersonEx
to be bound to its own XML
type.
Example 16. Extended Person class
package org.acme.foo.impl; class PersonEx extends Person { @Override public void setName(String name) { if(name.length()<3) throw new IllegalArgumentException(); super.setName(name); } } @XmlRegistry class ObjectFactoryEx extends ObjectFactory { @Override Person createPerson() { return new PersonEx(); } }
At runtime, you can create JAXBContext
normally, like
this.
Example 17. Creating JAXBContext
JAXBContext context = JAXBContext.newInstance(ObjectFactory.class);
PersonEx
can be marshalled out just like
Person
:
Example 18. Marshalling
Person p = new PersonEx();
context.createMarshaller().marshal(p,System.out);
To unmarshal XML documents into PersonEx
, you’ll need
to configure the unmarshaller to use your ObjectFactoryEx
as
the factory, like this:
Example 19. Unmarshalling
Unmarshaller u = context.createUnmarshaller(); u.setProperty("com.sun.xml.bind.ObjectFactory",new ObjectFactoryEx()); PersonEx p = (PersonEx)u.unmarshal(new StringReader("<person />"));
If you have multiple packages and thus multiple
ObjectFactory
s, you can pass in an array of them (new
.)
Object[]{new OFEx1(),new OFEx2(),...}
1.6.1. Inserting your class in the middle
If you have a type hierarchy and would like to insert your class
in the middle, you can use the combination of XmlTransient
and @implClass
of <class>
customization. See the following example:
Example 20. Hierarchy of types and <jaxb:class implClass>
<xs:schema ...> <xs:complexType name="vehicle"> <xs:annotation><xs:appinfo> <jaxb:class implClass="MyVehicle" /> </xs:appinfo></xs:annotation> </xs:complexType> <xs:complexType name="car"> <xs:complexContent> <xs:extension base="vehicle" /> </xs:complexContent> </xs:complexType> <xs:complexType name="bicycle"> <xs:complexContent> <xs:extension base="vehicle" /> </xs:complexContent> </xs:complexType> </xs:schema>
Example 21. This creates a class hierarchy like the following (among
the generated Java code):
Vehicle ^ | MyVehicle ^ _____|______ | | Car Bicycle
You’ll then manually write MyVehicle
class that
extends from Vehicle
. Annotate this class with XmlTransient
to achieve the desired effect.
1.7. Avoid strong databinding
Under some limited circumstances, a weaker databinding is preferable
for various reasons. JAXB does offer a few ways for you to achieve
this.
1.7.1. Avoid mapping to enum
The following customization will stop binding a simple type to a
type-safe enum. This can be convenient when number of constants is too
large to be an useful enum (by default, the JAXB spec won’t generate
enum with more than 256 constants, but even 100 might be too large for
you.)
Example 22. Avoid mapping one simple type
<xs:simpleType name="foo"> <xs:annotation><xs:appinfo> <jaxb:typesafeEnumClass map="false" /> </xs:appinfo></xs:annotation> <xs:restriction base="xs:string"> <xs:enumeration value="x" /> <xs:enumeration value="y" /> <xs:enumeration value="z" /> </xs:restriction> </xs:simpleType>
To disable such type-safe enum binding altogether for the entire
schema, use a global binding setting like this (this is actually
telling XJC not to generate enums if a simple type has more than 0
constants — the net effect is no enum generation):
Example 23. Avoid generating enums at all
<xs:schema ...> <xs:annotation><xs:appinfo> <jaxb:globalBindings typesafeEnumMaxMembers="0" /> </xs:appinfo></xs:annotation> ... </xs:schema>
1.7.2. Mapping to DOM
The <jaxb:dom>
customization allows you to map
a certain part of the schema into a DOM tree. This customization can
be attached to the following schema components:
-
Wildcards (
<xs:any>
) -
Type definitions (
<xs:complexType>
and
<xs:simpleType>
) -
Model groups
(<xs:choice>
,<xs:all>
,<xs:sequence>
) -
Model group declarations (
<xs:group>
) -
Particles
-
Element declarations (
<xs:element>
)
In the following example, a wildcard is mapped to a DOM node.
Each element that matches to the wildcard will be turned into a DOM
tree.
Example 24. Dom Customization example
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"> <xs:element> <xs:complexType> <xs:sequence> <xs:any maxOccurs="unbounded" processContents="skip"> <xs:annotation><xs:appinfo> <jaxb:dom/> </xs:appinfo></xs:annotation> </xs:any> </xs:sequence> </xs:complexType> </xs:element> . . . </xs:schema>
This extension can be used to access wildcard content or can be
used to process a part of a document by using other technologies that
require «raw» XML. By default, JAXB generates a getContent()
method
for accessing wildcard content, but it only supports «lax» handling
which means that unknown content is discarded. You may find more
information in 7.12 chapter of JAXB 2
specification.
1.8. Working with generated code in memory
1.8.1. Cloning
The generated beans (and in particular the
JAXBElement
class) do not support the clone operation.
There was a suggestion by another user that beanlib has been
used successfully to clone JAXB objects.
2. Customization of Schema Compilation
2.1. Customizing Java packages
The JAXB specification provides a <jaxb:schemaBindings>
customization so that you can control which namespace goes to which
package. See the example below:
Example 25. package customization
<jaxb:schemaBindings> <jaxb:package name="org.acme.foo"/> </jaxb:schemaBindings>
You can do this as an internal customization (in which case you put
this in <xs:annotation>
<xs:appinfo>
under place it right under
the <xs:schema>
element), or do this as an external customization,
like this:
Example 26. External package customization
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1"> <bindings schemaLocation="../path/to/my.xsd"> <schemaBindings> <package name="org.acme.foo"/> </schemaBindings> </bindings> </bindings>
Note that this customization is per namespace. That is, even if your
schema is split into multiple schema documents, you cannot put them into
different packages if they are all in the same namespace.
2.1.1. Tip: get rid of the org.w3._2001.xmlschema package
Under some rare circumstances, XJC will generate some Java
classes into a package called org.w3._2001.xmlschema
.
This happens when XJC decides that it needs some Java artifacts for
the XML Schema built-in namespace of
http://www.w3.org/2001/XMLSchema
.
Since this package name is most often problematic, you can
rename this by simply saving the following text in an .xsd file and
submitting it to XJC along with the other schemas you have:
Example 27. Schemalet to get rid of org.w3._2001.xmlschema
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"> <annotation><appinfo> <jaxb:schemaBindings> <jaxb:package name="org.acme.foo"/> </jaxb:schemaBindings> </appinfo></annotation> </schema>
This is bit tricky, but the idea is that since you can define a
schema for one namespace in multiple schema documents, this makes XJC
think that this schema is a part of the built-in «XML Schema for XML
Schema».
2.2. Using SCD for customizations
When using an external customization file, the JAXB spec requires
that you use XPath as a means to specify what your customization is
attached to. For example, if you want to change the class name generated
from a complex type, you’d write something like:
Example 28. External customization example
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <bindings schemaLocation="../path/to/my.xsd" node="/xs:schema/xs:complexType[@name='foo']"> <class name="FooType"/> </bindings> </bindings>
While the above process works, the problem with this is that the
XPath+ schemaLocation
combo tends to be verbose and error
prone. It’s verbose, because often a trivial target schema component like
this «global complex type foo» takes up a lot of characters. The xs
namespace declaration also takes up some space, although in this case we
managed to avoid declaring the «tns» namespace (that represents the
namespace that the schema defines.)
It’s also error prone, because it relies on the way schema documents
are laid out, because the schemaLocation attribute needs to point to the
right schema document file. When a schema is split into multiple files for
modularity (happens especially often with large schemas), then you’d have
to find which schema file it is. Even though you can use relative paths,
this hard-coding of path information makes it hard to pass around the
binding file to other people.
JAXB RI 2.1 and onward offers a better way to do this as a vendor
extension.
The key technology to solve this problem is a «schema component
» (SCD.) This is a path language just like XPath, but
designator
whereas XPath is designed to refer to XML infoset items like elements and
attributes, SCD is designed to refer to schema components like element
declarations or complex types.
With SCD, the above binding can be written more concisely as
follows:
Example 29. External customization by SCD
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1" xmlns:tns="http://my.namespace/"> <bindings scd="/type::tns:foo"> <class name="FooType"/> </bindings> </bindings>
/type::tns:foo
can be written more concisely as
/~tns:foo
, too. If you are interested in more about the
syntax of SCDs, read the
example part of the spec, and maybe EBNF.
If you know XPath, I think you’ll find this fairly easy to learn.
Another benefit of an SCD is that tools will have easier time
generating SCDs than XPath, as XPaths are often vulnerable to small
changes in the schema document, while SCDs are much more robust. The
downside of using SCD is as of JAXB 2.1, this feature is a vendor
extension and not defined in the spec.
2.3. Using different datatypes
JAXB has a built-in table that determines what Java classes are used
to represent what XML Schema built-in types, but this can be
customized.
One of the common use cases for customization is to replace the
XMLGregorianCalendar
with the friendlier
Calendar
or Date
.
XMLGregorianCalendar
is designed to be 100% compatible with
XML Schema’s date/time system, such as providing infinite precision in
sub-seconds and years, but often the ease of use of those familiar Java
classes win over the precise compatibility.
One very easy way to do this is to simply use your IDE (or even
«sed
«) to replace all the references to XMLGregorianCalendar
by Calendar
. This is of course not a very attractive option
if your build process runs XJC as a part of it.
Alternatively, the following customization file can be used to do
this. When using external customization file, the JAXB spec requires you
to use XPath as a means to specify what your customization is attached to.
For example, if you want to change the class name generated from a complex
type, you’d use the following customization:
Example 30. Customization to use Calendar for xs:date
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <globalBindings> <javaType name="java.util.Calendar" xmlType="xs:date" parseMethod="javax.xml.bind.DatatypeConverter.parseDate" printMethod="javax.xml.bind.DatatypeConverter.printDate" /> </globalBindings> </bindings>
Save this in a file and specify this to JAXB with the «-b»
option.
To use the Date
class, you’ll need to do a bit more
work. First, put the following class into your source tree:
Example 31. Adapter for Date
package org.acme.foo; public class DateAdapter { public static Date parseDate(String s) { return DatatypeConverter.parseDate(s).getTime(); } public static String printDate(Date dt) { Calendar cal = new GregorianCalendar(); cal.setTime(dt); return DatatypeConverter.printDate(cal); } }
… then your binding file will be the following:
Example 32. Customization to use Date for xs:date
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <globalBindings> <javaType name="java.util.Date" xmlType="xs:date" parseMethod="org.acme.foo.DateAadpter.parseDate" printMethod="org.acme.foo.DateAdapter.printDate" /> </globalBindings> </bindings>
3. Annotating Your Classes
3.1. Mapping your favorite class
3.1.1. ResultSet
JAXB (or any other databinding engine, for that matter) is for
binding strongly-typed POJO-like objects to XML, such as
AddressBook
class, PurchaseOrder
class, and
so on, where you have fields and methods that shape a class.
There are other kinds of classes that are more close to
reflection. Those classes don’t have methods like
getAddress
, and instead you’d do
get("Address")
. JDBC ResultSet is one of those classes.
It’s one class that represents million different data structures, be
it a customer table or a product table. Generally speaking, these
classes does not allow JAXB to statically determine what the XML
representation should look like. Instead, you almost always need to
look at an instance to determine the shape of XML.
These classes are not really suitable for binding in JAXB. If
this is the only object that you’d want to write out, then you’d be
better off using XMLStreamWriter or some such XML infoset writing API.
There are a few online
articles that cover this topic. Also, many modern database
offers a native ability to export a query into XML, which is supposed
to work a lot faster than you’d do in Java (and saves your time of
writing code.)
If you are using ResultSet as a part of your object tree that
you want to marshal to JAXB, then you can use
XmlJavaTypeAdapter
.
3.1.2. HashMap
JAXB spec defines a special handling for Map
when
it’s used as a propety of a bean. For example, the following bean
would produce XMLs like the following:
Example 33. Bean with Map
@XmlRootElement class Foo { public HashMap<String,Integer> map; }
Example 34. XML representation
<foo> <map> <entry> <key>a</key> <value>1</value> </entry> <entry> <key>b</key> <value>2</value> </entry> </map> </foo>
Unfortunately, as of 2.1, this processing is only defined for
bean properties and not when you marshal HashMap
as a
top-level object (such as a value in JAXBElement
.) In
such case, HashMap
will be treated as a Java bean, and
when you look at HashMap
as a bean it defines no
getter/setter property pair, so the following code would produce the
following XML:
Example 35. Bean with Map
m = new HashMap(); m.put("abc",1); marshaller.marshal(new JAXBElement(new QName("root"),HashMap.class,m),System.out);
Example 36. XML representation
This issue has been recorded as #223
and the fix needs to happen in later versions of the JAXB spec.
In the mean time, such top-level objects have to be first
adapted to a bean that JAXB can process. This has added benefit of
being able to control XML representation better. The following code
illustrates how to do this:
Example 37. Adapting HashMap
public class MyHashMapType { public List<MyHashMapEntryType> entry = new ArrayList<MyHashMapEntryType>(); public MyHashMapType(Map<String,Integer> map) { for( Map.Entry<String,Integer> e : map.entrySet() ) entry.add(new MyHashMapEntryType(e)); } public MyHashMapType() {} } public class MyHashMapEntryType { @XmlAttribute public String key; @XmlAttribute public int value; public MyHashMapEntryType() {} public MyHashMapEntryType(Map.Entry<String,Integer> e) { key = e.getKey(); value = e.getValue(); } } marshaller.marshal(new JAXBElement(new QName("root"),MyHashMapType.class,new MyHashMapType(m)),System.out);
If you have a lot of difference kinds of Map
, you
can instead use Object
as the key and the value type. In
that way, you’ll be able to use maps with different type parameters,
at the expense of seeing xsi:type
attribute on the
instance document.
3.2. Mapping interfaces
Because of the difference between the XML type system induced by W3C
XML Schema and the Java type system, JAXB cannot bind interfaces out of
the box, but there are a few things you can do.
3.2.1. Use @XmlRootElement
When your interface is implemented by a large number of
sub-classes, consider using XmlRootElement
annotation like this:
Example 38. XmlRootElement for open-ended interfaces
@XmlRootElement class Zoo { @XmlAnyElement public List<Animal> animals; } interface Animal { void sleep(); void eat(); ... } @XmlRootElement class Dog implements Animal { ... } @XmlRootElement class Lion implements Animal { ... }
This will produce XML documents like this:
Example 39. XML for XmlRootElement
<zoo> <lion> ... </lion> <dog> ... </dog> </zoo>
The key characteristics of this approach is:
-
Implementations are open-ended; anyone can implement
those interfaces, even by different people from different
modules, provided they are all given to the
JAXBContext.newInstance
method. There’s no need
to list all the implementation classes in anywhere. -
Each implementation of the interface needs to have an
unique element name. -
Every reference to interface needs to have the
XmlElementRef
annotation. The
type=Object.class
portion tells JAXB that the
greatest common base type of all implementations would be
java.lang.Object
.
@XmlElementWrapper
is often useful with this,
as it allows you need to group them. Such as:
Example 40. XmlRootElement for open-ended interfaces
@XmlRootElement class Zoo { @XmlElementWrapper @XmlAnyElement public List<Animal> onExhibit; @XmlElementWrapper @XmlAnyElement public List<Animal> resting; }
Example 41. Effect of XmlElementWrapper
<zoo> <onExhibit> <lion> ... </lion> <dog> ... </dog> </onExhibit> <resting> <lion> ... </lion> <dog> ... </dog> </resting> </zoo>
3.2.2. Use @XmlJavaTypeAdapter
When you use interfaces just to hide your implementation classes
from exposure, and when there’s 1-to-1 (or close to 1-on-1)
relationship between a class and an interface, XmlJavaTypeAdapter
can be used like below.
Example 42. XmlJavaTypeAdapter for interfaces
@XmlJavaTypeAdapter(FooImpl.Adapter.class) interface IFoo { ... } class FooImpl implements IFoo { @XmlAttribute private String name; @XmlElement private int x; ... static class Adapter extends XmlAdapter<FooImpl,IFoo> { IFoo unmarshal(FooImpl v) { return v; } FooImpl marshal(IFoo v) { return (FooImpl)v; } } } class Somewhere { public IFoo lhs; public IFoo rhs; }
Example 43. XML of XmlJavaTypeAdapter
<somewhere> <lhs name="..."> <x>5</x> </lhs> <rhs name="..."> <x>5</x> </rhs> </somewhere>
The key characteristics of this approach is:
-
Interface and implementation will be tightly coupled
through an adapter, although changing an adapter code will
allow you to support multiple implementations. -
There’s no need of any annotation in where interfaces
are used.
A variation of this technique is when you have a few
implementations for interface, not just one.
Example 44. XmlJavaTypeAdapter for interfaces with multiple
implementations
@XmlJavaTypeAdapter(AbstractFooImpl.Adapter.class) interface IFoo { ... } abstract class AbstractFooImpl implements IFoo { ... static class Adapter extends XmlAdapter<AbstractFooImpl,IFoo> { IFoo unmarshal(AbstractFooImpl v) { return v; } AbstractFooImpl marshal(IFoo v) { return (AbstractFooImpl)v; } } } class SomeFooImpl extends AbstractFooImpl { @XmlAttribute String name; ... } class AnotherFooImpl extends AbstractFooImpl { @XmlAttribute int id; ... } class Somewhere { public IFoo lhs; public IFoo rhs; }
Example 45. XML of XmlJavaTypeAdapter with multiple
implementations
<somewhere> <lhs xsi:type="someFooImpl" name="..."> </lhs> <rhs xsi:type="anotherFooImpl" id="3" /> </somewhere>
Note that SomeFooImpl
and
AnotherFooImpl
must be submitted to
JAXBContext.newInstance
one way or the other.
To take this example a bit further, you can use
Object
instead of AbstractFooImpl
. The
following example illustarates this:
Example 46. XmlJavaTypeAdapter for interfaces with multiple
implementations
@XmlJavaTypeAdapter(AnyTypeAdapter.class) interface IFoo { ... } public class AnyTypeAdapter extends XmlAdapter<Object,Object> { Object unmarshal(Object v) { return v; } Object marshal(Object v) { return v; } } class SomeFooImpl implements IFoo { @XmlAttribute String name; ... } class Somewhere { public IFoo lhs; public IFoo rhs; }
Example 47. Corresponding schema
<xs:complexType name="somewhere"> <xs:sequence> <xs:element name="lhs" type="xs:anyType" minOccurs="0"/> <xs:element name="rhs" type="xs:anyType" minOccurs="0"/> </xs:sequence> </xs:complexType>
As you can see, the schema will generated to accept
xs:anyType
which is more relaxed than what the Java code
actually demands. The instance will be the same as the above example.
Starting from JAXB RI 2.1, we bundle the
com.sun.xml.bind.AnyTypeAdapter
class in the runtime that
defines this adapter. So you won’t have to write this adapter in your
code.
3.2.3. Use @XmlElement
If the use of interface is very little and there’s 1-to-1 (or
close to) relationship between interfaces and implementations, then
you might find XmlElement
to be the least amount of work.
Example 48. XmlElement for interfaces
interface IFoo { ... } class FooImpl implements IFoo { ... } class Somewhere { @XmlElement(type=FooImpl.class) public IFoo lhs; }
Example 49. XML of XmlElement
<somewhere> <lhs> ... </lhs> </somewhere>
This effectively tells JAXB runtime that «even though the field
is IFoo
, it’s really just FooImpl
.
In this approach, a reference to an interface has to have
knowledge of the actual implementation class. So while this requires
the least amount of typing, it probably wouldn’t work very well if
this crosses module boundaries.
Like the XmlJavaTypeAdapter
approach, this can be used
even when there are multiple implementations, provided that they share
the common ancestor.
The extreme of this case is to specify
@XmlElement(type=Object.class)
.
3.2.4. Hand-write schema
Occasionally the above approaches cause the generated schema to
become somewhat ugly, even though it does make the JAXB runtime work
correctly. In such case you can choose not to use the generated schema
and instead manually modify/author schemas tht better match your
needs.
3.2.5. Do schema-to-java
With sufficient knowlege, one can also use <jaxb:class
annotation so that you can cause XJC to use the classes
ref="..."/>
you already wrote. See this
thread for an example. TODO: more details and perhaps an
example.
3.2.6. DOESN’T WORK: Have JAXB generate interaces and swap different
implementations
Some
users attempted to use the «generateValueClass
» customization
and see if they can completely replace the generated implementations
with other implementations. Unfortunately, this does not work.
Even with the interface/implementation mode, JAXB runtime still
requires that the implementation classes have all the JAXB
annotations. So just implementing interfaces is not sufficient. (This
mode is mainly added to simplify the migration from JAXB 1.0 to JAXB
2.0, and that’s a part of the reason why things are done this
way.)
3.3. Evolving annotated classes
Here is the basic problem of evolution. You got your CoolApp v1,
which contains class Foo that has some JAXB annotations. Now you are
working towawrd CoolApp v2, and you want to make some changes to Foo. But
you want to do so in such a way that v1 and v2 can still talk to each
other.
The evolution compatibility has two different aspects. One is the
schema compatibility, which is about the relationship
between the v1 schema and the v2 schema. The other is about
runtime compatibility, which is about reading/writing
documents between two versions.
3.3.1. Runtime compatibility
There are two directions in the runtime compatibility. One is
whether v1 can still read what v2 write (forward
compatible), and the other is whether v2 can read what v1
wrote (backward compatible).
3.3.2. «Semi-compatible
«
JAXB can read XML documents that don’t exactly match what’s
expected. This is the default behavior of the JAXB unmarshaller, yet
you can change it to a more draconian behavior (TODO: pointer to the
unmarshalling section.)
When we are talking about evolving classes, it’s often
convenient to leave it in the default behavior, as that would allow
JAXB to nicely ignore elements/attributes newly added in v2. So we
call it backward semi-compatible if v2 can read
what v1 wrote in this default unmarshalling mode, and similarly
forward semi-compatible if v1 can read what v2
wrote in this default unmarshalling mode.
Technically, these are weaker than true backward/forward
compatibility (since you can’t do a draconian error detection), yet in
practice it works just fine.
3.3.3. Adding/removing/changing non-annotated things
You can add, remove, or change any non-annotated fields,
methods, inner/nested types, constructors, interfaces. Those changes
are both backward and forward compatible, as they don’t cause any
change to the XML representation.
Adding super class is backward compatible and forward
semi-compatible. Similarly, removing super class is forward compatible
and backward semi-compatible.
3.3.4. Adding/removing/changing properties
Adding new annotated fields or methods is backward compatible
and forward semi-compatible. Similarly, removing them is forward
compatible and backward semi-compatible.
Changing a property is bit more tricky.
-
If you change the property name from X to Y, that would
be the equivalent of deleting X and adding Y, so it would be
backward and forward semi-compatible. What JAXB really cares
is properties’ XML names and not Java names, so by using the
name
parameter ofXmlElement
,XmlAttribute
et al, you can change Java
property names without affecting XML, or change XML without
affecting Java properties. These are backward and forward
semi-compatible. See below: -
Example 50. Changing Java without affecting XML
public class Foo { public String abc; } public class Foo { @XmlElement(name="abc") public String def; }
Example 51. Changing XML without affecting Java
public class Foo { public String abc; } public class Foo { @XmlElement(name="def") public String abc; }
-
If you change a property type, generally speaking it
will be not compatible at all. For example, you can’t change
fromjava.util.Calendar
toint
and
expect it to work. To make it a somewhat compatible change,
the old type and the new type has to be related. For example,
String
can represent allint
values,
so changingint
toString
would be a
backward compatible and forward semi-compatible change.XmlJavaTypeAdapter
allows you to make
changes to Java without affecting XML (or vice versa.)
3.3.5. Changing class names
XmlType
and XmlRootElement
allows you to change a class name
without affecting XML.
Example 52. Changing class name without affecting XML (1)
@XmlRootElement public class Foo { ... } @XmlRootElement(name="foo") @XmlType(name="foo") public class Bar { ... }
Example 53. Changing class name without affecting XML (2)
public class Foo { ... } @XmlType(name="foo") public class Bar { ... }
3.3.6. Schema Compatibility
TODO.
3.4. XML layout and in-memory data layout
Your program sometimes needs to have a different in-memory data
structure from its XML representation. JAXB has a few different ways to
achieve this.
3.4.1. XmlJavaTypeAdapter
XmlJavaTypeAdapter
allows you to de-couple the
in-memory representation and the XML representation by introducing an
intermediate representation. The basic model is as follows:
In-memory objects <===> Intermediate objects <===> XML adapter JAXB
Your adapter code will be responsible for converting in-memory
objects to/from intermediate objects. Intermediate objects are then
bound to XML by following the standard JAXB rules. See XmlAdapter
for a general description of how
adapters works.
Adapters extend from the XmlAdapter
class and provide two methods
«unmarshal» and «marshal» that converts values in both directions, and
then the XmlJavaTypeAdapter
annotation is used to tell
JAXB where and what adapters kick in.
(TODO: more info about XmlJavaTypeAdapter needed)
-
adapting a class
-
adapting a property
-
adapting an external class
-
adapting a collection and its effect
-
adapting and using interfaces
3.4.2. Using XmlJavaTypeAdapter for element/attribute values
One of the common use cases of XmlJavaTypeAdapter
is to map a «value object» to
a string in XML. The following example illustrates how to do this, by
using java.awt.Color
as an example.
Example 54. Mapping Color to #RRGGBB
@XmlRootElement class Box { @XmlJavaTypeAdapter(ColorAdapter.class) @XmlElement Color fill; } class ColorAdapter extends XmlAdapter<String,Color> { public Color unmarshal(String s) { return Color.decode(s); } public String marshal(Color c) { return "#"+Integer.toHexString(c.getRGB()); } }
This maps to the following XML representation:
Example 55. Box instance
<box> <fill>#112233</fill> </box>
Since XmlJavaTypeAdapter
is on a field, this adapter
only kicks in for this particular field. If you have many
Color
fields and would like them all to use the same
adapter, you can move the annotation to a package:
Example 56. package-info.java
@XmlJavaTypeAdapter(type=Color.class,value=ColorAdapter.class) package foo;
Example 57. Box.java
@XmlRootElement class Box { @XmlElement Color fill; @XmlElement Color border; }
This causes all the fields in the classes in the
foo
package to use the same specified adapter.
Also see the DatatypeConverter
class that defines a
series of basic conversion routines that you may find useful.
3.4.3. Pair property
Another useful technique is to define two properties, one for
JAXB and the other for your application. See the following
example:
Example 58. Pair property sample
@XmlRootElement class Person { private int age; @XmlTransient public int getAge() { return age; } public void setAge(int age) { this.age = age; } @XmlAttribute(name="age") private String getAge_() { if(age==-1) return "dead"; else return String.valueOf(age); } private void setAge_(String v) throws NumberFormatException { if(v.equals("dead")) this.age=-1; else this.age=Integer.parseInt(age); }
The main «age
» property is public, but marked as XmlTransient
, so it’s exposed in your program,
but JAXB will not map this to XML. There’s another private «age_
»
property. Since this is marked with XmlAttribute
, this is what JAXB is going to use
to map to the attribute. The getter and setter methods on this
property will handle the conversion between the in-memory
representation and the XML representation.
3.5. Mapping cyclic references to XML
Object models designed in Java often have cycles, which prevent
straight-forward conversion to XML by JAXB. In fact, when you try to
marshal an object tree that contains a cycle, the JAXB marshaller reports
an error, pointing out the objects that formed the cycle. This is because
JAXB by itself cannot figure out how to cut cycles into a tree.
Thus it is your responsibility to annotate classes and use other
means to «tell» JAXB how to handle a cycle. This chapter talks about
various techniques to do this.
3.5.1. Parent pointers
One of the very common forms of cycle is a parent pointer. The
following example illustrates a typical parent pointer, and how this
can be turned into «natural» XML:
Example 59. Classes with parent pointer
@XmlRootElement class Department { @XmlAttribute String name; @XmlElement(name="employee") List<Employee> employees; } class Employee { @XmlTransient Department department; @XmlAttribute String name; public void afterUnmarshal(Unmarshaller u, Object parent) { this.department = (Department)parent; } }
This will produce the following XML:
Example 60. XML view of department
<department name="accounting"> <employee name="Joe Chin" /> <employee name="Adam Smith" /> ... </department>
And reading this document back into Java objects will produce
the expected tree with all the proper parent pointers set up
correctly.
The first technique here is the use of XmlTransient
on the parent pointer. This tells
JAXB that you don’t need this parent pointer to be represented
explicitly in XML, because the fact that employee
is
always contained inside department
implies the
parent/child relationship. This causes the marshaller to produce the
expected XML. However, when you unmarshal it, since this field is not
bound, the Employee.department
field will be left
null.
That’s where the second technique comes in, which is the use of
the afterUnmarshal
callback. This method is invoked by
the JAXB implementation on each instance when the unmarshalling of a
Employee
object completes. Furthermore, the second
parameter to the method is the parent object, which in this case is a
Department
object. So in this example, this sets up the
parent pointer correctly.
This callback can be also used to perform other
post-unmarshalling set up work.
3.5.2. Many-to-many relationship
TBD
3.5.3. @XmlID
and
@XmlIDREF
When a reference to another object is annotated with XmlIDREF
, its corresponding XML it will be
referenced by xs:IDREF
, instead of containment. See below
for an example:
Example of @XmlID
and
@XmlIDREF
@XmlRootElement class Root { List<Foo> foos; List<Bar> bars; } class Foo { @XmlAttribute @XmlIDREF Bar bar; } class Bar { @XmlAttribute @XmlID String id; }
Example 61. Schema for above
<xs:complexType name="foo"> <xs:sequence/> <xs:attribute name="bar" type="xs:IDREF"/> </xs:sequence> </xs:complexType> <xs:complexType name="bar"> <xs:sequence/> <xs:attribute name="id" type="xs:ID"/> </xs:complexType>
Example 62. A sample instance
<root> <foo bar="x"/> <foo bar="y"/> <bar id="x"/> <bar id="y"/> </root>
There are a few things to consider when you do this. First, the
object to be referenced must have an ID that is unique within the
whole document. You’d also need to ensure that the referenced objects
are contained somewhere else (like in the
Root
class in this case), or else Bar
objects will never be marshalled. This technique can be used to remove
the cyclic references, but it’s only possible when your object model
has an easy cut point.
3.5.4. Use the CycleRecoverable interface
Starting 2.1 EA2, the JAXB RI exposes CycleRecoverable
interface. Applications can
choose to implement this interface in some of its objects. When a
cyclic reference is detected during marshalling, and if the object
that formed a cycle implements this interface, then the method on this
interface is called to allow an application to nominate its
replacement to be written to XML. In this way, the application can
recover from a cycle gracefully.
This technique allows you to cope with a situation where you
cannot easily determine upfront as to where a cycle might happen. On
the other hand, this feature is a JAXB RI feature. Another downside of
this is that unless you nominate your replacement carefully, you can
make the marshalling output invalid with respect to the schema, and
thus you might hit another problem when you try to read it back
later.
4. Unmarshalling
4.1. @XmlRootElement
and unmarshalling
Classes with XmlRootElement
can be unmarshalled from XML elements
simply by invoking the unmarshal method that takes one parameter. This is
the simplest mode of unmarshalling.
Unmarshalling with @XmlRootElement
@XmlRootElement class Foo { @XmlAttribute String name; @XmlElement String content; } Unmarshaller u = ...; Foo foo = (Foo)u.unmarshal(new File("foo.xml"));
Example 63. foo.xml
<foo name="something"> <content>abc</content> </foo>
However, sometimes you may need to unmarshal an instance of a type
that does not have an XmlRootElement
. For example, you might dynamically
find out at the runtime that a certain element has a certain type. For
example, the following document illustrates an XML instance where the
content of <someOtherTagName>
element is represented by the
Foo
class.
Example 64. foo2.xml
<someOtherTagName name="something"> <content>abc</content> </someOtherTagName>
To unmarshal this into a Foo
class, use the version of
the unmarshal
method that takes the ‘expectedType’ argument,
as follows:
Example 65. Unmarshalling into a known type
Unmarshaller u = ...; JAXBElement<Foo> root = u.unmarshal(new StreamSource(new File("foo.xml")),Foo.class); Foo foo = root.getValue();
To reduce the number of the unmarshal
methods, this
two-argument version is not defined for every single-argument version. So
as in this example, you might need to perform additional wrapping of the
input parameter.
This instructs JAXB that the caller is expecting to unmarshal
Foo
instance. JAXB returns a JAXBElement
of
Foo
, and this JAXBElement
captures the tag name
of the root element.
4.2. Unmarshalling is not working! Help!
There are a few common causes for this problem. These causes often
exhibit similar symptoms:
-
Instance documents are invalid
-
JAXBContext
is not created correctly.
4.2.1. Make sure your instance document is valid
First, use an independent schema validator to check if your
document is really valid with respect to the schema you compiled. When
the root element of a document is invalid, then the unmarshaller will
issue «unexpected element» errors. When a portion of a document is
invalid, JAXB skips that portion, so the end result is that the
unmarshalling returns normally, yet you notice that a part of the
content tree is missing. This is often the desirable behavior, but it
sometimes ends up masking a problem.
Also, try to install ValidationEventHandler
on the
unmarshaller. When a portion of a document is skipped, the
unmarshaller notifies a ValidationEventHandler
, so it
allows you to see what’s going on.
Example 66. Installing ValidationEventHandler
Unmarshaller u = ...; u.setEventHandler(new javax.xml.bind.helpers.DefaultValidationEventHandler()); u.unmarshal(new File("foo.xml"));
Also consider installing a Schema
object to the
unmarshaller, so that the unmarshaller performs a schema validation
while unmarshalling. Earlier I suggested that you try an independent
schema validator, but for various reasons (not all tools are reliable,
you might have made an error and used a different schema/instance),
using validating unmarshalling is a better way to guarantee the
validity of your instance document being unmarshalled. Please follow
the JAXP
tutorial for more about how to construct a Schema
object from your schema.
If you are unmarshalling from XML parser APIs (such as DOM, SAX,
StAX), then also make sure that the parser/DOM is configured with the
namespace enabled.
4.2.2. Check if your JAXBContext is correct
(TODO: This also applies to the marshaller. Think about moving
it.)
The other possibility is that JAXBContext
is not
set up correctly. JAXBContext
«knows» a set of classes,
and if it doesn’t know a class that it’s supposed to know, then the
unmarshaller may fail to perform as you expected.
To verify that you created JAXBContext
correctly,
call JAXBContext.toString()
. It will output the list of
classes it knows. If a class is not in this list, the unmarshaller
will never return an instance of that class. Make you see all the
classes you expect to be returned from the unmarshaller in the list.
When dealing with a large schema that spans across a large number of
classes and packages, this is one possible cause of a problem.
If you noticed that a class is missing, explicitly specify that
to JAXBContext.newInstance
. If you are binding classes
that are generated from XJC, then the easiest way to include all the
classes is to specify the generated ObjectFactory
class(es).
4.3. Element default values and unmarshalling
Because of the «strange» way that element default values in XML
Schema work, people often get confused about their behavior. This section
describes how this works.
When a class has an element property with the default value, and if
the document you are reading is missing the element, then the unmarshaller
does not fill the field with the default value.
Instead, the unmarshaller fills in the field when the element is present
but the content is missing. See below:
Example 67. XML instance 1
Example 68. XML instance 2
Example 69. XML instance 3
Example 70. Element defaults and XML
@XmlRootElement class Foo { @XmlElement(defaultValue="value") public String a=null; } Foo foo = unmarshaller.unmarshal("instance1.xml"); System.out.println(foo.a); Foo foo = unmarshaller.unmarshal("instance2.xml"); System.out.println(foo.a); Foo foo = unmarshaller.unmarshal("instance3.xml"); System.out.println(foo.a);
This is consistent with the XML Schema spec, where it essentially
states that the element defaults do not kick in when the element is
absent, so unfortunately we can’t change this behavior.
Depending on your expectation, using a field initializer may achieve
what you are looking for. See below:
Example 71. Possible changes by using field initializer
@XmlRootElement class Foo { @XmlElement public String a="value"; } Foo foo = unmarshaller.unmarshal("instance1.xml"); System.out.println(foo.a); Foo foo = unmarshaller.unmarshal("instance2.xml"); System.out.println(foo.a); Foo foo = unmarshaller.unmarshal("instance3.xml"); System.out.println(foo.a);
Alternatively, attribute default values work in a way that agrees
with the typical expectation, so consider using that. Also, see Element default values and marshalling.
4.4. Dealing with large documents
JAXB API is designed to make it easy to read the whole XML document
into a single tree of JAXB objects. This is the typical use case, but in
some situations this is not desirable. Perhaps:
-
A document is huge and therefore the whole may not fit the
memory. -
A document is a live stream of XML (such as XMPP) and therefore you
can’t wait for the EOF. -
You only need to databind the portion of a document and
would like to process the rest in other XML APIs.
This section discusses several advanced techniques to deal with
these situations.
4.4.1. Processing a document by chunk
When a document is large, it’s usually because there’s
repetitive parts in it. Perhaps it’s a purchase order with a large
list of line items, or perhaps it’s an XML log file with large number
of log entries.
This kind of XML is suitable for chunk-processing; the main idea
is to use the StAX API, run a loop, and unmarshal individual chunks
separately. Your program acts on a single chunk, and then throws it
away. In this way, you’ll be only keeping at most one chunk in memory,
which allows you to process large documents.
See the streaming-unmarshalling example and the
partial-unmarshalling example in the JAXB RI distribution for more
about how to do this. The streaming-unmarshalling example has an
advantage that it can handle chunks at arbitrary nest level, yet it
requires you to deal with the push model — JAXB unmarshaller will
«push
» new chunk to you and you’ll need to process them right
there.
In contrast, the partial-unmarshalling example works in a pull
model (which usually makes the processing easier), but this approach
has some limitations in databinding portions other than the repeated
part.
4.4.2. Processing a live stream of XML
The techniques discussed above can be used to handle this case
as well, since they let you unmarshal chunks one by one. See the
xml-channel example in the JAXB RI distribution for more about how to
do this.
4.4.3. Creating virtual infosets
For further advanced cases, one could always run a streaming
infoset conversion outside JAXB API and basically curve just the
portion of the infoset you want to data-bind, and feed it as a
complete infoset into JAXB API. JAXB API accepts XML infoset in many
different forms (DOM, SAX, StAX), so there’s a fair amount of
flexibility in choosing the right trade off between the development
effort in doing this and the runtime performance.
For more about this, refer to the respective XML infoset
API.
5. Marshalling
5.1. Changing prefixes
By default, a JAXB marshaller uses random namespace prefixes (such
as ns1
, ns2
, …) when it needs to declare new
namespace URIs. While this is perfectly valid XML wrt the schema, for
human readability, you might want to change them to something that makes
more sense.
The JAXB RI defines NamespacePrefixMapper to allow you to do this. See
the namespace-prefix
sample in the distribution for more
details.
5.2. Element default values and marshalling
Because of a «strange» way element default values in XML Schema
work, people often get confused about its behavior. This section describes
how this works.
When a class has an element property with the default value, and if
a value is null, then the marshaller will not produce the corresponding
element in XML:
Example 72. Element defaults and XML
@XmlRootElement class Foo { @XmlElement(defaultValue="value") public String a=null; } marshaller.marshal(new Foo(),System.out);
Example 73. Marshalling output from above
This is consistent with the XML Schema spec, where it essentially
states that the element defaults do not kick in when the element is
absent. Attribute default values do not have this problem, so if you can
change the schema, changing it to an attribute is usually a better idea.
Alternatively, depending on your expectation, setting the field to a
default value in Java may achieve what you are looking for.
Example 74. Possible changes
@XmlRootElement class Foo { @XmlElement public String a="value"; } @XmlRootElement class Bar { @XmlAttribute public String a; } marshaller.marshal(new Foo(),System.out); marshaller.marshal(new Bar(),System.out);
Example 75. Marshalling output from above
<foo> <a>value</a> </foo> <bar/>
Also, see Element default values and unmarshalling.
5.3. Different ways of marshalling
5.3.1. Different output media
The most basic notion of the marshalling is to take a JAXB-bound
object that has @XmlRootElement
, and write it out as a
whole XML document. So perhaps you have a class like this:
Example 76. JAXB POJO
class Point { @XmlElement public int x; @XmlElement public int y; Point(...) { ... } }
Then you can do:
Example 77. Plain marshalling
marshaller.marshal( new Point(1,3), System.out ); marshaller.marshal( new Point(1,3), new File("out.xml") );
.. and so on. There’re seven Marshaller.marshal
methods that takes different output media as the second parameter. If
you are writing to a file, a socket, or memory, then you should use
the version that takes OutputStream
. Unless you change
the target encoding to something else (default is UTF-8), there’s a
special marshaller codepath for OutputStream
, which makes
it run really fast. You also don’t have to use
BufferedOutputStream
, since the JAXB RI does the adequate
buffering.
You can also write to Writer
, but in this case
you’ll be responsible for encoding characters, so in general you need
to be careful. If you want to marshal XML into an encoding other than
UTF-8, it’s best to use the JAXB_ENCODING
property and
then write to OutputStream
, as it escapes characters to
things like ᠤ
correctly.
The next medium we support is W3C DOM. This is bit unintuitive,
but you’ll do it like this:
Example 78. Marshal to DOM
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().newDocument(); marshaller.marshal( new Point(1,3), doc );
And after the method invocation you get a complete DOM tree that
represents the marshalled document.
The other versions of the marshal methods are there to write XML
documents in terms of other XML APIs, such as SAX and StAX. The
version that takes ContentHandler
is useful when you need
a custom formatting needs (like you want each attribute to be in new
line, etc), but otherwise they are not very interesting if you are
writing a whole document.
5.3.2. Marshalling into a subtree
Another common use of JAXB is where you are writing a bigger
document, and you use JAXB to generate part(s) of it. The JAX-WS RI is
the prime example. It produces a SOAP message, and JAXB is only used
to produce the body. When you are doing this, you first set
JAXB_FRAGMENT
property on the marshaller. This changes
the behaviors of the marshaller so that it works better in this
situation.
If you are writing to an OutputStream
or
Writer
and generally sending it to someone else, you can
do something like this:
Example 79. Marshalling into a subtree
System.out.println("<envelope>"); marshaller.marshal( object, System.out ); System.out.println("</envelope>");
Like I mentioned, this is probably the fastest, even though
println
isn’t very pretty. JAXB_FRAGMENT
prevents the marshaller from producing an XML declaration, so the
above works just fine. The downside of this approach is that if the
ancestor elements declare the namespaces, JAXB won’t be able to take
advantage of them.
You can also marshal an object as a subtree of an existing DOM
tree. To do this, you pass the Element
object as the
second parameter, and the marshaller will marshal an object as a child
of this node.
StAX is also very convenient for doing this sort of things. You
can create XMLStreamWriter
, write some stuff, and then
pass that to the marshaller. JAXB_FRAGMENT
prevents the
marshaller from producing startDocument
and
endDocument
token. When doing this sub-tree marshaling to
DOM and StAX, JAXB can take advantage of available in-scope namespace
bindings.
Finally, you can marshal an object as a subtree into
ContentHandler
, but it requires a fair amount of SAX
programming experience, and it goes beyond the scope of this
entry.
5.3.3. Marshalling a non-element
Another common use case is where you have an object that doesn’t
have @XmlRootElement
on it. JAXB allows you to marshal it
like this:
Example 80. Marshalling a non-element
marshaller.marshal( new JAXBElement( new QName("","rootTag"),Point.class,new Point(...)));
This puts the <rootTag>
element as the root element,
followed by the contents of the object, then </rootTag>
. You can
actually use it with a class that has @XmlRootElement
,
and that simply renames the root element name.
At the first glance the second Point.class
parameter may look redundant, but it’s actually necessary to determine
if the marshaller will produce (infamous)
@xsi
:type. In this example, both the class and the
instance are Point
, so you won’t see
@xsi
:type. But if they are different, you’ll see
it.
This can be also used to marshal a simple object, like
String
or an integer.
Marshalling a non-element with
@xsi
:type
marshaller.marshal( new JAXBElement( new QName("","rootTag"),String.class,"foo bar"));
But unfortunately it cannot be
used to marshal objects like List
or Map
, as
they aren’t handled as the first-class citizen in the JAXB
world.
5.3.4. Connecting to other XML APIs
Because of the Source
and Result
support, JAXB objects can be easily marshalled into other XML APIs
that are not mentioned here. For example, dom4j has
DocumentResult
that extends Result
, so you
can do:
Example 81. Marshalling to dom4j
DocumentResult dr = new DocumentResult();
marshaller.marshal( object, dr );
o = dr.getDocument();
Similar mechanism is available for JDOM and XOM. This conversion
is much more efficient than first marshalling to
ByteArrayOutputStream
and then read it back into these
DOMs. The same mechanism can be used to marshal to FastInfoset or send the
marshaled document to an XSLT engine (TransformerHandler
.)
The other interesting connector is JAXBSource
,
which wraps a marshaller and allows a JAXB object to be used as a
«source» of XML. Many XML APIs take Source
as an input,
and now JAXB object can be passed to them directly.
For example, you can marshal a JAXB object and unmarshal it into
another JAXBContext like this:
Example 82. Loading into a different JAXBContext
JAXBContext context1 = ... ;
JAXBContext context2 = ... ;
context1.createUnmarshaller().unmarshal( new JAXBSource(context2,object) );
This amounts to looking at the same XML by using different
schema, and again this is much more efficient than going through
ByteArrayOutputStream
.
5.4. Interaction between marshalling and DOM
Sometimes you may notice that JAXB is producing XML with seemingly
unnecessary namespace declarations. In this section, we’ll discuss the
possible causes and how to resolve this.
5.4.1. Caused by DOM mapping
The #1 cause of extra namespace declarations is due to the DOM
mapping. This mainly happens because of a schema construct that forces
XJC to generate a property with DOM. This includes the use of wildcard
<xs:any/>
(see more about this Mapping of <xs:any />
), as well as xs:anyType
(which can also happen by omission, such as <xs:element
, which is interpreted as
name="foo"/><xs:element
.
name="foo" type="xs:anyType" />
During unmarshalling, when a subtree of the input XML is
converted into XML, JAXB copies all the in-scope namespace bindings
active at that time to the root of the DOM element. So for example,
given the following Java class and XML, the DOM tree that the
child
field will get will look like the following:
Example 83. Bean with wildcard
@XmlRootElement class Foo { @XmlAnyElement public Element child; }
Example 84. Instance with subtree matching wildcard
<foo xmlns:a="a" xmlns:b="b" xmlns:c="c"> <subtree xmlns:c="cc"> <data>a:xyz</data> </subtree> </foo>
Example 85. DOM tree to be stored in Foo.child
<subtree xmlns:a="a" xmlns:b="b" xmlns:c="cc"> <data>a:xyz</data> </subtree>
Note that the two namespace declarations are copied over, but
c
is not because it’s overridden. Also not that JAXB is
not touching the whitespace in document. This copying of namespace
declarations is necessary to preserve the infoset in the input
document. For example, if the <data>
is a QName, its meaning
would change if JAXB unmarshaller doesn’t copy it.
Now, imagine what happens when you marshal this back to XML.
Despite the fact that in this example neither b
nor
c
prefixes are in use, JAXB cannot delete them, because
it doesn’t know if those attributes are significant to the application
or not. Therefore, this could end up producing XML with «extra
namespace declarations» like:
Example 86. DOM tree to be stored in Foo.child
<foo> <subtree xmlns:a="a" xmlns:b="b" xmlns:c="cc"> <data>a:xyz</data> </subtree> </foo>
Resolving this problem is not possible in the general case, but
sometimes one of the following strategy works:
-
Sometimes schema author incorrectly assumes that
<xs:element name="foo"/>
means
<xs:element name="foo" type="xs:string"/>
,
because attribute declarations work somewhat like this. In
such a case, adding explicittype
attribute
avoids the use of DOM, so things will work as expected. -
The wildcard processing mode »
strict
»
would force a typed binding, and thereby eliminate any DOM
mapping. -
You might be able to manulally go into the DOM tree and
remove unnecessary namespace declarations, if your application
knows what are necessary and what are not.
6. Schema Generation
6.1. Invoking schemagen programatically
Schemagen tools by default come in as CLI, ant task, and Maven
plugin. These interfaces allow you to invoke schemagen functionality from
your program.
6.1.1. At runtime
If the classes you’d like to generate schema from are already
available as java.lang.Class
objects (meaning they are
already loaded and resolved in the current JVM), then the easiest way
to generate a schema is to use the JAXB API:
Example 87. Generate schema at runtime
File baseDir = new File("."); class MySchemaOutputResolver extends SchemaOutputResolver { public Result createOutput( String namespaceUri, String suggestedFileName ) throws IOException { return new StreamResult(new File(baseDir,suggestedFileName)); } } JAXBContext context = JAXBContext.newInstance(Foo.class, Bar.class, ...); context.generateSchema(new MySchemaOutputResolver());
6.1.2. CLI interface
The CLI
interface (public static int
) is the
com.sun.tools.jxc.SchemaGenerator.run(String[])
easiest API to access. You can pass in all the schemagen command-line
arguments as a string array, and get the exit code as an int value.
Messages are sent to System.err
and
System.out
.
6.1.3. Ant interface
Ant task can be invoked very easily from a non-Ant program. The
schemagen ant task is defined in the
SchemaGenTask class,
6.1.4. Native Java API
The above two interfaces are built on top of externally
committed contracts, so they’ll evolve only in a compatibile way. The
downside is that the amount of control you can exercise over them
would be limited.
So yet another approach to invoke schemagen is to use JAXB RI’s
internal interfaces. But be warned that those interfaces are subject
to change in the future versions, despite our best effort to preserve
them. This is the API that the JAX-WS RI uses to generate schema
inside WSDL when they generate WSDL, so does some other web services
toolkits that work with the JAXB RI.
Most of those interfaces are defined and well-documented in
the com.sun.tools.xjc.api package. You can see how the schemagen
tools are eventually calling into this API at the
implementaion of SchemaGenerator class.
6.2. Generating Schema that you want
This section discusses how you can change the generated XML schema.
For changes that also affect the infoset (such as changing elements to
attributes, namespaces, etc.), refer to a different section «XML
layout and in-memory data layout».
6.2.1. Adding facets to datatypes
As of JAXB 2.1.4, currently no support for this, although there
has been several discussions in the users alias.
The JAXB project is currently lacking resources to attack this
problem, and therefore looking for volunteers to work on this project.
The basic idea would be to define enough annotations to cover the
basic constraint facets (such as length, enumerations, pattern, etc.)
The schema generator would have to be then extended to honor those
annotations and generate schemas accordingly.
Some users pointed out relevance of this to JSR 303: Bean
Validation. If you are interested in picking up this task, let
us know!
7. Deployment
7.1. Using JAXB with Maven
7.1.1. Maven coordinates for JAXB artifacts
-
java.xml.bind:jaxb-api API classes for JAXB.
Required to compile against JAXB. -
org.glassfish.jaxb:jaxb-runtime Contains the main runtime used
for serialization and deserialization java objects to/from xml. -
org.glassfish.jaxb:jaxb-xjc: Tool to generate JAXB java sources
from XML representation. -
org.glassfish.jaxb:jaxb-jxc: Tool to generate XML schema from
JAXB java sources. -
com.sun.xml.bind:jaxb-ri: Zip distribution containing tooling scripts
and all dependency jars in one archive.
7.1.2. JAXB API and Runtime
Minimum requirement to compile is jaxb-api. If a client application is running on an environment where JAXB
runtime is provided, jaxb-api
is all that is needed.
Example 88. API only
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>${jaxb.version}</version> </dependency>
If client application needs to include the runtime, e.g. running standalone on JavaSE
jaxb-runtime
should be also included.
Example 89. API + Runtime
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>${jaxb.version}</version> </dependency>
7.1.3. Using JAXB tools for java sources and XML schema generation
To generate JAXB classes from schema community
maven-jaxb2-plugin can be used.
Example 90. Using maven-jaxb2-plugin
<build> <plugins> <plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <executions> <execution> <id>generate</id> <goals> <goal>generate</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
Alternatively to community plugins, there are tooling artifacts jaxb-xjc and jaxb-jxc,
which can be used for
java from XML schema generation and vice versa.
Example 91. Using JAXB tooling artifacts
<dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-xjc</artifactId> <version>${jaxb.version}</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-jxc</artifactId> <version>${jaxb.version}</version> </dependency> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <execution> <id>xjc</id> <goals> <goal>exec</goal> </goals> <configuration> <executable>java</executable> <arguments> <argument>--module-path</argument> <modulepath/> <argument>-m</argument> <argument>com.sun.tools.xjc/com.sun.tools.xjc.XJCFacade</argument> <argument>-p</argument> <argument>com.example</argument> <argument>-d</argument> <argument>${project.build.directory}/generated-sources</argument> <argument>${project.build.directory}/classes/schema.xsd</argument> </arguments> </configuration> </execution> <execution> <id>jxc</id> <goals> <goal>exec</goal> </goals> <configuration> <executable>java</executable> <arguments> <argument>--module-path</argument> <modulepath/> <argument>-m</argument> <argument>com.sun.tools.jxc/com.sun.tools.jxc.SchemaGeneratorFacade</argument> <argument>-d</argument> <argument>${project.build.directory}/generated-sources</argument> <argument>${project.build.directory}/classes/com/example/Author.java</argument> <argument>${project.build.directory}/classes/com/example/Book.java</argument> </arguments> <longModulepath>false</longModulepath> </configuration> </execution> </executions> </plugin>
See also xml schema compiler usage.
Where are schemagen and xjc command line scripts available in JavaSE prior to 11?
These are included only in the zip distribution.
7.2. Using JAXB on JPMS
JavaSE 9 features JSR 376 Java Platform Module System.
Starting from 2.4.0 JAXB supports JPMS and can be loaded and used from module path.
There are only a few things to be aware of.
7.2.1. JAXB classes openness
JAXB does reflectively access private members of the class, so client application if loaded from module path
needs to «open» packages containing jaxb classes to JAXB. There are alternative JAXB implementations,
which will have different module names, JAXB requires pojo classes to be open only to API module.
Example 92. JPMS module descriptor opening JAXB pojo classes to JAXB API
module com.example.jaxbclasses { requires java.xml.bind; opens com.example.jaxbclasses.pojos to java.xml.bind;
JAXB API will delegate openness to implementation module after resolving it with service discovery mechanism.
7.2.2. Upgrading JavaSE modules on Java 9 and 10.
Prior to Java 11, JavaSE contains JAXB bundled inside JDK. Module java.xml.bind
contains JAXB API and runtime.
-
If bundled JavaSE JAXB is used, there is no need
to provide standalone JAXB jars to java runtime. -
If standalone JAXB is used, JavaSE bundled java.xml.bind module should be replaced with
JAXB API.
Similar to
endorsed mechanism
prior to Java 9, starting from 9 there is an «upgrade module» mechanism which can replace content of JDK module.
JavaSE bundled java.xml.bind
module contains both API and Runtime classes and
should be replaced with JAXB API module, which has the same java.xml.bind
module name.
Example 93. Upgrading JavaSE java.xml.bind module with JAXB API
# Using JAXB standalone jars # Replace JavaSE bundled java.xml.bind with standalone API jar user@host: java com.example.jaxb.Main -cp jaxbclient.jar --upgrade-module-path path/to/jaxb-api.jar --module-path path/to/jaxb-runtime.jar --add-modules com.sun.xml.bind #Same as above with client on module path user@host: java -m com.example.jaxbclasses/com.example.jaxb.Main --upgrade-module-path path/to/jaxb-api.jar --module-path path/to/jaxb-runtime.jar:jaxbclient.jar --add-modules com.sun.xml.bind
—upgrade-module-path will replace JavaSE java.xml.bind (runtime and API) with jaxb-api.jar contents.
Since java.xml.bind module
is removed starting from Java 11, there is no need
to upgrade this module on 11 and later.
Example 94. Using bundled JavaSE JAXB
# Using JAXB bundled in JDK # No need for standalone jars here user@host: java com.example.jaxb.Main -cp jaxbclient.jar user@host: java -m com.example.jaxbclasses/com.example.jaxb.Main --module-path jaxbclient.jar
7.3. Older versions of JAXB and JavaSE
JavaSE 6 ships with its own JAXB 2.0 implementation. This
implementation is based on the JAXB RI, where the only differences
are:
-
No RI-specific vendor extensions are
supported: This is so that portability across different
JavaSE 6 implementations will be guaranteed. -
Code in JavaSE 6 is hosted in its own
packages to avoid conflicts: This allows applications
to continue to use a specific version of the JAXB RI that they
choose to use.
Therefore, if you develop an application that uses JAXB 2.0 for
JavaSE 5 today, the easiest way to upgrade to JavaSE 6 is to do nothing.
You should keep the JAXB RI in your development environment, keep bundling
the JAXB RI runtime jars to your app, just like you do that today.
7.3.1. Reducing footprint
If you’d like to reduce the footprint of your application by
taking advantage of a JAXB implementation in JavaSE, you can take
the following steps:
-
You will no longer have to ship
jaxb-api.jar
in your application. This doesn’t
require any change to your code. -
If your application does not use any of the vendor
extension features of the JAXB RI runtime (such as
unmarshaller/marshaller properties whose names start with
«com.sun.
«), then you will no longer have to ship
jaxb-impl.jar
(norjaxb1-impl.jar
,
jaxb-libs.jar
.) When you do this, be sure to test
your application since it’s not very easy to find all such
dependencies.
7.3.2. Using JAXB with Java SE
JavaSE comes with JAXB 2.x API/implementation in rt.jar
. Each
version of JavaSE (6, 7, 8, …) contains different version of JAXB 2.x
API. Therefore, if you want to use different version of JAXB API/implementation
than the one present in your version of JDK, you are required to override
a portion of rt.jar
with the new API. There are
several ways to achieve this:
-
Place the
jaxb-api.jar
into
$JRE_HOME/lib/endorsed
. Do not put other JAXB jars into the
endorsed directory. And put jaxb-impl, jaxb-core to classpath of your application.
This essentially makes your JRE to «JRE X + JAXB 2.y». This would
affect any other applications that use this JRE, and it’s easy.
On the other hand, in various scenarios you may not be able to
alter the JRE. -
Use the system property
java.endorsed.dirs
when you launch your application, and
have it point to the directory which contains thejaxb-api.jar
only.
The directory must not contain any other jaxb artifacts (like jaxb-impl.jar or
jaxb-xjc.jar). This allows you use to use different version of JAXB for different
applications.
No matter which approach you take, make sure not to include jar
files other than jaxb-api.jar
. Doing so, for example
including jaxb-xjc.jar
, may result in classloading
related errors such as «taskdef A class needed by class
com.sun.tools.xjc.XJCTask cannot be found:
org/apache/tools/ant/….»
See the
endorsed directory mechanism for more details.
7.3.3. Where’s the XJC ant task?
JavaSE has never shipped an Ant task implementation, so we are
just following that tradition. There’s an (process-wise) overhead of
adding additional dependencies during the JavaSE build, and there
would likely be some runtime dependency issues in having a class in
tools.jar
that would require the ant classes, due to
class loader delegation.
We are thinking about perhaps releasing a small jar that only
contains the ant task for JDK6.
Please also note that the syntax of <xjc>
task is neither
defined in the JAXB spec nor in the JavaSE spec. Therefore other
JavaSE vendors may not implement that at all, or do so in a different
class name, etc. Therefore, from a portability perspective, if you
choose to depend on the <xjc>
task you should bundle the JAXB
RI.
7.4. Which JAXB RI is included in which JDK?
This table captures the history of the JAXB RI integration into JDK.
This is for information purposes only. In particular, the JAXB RI in JDK
is package renamed to avoid any conflict with the stand-alone JAXB RI
distribution or with the jaxb2-reflection library. You can use any version
of these with any version of JDK without worrying about implementation
conflicts.
7.5. Runtime Errors
7.5.1. Illegal class modifiers for package-info: 0x1600
When you compile your sources files with JDK from Java6 and try
to run it on Java5 JVMs, you may see a ClassFormatError
at runtime like this:
main" java.lang.ClassFormatError: Illegal class modifiers in class com/alu/parentalcontrol/jaxb/package-info: 0x1600 at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:620) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) at java.net.URLClassLoader.access$100(URLClassLoader.java:56) at java.net.URLClassLoader$1.run(URLClassLoader.java:195) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:242) at java.lang.Package.getPackageInfo(Package.java:350) at java.lang.Package.getAnnotation(Package.java:361) at com.sun.xml.bind.v2.model.annotation.RuntimeInlineAnnotationReader.getPackageAnnotation(RuntimeInlineAnnotationReader.java:125) at com.sun.xml.bind.v2.model.annotation.RuntimeInlineAnnotationReader.getPackageAnnotation(RuntimeInlineAnnotationReader.java:53) at com.sun.xml.bind.v2.model.impl.TypeInfoImpl.parseElementName(TypeInfoImpl.java:122) at com.sun.xml.bind.v2.model.impl.ClassInfoImpl.<init>(ClassInfoImpl.java:166)
This is due to a bug, and so far the only way to fix this is to
compile your project with JavaSE 5.
Here is what’s happening. Java5 added a new class file modifier
attribute called ACC_SYNTHETIC
, whose bit value is
0x1000. This attribute marks types and methods that are not present in
the source file but generated by the compiler. When
package-info.java
is compiled into
package-info.class
, javac in Java5 apparently only put
0x0600 (= ACC_ABSTRACT|ACC_INTERFACE
.) Some time during
Java6 development, someone filed a
bug, saying it should also include ACC_SYNTHETIC
bit, since it was a synthesized class.
Later it
is discovered that the corresponding VM change needs to be made to
allow this 0x1600 combination, but apparently no one realized
the real implication of this — namely, 0x1600 will break all the
past JVMs. Of course, this problem is eventually
discovered, but as of this writing there’s still no fix for
this.
So as you see, this is why the only workaround is to use javac
from Java5.
8. Other Miscellaneous Topics
8.1. Performance and thread-safety
The JAXBContext class is thread safe, but the Marshaller,
Unmarshaller, and Validator classes are not thread safe.
For example, suppose you have a multi-thread server application that
processes incoming XML documents by JAXB. In this case, for the best
performance you should have just one instance of JAXBContext in your whole
application like this:
Example 95. Singleton JAXBContext
class MyServlet extends HttpServlet { static final JAXBContext context = initContext(); private static JAXBContext initContext() { return JAXBContext.newInstance(Foo.class,Bar.class); } }
And each time you need to unmarshal/marshal/validate a document.
Just create a new Unmarshaller/Marshaller/Validator from this context,
like this:
Example 96. Thread local Unmarshaller
public void doGet( HttpServletRequest req, HttpServletResponse ) { Unmarshaller u = context.createUnmarshaller(); u.unmarshal(...); }
This is the simplest safe way to use the JAXB RI from multi-threaded
applications.
If you really care about the performance, and/or your application is
going to read a lot of small documents, then creating Unmarshaller could
be relatively an expensive operation. In that case, consider pooling
Unmarshaller objects. Different threads may reuse one Unmarshaller
instance, as long as you don’t use one instance from two threads at the
same time.
8.2. Compiling DTD
The JAXB RI is shipped with an «experimental» DTD support, which
let’s you compile XML DTDs. It is marked «experimental» not because the
feature is unstable nor unreliable, but rather because it’s not a part of
the JAXB specification and therefore the level of commitment to
compatibility is lower.
Example 97. To compile a DTD, run the XJC binding compiler as
follows:
All the other command-line options of the XJC binding compiler can
be applied. Similarly, the XJC ant task supports DTD. The generated code
will be no different from what is generated from W3C XML Schema. You’ll
use the same JAXB API to access the generated code, and it is portable in
the sense that it will run on any JAXB 2.0 implementation.
DTD long predates XML namespace, although people since then
developed various techniques to use XML namespaces in conjunction with
DTD. Because of this, XJC is currently unable to reverse-engineer the use
of XML namespace from DTD. If you compile DTDs that use those techniques,
you’d either manuallly modify the generated code, or you can try a tool
like Trang
that can convert DTD into XML Schema in ways that better preserves XML
namespaces.
8.2.1. Customizations
The customization syntax for DTD is roughly based on the
ver.0.21 working draft of the JAXB specification, which is available
at xml.coverpages.org.
The deviations from this document are:
-
The
whitespace
attribute of the
conversion
element takes »
preserve
«, »replace
«, and »
collapse
» instead of »preserve
«, »
normalize
«, and »collapse
» as
specified in the document. -
The
interface
customization just generates
marker interfaces with no method.
8.2.2. Compiling DTD from Maven2
Example 98. The following POM snippest describes how to invoke XJC to
compile DTD from a Maven 2 project:
<plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <executions> <execution> <goals> <goal>generate</goal> </goals> <configuration> <extension>true</extension> <schemaLanguage>DTD</schemaLanguage> <schemaIncludes> <schemaInclude>*.dtd</schemaInclude> </schemaIncludes> <bindingIncludes> <bindingInclude>*.jaxb</bindingInclude> </bindingIncludes> <args> <arg>-Xinject-listener-code</arg> </args> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.jvnet.jaxb2-commons</groupId> <artifactId>property-listener-injector</artifactId> <version>1.0</version> </dependency> </dependencies> </plugin>
Example 99. The dependencies section inside the plugin element can be
used to specify additional XJC plugins. If you’d like to use more
recent version of the JAXB RI, you can specify a dependency to XJC
here to do so, like this:
<dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-xjc</artifactId> <version>2.1.2</version> </dependency>
8.3. Designing a client/server protocol in XML
Occasionally, people try to define a custom protocol that allows
multiple XML requests/responses to be sent over a single transport channel.
This section discusses the non-trivial interaction between XML and
sockets, and how you can design a protocol correctly.
XML1.0 requires a conforming parser to read the entire data till end
of the stream (because a parser needs to handle documents like
<root/><!-- post root comment -->
). As a result,
a naive attempt to keep one OutputStream
open and marshal
objects multiple times fails.
Example 100. One easy way to work around this limitation is to design your
protocol so that the data on the wire will look like the
following:
<conversation> <message> ... </message> <message> ... </message> ... </conversation>
The <conversation>
start tag is sent immediately after the
socket is opened. This works as a container to send multiple «messages»,
and this is also an excellent opportunity to do the hand-shaking (e.g.,
protocol-version='1.0'
attribute.) Once the
<conversation>
tag is written, multiple messages can be marshalled
as a tree into the channel, possibly with a large time lag in between. You
can use the JAXB marshaller to produce such message. When the sender wants
to disconnect the channel, it can do so by sending the
</conversation>
end tag, followed by the socket
disconnection.
Of course, you can choose any tag names freely, and each message can
have different tag names.
The receiver would use the StAX API and use
XMLStreamReader
to read this stream. You’d have to use this
to process the first <conversation>
start tag. After that, every
time you call a JAXB unmarshaller, you’ll get the next message.
For the concrete code, see the xml-channel
example in
the JAXB RI distribution.
This issue, and its workaround, has been identified by the Unofficial JAXB Guide – Dealing with errors (Project JAXB 2012).
When one of my colleagues and I faced this issue, we still had to spend some amount of time trying to “understand” why, and how to fix it. I thought I’ll share some examples and findings so that in the future people can easily resolve it.
To start with, the error occur because the same name between a TYPE
and an ELEMENT
. Please refer to the following XML snippet. (The example that is used here is based on the XSD obtained from Personal Property Securities Register).
<?xml version="1.0" encoding="utf-8"?> <xs:schema xmlns:tns="http://schemas.ppsr.gov.au/2011/04/data" elementFormDefault="qualified" targetNamespace="http://schemas.ppsr.gov.au/2011/04/data" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <!-- The rest of the code removed --> <xs:complexType name="GrantorOrganisation"> <!-- Content removed --> </xs:complexType> <xs:element name="GrantorOrganisation" nillable="true" type="tns:GrantorOrganisation" /> <!-- The rest of the code removed --> </xs:schema>
Notice that the GrantorOrganisation
is used as the name for both name and type, hence the collision.
To resolve this, use the JAXB binding and modify the objectFactory method name. Please refer to the bindings.xjb below:
<?xml version="1.0" encoding="UTF-8"?> <bindings xmlns="http://java.sun.com/xml/ns/jaxb" xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd" version="2.1"> <globalBindings> <serializable uid="1" /> </globalBindings> <bindings schemaLocation="schemas.ppsr.gov.au.2011.04.data.xsd"> <bindings node=".//xs:element[@name='GrantorOrganisation']"> <factoryMethod name="GrantorOrganisationElement" /> </bindings> <!-- rest of the code remove, need to do it for every collision --> </bindings> </bindings>
Some findings:
- I was under impression that since it is collision, I can also bind the type instead. So the node will be
node=".//xs:complexType[@name='GrantorOrganisation']"
. That did NOT work. - Since the node argument has the prefix
xs:
, also need to add the xs in the declaration of my binding file (Even thought I did not use it anywhere else).
P.S. Many thanks to George Gao for sharing the solution.
References:
Project JAXB, 2012, ‘Unofficial JAXB Guide – Dealing with errors’, accessed 08 March 2012.
Personal Property Securities Register, 2012, Accessing the PPSR Business to Government (B2G) Channel, accessed 08 March 2012.
1. Получил странную ошибку при генерации: Two declarations cause a collision in the ObjectFactory class.
2. Непонятно где ошибка, поскольку xsd без перевода строки
3. Скачал локально, отформатировал, переписал все импорты в xsd и wsdl
4. Проблемных мест было два, в первой xsd:
первое объявление
<xs:element name=»PersonAddress» nillable=»true» type=»tns:PersonAddress»/>
второе объявление
<xs:complexType name=»Person»>
<xs:sequence>
<xs:element minOccurs=»0″ name=»Address» nillable=»true» type=»tns:PersonAddress»/>
skip
во второй:
<xs:element name=»BankFlags» nillable=»true» type=»tns:BankFlags»/>
<xs:complexType name=»Bank»>
<xs:sequence>
<xs:element minOccurs=»0″ name=»Flags» nillable=»true» type=»tns:BankFlags»/>
skip
т.е ObjectFactory генерируется не совсем корректно для подобных случаев.
5. Решение нашлось тут: http://stackoverflow.com/questions/13422253/xjc-two-declarations-cause-a-collision-in-the-objectfactory-class
6. Создал фалы биндингов для этих случаев:
jaxb-binding-xsd4.xml
<jaxb:bindings xmlns:jaxb=»http://java.sun.com/xml/ns/jaxb»
xmlns:xs=»http://www.w3.org/2001/XMLSchema»
version=»1.0″>
<jaxb:bindings schemaLocation=»xsd4.xsd»>
<jaxb:bindings node=»//xs:element[@name=’PersonAddress’]»>
<jaxb:factoryMethod name=»TypePersonAddress»/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
и
jaxb-binding-xsd9.xml
<jaxb:bindings xmlns:jaxb=»http://java.sun.com/xml/ns/jaxb»
xmlns:xs=»http://www.w3.org/2001/XMLSchema»
version=»1.0″>
<jaxb:bindings schemaLocation=»xsd9.xsd»>
<jaxb:bindings node=»//xs:element[@name=’BankFlags’]»>
<jaxb:factoryMethod name=»TypeBankFlags»/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
7. Прописываем параметры в pom.xml
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>2.7.3</version>
<executions>
<execution>
<goals>
<goal>wsdl2java</goal>
</goals>
<configuration>
<sourceRoot>${basedir}/target/generated-sources</sourceRoot>
<wsdlOptions>
<wsdlOption>
<extraargs>
<extraarg>-verbose</extraarg> <extraarg>-b</extraarg>
<extraarg>${basedir}/src/main/resources/jaxb-binding-xsd4.xml</extraarg>
<extraarg>-b</extraarg>
<extraarg>${basedir}/src/main/resources/jaxb-binding-xsd9.xml</extraarg>
</extraargs>
<wsdl>
${basedir}/src/main/resources/service.wsdl
</wsdl>
<wsdlLocation>classpath:service.wsdl</wsdlLocation>
</wsdlOption>
</wsdlOptions>
</configuration>
</execution>
</executions>
</plugin>
8. Классы сгенерировались, ура!
Answer by Anastasia Finley
Thanks to the help of @Petru Gardea I was able to eventually get past this by omitting the -p com.generated package specification to wsimport. So this is what I was eventually able to run to get past this problem:,The reasoning for it is wsimport is trying to generate classes in the same package with the same name and/or methods, which it obviously cannot do. ,
Any chance you can post a set of files which would give the same? This error message is typically caused by loading the same definition twice or more in a way that confuses the loader with regards to the base URI.
– Petru Gardea
Aug 9 ’12 at 13:21
,Trying to use wsimport to generate a client for a SOAP endpoint. The WSDL and all XSD files used are local copies.
Thanks to the help of @Petru Gardea I was able to eventually get past this by omitting the -p com.generated
package specification to wsimport. So this is what I was eventually able to run to get past this problem:
wsimport ./bwWsdl.xml -Xnocompile -d ../src -extension -keep -XadditionalHeaders -B-XautoNameResolution
Answer by Kamdyn Moore
This is the command being executed:,Trying to use wsimport to generate a client for a SOAP endpoint. The WSDL and all XSD files used are local copies.,The reasoning for it is wsimport is trying to generate classes in the same package with the same name and/or methods, which it obviously cannot do. ,ADBlock is blocking some content on the site
This is the command being executed:
wsimport ./bwWsdl.xml -p com.generated -Xnocompile -d ../src -extension -keep -XadditionalHeaders -B-XautoNameResolution
Which gives this error:
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 16 of file:/schemas/newSchema.xsd
[ERROR] (Related to above error) This is the other declaration.
line 16 of file:/schemas/newSchema.xsd
Here’s the schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
version="2.004" id="OTA2003A2009A">
<xs:complexType name="TPA_ExtensionsType">
<xs:annotation>
<xs:documentation xml:lang="en">Description here.
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:element name="TPA_Extensions" type="TPA_ExtensionsType">
<xs:annotation>
<xs:documentation xml:lang="en">More description here.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:schema>
Here’s the lines where the WSDL imports these schemas:
<definitions name='ResLookupGet' targetNamespace='http://org.jboss.ws/resLookupGet' xmlns='http://schemas.xmlsoap.org/wsdl/' xmlns:http='http://schemas.xmlsoap.org/wsdl/http/' xmlns:mime='http://schemas.xmlsoap.org/wsdl/mime/' xmlns:ns='http://www.opentravel.org/OTA/2003/05/beta' xmlns:rq='http://www.opentravel.org/OTA/2003/05/betarq' xmlns:rs='http://www.opentravel.org/OTA/2003/05/betars' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:tns='http://org.jboss.ws/resLookupGet' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<types>
<xsd:schema targetNamespace='http://org.jboss.ws/resLookupGet' xmlns:tns='http://org.jboss.ws/resLookupGet' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<xsd:import namespace='http://www.opentravel.org/OTA/2003/05/betarq' schemaLocation='./schemas/FooAffiliateHeaderRQ.xsd'/>
<xsd:import namespace='http://www.opentravel.org/OTA/2003/05/betarq' schemaLocation='./schemas/FooResLookupGetRQ.xsd'/>
<xsd:import namespace='http://www.opentravel.org/OTA/2003/05/betars' schemaLocation='./schemas/FooResLookupGetRS.xsd'/>
</xsd:schema>
</types>
<message name='ResLookupGetRQ'>
<part element='rq:FooResLookupGetRQ' name='FooResLookupGetRQ'></part>
</message>
<message name='ResLookupGetRS'>
<part element='rs:FooResLookupGetRS' name='FooResLookupGetRS'></part>
</message>
Answer by Norah Jimenez
This is the command being executed:,Trying to use wsimport to generate a client for a SOAP endpoint. The WSDL and all XSD files used are local copies.,The reasoning for it is wsimport is trying to generate classes in the same package with the same name and/or methods, which it obviously cannot do. ,The first is to define an external binding XML like this
This is the command being executed:
wsimport ./bwWsdl.xml -p com.generated -Xnocompile -d ../src -extension -keep -XadditionalHeaders -B-XautoNameResolution
Which gives this error:
[ERROR] Two declarations cause a collision in the ObjectFactory class.
line 16 of file:/schemas/newSchema.xsd
[ERROR] (Related to above error) This is the other declaration.
line 16 of file:/schemas/newSchema.xsd
Here’s the schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
version="2.004" id="OTA2003A2009A">
<xs:complexType name="TPA_ExtensionsType">
<xs:annotation>
<xs:documentation xml:lang="en">Description here.
</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
<xs:element name="TPA_Extensions" type="TPA_ExtensionsType">
<xs:annotation>
<xs:documentation xml:lang="en">More description here.</xs:documentation>
</xs:annotation>
</xs:element>
</xs:schema>
Here’s the lines where the WSDL imports these schemas:
<definitions name='ResLookupGet' targetNamespace='http://org.jboss.ws/resLookupGet' xmlns='http://schemas.xmlsoap.org/wsdl/' xmlns:http='http://schemas.xmlsoap.org/wsdl/http/' xmlns:mime='http://schemas.xmlsoap.org/wsdl/mime/' xmlns:ns='http://www.opentravel.org/OTA/2003/05/beta' xmlns:rq='http://www.opentravel.org/OTA/2003/05/betarq' xmlns:rs='http://www.opentravel.org/OTA/2003/05/betars' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:tns='http://org.jboss.ws/resLookupGet' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<types>
<xsd:schema targetNamespace='http://org.jboss.ws/resLookupGet' xmlns:tns='http://org.jboss.ws/resLookupGet' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<xsd:import namespace='http://www.opentravel.org/OTA/2003/05/betarq' schemaLocation='./schemas/FooAffiliateHeaderRQ.xsd'/>
<xsd:import namespace='http://www.opentravel.org/OTA/2003/05/betarq' schemaLocation='./schemas/FooResLookupGetRQ.xsd'/>
<xsd:import namespace='http://www.opentravel.org/OTA/2003/05/betars' schemaLocation='./schemas/FooResLookupGetRS.xsd'/>
</xsd:schema>
</types>
<message name='ResLookupGetRQ'>
<part element='rq:FooResLookupGetRQ' name='FooResLookupGetRQ'></part>
</message>
<message name='ResLookupGetRS'>
<part element='rs:FooResLookupGetRS' name='FooResLookupGetRS'></part>
</message>
Answer by Fabian Schmidt
The JAXB specification provides a <jaxb:schemaBindings>
customization so that you can control which namespace goes to which
package. See the example below:,Notice that <class>
customization doesn’t affect the ObjectFactory method
name by itself.,This section discusses several advanced techniques to deal with
these situations.,The <jaxb:dom>customization allows you to map
a certain part of the schema into a DOM tree. This customization can
be attached to the following schema components:
parsing a schema...
[ERROR] Property "MiOrMoOrMn" is already defined.
line 132 of
file:/C:/kohsuke/Sun/JAXB/jaxb-unit/schemas/individual/MathML2/presentation/scripts.xsd
[ERROR] The following location is relevant to the above error
line 138 of
file:/C:/kohsuke/Sun/JAXB/jaxb-unit/schemas/individual/MathML2/presentation/scripts.xsd