JAXB Description:
JAXB is a set of tools and libraries used to generate class libraries specifically to parse a defined XML schema.
Java classes can be generated automatically for an XML schema as defined by an XSD file or can be coded manually.
This tutorial will show an example of using JAXB to generate classes automatically from an XSD.
The generated library will be used for parsing of an XML file conforming to the specified XSD schema.
JAXB Installation:
Two approaches can be taken. One is to use the Java JDK with the JAXB jar library and the other is to use the Java JDK exclusivly.
Apache Ant script examples for each approach are provided below.
As a prerequisite the Java JDK need to be installed. See our tutorial on installing Java on Linux.
This example was compiled and run with jdk1.8.0_112
If using the JAXB jar libraries, download the latest JAXB jar libraries from:
JAXB home page
cd /opt
unzip ~/Downloads/jaxb-ri-2.2.11.zip
Update your ~/.bashrc:
..
...
#
# JAXB
#
if [ -d /opt/jaxb-ri ]
then
PATH=/opt/jaxb-ri/bin:$PATH
export CLASSPATH=/opt/jaxb-ri/lib/jaxb-xjc.jar:$CLASSPATH
fi
...
..
Simple but less desirable (jar only and not complete SDK) alternative: The JAXB jaxb-xjc.jar, is available as a JAR file and can be placed in /opt/java/latest/lib/.
See: FindJar.com
If using JBoss, your CLASSPATH can reference JAXB from the JBoss library: /opt/jboss-X.X.X.XXXXX/lib/jaxb-xjc.jar
Generate JAXB class library:
Define an XML schema file (XSD) using your favorite XSD/XML editor:
File:
corporation.xsd
Generate a Java class library files from the XSD: xjc -d ./ corporation.xsd
For a description of commands try: xjc -help or java -jar $JAVA_HOME/lib/jaxb-xjc.jar -help
The following ant snippet will be used to perform this task:
01 | < taskdef name = "xjc" classname = "com.sun.tools.xjc.XJCTask" > |
02 | < classpath refid = "classpath" /> |
08 | < xjc schema = "corporation.xsd" package = "com.megacorp.projectx.xml.jaxb" destdir = "generated" > |
09 | < produces dir = "generated/com/megacorp/projectx/xml/jaxb" includes = "**/*.java" /> |
This will generate the Java classes:
JAXB XML Parsing Example:
File:
src/com/megacorp/projectx/xml/TestJaxb.java
01 | package com.megacorp.projectx.xml; |
04 | import java.util.Iterator; |
05 | import java.util.ArrayList; |
07 | import javax.xml.bind.JAXBContext; |
08 | import javax.xml.bind.JAXBElement; |
09 | import javax.xml.bind.JAXBException; |
10 | import javax.xml.bind.Unmarshaller; |
12 | import com.megacorp.projectx.xml.jaxb.Root; |
13 | import com.megacorp.projectx.xml.JAXBXMLHandler; |
14 | import com.megacorp.projectx.xml.JAXBXMLException; |
18 | static public void main (String[] args) |
20 | String fileName = "CorporationMegaX.xml" ; |
28 | System.out.println( "Error! Exception caught" ); |
33 | public static void readFile(String fileName) |
37 | java.io.File XMLfile = new java.io.File(fileName); |
38 | Root root = JAXBXMLHandler.unMarshal(Root. class ,XMLfile); |
39 | Root.Corporation corporation = root.getCorporation(); |
41 | System.out.println( "Corporation: " + corporation.getName()); |
42 | System.out.println( "Corp address: " + corporation.getAddress()); |
44 | Root.People people = root.getPeople(); |
46 | List<Root.People.Employee> employee = people.getEmployee(); |
47 | System.out.println( "There are " + employee.size() + " employees." ); |
48 | System.out.println( "Employees:" ); |
50 | for (Iterator employeeIter = employee.iterator(); employeeIter.hasNext();) { |
51 | Root.People.Employee employeeItem = (Root.People.Employee)employeeIter.next(); |
52 | String name = employeeItem.getName(); |
53 | System.out.println( " Employee Name: " + name); |
54 | String taxStatus = employeeItem.getTaxStatus().value(); |
55 | System.out.println( " Tax Status: " + taxStatus); |
56 | System.out.println( " Gender: " + employeeItem.getGender().value()); |
57 | String workPhone = employeeItem.getData().getWorkPhone(); |
58 | System.out.println( " Work Phone: " + workPhone); |
59 | if (taxStatus.equalsIgnoreCase( "US-W2" )) |
61 | System.out.println( " Employee Number: " + employeeItem.getUSW2().getEmpNumber()); |
62 | System.out.println( " Manager: " + employeeItem.getUSW2().getManager()); |
63 | System.out.println( " Start Year: " + employeeItem.getUSW2().getYearStart()); |
65 | else if (taxStatus.equalsIgnoreCase( "US-1099" )) |
67 | System.out.println( " SSN Number: " + employeeItem.getUS1099().getSsnNumber()); |
68 | System.out.println( " Corp Name: " + employeeItem.getUS1099().getCorpName()); |
69 | System.out.println( " Hire Relationship: " + employeeItem.getUS1099().getRelationship().value()); |
73 | System.out.println( "No tax status specified" ); |
79 | System.out.println( "Error! Exception caught" ); |
File:
src/com/megacorp/projectx/xml/JAXBXMLException.java
01 | package com.megacorp.projectx.xml; |
04 | * Checked exception thrown by Data Access Service layer to clients to report |
05 | * system level errors. |
08 | public class JAXBXMLException extends Exception { |
11 | * Construct a JAXBXMLException with no arguments. |
13 | public JAXBXMLException() { |
17 | public JAXBXMLException(Exception e) { |
22 | * Construct a JAXBXMLException with the specified message ID. |
24 | public JAXBXMLException( String msg ) { |
32 | public JAXBXMLException(String message, Exception exception) { |
33 | super (message, exception); |
File:
src/com/megacorp/projectx/xml/JAXBXMLHandler.java
01 | package com.megacorp.projectx.xml; |
05 | import java.util.Arrays; |
08 | import javax.xml.bind.JAXBContext; |
09 | import javax.xml.bind.JAXBException; |
10 | import javax.xml.bind.JAXBElement; |
11 | import javax.xml.bind.Marshaller; |
12 | import javax.xml.bind.Unmarshaller; |
13 | import javax.xml.transform.stream.StreamSource; |
14 | import com.megacorp.projectx.xml.JAXBXMLException; |
16 | public class JAXBXMLHandler { |
18 | public static <T> T unMarshal(Class<T> typeClass, File file) |
20 | throws JAXBXMLException { |
22 | JAXBContext jaxbContext = JAXBContext.newInstance(typeClass); |
23 | Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); |
27 | (T) jaxbUnmarshaller.unmarshal(file); |
29 | } catch (JAXBException e) { |
30 | throw new JAXBXMLException(e); |
31 | } catch (Exception e) { |
32 | throw new JAXBXMLException(e); |
XML data file:
CorporationMegaX.xml
01 | <? xml version = "1.0" encoding = "UTF-8" ?> |
04 | < Name >Corporation MegaX</ Name > |
05 | < Phone >1-800-555-1212</ Phone > |
06 | < Fax >1-877-555-1212</ Fax > |
07 | < Address >512 Megacorp Way, Gotham City</ Address > |
11 | < Employee TaxStatus = "US-W2" Gender = "Male" Desc = "OnSite" > |
12 | < Name >Mr Grand Kahuna</ Name > |
14 | < EmpNumber >1</ EmpNumber > |
15 | < Manager >None</ Manager > |
16 | < YearStart >1998</ YearStart > |
19 | < WorkPhone >1-800-555-1213</ WorkPhone > |
20 | < CellPhone >1-800-555-1214</ CellPhone > |
21 | < Address >100 Cherry Hill Lane, Gotham City</ Address > |
25 | < Employee TaxStatus = "US-1099" Gender = "Male" Desc = "OnSite" > |
26 | < Name >Mr Special Tee</ Name > |
28 | < SsnNumber >123-45-6788</ SsnNumber > |
29 | < Phone >1-817-555-1212</ Phone > |
30 | < CorpName >ABC Consulting</ CorpName > |
31 | < CorpAddress >3 Mockingbird Lane, Smallville AK</ CorpAddress > |
32 | < Relationship >CorpToIndividual</ Relationship > |
35 | < WorkPhone >1-800-555-1215</ WorkPhone > |
36 | < CellPhone >1-800-555-1216</ CellPhone > |
37 | < Address >200 Lookout Hill, Gotham City</ Address > |
41 | < Employee TaxStatus = "US-W2" Gender = "Female" Desc = "OnSite" > |
42 | < Name >Mrs Jenny Reliable</ Name > |
44 | < EmpNumber >2</ EmpNumber > |
45 | < Manager >Mr Grand Kahuna</ Manager > |
46 | < YearStart >1999</ YearStart > |
49 | < WorkPhone >1-800-555-1217</ WorkPhone > |
50 | < CellPhone >1-800-555-1218</ CellPhone > |
51 | < Address >300 Riverside View, Gotham City</ Address > |
Building With Ant:
Two approaches are taken:
- # Reference the JAXB jar file library and use the Ant built-in "xjc" directive to generate the parser source
- # Reference the existing JAXB facilities within the Java JDK
1) Use the JAXB jar with the "xjc" directive:
Ant build script:
build.xml
01 | <? xml version = "1.0" encoding = "utf-8" ?> |
02 | < project basedir = "." default = "run" > |
03 | < property name = "jaxb.home" value = "." /> |
05 | < pathelement path = "src" /> |
06 | < pathelement path = "classes" /> |
07 | < pathelement path = "schemas" /> |
08 | < fileset dir = "${jaxb.home}" includes = "/opt/jaxb-ri/lib/*.jar" /> |
10 | < taskdef name = "xjc" classname = "com.sun.tools.xjc.XJCTask" > |
11 | < classpath refid = "classpath" /> |
15 | < target name = "jaxb" description = "Generate JAXB classes" > |
16 | < echo message = "Compiling the schema..." /> |
17 | < mkdir dir = "gen-src/com/megacorp/projectx/xml/jaxb" /> |
18 | < xjc schema = "corporation.xsd" package = "com.megacorp.projectx.xml.jaxb" destdir = "gen-src" > |
19 | < produces dir = "gen-src/com/megacorp/projectx/xml/jaxb" includes = "**/*.java" /> |
24 | < target name = "compile" depends = "jaxb" description = "Compile all Java source files" > |
25 | < echo message = "Compiling the java source files..." /> |
26 | < mkdir dir = "classes" /> |
27 | < javac destdir = "classes" debug = "on" includeAntRuntime = "false" > |
28 | < src path = "src/com/megacorp/projectx/xml" /> |
29 | < src path = "gen-src" /> |
30 | < classpath refid = "classpath" /> |
34 | < target name = "run" depends = "compile" description = "Run the sample app" > |
35 | < echo message = "Running the sample application..." /> |
36 | < java classname = "com.megacorp.projectx.xml.TestJaxb" fork = "true" > |
37 | < classpath refid = "classpath" /> |
41 | < target name = "javadoc" description = "Generates javadoc" depends = "compile" > |
42 | < echo message = "Generating javadoc..." /> |
43 | < mkdir dir = "docs/api" /> |
44 | < javadoc sourcepath = "gen-src" destdir = "docs/api" windowtitle = "Using unmarshaller" useexternalfile = "yes" > |
45 | < fileset dir = "." includes = "gen-src/**/*.java" /> |
49 | < target name = "clean" description = "Deletes all the generated artifacts." > |
50 | < delete dir = "docs/api" /> |
51 | < delete dir = "gen-src" /> |
52 | < delete dir = "schemas" /> |
53 | < delete dir = "classes" /> |
Compile:
ant compile
[user1@tux JavaJaxb]$ ant compile
ant compileBuildfile: /home/user1/Desktop/JavaJaxb/build.xml
jaxb:
[echo] Compiling the schema...
[mkdir] Created dir: /home/user1/Desktop/JavaJaxb/gen-src/com/megacorp/projectx/xml/jaxb
[xjc] Compiling file:/home/user1/Desktop/JavaJaxb/corporation.xsd
[xjc] Writing output to /home/user1/Desktop/JavaJaxb/gen-src
compile:
[echo] Compiling the java source files...
[javac] Compiling 9 source files to /home/user1/Desktop/JavaJaxb/classes
[javac] Note: /home/user1/Desktop/JavaJaxb/src/com/megacorp/projectx/xml/JAXBXMLHandler.java uses unchecked or unsafe operations.
[javac] Note: Recompile with -Xlint:unchecked for details.
BUILD SUCCESSFUL
Total time: 1 second
[Potential Pitfall]:
You may get the following error: taskdef class com.sun.tools.xjc.XJCTask cannot be found
This typically means that jaxb-xjc.jar is missing from your classpath
Run:
ant run
[user1@tux JavaJaxb]$ ant run
run:
[echo] Running the sample application...
[java] Corporation: Corporation MegaX
[java] Corp address: 512 Megacorp Way, Gotham City
[java] There are 3 employees.
[java] Employees:
[java] Employee Name: Mr Grand Kahuna
[java] Tax Status: US-W2
[java] Gender: Male
[java] Work Phone: 1-800-555-1213
[java] Employee Number: 1
[java] Manager: None
[java] Start Year: 1998
[java] Employee Name: Mr Special Tee
[java] Tax Status: US-1099
[java] Gender: Male
[java] Work Phone: 1-800-555-1215
[java] SSN Number: 123-45-6788
[java] Corp Name: ABC Consulting
[java] Hire Relationship: CorpToIndividual
[java] Employee Name: Mrs Jenny Reliable
[java] Tax Status: US-W2
[java] Gender: Female
[java] Work Phone: 1-800-555-1217
[java] Employee Number: 2
[java] Manager: Mr Grand Kahuna
[java] Start Year: 1999
2) Reference the Java JDK only:
This method does not require the JAXB jar file and relies on JAXB as it resides in the JDK.
The only change in the Ant build script is the target "jaxb" which will execute the Java "xjc" compiler to generate the parser code.
Ant build script:
build.xml
01 | <? xml version = "1.0" encoding = "utf-8" ?> |
02 | < project basedir = "." default = "run" > |
03 | < property name = "jaxb.home" value = "." /> |
05 | < pathelement path = "src" /> |
06 | < pathelement path = "classes" /> |
07 | < pathelement path = "schemas" /> |
08 | < fileset dir = "${jaxb.home}" includes = "/opt/jaxb-ri/lib/*.jar" /> |
10 | < taskdef name = "xjc" classname = "com.sun.tools.xjc.XJCTask" > |
11 | < classpath refid = "classpath" /> |
15 | < target name = "jaxb" description = "Generate JAXB classes" > |
16 | < echo message = "Compiling the schema..." /> |
17 | < mkdir dir = "gen-src/com/megacorp/projectx/xml/jaxb" /> |
18 | < exec executable = "xjc" > |
20 | < arg value = "gen-src/com/megacorp/projectx/xml/jaxb" /> |
22 | < arg value = "com.megacorp.projectx.xml.jaxb" /> |
23 | < arg value = "corporation.xsd" /> |
28 | < target name = "compile" depends = "jaxb" description = "Compile all Java source files" > |
29 | < echo message = "Compiling the java source files..." /> |
30 | < mkdir dir = "classes" /> |
31 | < javac destdir = "classes" debug = "on" includeAntRuntime = "false" > |
32 | < src path = "src/com/megacorp/projectx/xml" /> |
33 | < src path = "gen-src" /> |
34 | < classpath refid = "classpath" /> |
38 | < target name = "run" depends = "compile" description = "Run the sample app" > |
39 | < echo message = "Running the sample application..." /> |
40 | < java classname = "com.megacorp.projectx.xml.TestJaxb" fork = "true" > |
41 | < classpath refid = "classpath" /> |
45 | < target name = "javadoc" description = "Generates javadoc" depends = "compile" > |
46 | < echo message = "Generating javadoc..." /> |
47 | < mkdir dir = "docs/api" /> |
48 | < javadoc sourcepath = "gen-src" destdir = "docs/api" windowtitle = "Using unmarshaller" useexternalfile = "yes" > |
49 | < fileset dir = "." includes = "gen-src/**/*.java" /> |
53 | < target name = "clean" description = "Deletes all the generated artifacts." > |
54 | < delete dir = "docs/api" /> |
55 | < delete dir = "gen-src" /> |
56 | < delete dir = "schemas" /> |
57 | < delete dir = "classes" /> |
Note that the JAXB execution requires the "xjc" command to be in your path.
This is typically
/opt/java/latest/bin/
Building With Maven:
Unlike Ant which explicitly specifies the configuration, Maven requires that the user operate under its convention.
Maven expects to find source located in directories specified by its convention.
Thus use the following directory layout:
pom.xml
CorporationMegaX.xml
src/main/java/com/megacorp/projectx/xml/TestJaxb.java
JAXBXMLException.java
JAXBXMLHandler.java
src/main/resources/corporation.xsd
Maven will generate the rest.
Maven build script:
pom.xml
01 | <? xml version = "1.0" encoding = "utf-8" ?> |
05 | < modelVersion >4.0.0</ modelVersion > |
08 | < groupId >com.megacorp.projectx</ groupId > |
09 | < artifactId >ProjectX</ artifactId > |
10 | < version >1.0.0</ version > |
11 | < packaging >jar</ packaging > |
17 | < groupId >org.apache.maven.plugins</ groupId > |
18 | < artifactId >maven-compiler-plugin</ artifactId > |
28 | < groupId >org.jvnet.jaxb2.maven2</ groupId > |
29 | < artifactId >maven-jaxb2-plugin</ artifactId > |
30 | < version >0.13.1</ version > |
42 | < generateDirectory >src/generated-sources/java</ generateDirectory > |
43 | < generatePackage >com.megacorp.projectx.xml.jaxb</ generatePackage > |
Compile/build:
mvn package
[user1@tux JavaJaxb]$ mvn package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building ProjecX 1.0.0
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-jaxb2-plugin:0.13.1:generate (default) @ ProjectX ---
[INFO] Up-to-date check for source resources [[file:/home/user1/ProjectX/src/main/resources/corporation.xsd, file:/home/user1/ProjectX/pom.xml]] and target resources [[file:/home/user1/ProjectX/src/generated-sources/java/com/megacorp/projectx/xml/jaxb/Root.java, file:/home/user1/ProjectX/src/generated-sources/java/com/megacorp/projectx/xml/jaxb/EGender.java, file:/home/user1/ProjectX/src/generated-sources/java/com/megacorp/projectx/xml/jaxb/ERelation.java, file:/home/user1/ProjectX/src/generated-sources/java/com/megacorp/projectx/xml/jaxb/ETaxStatus.java, file:/home/user1/ProjectX/src/generated-sources/java/com/megacorp/projectx/xml/jaxb/ObjectFactory.java, file:/home/user1/ProjectX/src/generated-sources/java/com/megacorp/projectx/xml/jaxb/ELocation.java, file:/home/user1/ProjectX/src/generated-sources/java/META-INF/sun-jaxb.episode]].
[INFO] Latest timestamp of the source resources is [2017-09-02 22:06:10.000], earliest timestamp of the target resources is [2017-09-02 22:06:22.000].
[INFO] Sources are up-to-date, XJC will be skipped.
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ ProjectX ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] Copying 1 resource
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ ProjectX ---
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 9 source files to /home/user1/ProjectX/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ ProjectX ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/user1/ProjectX/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ ProjectX ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ ProjectX ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ ProjectX ---
[INFO] Building jar: /home/user1/ProjectX/target/ProjectX-1.0.0.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.702s
[INFO] Finished at: Sat Sep 02 22:08:33 PDT 2017
[INFO] Final Memory: 16M/359M
[INFO] ------------------------------------------------------------------------
Run:
java -cp ./target/ProjectX-1.0.0.jar com.megacorp.projectx.xml.TestJaxb
Corporation: Corporation MegaX
Corp address: 512 Megacorp Way, Gotham City
There are 3 employees.
Employees:
Employee Name: Mr Grand Kahuna
Tax Status: US-W2
Gender: Male
Work Phone: 1-800-555-1213
Employee Number: 1
Manager: None
Start Year: 1998
Employee Name: Mr Special Tee
Tax Status: US-1099
Gender: Male
Work Phone: 1-800-555-1215
SSN Number: 123-45-6788
Corp Name: ABC Consulting
Hire Relationship: CorpToIndividual
Employee Name: Mrs Jenny Reliable
Tax Status: US-W2
Gender: Female
Work Phone: 1-800-555-1217
Employee Number: 2
Manager: Mr Grand Kahuna
Start Year: 1999
Complex Types with Mixed Content:
Our example above is for a standard XML file containing only XML content.
This is common for configuration files.
This is specified in our example by the XML XSD schema:
<xs:element name="US-1099">
<xs:complexType mixed="false">
...
...
</xs:complexType>
One can also have mixed content where there is plain text around the XML content.
The XSD would be stated as:
<xs:element name="US-1099">
<xs:complexType mixed="true">
...
...
</xs:complexType>
and the XML would have plain text mixed with the XML as in this example snippet:
<US-1099>
SSN Number: <SsnNumber>123-45-6788</SsnNumber>
Phone Number: <Phone>1-817-555-1212</Phone>
Corporation: <CorpName>ABC Consulting</CorpName>
Corp Adress: <CorpAddress>3 Mockingbird Lane, Smallville AK</CorpAddress>
Relationship: <Relationship>CorpToIndividual</Relationship>
</US-1099>
JAXB can handle a complexType with a "mixed" text of both "true" and "false"
but only with a substantial change to the code.
First note the the generated code is different:
One can avoid the mixed text hassle by using XmlBeans or you can code for this conditions.
Here is a solid coding discussions on this topic:
Links:
YoLinux Tutorials:

Books:
 |
"Core Java 2, Volume 1: Fundamentals "
by Cay S. Horstmann, Gary Cornell
ISBN # 0132354764, Prentice Hall PTR 8th edition
The industry standard. Need I say more?
|
|
 |
"Core Java 2: Volume 2 Advanced Features "
by Cay S. Horstmann, Gary Cornell
ISBN # 0132354799, Prentice Hall PTR 8th edition
The industry standard. Need I say more?
|
|
 |
"Core Java Server Faces"
by David Geary, Cay S. Horstmann
ISBN # 0131738860, Prentice Hall PTR 2nd edition
|
|
 |
"JSP, Servlets, and MySQL"
by David Harms
ISBN # 0764547879, Hungry Minds, Inc
|
|