The XmlAdapter Field example demonstrates how to use the XmlAdapter interface and the @XmlJavaTypeAdapter annotation to provide a custom mapping of XML content into and out of a HashMap (field) that uses an int as the key and a String as the value.
Interface XmlAdapter and annotation @XmlJavaTypeAdapter are used for special processing of data types during unmarshalling/marshalling. There are a variety of XML data types for which the representation does not map easily into Java (for example, xs:DateTime and xs:Duration), and Java types which do not map conveniently into XML representations, for example implementations of java.util.Collection (such as List) and java.util.Map (such as HashMap) or for non-JavaBean classes.
The XmlAdapter interface and the @XmlJavaTypeAdapter annotation are provided for cases such as these. This combination provides a portable mechanism for reading/writing XML content into and out of Java applications.
The XmlAdapter interface defines the methods for data reading/writing.
/*
* ValueType - Java class that provides an XML representation
* of the data. It is the object that is used for
* marshalling and unmarshalling.
*
* BoundType - Java class that is used to process XML content.
*/
public abstract class XmlAdapter<ValueType,BoundType> {
// Do-nothing constructor for the derived classes.
protected XmlAdapter() {}
// Convert a value type to a bound type.
public abstract BoundType unmarshal(ValueType v);
// Convert a bound type to a value type.
public abstract ValueType marshal(BoundType v);
}
You can use the @XmlJavaTypeAdapter annotation to associate a particular XmlAdapter implementation with a Target type, PACKAGE, FIELD, METHOD, TYPE, or PARAMETER.
The XmlAdapter Field example shows how to use an XmlAdapter for mapping XML content into and out of a (custom) HashMap. The HashMap object, basket, in class KitchenWorldBasket, uses a key of type int and a value of type String. These data types should be reflected in the XML content that is read and written, so the XML content should look like this.
<basket>
<entry key="9027">glasstop stove in black</entry>
<entry key="288">wooden spoon</entry>
</basket>
The default schema generated for Java type HashMap does not reflect the desired format.
<xs:element name="basket">
<xs:complexType>
<xs:sequence>
<xs:element name="entry" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="key" minOccurs="0" type="xs:anyType"/>
<xs:element name="value" minOccurs="0" type="xs:anyType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
In the default HashMap schema, key and value are both elements and are of data type anyType. The XML content will look like this:
<basket>
<entry>
<key>9027</>
<value>glasstop stove in black</>
</entry>
<entry>
<key>288</>
<value>wooden spoon</>
</entry>
</basket>
To resolve this issue, the example uses two Java classes, PurchaseList and PartEntry, that reflect the needed schema format for unmarshalling/marshalling the content. The XML schema generated for these classes is as follows:
<xs:complexType name="PurchaseListType">
<xs:sequence>
<xs:element name="entry" type="partEntry"
nillable="true" maxOccurs="unbounded"
minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="partEntry">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="key" type="xs:int"
use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
Class AdapterPurchaseListToHashMap implements the XmlAdapter interface. In class KitchenWorldBasket, the @XmlJavaTypeAdapter annotation is used to pair AdapterPurchaseListToHashMap with field HashMap basket. This pairing will cause the marshal/unmarshal method of AdapterPurchaseListToHashMap to be called for any corresponding marshal/unmarshal action on KitchenWorldBasket.
Follow these instructions to build and run the XmlAdapter Field example on your Application Server instance using the NetBeans IDE.
In NetBeans IDE, select File->Open Project.
In the Open Project dialog, navigate to tut-install/javaeetutorial5/examples/jaxb/.
Select the j2s-xmlAdapter-field folder.
Select the Open as Main Project check box.
Click Open Project.
Right-click the j2s-xmlAdapter-field project and select Run.
To compile and run the XmlAdapter Field example using Ant, in a terminal window, go to the tut-install/javaeetutorial5/examples/jaxb/j2s-xmlAdapter-field/ directory and type the following:
ant runapp |