Skip to main content

@XmlJavaTypeAdapter for class without a no-arg constructor

2 replies [Last post]
alewando
Offline
Joined: 2006-06-13
Points: 0

I've got a class that doesn't have a no-arg constructor that I want to marshal with JAXB 2.1. I've created an adapter class and applied the @XmlJavaTypeAdapter annotation, but when I try to marshal an instance of the class I get:

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
MyDataType does not have a no-arg default constructor.

I looked at the JAXB 2.1 spec and saw the following (section 8.7.1.2):
- a class must have a public or protected no-arg constructor or a factory method identified by {factoryClass(), factoryMethod()} unless it is adapted using @XmlJavaTypeAdapter.

Also, the blog post at http://weblogs.java.net/blog/2005/09/30/using-jaxb-20s-xmljavatypeadapter makes me think this should be working.
Here is a simple test case to exhibit the problem, is there something wrong with the way I've applied the annotation? Do I still need a no-arg constructor even with the adapter? This is using the JAXB 2.1 reference implementation.

public static void main(String[] args) throws Exception {
JAXBContext ctx = JAXBContext.newInstance(MyDataType.class);
MyDataType obj = MyDataType.CONST;
StringWriter out = new StringWriter();
ctx.createMarshaller().marshal(obj, out);
System.out.print(out);
}

@XmlJavaTypeAdapter(Adapter.class)
public class MyDataType {
public static final MyDataType CONST = new MyDataType("foo");
private MyDataType(String x) { }
}

public class Adapter extends XmlAdapter {
public String marshal(MyDataType v) throws Exception {
return "X";
}
public MyDataType unmarshal(String v) throws Exception {
return MyDataType.CONST;
}
}

Thanks,
Adam Lewandowski

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
vladfi2
Offline
Joined: 2009-07-24
Points: 0

I am having the exact same problem! I have a partial understanding of the situation. Classes annotated by @XmlJavaTypeAdapter marshal/unmarshal correctly only when they are elements of another object. They themselves cannot be top-level elements. That is, if Foo is my class that is being adapted (say through XmlFoo), then I cannot marshal a Foo, but I can have Foo as a member of another class annotated with @XmlElement, such as the following:

@XmlRootElement
public class Bar {
@XmlElement
Foo foo;
}

@XmlJavaTypeAdapter(FooAdapter.class)
public class Foo {
//data
}

public class XmlFoo {
//data
}

public class FooAdapter extends XmlAdapter {
//marshal and unmarshal
}

So JAXB.marshal(new Foo(), System.out) will not work correctly (sometimes gives an error saying there is no @XmlRootElement) but JAXB.marshal(new Bar(), System.out) works without a problem.

alewando
Offline
Joined: 2006-06-13
Points: 0