viernes, 6 de septiembre de 2013

JAXB. Introducción. Crear un archivo XML a partir de un objeto en Java

JAXB (Java Architecture for XML Binding) es un paquete del estándar Java que permite realizar mapeos entre clases Java y ficheros XML. Es bastante empleado, por ejemplo, a la hora de realizar servicios web como veremos en entradas posteriores. Como me toca empollarme este paquete para realizar una implementación vamos a ir poniendo ejemplos que me permita documentar lo aprendido y a la misma vez sirvan a la comunidad para aprender más rápido. 
Como habitualmente trabajo contra PostgreSQL, iré poniendo las sentencias para crear las tablas que posteriormente mapearemos con clases Java para terminar viendo como se implementan las anotaciones con JAXB y posteriormente lo que se conoce como Marshalling y unMarshalling, es decir, de objetos Java a XML y de ficheros con XML a objetos Java.  Además emplearé Annotations e Hibernate, herramientas ampliamente empleadas y que seguramente serán de sobra conocidas.
Mostramos a continuación una ilustración que nos aclarará la utilidad de este paquete extraida de aquí:


Vamos a crearnos una tabla llamada Clientes en PostgreSQL donde tendremos los siguientes atributos:
DROP SEQUENCE IF EXISTS cliente_seq;
create sequence cliente_seq;
DROP TABLE IF EXISTS "cliente" CASCADE;
CREATE TABLE "cliente" (
id int default nextval('cliente_seq') primary key,
"razonsocial" varchar(50) NOT NULL,
"cif" varchar(10) NOT NULL,
"direccion" varchar(80),
"codpostal" varchar(5),
"localidad" varchar(20),
"pais" varchar(15),
"telf1" varchar(13),
"telf2" varchar(13),
"fax" varchar(13),
"email1" varchar(50) NOT NULL,
"email2" varchar(50)
) WITHOUT OIDS;
Vamos a insertar un par de elementos dentro de dicha tabla. Para ello necesitamos lo siguiente:
insert into cliente (razonsocial, cif, direccion, codpostal, localidad, pais, telf1, telf2, fax, email1, email2) values ('Mecánicas Jaimito', 'B30776523', 'Calle de la Alegría', '07342', 'Madrid', 'España', '91345345', '91345346', '91345347', 'j@j.com', 'info@j.com');
insert into cliente (razonsocial, cif, direccion, codpostal, localidad, pais, telf1, telf2, fax, email1, email2) values ('Imprenta Juanito', 'C8763456', 'Calle de la Tristeza', '33445', 'Barcelona', 'España', '93456456', '93457457', '93458458', 'p@p.com', 'info@p.com');
Podemos ver que hay un id del tipo secuencia y varios atributos típicos de una tabla de estas características. La creación de la entity que nos mapea la tabla añadiendo las anotaciones JAXB que necesitamos sería la siguiente:

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;


@Entity
@SequenceGenerator(
    name="cliente_seq",
    sequenceName="cliente_seq",
    initialValue=1,
    allocationSize=1
)

@XmlRootElement
@Table(name = "cliente")
public class Cliente {
   
    private static final long serialVersionUID = 1L;
   
    protected long id;
    protected String razonSocial;
    protected String cif;
    protected String direccion;
    protected String codPostal;
    protected String localidad;
    protected String pais;
    protected String telf1;
    protected String telf2;
    protected String email1;
    protected String email2;
    protected String fax;


    public Cliente() {
        super();
    }
   
    @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="cliente_seq")
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }
   
    public String getDireccion() {
        return direccion;
    }

    public void setDireccion(String direccion) {
        this.direccion = direccion;
    }

    public String getCodPostal() {
        return codPostal;
    }

    public void setCodPostal(String codPostal) {
        this.codPostal = codPostal;
    }

    public String getLocalidad() {
        return localidad;
    }

    public void setLocalidad(String localidad) {
        this.localidad = localidad;
    }

    public String getPais() {
        return pais;
    }

    public void setPais(String pais) {
        this.pais = pais;
    }

    public String getTelf1() {
        return telf1;
    }

    public void setTelf1(String telf1) {
        this.telf1 = telf1;
    }

    public String getTelf2() {
        return telf2;
    }

    public void setTelf2(String telf2) {
        this.telf2 = telf2;
    }

    public String getEmail1() {
        return email1;
    }

    public void setEmail1(String email1) {
        this.email1 = email1;
    }

    public String getEmail2() {
        return email2;
    }

    public void setEmail2(String email2) {
        this.email2 = email2;
    }

    public String getRazonSocial() {
        return razonSocial;
    }

    public void setRazonSocial(String razonSocial) {
        this.razonSocial = razonSocial;
    }

    public String getCif() {
        return cif;
    }

    public void setCif(String cif) {
        this.cif = cif;
    }

    public String getFax() {
        return fax;
    }

    public void setFax(String fax) {
        this.fax = fax;
    }   
}

Hemos marcado en negrita la annotation @XmlRootElement ya que es la parte fundamental de este ejemplo. Con ella le indicamos que esta es la raiz de nuestro elemento XML. Ahora solamente necesitamos lo siguiente para crearnos un archivo que llamaremos salida.xml con el primero de nuestros elementos:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;


try {
 Cliente cliente =  (Cliente) session.get(Cliente.class, new Long(1));
 File file = new File("salida.xml");

 JAXBContext jaxbContext = JAXBContext.newInstance(Cliente.class);
 Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
   
             jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(cliente, file);
}
             
catch (JAXBException e) {
 e.printStackTrace();
}

Podemos ver como lo primero que hacemos es traernos un objeto con el id 1 en base de datos y crearnos un fichero que llamaremos salida.xml. Luego viene la parte importante, lo primero es crearnos un JAXBContext con la clase que queremos mapear, en este caso la clase Cliente, para posteriormente creanos un Marshaller a partir de dicho JAXBContext. Una vez que hemos hecho esto llamamos al método marshal del Marshaller donde le pasamos el objeto y el fichero que nos hemos creado para obtener una salida como la que mostramos a continuación.


No hay comentarios :

Publicar un comentario