Подтвердить что ты не робот

Почему JAXB не нужен конструктор arg для сортировки?

Если вы попытаетесь маршалировать класс, который ссылается на сложный тип, у которого нет конструктора no-arg, например:

import java.sql.Date;

@XmlRootElement(name = "Foo")
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {
    int i;
    Date d; //java.sql.Date does not have a no-arg constructor
}

с реализацией JAXB, которая является частью Java, выглядит следующим образом:

    Foo foo = new Foo();
    JAXBContext jc = JAXBContext.newInstance(Foo.class);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    Marshaller marshaller = jc.createMarshaller();
    marshaller.marshal(foo, baos);

JAXB выкинет

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

Теперь я понимаю, почему JAXB нужен конструктор no-arg для unmarshalling - потому что ему нужно создать экземпляр объекта. Но почему JAXB нужен конструктор no-arg при сортировке?

Кроме того, еще один nit, почему реализация Java JAXB генерирует исключение, если поле имеет значение NULL и в любом случае не собирается сортироваться?

Я что-то упустил или это просто неправильные варианты реализации в реализации Java JAXB?

4b9b3361

Ответ 1

Когда реализация JAXB (JSR-222) инициализирует свои метаданные, она гарантирует, что она может поддерживать как маршаллинг, так и безмаршаллинг.

Для классов POJO, у которых нет конструктора no-arg, вы можете использовать тип уровня XmlAdapter для его обработки:

java.sql.Date не поддерживается по умолчанию (хотя в EclipseLink JAXB (MOXy) он есть). Это также можно обрабатывать с помощью XmlAdapter, указанного через @XmlJavaTypeAdapter на уровне поля, свойства или пакета:


Кроме того, еще один nit, почему реализация Java JAXB исключение, если поле имеет значение NULL и не собирается сортироваться в любом случае?

Какое исключение вы видите? Обычно, когда поле является нулевым, оно не включается в результат XML, если оно не аннотируется с @XmlElement(nillable=true), и в этом случае элемент будет включать xsi:nil="true".


UPDATE

Вы можете сделать следующее:

SqlDateAdapter

Ниже приведено XmlAdapter, которое преобразует из java.sql.Date, что ваша реализация JAXB не знает, как обращаться с java.util.Date, который она выполняет:

package forum9268074;

import javax.xml.bind.annotation.adapters.*;

public class SqlDateAdapter extends XmlAdapter<java.util.Date, java.sql.Date> {

    @Override
    public java.util.Date marshal(java.sql.Date sqlDate) throws Exception {
        if(null == sqlDate) {
            return null;
        }
        return new java.util.Date(sqlDate.getTime());
    }

    @Override
    public java.sql.Date unmarshal(java.util.Date utilDate) throws Exception {
        if(null == utilDate) {
            return null;
        }
        return new java.sql.Date(utilDate.getTime());
    }

}

Foo

XmlAdapter регистрируется посредством аннотации @XmlJavaTypeAdapter:

package forum9268074;

import java.sql.Date;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement(name = "Foo")
@XmlAccessorType(XmlAccessType.FIELD)
public class Foo {
    int i;

    @XmlJavaTypeAdapter(SqlDateAdapter.class)
    Date d; //java.sql.Date does not have a no-arg constructor
}

Ответ 2

У вас, похоже, создается впечатление, что код интроспекции JAXB будет иметь конкретные пути действий для инициализации. если да, то это приведет к большому дублированию кода и будет плохой реализацией. я бы предположил, что код JAXB имеет общую процедуру, которая в первый раз проверяет класс модели и подтверждает, что он соответствует всем необходимым соглашениям. в этой ситуации он терпит неудачу, потому что у одного из членов нет требуемого конструктора no-arg. логика инициализации, скорее всего, не специфична для маршалла/немаршала, а также крайне маловероятна для учета текущего экземпляра объекта.

Ответ 3

Некоторые предприятия и Фундаменты зависимостей используют отражение Class.newInstance(), чтобы создать новый экземпляр ваших классов. Этот метод требует, чтобы публичный конструктор no-arg мог создавать экземпляр объекта.