Dlaczego JAXB potrzebuje konstruktora no arg do rozlokowania?

Jeśli spróbujesz utworzyć klasę, która odwołuje się do typu złożonego, który nie ma konstruktora no-arg, np.:

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
}

Z implementacją JAXB będącą częścią Javy, w następujący sposób:

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

JAXB rzuci

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

Teraz rozumiem, dlaczego JAXB potrzebuje konstruktora no-arg przy unmarshalingu-ponieważ musi utworzyć instancję obiektu. Ale dlaczego JAXB potrzebuje konstruktora bez arg podczas rozlokowania?

Również, kolejny nit, dlaczego Java JAXB implementacja rzuca wyjątek, jeśli pole jest null, a i tak nie zostanie zmienione?

Czy coś mi umyka, czy są to tylko złe implementacje w implementacji JAXB Javy?

Author: bluish, 2012-02-14

3 answers

Gdy a JAXB (JSR-222) implementacja inicjalizuje swoje metadane i zapewnia, że może obsługiwać zarówno marshalling, jak i unmarshalling.

Dla klas POJO, które nie mają konstruktora no-arg, możesz użyć poziomu typu XmlAdapter, aby go obsłużyć:

java.sql.Date nie jest obsługiwana domyślnie (chociaż w EclipseLink JAXB (MOXy) jest). Może to być również obsługiwane za pomocą XmlAdapter określonego za pomocą {[5] } na poziomie pola, właściwości lub pakietu:


Również, kolejny nit, dlaczego implementacja JAXB Javy rzuca wyjątek, jeśli pole jest null i nie będzie marshalled w każdym razie?

Co widzisz wyjątek? Zwykle, gdy pole jest null, nie jest zawarte w wyniku XML, chyba że jest opatrzone adnotacją @XmlElement(nillable=true), w którym to przypadku element będzie zawierał xsi:nil="true".


UPDATE

Możesz zrobić co następuje:

SqlDateAdapter

Poniżej znajduje się XmlAdapter, który konwertuje z java.sql.Date, że Twoja implementacja JAXB nie wie, jak obsługiwać java.util.Date, co robi:

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

The XmlAdapter jest zarejestrowany przez @XmlJavaTypeAdapter adnotacja:

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
}
 22
Author: Blaise Doughan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-14 00:55:41

Wydaje się, że masz wrażenie, że kod introspekcji JAXB będzie miał ścieżki inicjalizacji specyficzne dla akcji. jeśli tak, to spowodowałoby to dużo zduplikowanego kodu i byłoby słabą implementacją. wyobrażam sobie, że kod JAXB ma wspólną procedurę, która bada klasę modelu za pierwszym razem, gdy jest potrzebna i potwierdza, że przestrzega wszystkich niezbędnych konwencji. w tej sytuacji zawodzi, ponieważ jeden z członków nie ma wymaganego no-arg konstruktor. logika inicjalizacji najprawdopodobniej nie jest specyficzna dla Marshalla/unmarshalla i jest bardzo mało prawdopodobne, aby uwzględnić bieżącą instancję obiektu.

 0
Author: jtahlborn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-13 21:43:46

Niektóre frameworki enterprise i Dependency Injection używają klasy reflection .newInstance () aby utworzyć nową instancję klas. Ta metoda wymaga publicznego konstruktora no-arg, aby móc utworzyć instancję obiektu.

 -2
Author: fiction,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-13 21:25:12