I am working on a a very simple Eclipse Plug-in with which uses EclipseLink's MOXy for XML binding (marshalling/unmarshalling). I get a couple of errors when I try to marshall a simple class (Person.java) during the starting process of the plugin (Activator.java). Here's the code:
Person.java
package test_rcp;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Activator.java
package test_rcp;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
public class Activator extends AbstractUIPlugin {
public void start(BundleContext context) throws Exception {
super.start(context);
plugin = this;
// Just to make sure EclipseLink is already loaded
System.out.println(org.eclipse.persistence.Version.getVersion());
Person p1 = new Person();
p1.setName("John Dewey");
p1.setAge(54);
JAXBContext jc = JAXBContext.newInstance("test_rcp",Person.class.getClassLoader());
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(p1, System.out);
}
}
MANIFEST.MF
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Test-RCP
Bundle-SymbolicName: Test-RCP; singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: test_rcp.Activator
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.persistence.core,
org.eclipse.persistence.moxy;bundle-version="2.4.1"
Bundle-ActivationPolicy: lazy
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
The package test_rcp
also contains jaxb.index
and jaxb.properties
:
jaxb.index
Person
jaxb.properties
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Running the plug-in however throws the following exception:
javax.xml.bind.JAXBException: Provider org.eclipse.persistence.jaxb.JAXBContextFactory could not be instantiated:
javax.xml.bind.JAXBException: Provider class org.eclipse.persistence.jaxb.JAXBContextFactory could not be instantiated:
javax.xml.bind.JAXBException:
ClassCastException: attempting to cast bundleresource://43.fwk583158213/javax/xml/bind/JAXBContext.class to jar:file:/usr/lib/jvm/java-7-oracle/jre/lib/rt.jar!/javax/xml/bind/JAXBContext.class. Please make sure that you are specifying the proper ClassLoader.
I understand that the problem arises from the fact that two class loaders have loaded javax.xml.bind
package, but I cannot figure out why and how to avoid this.
Morover, by using JAXBContextFactory
instead of JAXBContext.newInstance
(as suggested here), i.e.:
JAXBContext jc = org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(new Class[] {Person.class}, null);
I would get the following exception:
java.lang.LinkageError: loader constraint violation:
loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) previously
initiated loading for a different type with name "javax/xml/bind/JAXBContext"
I have already tried out following solutions with no success:
https://stackoverflow.com/a/12943115/2295964
https://stackoverflow.com/a/11797373/2295964
I would really appreciate if someone could help me getting out of this misery!
You need to ensure that you import the javax.xml.bind
bundle instead of getting the JAXB APIs from the JRE.