Monday, October 8, 2007

JAXBContext Issues

I really like the Java API for XML Binding (JAXB). While there are many specifications and technologies that seem oversold or otherwise disappointing, JAXB repeatedly proves itself useful, easy to work with, and lives up to its hype. That being stated, there are times when working with the JAXB reference implementation (RI) has been slightly less straightforward than I would have hoped. This blog entry summarizes a few related issues that I have run into when using JAXB and how I got around them.

As shown in the "Java Web Services Tutorial" section covering Basic Examples of Using JAXB, a JAXBContext is obtained by calling JAXBContext.newInstance(). In the examples on this page, all calls to JAXBContext.newInstance are passed a single argument (a String representing a context path). For many applications using JAXB RI, this approach to acquiring a JAXBContext is sufficient.

Unfortunately, I have run into situations where I have needed to use a different version of JAXBContext.newInstance() to get my applications to work properly without exception. As shown in the Java EE 5 Javadoc documentation for JAXBContext, there are five different versions of the newInstance method. The version that I often need to use to avoid exceptions is the newInstance method that accepts the String as a context path and accepts a ClassLoader. For the second argument, the ClassLoader, it seems best and easiest to use ClassLoader.getSystemClassLoader().

Even when explicitly passing in a ClassLoader to the newInstance method, I have observed other conditions that can cause a JAXBException to occur when trying to obtain the JAXBContext. One of these issues is the conflict between the JAXB 2.0 RI that comes with Java SE 6 and the JAXB 2.1 that comes with the GlassFish Java EE application server reference implementation. The conflict is covered in jaxb: Unofficial JAXB Guide - Migrating JAXB 2.0 Applications to Java SE 6, which explains different ways to resolve the problem. I think that the easiest method is to simply copy the appropriate libraries into the JRE endorsed area. Kohsuke Kawaguchichi's blog entry JAXB 2.1 released also covers the issue of running a JAXB 2.1 implementation (such as comes with GlassFish v2) in a Java SE 6 environment and mentions using the Java Endorsed Standards Override Mechanism. The document Which JAXB RI is Included in Which JDK provides some useful information as well.

Rama Pulavarthi covers a similar problem (and an endorsed libraries fix related to use of JAXB and JAX-WS) in his blog entry Problems Using JAX-WS 2.1 and JAXB 2.1 with Java 6.

Finally, even with an appropriate class loader explicitly passed to JAXBContext.newInstance and the proper libraries from GlassFish copied into my JRE's endorsed libraries folder, I have occasionally still run into problems trying to obtain a JAXBContext. When all of the previous recommendations have been handled, the problem has usually been conflicting versions of Java JRE on my machine. To fix this on a Windows machine, I have ensured that only one version of Java (one JDK and one JRE directory) reside in the "Program Files/Java" directory. Also, I have ensured that no other conflicting Java versions, such as in System32 directory, are causing problems.

To summarize, exceptions encountered when trying to obtain a JAXBContext can usually be resolved by taking the following steps:

  1. Ensuring that JAXB implementation classes are in my classpath. This is not covered previously in this blog and should not usually be an issue anymore (in Java SE 6) because the JAXB reference implementation comes with Java SE 6.

  2. Explicitly pass a classloader to the JAXBContext.newInstance method to avoid confusion about the appropriate class loader.

  3. Copying appropriate endorsed libraries from GlassFish directory to Java SE JRE endorsed libs directory when using GlassFish with JAXB 2.1 and Java SE 6.0 with JAXB 2.0.

  4. Removing old versions of Java from system or at least moving old, unused versions into directories other than normal location of Java installation.

This blog entry may make use of JAXB RI sound more difficult than it normally is. I have used this entry to capture my experience and lessons learned from working with the JAXB RI, but overall I have been very happy with it. I have used JAXB in many different situations and find it extremely easy to use in most cases. One nice use of JAXB is described in my OTN (Oracle Technology Network) article Better JPA, Better JAXB, and Better Annotations Processing with Java SE 6.

No comments: