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>