En esta página:
Servicios Web (Parte II)
SAAJ
El API SOAP with Attachments API for Java (SAAJ) es una herramienta SOAP basada en API que modela la
estructura de los mensajes SOAP. Para ser precisos, SAAJ modela los mensajes SOAP con Attachments
(SwA), el formato de mensaje MIME para SOAP. La especificiación SwA realmente es una nota
mantenida por el World Wide Web Consortium (W3C). El W3C utiliza "nota" para distinguir sugerencias y
trabajos en progreso de sus recomendaciones oficiales. A pesar de todos los intentos y propósitos SwA es
un estándar utilizado por la industria de los Servicio Web.
Los desarrolladores Java pueden utilizar SAAJ para crear, leer o modificar mensajes SOAP. El API incluye clases e
interfaces que modelan elementos SOAP (Envelope, Body, Header, Fault, etc.),
espacios de nombres XML, atributos, nodos de texto y attachments MIME. Podemos utilizar SAAJ para manipular
simples mensajes SOAP (sólo el XML, sin ningún attachment) o mensajes SOAP más complejos, con attachments
MIME. SAAJ se puede utilizar en combinación con JAX-RPC, que es el API estándar de J2EE para enviar y recibir
mensajes SOAP, para representar fragmentos de documentos XML literales. También podemos suar SAAJ
independietemente de JAX-RPC; con sus propias facilidades opcionales para mensajería básica utilizando el estilo
de mensajería solicitud-respuesta con la unión HTTP 1.1.
SAAJ está basado ene l patrón Abstract Factory. SAAJ es una familia de tipos abstractos, donde
cada tipo de objeto está fabricado por otros tipo de la familia SAAJ. En la implementación que hace SAAJ de
Abstract Factory, la raíz es la clase MessageFactory. Ella es responsable de fabricar un
ejemplar de sí mismas, que a su vez se puede utilizar para fabricar un SOAPMessage. Un
SOAPMessage contiene un SOAPPart que representa un documento SOAP, y cero o más
objetos AttachmentPart que representan attachments (GIFs, PDFs, etc.). SOAPPart contiene
un SOAPEnvelope, un SOAPBody, un SOAPHeader,
y otros tipos de objetos. La siguiente figura muestra la relación entre los tipos de clases en SAAJ:
y la siguiente figura muestra el árbol de los interfaces de SAAJ que modelan el documento SOAP:
Podrías haber observado que hay prociones del API SAAJ, especialmente el tipo SOAPElement, que
duplica la semántica ya definida por el DOM (Document Object Model) de la W3C. Aparentemente, el grupo de
expertos que creó SAAJ decidió no utilizar DOM porque pensarón que no proporcionaba el soporte adecuado para
los espacios de nombres XML, que es una parte importante de la mensajería SOAP.
Como alternativa a crear objetos SOAPMessage completos usandos la MessageFactory,
es utilizar la clase SOAPFactory para crear fragmentos de documentos XML. Esta la factoría que
utilizaremos normalemtne cuando usemos SAAJ con JAX-RPC.
La mejor forma de aprender SAAJ es meterse de lleno, y utilizarlo para construir un sencillo mensaje SOAP como
este escrito en correcto XML:
<?xml version='1.0' ?>
<env:Envelope
xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:titan='http://www.jwsbook.org/1ed/BookPrice'
encodingStyle='http://schemas.xmlsoap.org/soap/encoding/'>
<Body>
<titan:getBookPrice>
<isbn xsi:type='string'>1565928695
</titan:getBookPrice>
</Body>
</env:Envelope>
La aplicación Java Example_1 usa SAAJ para crear un mensaje semánticamente equivalente al que
hemos visto arriba:
import javax.xml.soap.*;
public class Example_1 {
public static void main(String [] args) throws SOAPException{
MessageFactory msgFactory = MessageFactory.newInstance();
SOAPMessage message = msgFactory.createMessage();
SOAPPart soap = message.getSOAPPart();
SOAPEnvelope envelope = soap.getEnvelope();
envelope.getHeader().detachNode();
SOAPBody body = envelope.getBody();
SOAPElement getBookPrice = body.addChildElement(
"getBookPrice","titan",
"http://www.jwsbook.org/1ed/BookPrice");
getBookPrice.setEncodingStyle(
SOAPConstants.URI_NS_SOAP_ENCODING);
SOAPElement isbn = getBookPrice.addChildElement("isbn");
isbn.addNamespaceDeclaration("xsi",
"http://www.w3.org/2001/XMLSchema-instance");
Name xsiType = envelope.createName("type","xsi",
"http://www.w3.org/2001/XMLSchema-instance");
isbn.addAttribute(xsiType,"string");
isbn.addTextNode("1565928695");
message.writeTo(System.out);
}
}
Si examinamos el ejemplo de arriba, vermos que SAAJ modela la estructura exacta del formato del mensaje
SwA. La siguiente figura muestra la correlación uno-a-uno entre los elementos del mensaje SOAP y los
tipos SAAJ usados para modelar esos elementos:
Por supuesto que el ejemplo de arriba es bastante simple. No incluye ningún attachment, que pueda complicar
las cosas. Los attachments en SwA normalment son ficheros binarios u otros tipos de ficheros
no-XML, que son referenciados por el documento SOAP. SAAJ trata con Java Activation Framework
(JAF) para añadir attachments y manejar las conversión de los objetos en streams de datos
y viceversa. El siguiente fragmento de código usa SAAJ para adjuntar un documento PDF a un mensaje
SOAP:
MessageFactory msgFactory = MessageFactory.newInstance();
SOAPMessage message = msgFactory.createMessage();
AttachmentPart pdfAttach = message.createAttachmentPart();
FileDataSource file = new FileDataSource("manuscript.pdf");
DataHandler pdfDH = new DataHandler(file);
pdfAttach.setDataHandler(pdfDH);
Para trabajar satisfactoriamente con attachments debemos entener JAF. JAF es un excelente marco de trabajo
para menejar datos MIME, pero tiene sus limitaciones, la mayoría de ellas asociadas con el uso de tipos
DataContentHandler; pero podemos evitarlas utilizando los tipos DataSource
de JAF como el tipo javax.activation.FileDataSource empleado en el ejemplo anterior.
SAAJ es un API muy útil que nos permite construir mensajes SwA en casi cualquier aplicación. En
algunos casos usaremos SAAJ con JAX-RPC para mensajería de estilo literal y manejadores de mensajes
SOAP pero también podemos utilizar SAAJ en conjunción con otros APIs como JavaMail, JMS, y JAXM.
Una vez que una aplicación Java ha construido un mensaje SwA, también puede utilizar SAAJ para
convertir el mensaje en un stream binario, que se puede intercambiar con un Servicio Web utilizando cualquier
API.
JAXM
JAXM originalmente formaba parte de J2EE, pero perdió el soporte de muchos vendedores cuando se dieron
cuenta del desmesurado solapamiento entre JAXM y otros APIs de mensaería. Los vendedores de J2EE objetaron
que las funcionalidades de JAXM se puede duplicar con JMS y JAX-RPC. Consideraron que "otro API de
mensajería" sería innecesario para la comunidad de desarrallodres J2EE.
El futuro de JAXM es incierto cuando menos. Sin soporte de la mayoría de vendedores J2EE es dificil imaginar
que pueda sobrevivir.