Skip to content

JAXB2 Simplify Plugin

highsource edited this page Oct 23, 2014 · 16 revisions

JAXB2 Simlify plugin

This plugin allows simplifying "complex" properties (ex. aOrBOrC generated from repeatable choices) into several "simple" properties (ex. a, b, c).

Activation

You also have to turn on the extension mode with -extension to use the plugin.

Usage

  • Add JAXB2 Basics to your build
  • The plugin is activated by the -Xsimplify command line option.
  • Declare http://jaxb2-commons.dev.java.net/basic/simplify as an extension namespace.

In the schema directly:

<xs:schema ...
	xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
	xmlns:simplify="http://jaxb2-commons.dev.java.net/basic/simplify"
	jaxb:extensionBindingPrefixes="... simplify">

...
</xs:schema>

Or in the bindings file:

<jaxb:bindings ...
	xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:simplify="http://jaxb2-commons.dev.java.net/basic/simplify"
	jaxb:extensionBindingPrefixes="... simplify">

</jaxb:bindings>
  • Use simplify:as-element-property or simplify:as-reference-property customization elements to specify, which properties you want to simplify. You can configure this elements directly in schema or in the bindings file.

Reference

This plugin allows simplifying "complex" properties. Thes properties are often generated from repeatable choices like this one:

	<xs:complexType name="typeWithReferencesProperty">
		<xs:choice maxOccurs="unbounded">
			<xs:element name="a" type="someType"/>
			<xs:element name="b" type="someType"/>
		</xs:choice> 
	</xs:complexType>

	<xs:complexType name="typeWithElementsProperty">
		<xs:choice maxOccurs="unbounded">
			<xs:element name="a" type="xs:string"/>
			<xs:element name="b" type="xs:int"/>
		</xs:choice> 
	</xs:complexType>

By default, XJC will generate complex properties modelling several references or elements in one.

    @XmlElementRefs({
        @XmlElementRef(name = "a", type = JAXBElement.class),
        @XmlElementRef(name = "b", type = JAXBElement.class)
    })
    protected List<JAXBElement<SomeType>> aOrB;
    @XmlElements({
        @XmlElement(name = "a", type = String.class)
        @XmlElement(name = "b", type = Integer.class),
    })
    protected List<Serializable> aOrB;

These complex properties are required to model complex content of the XML schema adequately, i.e. to maintain the order of the elements in the repeatable choice.

Unfortunately, they are not idiomatic as bean properties. These properties are "heterogeneous" (in a sense that they store different types), which makes it hard to work with them.

However, if the order of the elements is not significant - that is, you can live with the fact that it will change afte re-marshalling, the structures of these properties can be simplified: complex properties can be split into several simple properties.

The JAXB2 Simplify Plugin implements this task. It allows you to simplify your complex properties. The plugin will remove the complex property and insert several simpler properties instead of the original (complex) property.

The JAXB2 Simplify Plugin works with two kinds of properties: elements property and references property.

Simplifying elements property

Consider the following choice:

	<xs:complexType name="typeWithElementsProperty">
		<xs:choice maxOccurs="unbounded">
			<xs:element name="a" type="xs:string"/>
			<xs:element name="b" type="xs:int"/>
		</xs:choice> 
	</xs:complexType>

Normally this would generate a complex elements property:

    @XmlElements({
        @XmlElement(name = "a", type = String.class)
        @XmlElement(name = "b", type = Integer.class),
    })
    protected List<Serializable> aOrB;

Note that it models two elements with different names and types in one property. if you want to avoid this, you can use the simplify:as-element-property customization:

  • In the bindings file:
<jaxb:bindings node="xs:complexType[@name='typeWithElementsProperty']/xs:choice">
	<simplify:as-element-property/>
</jaxb:bindings>
  • Directly in the schema:
	<xs:complexType name="typeWithElementsProperty">
		<xs:choice maxOccurs="unbounded">
			<xs:annotation>
				<xs:appinfo>
					<simplify:as-element-property/>
				</xs:appinfo>
			</xs:annotation>
			<xs:element name="a" type="xs:string"/>
			<xs:element name="b" type="xs:int"/>
		</xs:choice> 
	</xs:complexType>

This will split one complex property into two simple ones:

    @XmlElement(name = "a", type = String.class)
    protected List<String> a;
    @XmlElement(name = "b", type = Integer.class)
    protected List<Integer> b;

As you can see, you will also get better typing.

Simplifying references property

Consider the following choice:

	<xs:complexType name="typeWithReferencesProperty">
		<xs:choice maxOccurs="unbounded">
			<xs:element name="a" type="someType"/>
			<xs:element name="b" type="someType"/>
		</xs:choice> 
	</xs:complexType>

This will normally generate a property like:

    @XmlElementRefs({
        @XmlElementRef(name = "a", type = JAXBElement.class),
        @XmlElementRef(name = "b", type = JAXBElement.class)
    })
    protected List<JAXBElement<SomeType>> aOrB;

You can use the simplify:as-element-property element to remodel this complex property as two element properties or simplify:as-reference-property as two reference properties.

Not that in the case of a reference property, you have to customize one of the xs:elements and not the xs:choice.

As element properties

  • In the bindings file:
<jaxb:bindings node="xs:complexType [@name='typeWithReferencesProperty']/xs:choice/xs:element[@name='a']">
	<simplify:as-element-property/>
</jaxb:bindings>
  • In the schema:
	<xs:complexType name="typeWithReferencesProperty">
		<xs:choice maxOccurs="unbounded">
			<xs:element name="a" type="someType">
				<xs:annotation>
					<xs:appinfo>
						<simplify:as-element-property/>
					</xs:appinfo>
				</xs:annotation>
			</xs:element>
			<xs:element name="b" type="someType"/>
		</xs:choice> 
	</xs:complexType>

Result:

    @XmlElement(name = "a")
    protected List<SomeType> a;
    @XmlElement(name = "b")
    protected List<SomeType> b;

As reference properties

	<xs:complexType name="typeWithReferencesProperty">
		<xs:choice maxOccurs="unbounded">
			<xs:element name="a" type="someType">
				<xs:annotation>
					<xs:appinfo>
						<simplify:as-reference-property/>
					</xs:appinfo>
				</xs:annotation>
			</xs:element>
			<xs:element name="b" type="someType"/>
		</xs:choice> 
	</xs:complexType>
    @XmlElementRef(name = "a", type = JAXBElement.class)
    protected List<JAXBElement<SomeType>> a;
    @XmlElementRef(name = "b", type = JAXBElement.class)
    protected List<JAXBElement<SomeType>> b;

Element properties are simpler to work with than reference properties, but you may need to retain reference properties if you have substitution groups, for instance.

Limitations

  • The plugin does not support class references:
	<xs:element name="issueJIIB44DummyClassRef" type="issueJIIB44DummyType">
		<xs:annotation>
			<xs:appinfo>
				<jaxb:class ref="org.jvnet.jaxb2_commons.tests.issues.IssueJIIB44DummyClassRef"/>
			</xs:appinfo>
		</xs:annotation>
	</xs:element>