JAXB hello world example
Jakarta XML Binding (JAXB; formerly Java Architecture for XML Binding) is an XML binding framework to convert Java objects to and from XML.
- XML Marshalling – Convert Java objects into XML.
- XML Unmarshalling – Convert XML back into Java Objects.
Note
This article will focus on Java 11, JAXB 3 and EclipseLink MOXy JAXB RI.
Table of contents
- 1. JAXB on Java 6, 7, 8, Java 9, 10, 11, and beyond
- 2. Java 11 and JAXB RI dependencies
- 3. JAXB hello world example
- 4. What is @XmlAccessorType(XmlAccessType.FIELD)
- 5. Difference between javax.xml.* and jakarta.xml.*
- 6. JAXB examples, List, adaptor for time and CDATA
- 7. JAXB Tips
- 8. Download Source Code
- 9. References
1. JAXB on Java 6, 7, 8, Java 9, 10, 11, and beyond
Below is a short history of Jakarta XML Binding (JAXB; formerly Java Architecture for XML Binding).
- The rise of XML-based web services, the JAXB became part of Java 6.
- The rise of JSON-based web services or REST web structure makes developers migrate from XML to JSON and REST.
- The JAXB still part of Java 7 and Java 8.
- Java 9 deprecated the Java EE modules, including the JAXB
javax.xml.*
, and mark it deprecated for removal, which means the JAXB still part of Java 9 and the future Java release will remove them. - JAXB
javax.xml.*
are still deprecated and part of Java 10. - The JAXB still part of Java 9 and Java 10 but disabled or not included in the default module path; However, we still can explicitly enable it via
--add-modules
(Not recommended). The recommended solution is to add a separate JAXB API and JAXB implementation. - The rise of microservices, developers want a small and lightweight Java runtime.
- Java 11 removed the JAXB
javax.xml.*
completely. Now, we need to add a separate JAXB API and JAXB implementation to use the JAXB features. - Oracle submitted the Java EE to Eclipse Foundation, and the Java EE rebrand to Jakarta EE because of the trademark "Java". The JAXB
javax.xml.*
also repackage tojakarta.xml.*
since version 3.0.
Further Reading
- Java 11 – JEP 320: Remove the Java EE and CORBA Modules
- Wikipedia – Jakarta XML Binding
- Wikipedia – Jakarta EE
2. Java 11 and JAXB RI dependencies
The JAXB is a specification JSR-222, and below are two common JAXB implementations:
2.1 EclipseLink MOXy
Below is the Maven EclipseLink MOXy dependency.
<!-- JAXB API only -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>3.0.0</version>
</dependency>
<!-- JAXB RI, EclipseLink MOXy -->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>3.0.0</version>
</dependency>
2.1 Jakarta XML Binding
Below is the Maven Jakarta XML Binding dependency.
<!-- JAXB API only -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>3.0.0</version>
</dependency>
<!-- JAXB RI, Jakarta XML Binding -->
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>3.0.0</version>
<scope>runtime</scope>
</dependency>
If we still prefer the old JAXB packages javax.xml.*
, stick with the JAXB version 2.x.
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-ri</artifactId>
<version>2.3.3</version>
</dependency>
Note
- In Java 6, 7, and 8, the JAXB is part of the JDK.
- In Java 9, 10, 11 and beyond, we need to add a separate JAXB API and JAXB RI or implementation libraries to use the JAXB features.
3. JAXB hello world example
A class with JAXB annotations.
package com.mkyong.xml.jaxb.model;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement
// order of the fields in XML
// @XmlType(propOrder = {"price", "name"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {
@XmlAttribute
int id;
@XmlElement(name = "n")
String name;
String price;
// getter, setter and toString...
}
3.1 JAXB XML marshalling – Convert Java objects to XML
The below JAXB example for XML marshalling convert Java objects into an XML.
package com.mkyong.xml.jaxb;
import com.mkyong.xml.jaxb.model.Fruit;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import java.io.File;
public class JaxbExampleFruit1 {
public static void main(String[] args) {
JAXBContext jaxbContext = null;
try {
// Normal JAXB RI
//jaxbContext = JAXBContext.newInstance(Fruit.class);
// EclipseLink MOXy needs jaxb.properties at the same package with Fruit.class
// Alternative, I prefer define this via eclipse JAXBContextFactory manually.
jaxbContext = org.eclipse.persistence.jaxb.JAXBContextFactory
.createContext(new Class[]{Fruit.class}, null);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Fruit o = new Fruit();
o.setId(1);
o.setName("Banana");
o.setPrice("9.99");
// output to a xml file
jaxbMarshaller.marshal(o, new File("C:\\test\\fruit.xml"));
// output to console
// jaxbMarshaller.marshal(o, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<fruit id="1">
<n>Banana</n>
<price>9.99</price>
</fruit>
3.2 JAXB XML Unmarshalling – Convert XML to Java objects
The below JAXB example for XML Unmarshalling, convert XML back into Java Objects.
package com.mkyong.xml.jaxb;
import com.mkyong.xml.jaxb.model.Fruit;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Unmarshaller;
import java.io.File;
public class JaxbExampleFruit2 {
public static void main(String[] args) {
JAXBContext jaxbContext = null;
try {
// Normal JAXB RI
//jaxbContext = JAXBContext.newInstance(Fruit.class);
// EclipseLink MOXy needs jaxb.properties at the same package with Fruit.class
// Alternative, I prefer define this via eclipse JAXBContextFactory manually.
jaxbContext = org.eclipse.persistence.jaxb.JAXBContextFactory
.createContext(new Class[]{Fruit.class}, null);
File file = new File("C:\\test\\fruit.xml");
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Fruit o = (Fruit) jaxbUnmarshaller.unmarshal(file);
System.out.println(o);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
Output
Fruit{id=1, name='Banana', price='9.99'}
4. What is @XmlAccessorType(XmlAccessType.FIELD)
By default, JAXB implementation will take getter/setter pair, public fields, and JAXB annotated non-public fields for XML conversion.
4.1 Review the Fruit
class again, if we comment out the @XmlAccessorType(XmlAccessType.FIELD)
, and rerun the above JAXB program.
@XmlRootElement
//@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {
@XmlAttribute
int id;
@XmlElement(name = "n")
String name;
String price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
@Override
public String toString() {
return "Fruit{" +
"id=" + id +
", name='" + name + '\'' +
", price='" + price + '\'' +
'}';
}
4.2 We will get the below Class has two properties of the same name
error message.
Class has two properties of the same name "id"
this problem is related to the following location:
at public int com.mkyong.xml.jaxb.model.Fruit.getId()
at com.mkyong.xml.jaxb.model.Fruit
this problem is related to the following location:
at int com.mkyong.xml.jaxb.model.Fruit.id
at com.mkyong.xml.jaxb.model.Fruit
Class has two properties of the same name "name"
this problem is related to the following location:
at public java.lang.String com.mkyong.xml.jaxb.model.Fruit.getName()
at com.mkyong.xml.jaxb.model.Fruit
this problem is related to the following location:
at java.lang.String com.mkyong.xml.jaxb.model.Fruit.name
at com.mkyong.xml.jaxb.model.Fruit
The JAXB will consider Fruit.getId()
and Fruit.id
(because we annotated with @XmlAttribute
or @XmlElement
) as the same property; To solve it, we add a @XmlAccessorType(XmlAccessType.FIELD)
on the class to tell JAXB only take Fruit.id
as the property.
Note
The EclipseLink MOXy JAXB doesn’t have the above problem.
5. Difference between javax.xml.* and jakarta.xml.*
Eclipse foundation rebrand the Java EE javax.xml.*
to Jakarta EE jakarta.xml.*
.
Below are some JAXB APIs in versions 2 and 3.
// Jakarta EE
// @Since 3.0.0, rebrand to jakarta.xml
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
// Java EE
// old APIs JAXB version 2.*
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
5.1 Java EE, javax.xml.* for JAXB version 2
In the JAXB version 2, the APIs are using the old Java EE package javax.xml.*
.
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- JAXB RI -->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.7.8</version>
</dependency>
5.2 Jakarta EE, jakarta.xml.* for JAXB version 3
In the JAXB version 3.x and above, the APIs are repackaged to the Jakarta EE package jakarta.xml.*
.
<!-- JAXB API -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>3.0.0</version>
</dependency>
<!-- JAXB RI -->
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>3.0.0</version>
</dependency>
6. JAXB examples, List, adaptor for time and CDATA
Below JAXB examples involve the following stuff:
- A
Company.class
contains a list ofStaff.class
, with JAXB annotations for XML conversion. - Convert Java 8
ZonedDateTime
using the@XmlJavaTypeAdapter
. - XML CDATA for special characters, the
@XmlCDATA
is only available in EclipseLink MOXy JAXB RI.
6.1 JAXB domain class
Two domain classes with JAXB annotations.
package com.mkyong.xml.jaxb.model;
import com.mkyong.xml.jaxb.adaptor.TimeZoneAdaptor;
// @Since 3.0
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlCDATA;
// Java 8?
//import com.sun.xml.internal.txw2.annotation.XmlCDATA;
// jaxb 2
//import javax.xml.bind.annotation.*;
import java.time.ZonedDateTime;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Staff {
@XmlAttribute
int id;
String name;
String Salary;
@XmlCDATA
String bio;
@XmlJavaTypeAdapter(TimeZoneAdaptor.class)
ZonedDateTime joinDate;
//getters, setters
}
package com.mkyong.xml.jaxb.model;
//import javax.xml.bind.annotation.*;
// @Since 3.0.0
import jakarta.xml.bind.annotation.*;
import java.util.List;
@XmlRootElement
@XmlType(propOrder = {"name", "list"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Company {
@XmlElement(name = "staff")
List<Staff> list;
String name;
// getters, and setters
}
6.2 JAXB Adapter
We can use @XmlJavaTypeAdapter
to convert ZonedDateTime
(or other types) to and from a String
.
package com.mkyong.xml.jaxb.adaptor;
// @Since 3.0.0
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
//import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
public class TimeZoneAdaptor extends XmlAdapter<String, ZonedDateTime> {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
@Override
public ZonedDateTime unmarshal(String v) throws Exception {
ZonedDateTime parse = ZonedDateTime.parse(v, dateTimeFormatter);
return parse;
}
@Override
public String marshal(ZonedDateTime v) throws Exception {
return dateTimeFormatter.format(v);
}
}
6.3 JAXB and CDATA
For some special characters in XML documents like <
and &
, we need CDATA.
We choose EclipseLink MOXy JAXB RI because there is a built-in @XmlCDATA
to wrap the text with CDATA
automatically.
import org.eclipse.persistence.oxm.annotations.XmlCDATA;
//...
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Staff {
//...
@XmlCDATA
String bio;
6.4 Run JAXB
The below JAXB example try to convert a list of objects to an XML document.
package com.mkyong.xml.jaxb;
import com.mkyong.xml.jaxb.model.Company;
import com.mkyong.xml.jaxb.model.Staff;
// @Since 3.0.0, rebrand to jakarta.xml
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
// old APIs 2.3.*,
//import javax.xml.bind.JAXBContext;
//import javax.xml.bind.JAXBException;
//import javax.xml.bind.Marshaller;
import java.io.File;
import java.time.ZonedDateTime;
import java.util.Arrays;
public class JaxbExample {
public static void main(String[] args) {
JAXBContext jaxbContext = null;
try {
//jaxbContext = JAXBContext.newInstance(Company.class);
// EclipseLink MOXy needs jaxb.properties at the same package with Company.class or Staff.class
// Alternative, I prefer define this via eclipse JAXBContextFactory manually.
jaxbContext = org.eclipse.persistence.jaxb.JAXBContextFactory
.createContext(new Class[] {Company.class}, null);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
//jaxbMarshaller.marshal(createCompanyObject(), new File("C:\\test\\company.xml"));
jaxbMarshaller.marshal(createCompanyObject(), System.out);
// XML Unmarshalling
/*File file = new File("C:\\test\\company.xml");
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Company o = (Company) jaxbUnmarshaller.unmarshal(file);
System.out.println(o);*/
} catch (JAXBException e) {
e.printStackTrace();
}
}
private static Company createCompanyObject() {
Company comp = new Company();
comp.setName("ABCDEFG Enterprise");
Staff o1 = new Staff();
o1.setId(1);
o1.setName("mkyong");
o1.setSalary("8000 & Bonus");
o1.setBio("<h1>support</h1>");
o1.setJoinDate(ZonedDateTime.now().minusMonths(12));
Staff o2 = new Staff();
o2.setId(2);
o2.setName("yflow");
o2.setSalary("9000");
o2.setBio("<h1>developer & database</h1>");
o2.setJoinDate(ZonedDateTime.now().minusMonths(6));
comp.setList(Arrays.asList(o1, o2));
return comp;
}
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<company>
<name>ABCDEFG Enterprise</name>
<staff id="1">
<name>mkyong</name>
<Salary>8000 & Bonus</Salary>
<bio><![CDATA[<h1>support</h1>]]></bio>
<joinDate>2020-04-21T12:19:28.5450719+08:00</joinDate>
</staff>
<staff id="2">
<name>yflow</name>
<Salary>9000</Salary>
<bio><![CDATA[<h1>developer & database</h1>]]></bio>
<joinDate>2020-10-21T12:19:28.5450719+08:00</joinDate>
</staff>
</company>
7. JAXB Tips
Some commonly asked JAXB questions and tips.
7.1 XML pretty print
By default, the JAXB output the XML in compact mode.
<?xml version="1.0" encoding="UTF-8"?><fruit id="1">
<n>Banana</n><price>9.99</price></fruit>
For JAXB to output the XML in pretty print or formatted mode, and we can set the property Marshaller.JAXB_FORMATTED_OUTPUT
to true
.
// default false
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Output
<?xml version="1.0" encoding="UTF-8"?>
<fruit id="1">
<n>Banana</n>
<price>9.99</price>
</fruit>
7.2 Change the XML encoding
JAXB default XML encoding to encoding="UTF8"
, and we can configure a specified XML encoding via the property Marshaller.JAXB_ENCODING
.
// change XML encoding
jaxbMarshaller.setProperty(Marshaller.JAXB_ENCODING, "ISO-8859-1");
Output
<?xml version="1.0" encoding="ISO-8859-1"?>
7.3 Remove the XML declaration
Set the property Marshaller.JAXB_FRAGMENT
to true
, and it will remove the beginning XML declaration.
// default false
// remove <?xml version="1.0" encoding="UTF-8"?>
jaxbMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
Output
<fruit id="1">
<n>Banana</n>
<price>9.99</price>
</fruit>
7.4 Change the order of the fields
We can use @XmlType propOrder
to change the order of the fields written to the XML document.
Review the Fruit
class again.
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {
@XmlAttribute
int id;
@XmlElement(name = "n")
String name;
String price;
//...
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<fruit id="1">
<n>Banana</n>
<price>9.99</price>
</fruit>
We can use @XmlType propOrder
to control the order of the fields; for example, the below example wants to display the price
first.
package com.mkyong.xml.jaxb.model;
import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
@XmlRootElement
@XmlType(propOrder = {"price", "name"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {
@XmlAttribute
int id;
@XmlElement(name = "n")
String name;
String price;
//...
}
Output
<?xml version="1.0" encoding="UTF-8"?>
<fruit id="1">
<price>9.99</price>
<n>Banana</n>
</fruit>
7.5 Hide a specified field for mapping
We can use @XmlTransient
to hide or prevent a specific field from converting into XML.
import jakarta.xml.bind.annotation.XmlTransient;
//...
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Fruit {
@XmlAttribute
int id;
@XmlElement(name = "n")
String name;
// Prevents the mapping
@XmlTransient
String price;
Output
<?xml version="1.0" encoding="UTF-8"?>
<fruit id="1">
<n>Banana</n>
</fruit>
7.6 Implementation of JAXB-API has not been found
We need to provide a JAXB RI or implementation, refer to this article.
Related errors
- java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
- java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory
8. Download Source Code
$ git clone https://github.com/mkyong/core-java
$ cd java-xml
$ cd src/main/java/com/mkyong/xml/jaxb/
9. References
- JAXB Spec JSR-222
- Oracle – Introduction to JAXB
- Wikipedia – Jakarta EE
- WIkipedia – Jakarta XML Binding
- JAXB Users Guide
- EclipseLink MOXy
- Java Architecture for XML Binding (JAXB)
- Jakarta XML Binding
- Java 11 – JEP 320: Remove the Java EE and CORBA Modules
- Java 8 – ZonedDateTime examples
- Java 8 – How to convert String to LocalDate
- JAXBException: Implementation of JAXB-API has not been found
- Stackoverflow – How to generate CDATA block using JAXB?
- JAXB on Java 9, 10, 11 and beyond
For single-time use JAXB has a handy facade.
JAXB.marshal(customer, new File("C:/file.xml"));
Customer customer = JAXB.unmarshall(new File("C:/file.xml"), Customer.class);
Hi Mkyong,
Another thing to point out about JAXB is that since it is a specification (JSR-222), there are multiple implementations: Metro, EclipseLink JAXB (MOXy), Apache JaxMe, etc.
For an example of specifying another JAXB provider see:
– http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
-Blaise
How would I parse below 2 xmls using JAXB when the XSD defines the body tag of type anyType, and can have either type Cust or Acc depending on the namespace prefix how can they be parsed to respective Class types.
body tag have Cust type in the below example:
body tag have Acc type in the below example:
Note – Either to annotate all fields or all getter methods in your Entity bean. A mix of both is not supported.
@XmlAccessorType(XmlAccessType.FIELD) at the class level if you want to annotate private fields instead of getter methods.
Hope this will be help. Thanks!!
Does Jakarta have a static utility class with prefabbed XmlJavaTypeAdapter’s for commonly used java data types… particularly the newer java data types?
I get that writing a converter is fairly easy and straight forward. But I’m find myself having copy the same implementation across all my disparate java projects. Seems like this should already be done for me.
There used to be javax.xml.bind.DatatypeConverter which has disappeared? Is there a replacement?
Hi,
can this framework convert xml constructs like following to java objects as well?
value of something
And if it can: How?
value of element
I cant show what I mean. I try to explain what I mean:
A element with an attribute and a value
element attribute=”valueOfAttribute” > Value of Element < element
Many thanks for posting this.
How about using JAXB to generate Java classes from xsd?
right click on the project -> new -> other -> JAXB Classes from Schema (if that doesn’t exist – in Eclipse, you need to install the JAXB plugin for Eclipse)