When using WildFly or JBoss EAP, the JAXB implementation is defined by the following specification in module.xml:
<module name="javax.xml.bind.api" xmlns="urn:jboss:module:1.7">
<dependencies>
<module name="javax.activation.api" export="true"/>
<module name="javax.xml.stream.api"/>
<module name="com.sun.xml.bind" services="import"/>
<module name="javax.api"/>
</dependencies>
<resources>
<resource-root path="jboss-jaxb-api_2.3_spec-1.0.1.Final-redhat-1.jar"/>
</resources>
</module>
In order to check the actual JAXB implementation, you can just create a new Instance of JAXBContext and execute a getClass() againsts its name:
@WebServlet(value = "/jaxb" )
public class DemoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) {
try {
PrintWriter out = res.getWriter();
JAXBContext jc = JAXBContext.newInstance(Employee.class);
String jcClassName = jc.getClass().getName();
out.println(jcClassName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@XmlRootElement
public class Employee {
private int id;
private String name;
private float salary;
public Employee() {}
public Employee(int id, String name, float salary) {
super();
this.id = id;
this.name = name;
this.salary = salary;
}
@XmlAttribute
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
}
If you want to check the exact version of your JAXB implementation, the following code will do it:
if (jc instanceof com.sun.xml.bind.v2.runtime.JAXBContextImpl) {
out.println("JAXB Version: " +
((com.sun.xml.bind.v2.runtime.JAXBContextImpl) jc).getBuildId());
}
Furthermore, if you want to check the JAXB implementation for a specific class, then you can do it as follows:
/**
* Print the JAXB Implementation information
*/
public static void outputJaxpImplementationInfo() {
logger.debug(getImplementationInfo("DocumentBuilderFactory", DocumentBuilderFactory.newInstance().getClass()));
logger.debug(getImplementationInfo("XPathFactory", XPathFactory.newInstance().getClass()));
logger.debug(getImplementationInfo("TransformerFactory", TransformerFactory.newInstance().getClass()));
logger.debug(getImplementationInfo("SAXParserFactory", SAXParserFactory.newInstance().getClass()));
}
/**
* Get the JAXB implementation information for a particular class
* @param componentName
* @param componentClass
* @return
*/
private static String getImplementationInfo(String componentName, Class componentClass) {
CodeSource source = componentClass.getProtectionDomain().getCodeSource();
return MessageFormat.format(
"{0} implementation: {1} loaded from: {2}",
componentName,
componentClass.getName(),
source == null ? "Java Runtime" : source.getLocation());
}
Building JAXB applications using Java 11 or newer
According to the release-notes, Java 11 removed the Java EE modules:
java.xml.bind (JAXB)- REMOVED
- Java 8 – OK
- Java 9 – DEPRECATED
- Java 10 – DEPRECATED
- Java 11 – REMOVED
You can fix the issue by using alternate versions of the Java EE technologies. Simply add Maven dependencies that contain the classes you need:
<dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-core</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.0</version> </dependency>
Jakarta EE 8 update
For Jakarta EE users, you can fix the issue by using Jakarta XML Binding from Jakarta EE 8:
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.3</version></dependency>