7

I am running a test on Ubuntu with Oracle Java 7 Update 3. According to the release notes it has JAXB-2.2.4 included with it.

/home/ubuntu# update-alternatives --config java
There is only one alternative in link group java: /usr/lib/jvm/java-7-oracle/bin/java
Nothing to configure.

The machine says it has JAXB-2.2.4 on it:

$ wsimport -version
JAX-WS RI 2.2.4-b01

$ java -version

java version "1.7.0_03"
Java(TM) SE Runtime Environment (build 1.7.0_03-b04)
Java HotSpot(TM) Client VM (build 22.1-b02, mixed mode)

However when I run my app which uses JAX-RS and marshalls some objects with JAXB I get the following error:

Apr 05, 2012 10:45:50 AM com.sun.jersey.api.json.JSONConfiguration natural
SEVERE: NATURAL JSON notation configured, but JAXB RI 2.1.10 not found. For the
recent builds to get this working correctly, you need even at least JAXB version
 2.1.12. Please add it to your classpath!
Apr 05, 2012 10:45:50 AM com.sun.jersey.core.spi.component.ProviderFactory __get
ComponentProvider
SEVERE: The provider class, class com.marketchorus.rest.config.JAXBContextResolv
er, could not be instantiated. Processing will continue but the class will not b
e utilized
java.lang.RuntimeException: NATURAL JSON notation configured, but JAXB RI 2.1.10
 not found. For the recent builds to get this working correctly, you need even a
t least JAXB version 2.1.12. Please add it to your classpath!

On the server side I got that same error initially so I installed metro-2.2-standalone into tomcat which fixed the issue. (Even though it was running in java 7).

On a windows client I was forced to add JAXB-2.2.5 api, impl, and jsr173 jars to my endorsed java directory to make it work (with Java 7 update 3 there as well).

When I try to do the jaxb trick under ubuntu I put the files under /usr/lib/jvm/java-7-oracle/jre/lib/endorsed I get a different error:

ERROR 10:55:44.694 taskScheduler-1 org.springframework.scheduling.support.TaskUt
ils$LoggingErrorHandler - Unexpected error occurred in scheduled task.
javax.xml.stream.FactoryConfigurationError: Provider com.bea.xml.stream.MXParser
Factory not found

I am initializing the JAX-RS/JAXB code in my class as follows:

config = new DefaultClientConfig();
config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
config.getClasses().add(JAXBContextResolver.class);
client = Client.create(config);
service = client.resource(UriBuilder.fromUri(proc.getUrl()).build());

I tried to compile it with source=1.7 and target=1.7 as it was still set for 1.6 and I was thinking maybe it was assuming the old version from the early 1.6 releases which was too old but that doesn't solve the problem either.

I ran @andih's test program and I still get the error. I am starting to think it is a VM issue:

ubuntu@ip-10-202-155-29:~/test$ java -cp jersey-client-1.12.jar:jersey-core-1.1
2.jar:jersery-fastinfoset-1.12.jar:jersey-json-1.12.jar:. TestNaturalJson
Apr 23, 2012 10:17:21 AM com.sun.jersey.api.json.JSONConfiguration natural
SEVERE: NATURAL JSON notation configured, but JAXB RI 2.1.10 not found. For the
recent builds to get this working correctly, you need even at least JAXB version
 2.1.12. Please add it to your classpath!
Exception in thread "main" java.lang.RuntimeException: NATURAL JSON notation con
figured, but JAXB RI 2.1.10 not found. For the recent builds to get this working
 correctly, you need even at least JAXB version 2.1.12. Please add it to your cl
asspath!
        at com.sun.jersey.api.json.JSONConfiguration.natural(JSONConfiguration.j
ava:447)
        at TestNaturalJson.main(TestNaturalJson.java:6)
ubuntu@ip-10-202-155-29:~/test$ java -version
java version "1.7.0_03"
Java(TM) SE Runtime Environment (build 1.7.0_03-b04)
Java HotSpot(TM) Client VM (build 22.1-b02, mixed mode)

Looking back at the endorsed solution with JAXB-2.2.5 RI I installed the files:

