Skip to main content

JAXB 2.0 annotations and POJO classes that implement non JAXB interfaces

3 replies [Last post]
aaronanderson
Offline
Joined: 2004-01-23
Points: 0

I am attempting to use JAXB to bind some POJO to the X3D(www.web3d.org) schema. Instead of using the schema generator I want to use my own classes that implement the X3D Scene Access Interface (SAI) interfaces.

The X3D specification is broken into multiple components so my plan is for each component to create a different package and in each package have a jaxb.index that lists the POJO objects in that package that have JAXB annotations for binding to the X3D content model. Each of my POJO's are annotated with JAXB 2.0 annotations and implement the SAI as well so I can parse in a X3D document using JAXB and then have the ability to use the SAI interface methods to manipulate the content tree.

However, in practice when I try to unmarshal a trivial X3D document I am getting JAXB exceptions stating that the SAI interfaces do not have default constructors. I am confused as to why these classes are evaluated by JAXB since they do not have any annotations nor are they in the jaxb.index

Here is an example of what I am trying to do

in package test I have a file jaxb.index that has two lines:
Runtime
MyProfile

and the following three classes :

@XmlRootElement("X3D")
public class Runtime implements ExcecutionContext{

@XmlAttribute("profile")
@XmlJavaTypeAdapter(ProfileAdapter.class)
MyProfile profile;

...
}

public class MyProfile implements ProfileInfo{...}

public class ProfileAdapter extends XmlJavaTypeAdapter{...}

and in the package org.web3d.sai:
interface ExecutionContext {...}
interface ProfileInfo {...}

and finally the X3D document (doesn't even read it in)

I am getting the JAXB exception that ProfileInfo does not contain a default constructor. Perhaps I need to add a getProfile() and setProfile(MyProfile) methods to Runtime?

JAXBContext ctx = JAXBContext.newInstance("test"); //throws error

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kohsuke
Offline
Joined: 2003-06-09
Points: 0

I don't see why the problem happens, either. Can you send me the result of .printStackTrace() for the JAXBException? It includes the "reference path" to the problem, and that can tell why JAXB thinks it needs to look at ProfileInfo.

The other thing that caught my attention is that you are writing an adapter between String and your own class, which is somewhat unusual. Is that because you need to invoke a particular kind of MyProfile constructor?

Have you considered using "JAXBContext.newInstance(Runtime.class). Every class that gets referenced from Root will be automatically sucked into the JAXBContext in this way, and you don't have to maintain a separate list of classes.

aaronanderson
Offline
Joined: 2004-01-23
Points: 0

It looks like I missed a getProfile(ProfileInfo profile) in my Runtime class. After removing it I get

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
The type of the getter is org.web3d.x3d.sai.ProfileInfo but that of the setter is org.nexus3d.profile.Nexus3DProfile. They have to be the same.
this problem is related to the following location:
at public volatile org.web3d.x3d.sai.ProfileInfo org.nexus3d.runtime.Runtime.getProfile()
at org.nexus3d.runtime.Runtime
this problem is related to the following location:
at public void org.nexus3d.runtime.Runtime.setProfile(org.nexus3d.profile.Nexus3DProfile)
at org.nexus3d.runtime.Runtime

at com.sun.xml.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:66)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:328)
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.(JAXBContextImpl.java:198)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:76)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:55)
at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:124)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:589)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:132)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:299)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:358)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:323)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:244)

with the code

@XmlRootElement(name="X3D")
public class Runtime implements X3DExecutionContext {

Nexus3DProfile profile;

@XmlAttribute(name="profile")
@XmlJavaTypeAdapter(ProfileAdapter.class)
public Nexus3DProfile getProfile(){
return profile;
}

public void setProfile(Nexus3DProfile profile){
this.profile = profile;
}
}

public class Nexus3DProfile implements ProfileInfo {..}

I guess JAXB is getting the return type from the interface instead of the class that has the annotation. This may be a limitation of reflection so maybe this approach will not work.

cmuk
Offline
Joined: 2003-06-13
Points: 0

If you have a public getter and setter, its very important to remember not to have the public access modifiers for class level variables. This will conflict and you would get exceptions that there are "n" counts of
IllegalAnnotationExceptions.