java constructor jaxb creation

java - JAXB y constructores



creation (4)

Estoy empezando a aprender JAXB, así que mi pregunta puede ser muy tonta. Ahora tengo clases y quiero generar esquema XML. Yendo tras this instrucción me sale la excepción.

IllegalAnnotationExceptions ... no tiene un constructor predeterminado sin argumentos.

Sí. Mis clases no tienen constructores no arg por defecto. Es demasiado fácil. Tengo clases con constructores visibles del paquete / métodos finales y fuera de curso con argumentos. ¿Qué debo hacer? ¿Crear algunas clases específicas de momemto / builder o especificar mis constructores para JAXB (de qué manera?)? Gracias.


Debes tener un constructor predeterminado para que JAXB pueda instanciar tus clases. Tal vez hay una solución que no sé sin embargo.

JAXB está especialmente diseñado para clases similares a bean, que permiten configurar objetos llamando a los definidores en ellos.


JAXB puede soportar este caso utilizando un Adaptador XML. Considera que tienes el siguiente objeto sin constructor cero-arg:

package blog.immutable; public class Customer { private final String name; private final Address address; public Customer(String name, Address address) { this.name = name; this.address = address; } public String getName() { return name; } public Address getAddress() { return address; } }

Simplemente necesita crear una versión asignable de esta clase:

package blog.immutable.adpater; import javax.xml.bind.annotation.XmlAttribute; import blog.immutable.Address; public class AdaptedCustomer { private String name; private Address address; @XmlAttribute public String getName() { return name; } public void setName(String name) { this.name = name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } }

Y un adaptador XML para convertir entre ellos:

package blog.immutable.adpater; import javax.xml.bind.annotation.adapters.XmlAdapter; import blog.immutable.Customer; public class CustomerAdapter extends XmlAdapter<AdaptedCustomer, Customer> { @Override public Customer unmarshal(AdaptedCustomer adaptedCustomer) throws Exception { return new Customer(adaptedCustomer.getName(), adaptedCustomer.getAddress()); } @Override public AdaptedCustomer marshal(Customer customer) throws Exception { AdaptedCustomer adaptedCustomer = new AdaptedCustomer(); adaptedCustomer.setName(customer.getName()); adaptedCustomer.setAddress(customer.getAddress()); return adaptedCustomer; } }

Luego, para las propiedades que se refieren a la clase Cliente, simplemente use la anotación @XmlJavaTypeAdapter:

package blog.immutable; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import blog.immutable.adpater.CustomerAdapter; @XmlRootElement(name="purchase-order") public class PurchaseOrder { private Customer customer; @XmlJavaTypeAdapter(CustomerAdapter.class) public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } }

Para un ejemplo más detallado ver:


JAXB vuelve a crear beans desde XML de una manera simple: crea una nueva instancia del bean, y luego hace todo el setXXX necesario para establecer los atributos. Por lo tanto, si su bean no tiene un constructor sin argumentos, JAXB no puede crearlo. Como se dijo en otras respuestas, JAXB funciona mejor para simples "contenedores" de beans, para los cuales el constructor no-args no es realmente un problema. Si está intentando crear beans que necesitan una inicialización específica, deberá hacerlo en los métodos setXXX .


Puede usar la anotación @XmlType y usar los atributos factoryMethod / factoryClass en varias combinaciones, tales como:

@XmlType(factoryMethod="newInstance") @XmlRootElement public class PurchaseOrder { @XmlElement private final String address; @XmlElement private final Customer customer; public PurchaseOrder(String address, Customer customer){ this.address = address; this.customer = customer; } private PurchaseOrder(){ this.address = null; this.customer = null; } /** Creates a new instance, will only be used by Jaxb. */ private static PurchaseOrder newInstance() { return new PurchaseOrder(); } public String getAddress() { return address; } public Customer getCustomer() { return customer; } }

Sorprendentemente, esto funciona y se obtiene una instancia inicializada cuando no es riguroso. Debe tomar nota de no llamar al método newInstance ningún lugar de su código, ya que devolverá una instancia no válida.