2012-02-13 27 views
43

Si intenta reunir una clase que hace referencia a un tipo complejo que no tiene un constructor sin argumentos, tales como:¿Por qué JAXB necesita un constructor no arg para ordenar?

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 
} 

con la aplicación JAXB que es parte de Java, de la siguiente manera:

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

JAXB arrojará un

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

Ahora, entiendo por qué JAXB necesita un constructor sin argumentos en unmarshalling - porque necesita crear una instancia del ob ject. Pero, ¿por qué JAXB necesita un constructor sin argumentos durante la clasificación?

Además, otra noción, ¿por qué la implementación JAXB de Java arroja una excepción si el campo es nulo, y de todos modos no se va a ordenar?

¿Me falta algo o son simplemente malas opciones de implementación en la implementación JAXB de Java?

+2

Es en realidad una mala implementación en mi humilde opinión. JAXB debería haber hecho lo que Jackson hace y ofrecer una anotación de argumento constructor: http://www.cowtowncoder.com/blog/archives/2011/07/entry_457.html. Dicho esto, JAXB es mucho mejor que otros JSR. –

Respuesta

22

Cuando una implementación JAXB (JSR-222) inicializa sus metadatos, se asegura de que pueda admitir tanto la clasificación como la desasignación.

Para las clases POJO que no tienen un constructor sin argumentos puede utilizar un nivel de tipo XmlAdapter para manejarlo:

java.sql.Date no está soportada por defecto (aunque en EclipseLink JAXB (MOXy) es). Esto también puede ser manejado usando un XmlAdapter especificado a través de @XmlJavaTypeAdapter en el campo, propiedad o nivel de paquete:


Además, otro nit, ¿por qué Java La implementación de JAXB arroja una excepción si el campo es nulo, y no va a ser coordinado de todos modos?

¿Qué excepción estás viendo? Normalmente, cuando un campo es nulo, no se incluye en el resultado XML, a menos que esté anotado con @XmlElement(nillable=true), en cuyo caso el elemento incluirá xsi:nil="true".


ACTUALIZACIÓN

Se podría hacer lo siguiente:

SqlDateAdapter

a continuación es un XmlAdapter que convertirá desde el java.sql.Date que su aplicación JAXB no sabe cómo para manejar a un java.util.Date que lo hace:

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

El XmlAdapter se registra a través de la @XmlJavaTypeAdapter anotación:

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 
} 
+0

Si intenta ordenar la clase que he pegado en la pregunta tal como está, arrojará una excepción, aunque el objeto Date sea nulo e incluso no será parte del XML. – rouble

+0

He actualizado mi respuesta para incluir un 'XmlAdapter' que podría usar para manejar el campo' java.sql.Date'. –

+1

Blaise - gracias. Ya uso un adaptador similar. Tenga en cuenta que no necesita la verificación nula en el adaptador. Solo estaba señalando ciertas cosas interesantes acerca de la implementación de JAXB de Java, ya que espera un adaptador (y arroja una excepción), incluso si el campo es nulo y no va a usar el adaptador. Me parece extraño. – rouble

-2

Algunos marcos empresariales y Dependency Injection usan la reflexión Class.newInstance() para crear una nueva instancia de sus clases. Este método requiere un constructor público no-arg para poder crear una instancia del objeto.

+3

gracias - Entiendo que - Solo tengo curiosidad por saber, ¿en qué parte del proceso de clasificación hay una necesidad de crear una nueva instancia de la clase que se organiza? – rouble

0

usted parece estar bajo la impresión de que el código de la introspección JAXB tendrá caminos específicos de acción para la inicialización. si es así, eso daría como resultado una gran cantidad de código duplicado y sería una implementación deficiente. Me imagino que el código JAXB tiene una rutina común que examina una clase modelo la primera vez que se necesita y valida que sigue todas las convenciones necesarias. en esta situación, está fallando porque uno de los miembros no tiene el constructor no-arg requerido. la lógica de inicialización probablemente no sea específica de marshall/unmarshall y tampoco es muy probable que tenga en cuenta la instancia de objeto actual.

Cuestiones relacionadas