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?
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:
- http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html
- http://blog.bdoughan.com/2011/01/jaxb-and-datetime-properties.html
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
}
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.
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.
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