2

When I marshall an instance of this class ...

@XmlRootElement
public static class TestSomething<T extends Serializable> {

    T id;

    public T getId() {
        return id;
    }

    public void setId(T id) {
        this.id = id;
    }
}

... the following Exception is thrown ...

com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of IllegalAnnotationExceptions
java.io.Serializable is an interface, and JAXB can't handle interfaces.
    this problem is related to the following location:
        at java.io.Serializable
        at public java.io.Serializable TestSomething.getId()
        at TestSomething
java.io.Serializable does not have a no-arg default constructor.
    this problem is related to the following location:
        at java.io.Serializable
        at public java.io.Serializable TestSomething.getId()
        at TestSomething

How can I avoid this (without changing the type parameter to something like <T>)?

Ethan Leroy
  • 15,804
  • 9
  • 41
  • 63

3 Answers3

1

You need to use a combination of @XmlElement and @XmlSchemaType:

import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;

@XmlRootElement 
public class TestSomething<T extends Serializable> { 

    T id; 

    @XmlElement(type=Object.class)
    @XmlSchemaType(name="anySimpleType")
    public T getId() { 
        return id; 
    } 

    public void setId(T id) { 
        this.id = id; 
    } 
}

If you run the following:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class Demo {

    public static void main(String[] args) throws JAXBException {
        JAXBContext jc = JAXBContext.newInstance(TestSomething.class);

        TestSomething<Integer> foo = new TestSomething<Integer>();
        foo.setId(4);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(foo, System.out);
    }
}

You will get:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<testSomething>
    <id xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:int">4</id>
</testSomething>
bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • Is there any way to get the `id` field into an attribute rather than a separate element? I'm trying to serialize an object similar to the OP's, but JAXB really doesn't like when I try to use `@XmlAttribute`. If needed I'll just open a new question. – Matt Ball May 02 '11 at 20:35
  • @Matt Ball - The above scenario will work with @XmlAttribute if you use EclipseLink JAXB (MOXy) http://www.eclipse.org/eclipselink/moxy.php. With the Metro JAXB Implementation I get an exception. – bdoughan May 02 '11 at 20:48
  • I did try switching from Metro to MOXy. If `` then I get the same errors as the OP, along with _"@XmlAttribute/@XmlValue need to reference a Java type that maps to text in XML"_. If it's just `` then I get an NPE deep down in the bowels of JAXB (stack trace [here](https://gist.github.com/952370)). The same NPE occurs with Metro. Any ideas? – Matt Ball May 02 '11 at 21:11
  • In the interest of not hijacking this question, I posted [my own question](http://stackoverflow.com/questions/5862677/). I'd be much obliged if you could take a look at some point. Thanks! – Matt Ball May 02 '11 at 21:29
0

Here is a guide how to use interfaces with JAXB.

JAXB needs concrete classes, because it has to instantiate them when marshalling from XML. And if T is no concrete class, it can't be instantiated.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • I already found this guide, but it doesn't help me much. When I put @XmlAnyElement to getId() and try to marshal an instance of TestSomething I get com.sun.istack.SAXException2: unable to marshal type "java.lang.Long" as an element because it is missing an @XmlRootElement annotation – Ethan Leroy Sep 19 '10 at 09:34
0

Adding @XmlAnyElement to the 'id' field (along with @XmlAccessorType(XmlAccessType.FIELD) annotation at class level) or adding the same for getter will resolve this. (But it makes the xml element's type any.)

Naveed S
  • 5,106
  • 4
  • 34
  • 52