jaxb-api.jar
jaxb-impl.jar
jsr173_1.0_api.jar

into the:

/usr/lib/jvm/java-7-oracle/jre/lib/endorsed

Directory. When I do that I get the above error from Spring the MXParser error. The wierd thing here is under windows this works, but not on Ubuntu. When I run @andhi's test program below with the endorsed setup I get OK instead of the error. But for some reason it looks like Spring under Ubuntu isn't picking up the JSR173 jar file that is installed in the endorsed dir (which is the STAX implementation).

haskovec
  • 370
  • 3
  • 12
  • I wonder why a "com.bea." class is refered as provider. Do you have WebLogic or JRockit classes in your ClassPath or somewhere on your system ? It may explain it conflicts with included versions of your JDK... – Yves Martin Apr 20 '12 at 05:21
  • Is it possible for you to post a code snippet, or even better a SSCCE ? – Yves Martin Apr 20 '12 at 05:23
  • We don't use weblogic or JRocket. Basically I fired up an Amazon EC2 instance where I want this service to run. I then installed Oracle JDK 7 from a PPA Package. http://www.webupd8.org/2012/01/install-oracle-java-jdk-7-in-ubuntu-via.html I think the bea stuff is part of the reference implementation of JAXB. I was able to make this work on my windows machine by installing JAXB 2.2.5 in my endorsed Directory of the Java VM. When I tried the same thing on ubuntu it didn't work. (I tried in /usr/lib/jvm/java-7-oracle/jre/endorsed). – haskovec Apr 20 '12 at 17:13
  • Can you use VisualVM from Oracle JDK and check if your java application uses JDK. I think that your app is running under different one. – chalimartines Apr 20 '12 at 17:21
  • 1
    SSCCE == [Short, Self Contained, Correct (Compilable), Example](http://sscce.org/) – Jason Braucht Apr 20 '12 at 17:37
  • Since it is running on EC2 I can't run VisualVM as there is no X to forward. The only VM installed on the image is Oracle JDK 7 as I showed above. I witnessed similar behavior on my windows machines with Oracle JDK 7 as well and this app, but on Windows it was fixable by grabbing the JAXB RI and putting the libs in the jre endorsed directory. On the serverside when Tomcat 6 or 7 is running and launched with the same VM (as it shows you which VM is launching when you run startup.sh) I saw the same issue. It was fixed by installing the latest metro libraries into tomcat. – haskovec Apr 20 '12 at 20:16
  • @haskovez placing something into the endorsed directory is usually a bad idea. You should try to fix your classpath problems in your application / tomcat ... . Placing something into the endorsed directory of your JRE influences the classpath of all your applications and may cause unexpected behavior or classpath problems. – andih Apr 21 '12 at 05:11
  • @andih for the server side of this app, I solved the problem with putting metro into tomcat, but for the client side it is a command line program (using spring 3.1 and Jersey 1.12) I tried endorsed as it seemed the only option if it wasn't picking up the stuff out of the Java 7 rt.jar. That being said endorsed only worked on windows but not on ubuntu where this will be deployed. – haskovec Apr 21 '12 at 18:06
  • Modifying the endorsed directory may help you. Are you the only user of the client? If you want to deploy your client on different machines with unknown environments modifying the endorsed dir is no valid solution. – andih Apr 21 '12 at 19:05
  • The Endorsed doesn't seem to play nice with spring under ubuntu. While it worked under windows I am now getting an error where it isn't picking up jsr-173, as it gives the provider error off of STAX when there is no implementation. – haskovec Apr 23 '12 at 18:16

3 Answers3

3

Seems to me like a Classpath Problem. Have you checked if there other jaxb-impl-x.y.z.jar or jaxb-api-k.l.m.jars in your classpath? The JSonConfiguration looks for the class com.sun.xml.bind.annotation.OverrideAnnotationOf which is part of the JRE7 rt.jar.

You can check your JRE installation using with the following simple programm:

import com.sun.jersey.api.json.JSONConfiguration;


public class TestNaturalJSon {
    public static void main(String[] args) {
        JSONConfiguration config = JSONConfiguration.natural().build();

        System.out.println("OK");

    }

}

If you use maven you can use a pom with the following dependencies:

<dependencies>
  <dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.12</version>

    <exclusions>
        <exclusion>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-impl</artifactId>
        </exclusion>
        <exclusion>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        </exclusion>
    </exclusions>

   </dependency>
</dependencies>
andih
  • 5,570
  • 3
  • 26
  • 36
  • I went through my lib dir to see if anytong else was pulling in that Class and it didn't come back with anything. I will try the test program of yours: for i in `ls`; do `jar -tvf $i | grep com.sun.xml.bind.annotation.OverrideAnnotationOf`; done – haskovec Apr 21 '12 at 18:02
  • jar -tvf rt.jar | grep Override returns `com/sun/xml/internal/bind/annotation/OverrideAnnotationOf.class'. I don't know which lib you've checked .If you've checked your appliction lib that's obvious otherwise the application would have found a valid JAXB implementation. You may have an old JAXB implementation on your classpath which does not contain the `OverrideAnnotationOf` class (i.e. JAXB < 2.1.0). If you want to find outdated JAXB search for 'javax/xml/bind/Marshaller.class'. If you just want to check your JRE you it's enough to check the `rt.jar` – andih Apr 21 '12 at 18:55
  • I have gone through all of my libs with jar | grep and none of them have the Marshaller in it. We use a script to build our whole classpath variable up for the app so I modified that script to check every jar. I can't see anything that would be overriding the base VM. I will try your test program now and see if I have any luck with that. – haskovec Apr 23 '12 at 15:00
2

To know from where a Class is loaded, you should run the JVM command line with -verbose:class option.

That way, you can guess what is wrong by looking at latest verbose lines just before the javax.xml.stream.FactoryConfigurationError exception is thrown, or just before the diagnostic message JAXB RI 2.1.10 not found.

So you can get the jar an implementation comes from and check that the endorsed directory is used or not...

Yves Martin
  • 10,217
  • 2
  • 38
  • 77
  • Thanks for the tip. I tried that and I see my endorsed jars being loaded so it is unclear why it is not working on ubuntu. I think I am just going to embed the app inside of a webapp so the container can just provide the libs. – haskovec Apr 24 '12 at 15:56
1

Well I appreciate all the comments on here, but no one managed to solve my problem, so I worked around it as follows. I installed Metro-2.2 into Tomcat 7. Then since my app is a Spring command line App I built a war out of it so it could run in the tomcat container. This involved putting all my libraries for my app in WEB-INF/lib my configuration files in WEB-INF/classes. In the WEB-INF dir I put a web.xml file that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd">
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/classes/remote-scheduler-spring-config.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>
</web-app>

index.jsp is empty as there is no web facing component to this app. The spring-config parameter is my top level spring config file that would get loaded from the command line. My ant build then builds a war out of this app, and it runs great. So still not sure why my endorsed files in the jvm didn't work as using the verbose:class flag as suggested showed them getting loaded, but by using tomcat as the container and loading the classes I need there, Jersey is happy and all the issues have gone away. Thanks again for all the help on this issue.

haskovec
  • 370
  • 3
  • 12
  • 1
    So you have use Tomcat for its specific classloading mechanism: the WAR ClassLoader give priority to WEB-INF/classes and WEB-INF/lib content BEFORE asking to the parent ClassLoader for resources. It solve your trouble but it is really heavy. Now you have a work-around, you should use your own ClassLoader to setup such a "parent-last" policy without running Tomcat you do not need: http://stackoverflow.com/questions/5445511/how-do-i-create-a-parent-last-child-first-classloader-in-java-or-how-to-overr – Yves Martin Apr 26 '12 at 05:52
  • I had never heard of the parent-last policy thanks for the link. I am still more concerned by the fact that they advertise having a new jaxb in the VM and I can't seem to actually use the latest features in it. All of the solutions required loading different jars (whether it was doing a new endorsed version of jaxb on windows or doing the tomcat thing on ubuntu). I still think there may be something wrong with the VM. – haskovec Apr 26 '12 at 12:49
  • If you want us to help, please post a runnable small part of your code as SSCCE. If your VM is wrong, ours may be not. – Yves Martin Apr 26 '12 at 13:31