Buscar en el Blog

miércoles, 11 de agosto de 2010

Utilización de JAXB para mapear clases Java a representaciones XML

JAXB es una tecnología Java que permite mapear clases de Java a representaciones XML. JAXB provee dos funciones fundamentales:

  1. marshal. Consiste en presentar un objeto Java en XML. Java Object > XML
  2. unmarshal. Consiste en presentar XML en un objeto Java. XML > Java Object
La versión 2.2.1 del API de JAXB puede ser descargada desde el siguiente link: https://jaxb.dev.java.net/2.2.1/JAXB2_20100511.jar

Esta versión trabaja con anotaciones con las cuáles se indica cuál será la raíz del documento XML, los elementos y los atributos. Las principales anotaciones son:

  • @XmlRootElement
  • @XmlElement
  • @XmlAttribute
En mi publicación anterior de "cómo exponer un servicio web en Mule" en el Bean Message sobrescribí el método toString para mostrar el contenido del objeto usando tags XML. Con el uso del API de JAXB ésto ya no es necesario y es reemplazado por anotaciones, como se muestra a continuación:

package com.blogspot.ingmmurillo.axisws;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;

@XmlRootElement
public class Message implements Serializable {

    private Field[] fields;
    private String from;
    private String to;   

    @XmlAttribute
    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    @XmlAttribute
    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    public Field[] getFields() {
        return fields;
    }

    public void setFields(Field[] fields) {
        this.fields = fields;
    }

    @Override
    public String toString() {

        OutputStream xmlOutput = new OutputStream() {
            private StringBuilder string = new StringBuilder();

            @Override
            public void write
                    (
                            int b) throws IOException {
                this.string.append((char) b);
            }

            @Override
            public String toString
                    () {
                return this.string.toString();
            }
        };

        JAXBContext contextObj = null;
        Marshaller marshallerObj = null;
        try {
            contextObj = JAXBContext.newInstance(Message.class);
            marshallerObj = contextObj.createMarshaller();
            marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshallerObj.marshal(this, xmlOutput);
            xmlOutput.flush();
            xmlOutput.close();
        } catch (JAXBException e) {
            e.printStackTrace();
            return e.getMessage();
        } catch (IOException e) {
            e.printStackTrace();
            return e.getMessage();
        } finally {
            if (contextObj != null) {
                contextObj = null;
            }
            if (marshallerObj != null) {
                marshallerObj = null;
            }
        }

        return xmlOutput.toString();
    }    
}

Al realizar la invocación del servicio web la respuesta obtenida es la siguiente:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <ns1:sendMessageResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://ingmmurillo.blogspot.com/webservices/axis">
         <sendMessageReturn xsi:type="xsd:string"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<message to="The World" from="My Blog">
    <fields>
        <name>FirstName</name>
        <value>Mauricio</value>
    </fields>
    <fields>
        <name>LastName</name>
        <value>Mauricio</value>
    </fields>
</message>]]></sendMessageReturn>
      </ns1:sendMessageResponse>
   </soapenv:Body>
</soapenv:Envelope>


El XML de respuesta ahora fue generado automáticamente usando JAXB. En conclusión, JAXB permite ahorrar tiempo para realizar los procesos de marshal y unmarshal. Además, JAXB permite que el mantenimiento de un bean sea menos costoso, ayudando a los desarrolladores a trabajar de forma más ágil.

4 comentarios:

  1. Que tal , me ha parecido interesante pero tengo un problema y no se si podrias ayudarme... anteriormente he utilizado Web services pero generaba el cliente a partir de la URl donde se encontraba el wsdl, ahora al generar los objetos a partir de .wsd no me queda clara la manera de invocar a mi servicio web no se si podrias darme alguna pista ya que acabo de comenzar a ver JAXB hace un par de días y estoy un poco perdida. Cualquier ayuda se agradece un saludo.

    ResponderEliminar
  2. Que tal Maria. Bueno JAXB es una tecnologia para mapear objetos a representaciones XML las tecnologias Java para Web Services mas usadas son Apache CXF y Apache AXIS estas usan por detrás ésta tecnología. Lo que tú primero necesitas hacer es generar el cliente del servicio web, observa el siguiente post: Tarea Ant Servicios Web

    Una vez creado el cliente del servicio web podrías consumirlo de la siguiente forma:


    public static void main(String[] args) {
    try {
    CurrencyConvertorLocator wsLocator = new CurrencyConvertorLocator();
    CurrencyConvertorSoap_PortType ws = wsLocator.getCurrencyConvertorSoap();

    double tasaConversion = ws.conversionRate(Currency.USD, Currency.COP);

    System.out.println("tasaConversion = " + tasaConversion + " Pesos Colombianos, 1 USD");

    } catch (ServiceException e) {
    System.err.println(e);
    } catch (RemoteException e) {
    System.err.println(e);
    }

    }

    Saludos,

    ResponderEliminar
  3. Muchas gracias por el post.
    Usamos JAXB para todos los proyectos y realmente es muy fácil y performante.

    Lo recomiendo para todos aquellos que requieran realizar mapeos de objetos a XML y viceversa.

    Muy bueno el blog, felicitaciones !

    ResponderEliminar
  4. Buenas tardes, me encuentro utilizando marshall para generar XMLś dinamicos, necesito quitar o que no me muestre en el Xml que genera el : xsi:type=XXXXXX

    Alguien puede ayudarme?
    Muchas gracias. Saludos

    ResponderEliminar