una tipos tener puede parametros herencia ejercicios cuantos constructores con clase java xml jaxb marshalling

tipos - this en java



¿Por qué JAXB necesita un constructor sin argumentos para el cálculo? (4)

Si intenta calcular una clase que hace referencia a un tipo complejo que no tiene un constructor sin argumentos, como por ejemplo:

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 implementación JAXB que es parte de Java, como sigue:

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

JAXB lanzará 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, comprendo por qué JAXB necesita un constructor sin argumentos para que no sea riguroso, porque necesita instanciar el objeto. Pero, ¿por qué JAXB necesita un constructor sin argumentos mientras se prepara?

Además, otro problema, ¿por qué la implementación de Java JAXB lanza una excepción si el campo es nulo y no va a ser ordenado de todos modos?

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



Cuando una implementación de JAXB (JSR-222) inicializa sus metadatos, se asegura de que sea compatible tanto con la clasificación como con la no severa.

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

java.sql.Date no es compatible de forma predeterminada (aunque en EclipseLink JAXB (MOXy) sí lo es). Esto también se puede manejar usando un XmlAdapter especificado a través de @XmlJavaTypeAdapter en el campo, la propiedad o el nivel del paquete:

Además, otro problema, ¿por qué la implementación de Java JAXB lanza una excepción si el campo es nulo y no va a ser ordenado 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" .

ACTUALIZAR

Podrías hacer lo siguiente:

SqlDateAdapter

A continuación se muestra un XmlAdapter que se convertirá de java.sql.Date que su implementación JAXB no sabe cómo manejar a un java.util.Date lo que 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 anotación @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 }


Para responder a su pregunta: creo que este es un diseño pobre en JAXB (o quizás en implementaciones de JAXB). La existencia de un constructor sin argumentos se valida durante la creación de JAXBContext y, por lo tanto, se aplica independientemente de si desea utilizar JAXB para realizar comparaciones o no atenuantes. Hubiera sido genial si JAXB aplazara este tipo de verificación a JAXBContext.createUnmarshaller() . Creo que sería interesante profundizar si este diseño es realmente obligatorio por la especificación o si es un diseño de implementación en JAXB-RI.

Pero de hecho hay una solución.

JAXB en realidad no necesita un constructor sin argumentos para el cálculo. A continuación, asumiré que está utilizando JAXB únicamente para la ordenación, no para nada desagradable. También asumo que tienes control sobre el objeto inmutable que deseas hacer para que puedas cambiarlo. Si este no es el caso, la única forma de avanzar es XmlAdapter como se describe en otras respuestas.

Supongamos que tienes una clase, Customer , que es un objeto inmutable. La creación de instancias se realiza mediante un patrón de generador o métodos estáticos.

public class Customer { private final String firstName; private final String lastName; private Customer(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } // Object created via builder pattern public static CustomerBuilder createBuilder() { ... } // getters here ... }

Es cierto que, de forma predeterminada, no puede hacer que JAXB elimine todo este objeto. Obtendrá el error " .... El cliente no tiene un constructor predeterminado sin argumentos ".

Hay al menos dos formas de resolver esto. Ambos confían en poner un método o un constructor únicamente para hacer feliz la introspección de JAXB.

Solución 1

En este método, le decimos a JAXB que hay un método de fábrica estático que puede usar para instanciar una instancia de la clase. Sabemos, pero JAXB no, que de hecho nunca se utilizará. El truco es la anotación factoryMethod con el parámetro factoryMethod . Así es cómo:

@XmlType(factoryMethod="createInstanceJAXB") public class Customer { ... private static CustomerImpl createInstanceJAXB() { // makes JAXB happy, will never be invoked return null; // ...therefore it doesn''t matter what it returns } ... }

No importa si el método es privado como en el ejemplo. JAXB todavía lo aceptará. Tu IDE marcará el método como no utilizado si lo haces privado, pero sigo prefiriendo el privado.

Solucion 2

En esta solución, agregamos un constructor privado sin argumentos que simplemente pasa nulo al constructor real.

public class Customer { ... private Customer() { // makes JAXB happy, will never be invoked this(null, null); // ...therefore it doesn''t matter what it creates } ... }

No importa si el constructor es privado como en el ejemplo. JAXB todavía lo aceptará.

Resumen

Ambas soluciones satisfacen el deseo de JAXB de crear instancias sin argumentos. Es una vergüenza que tengamos que hacer esto, cuando sabemos por nosotros mismos que solo necesitamos ordenar, no unmarshal.

Debo admitir que no sé en qué medida se trata de un hack que solo funcionará con JAXB-RI y no, por ejemplo, con EclipseLink MOXy. Definitivamente funciona con JAXB-RI.


Parece que tienes la impresión de que el código de introspección JAXB tendrá rutas de acción específicas para la inicialización. si es así, eso resultaría en 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 sin argumentos requerido. lo más probable es que la lógica de inicialización no sea específica de marshall / unmarshall y también es muy poco probable que tenga en cuenta la instancia de objeto actual.