Ejemplo: transferencia de mensajes SOAP con archivos adjuntos utilizando WSIF
Información y código de ejemplo para utilizar el proveedor SOAP de WSIF para pasar adjuntos contenidos en un mensaje compuesto de varias partes MIME relacionadas, de modo que las reglas de proceso SOAP para un mensaje SOAP estándar no se modifiquen. Esto incluye una descripción de cómo escribir extensiones WSDL (Web Services Description Language) para adjuntos SOAP y cómo trabajar con tipos y correlaciones de tipos.
El documento W3C SOAP Messages with Attachments describe un método estándar para asociar un mensaje SOAP con uno o más archivos adjuntos en su formato nativo (por ejemplo, GIF o JPEG) utilizando una estructura MIME de varias partes para el transporte. Define el uso específico del tipo de soporte MIME "relacionado/de varias partes", y las normas de uso de las referencias URI a las entidades empaquetadas en el paquete MIME. De este modo, describe una técnica que permite que un mensaje MIME de varias partes relacionadas incluya un mensaje SOAP 1.1 de tal modo que no se modifican los estándares de proceso de SOAP para mensajes SOAP estándar.
WSIF da soporte a la transferencia de archivos adjuntos en un mensaje MIME utilizando el proveedor SOAP para enlazar un servicio WSIF con un servicio SOAP a través de HTTP. El adjunto es un javax.activation.DataHandler. Se utilizan los distintivos mime:multipartRelated, mime:part y mime:content para describir el adjunto en WSDL.
Ejemplo: Escritura de extensiones WSDL para adjuntos SOAP
El WSDL de ejemplo siguiente ilustra una operación sencilla que tiene un adjunto llamado attch:
<binding name="MyBinding" type="tns:abc" >
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="MyOperation">
<soap:operation soapAction=""/>
<input>
<mime:multipartRelated>
<mime:part>
<soap:body use="encoded" namespace="http://mynamespace"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding"/>
</mime:part>
<mime:part>
<mime:content part="attch" type="text/html"/>
</mime:part>
</mime:multipartRelated>
</input>
</operation>
</binding>
- Debe haber un atributo part (en este ejemplo, attch) en el mensaje de entrada para la operación (en este ejemplo, MyOperation). Puede haber otras partes de entrada en MyOperation que no sean archivos adjuntos.
- En la entrada de enlace debe haber un distintivo <soap:body> o un distintivo <mime:multipartRelated>, pero no ambos.
- Para mensajes MIME, el distintivo <soap:body> está dentro del distintivo <mime:part>. Sólo debe haber un distintivo <mime:part> que contiene un distintivo <soap:body> en la entrada de enlace y que tampoco debe contener un distintivo <mime:content>, porque se da por supuesto un tipo de contenido text/xml para el distintivo <soap:body>.
- En un mensaje MIME puede haber varios archivos adjuntos, cada uno descrito por un distintivo <mime:part>.
- Cada distintivo <mime:part> que no contiene un distintivo <soap:body> contiene un distintivo <mime:content> que describe el archivo adjunto. El atributo type dentro del distintivo <mime:content> no es comprobado ni utilizado por WSIF (Web Services Invocation Framework). Se incluye ahí para sugerir a la aplicación que utiliza WSIF lo que contiene el adjunto. Varios distintivos <mime:content> dentro de un único distintivo <mime:part> significa que el servicio de programa de fondo espera un solo archivo adjunto con un tipo especificado por uno de los distintivos <mime:content> dentro de dicho distintivo <mime:part>.
- Se presupone que el atributo parts="..." (opcional) dentro del distintivo <soap:body> contiene los nombres de todas las partes MIME, así como los nombres de todas las partes SOAP del mensaje.
Ejemplo: Utilización de WSIF para pasar adjuntos SOAP
El fragmento de código siguiente puede invocar al servicio descrito por el ejemplo de WSDL en el tema Ejemplo: Escritura de extensiones WSDL para adjuntos SOAP:
import javax.activation.DataHandler;
. . .
DataHandler dh = new DataHandler(new FileDataSource("miimagen.jpg"));
WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
WSIFService service = factory.getService("mi.wsdl",null,null,"http://miespaciodenombres","abc");
WSIFOperation op = service.getPort().createOperation("MiOperación");
WSIFMessage in = op.createInputMessage();
in.setObjectPart("attch",dh);
op.executeInputOnlyOperation(in);
La correlación de tipos asociados del archivo DeploymentDescriptor.xml depende del servidor SOAP. Por ejemplo, si utiliza Tomcat con SOAP 2.3, entonces el archivo DeploymentDescriptor.xml contiene la correlación de tipos siguiente:
<isd:mappings>
<isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:x="http://miespaciodenombres"
qname="x:datahandler"
javaType="javax.activation.DataHandler"
java2XMLClassName="org.apache.soap.encoding.soapenc.MimePartSerializer"
xml2JavaClassName="org.apache.soap.encoding.soapenc.MimePartSerializer" />
</isd:mappings>
En este caso, se invocará al servicio de programa de fondo con la firma siguiente:
public void Mioperación(DataHandler dh);
Asimismo, puede utilizar archivos de apéndice para transferir archivos adjuntos a Web Services Invocation Framework (WSIF):
DataHandler dh = new DataHandler(new FileDataSource("miimagen.jpg"));
WSIFServiceFactory factory = WSIFServiceFactory.newInstance();
WSIFService service = factory.getService("mi.wsdl",null,null,"http://miespaciodenombres","abc");
MyInterface stub = (MyInterface)service.getStub(MyInterface.class);
stub.Mioperación(dh);
También se pueden devolver los adjuntos desde una operación, pero sólo se puede devolver un adjunto como parámetro de devolución.
Adjuntos SOAP: cómo trabajar con tipos y correlaciones de tipo
De manera predeterminada, los adjuntos se transfieren a WSIF como objetos DataHandler. Si la parte del mensaje que correlaciona el objeto DataHandler con un distintivo <mime:part> del WSDL, WSIF correlaciona automáticamente el nombre completo del tipo WSDL con la clase DataHandler y configura la correlación de tipo con el proveedor SOAP.
En WSDL podría haber definido un esquema para el adjunto (por ejemplo como tipo binary[]). WSIF ignora en silencio esta correlación y tratará el adjunto como un objeto DataHandler (Gestor de datos), a no ser que emita expresamente un método mapType(). WSIF permite que el proveedor de SOAP establezca el tipo de contenido MIME en función del tipo de objeto DataHandler, en lugar del atributo type especificado para el código <mime:content> en WSDL.
Adjuntos SOAP: escenarios no soportados
- Utilización de DIME.
- La transferencia de javax.xml.transform.Source y javax.mail.internet.MimeMultipart.
- El uso del distintivo mime:mimeXml WSDL.
- La anidación de una mime:multipartRelated dentro de una mime:part.
- El uso de tipos que amplían DataHandler, Image, etc.
- El uso de tipos que contienen DataHandler, Image, etc.
- El uso de Arrays (matrices) o Vectors (vectores) de DataHandlers (gestores de datos), Images (imágenes), etc.
- El uso de varios adjuntos de entrada/salida o salida.