@XmlRootElement и ‹T extends Serializable› выбрасывают исключения IllegalAnnotationExceptions

Когда я маршаллирую экземпляр этого класса ...

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

    T id;

    public T getId() {
        return id;
    }

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

... выбрасывается следующее исключение ...

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

Как я могу этого избежать (не меняя параметр типа на что-то вроде <T>)?


person Ethan Leroy    schedule 18.09.2010    source источник


Ответы (3)


Вам нужно использовать комбинацию @XmlElement и @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; 
    } 
}

Если вы запустите следующее:

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);
    }
}

Ты получишь:

<?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>
person bdoughan    schedule 20.09.2010
comment
Есть ли способ поместить поле id в атрибут, а не в отдельный элемент? Я пытаюсь сериализовать объект, похожий на OP, но JAXB действительно не любит, когда я пытаюсь использовать @XmlAttribute. Если нужно, я просто открою новый вопрос. - person Matt Ball; 03.05.2011
comment
@Matt Ball - Приведенный выше сценарий будет работать с @XmlAttribute, если вы используете EclipseLink JAXB (MOXy) eclipse. org / eclipselink / moxy.php. С реализацией Metro JAXB я получаю исключение. - person bdoughan; 03.05.2011
comment
Я попробовал перейти с Metro на MOXy. Если <T extends Serializable>, то я получаю те же ошибки, что и OP, вместе с тем, что @ XmlAttribute / @ XmlValue необходимо ссылаться на тип Java, который отображается в текст в XML. Если это просто <T>, то я получаю NPE глубоко в недрах JAXB (трассировка стека здесь). То же самое NPE происходит с Metro. Любые идеи? - person Matt Ball; 03.05.2011
comment
Чтобы не перехватить этот вопрос, я разместил свой вопрос. Я был бы очень признателен, если бы вы могли взглянуть на какой-нибудь момент. Спасибо! - person Matt Ball; 03.05.2011

Здесь приведено руководство по использованию интерфейсов с JAXB.

JAXB нужны конкретные классы, потому что он должен создавать их экземпляры при маршалинге из XML. И если T не является конкретным классом, его нельзя создать.

person Bozho    schedule 18.09.2010
comment
Я уже нашел это руководство, но оно мне мало помогает. Когда я помещаю @XmlAnyElement в getId () и пытаюсь маршалировать экземпляр TestSomething ‹Long›, я получаю com.sun.istack.SAXException2: невозможно маршалировать тип java.lang.Long как элемент, потому что в нем отсутствует аннотация @XmlRootElement - person Ethan Leroy; 19.09.2010

Добавление @XmlAnyElement в поле 'id' (вместе с аннотацией @XmlAccessorType(XmlAccessType.FIELD) на уровне класса) или добавление того же значения для геттера решит эту проблему. (Но это делает элемент xml типом any.)

person Naveed S    schedule 26.12.2017