martes, 27 de julio de 2010

Spring Web Services y MTOM Parte 2

Continuando con el post anterior ahora les voy a presentar el cliente del servicio web implementando mediante saaj y axiom integrado a spring. Veamos:

El cliente se despliega de la siguiente manera:

1. Maven ejecuta la clase principal CalculadoraClientWebServiceZip mediante un plugin:



org.codehaus.mojo
exec-maven-plugin
1.1.1



java




pe.com.slcsccy.pc.springws.client.CalculadoraClientWebServiceZip




2. La clase CalculadoraClientWebServiceZip crea los beans que se conectaran con el web service, este contenedor de beans se llama applicationContextZip.xml:



xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">









C:\\logs\spring.config



































Una vez creados los beans anteriores la aplicación cliente llamará al bean 'clienteWebServiceSaaj' y ejecutará el método enviarZip(nombreArchivo), este buscará en el sistema de archivos el archivo zip y lo enviará al web service, para poder hacer esto es necesario que previamente se hayan creado los proxies del web service mediante una llamada a la meta maven 'jaxb2:xjc', está meta buscará el schema XSD y generará las fuentes java, es decir realizará el binding entre el web service y su cliente. El plugin que implementa la meta maven se ejecuta como parte del proceso generate sources de maven, pero para evitar que eclipse me muestre errores de compilación la ejecuto antes:



org.codehaus.mojo
jaxb2-maven-plugin
1.3



xjc




src/main/resources
src/main/java
pe.com.slcsccy.pc.springws.client.schema
false




La clase que crea el mensaje de envío al web service y que recepciona su respuesta mediante Saaj es la siguiente:CalculadoraClientSaajMTOM.java


package pe.com.slcsccy.pc.springws.client;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;

import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;

import pe.com.slcsccy.pc.springws.client.schema.MensajeRequest;
import pe.com.slcsccy.pc.springws.client.schema.MensajeResponse;
import pe.com.slcsccy.pc.springws.client.schema.ObjectFactory;
import pe.com.slcsccy.pc.springws.client.schema.OperacionesZipType;

public class CalculadoraClientSaajMTOM extends WebServiceGatewaySupport {

private ObjectFactory objectFactory = new ObjectFactory();

public CalculadoraClientSaajMTOM(SaajSoapMessageFactory messageFactory) {
super(messageFactory);
}

public MensajeResponse enviarZip(String nombreArchivo){
MensajeRequest mensajeRequest = objectFactory.createMensajeRequest();
OperacionesZipType zipType = new OperacionesZipType();
zipType.setNombreArchivoZip(nombreArchivo);
DataHandler handler = new DataHandler(new FileDataSource(nombreArchivo));
zipType.setArchivoZip(handler);
mensajeRequest.setOperacionesZip(zipType);
Object respuesta = getWebServiceTemplate().marshalSendAndReceive(mensajeRequest);
return (MensajeResponse)respuesta;
}
}


La clase que realiza lo mismo que la anterior pero mediante Axiom es la siguiente:CalculadoraClientAxiomMTOM.java


package pe.com.slcsccy.pc.springws.client;

import java.io.IOException;
import java.util.Iterator;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.xml.namespace.QName;
import javax.xml.transform.TransformerException;

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.OMText;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axiom.soap.SOAPMessage;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.WebServiceMessageExtractor;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.soap.axiom.AxiomSoapMessage;
import org.springframework.ws.soap.axiom.AxiomSoapMessageFactory;

public class CalculadoraClientAxiomMTOM extends WebServiceGatewaySupport {

public CalculadoraClientAxiomMTOM(AxiomSoapMessageFactory messageFactory) {
super(messageFactory);
}

public void enviarZip(final String nombreArchivo){

WebServiceMessageCallback requestCallback = new WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
AxiomSoapMessage soapMessage = (AxiomSoapMessage) message;
SOAPMessage axiomMessage = soapMessage.getAxiomMessage();
SOAPFactory factory = (SOAPFactory) axiomMessage.getOMFactory();

//Armamos el contenido del mensaje:
SOAPBody cuerpoMensaje = axiomMessage.getSOAPEnvelope().getBody();
OMNamespace ns = factory.createOMNamespace("http://www.slcsccy.com.pe/pc/springws/calculadora", "calc");
OMElement mensajeRequestElement = factory.createOMElement("mensajeRequest",ns);
cuerpoMensaje.addChild(mensajeRequestElement);
OMElement operacionesZipElement = factory.createOMElement("operacionesZip", ns);

//Creo el archivo zip
OMAttribute nombreArchivoZipAttribute = factory.createOMAttribute("nombreArchivoZip",ns,nombreArchivo);
operacionesZipElement.addAttribute(nombreArchivoZipAttribute);
OMElement archivoZipElement = factory.createOMElement("archivoZip", ns);
DataSource dataSource = new FileDataSource(nombreArchivo);
DataHandler dataHandler = new DataHandler(dataSource);
OMText archivoZipText = factory.createOMText(dataHandler, true);
archivoZipElement.addChild(archivoZipText);
operacionesZipElement.addChild(archivoZipElement);
mensajeRequestElement.addChild(operacionesZipElement);

OMOutputFormat outputFormat = new OMOutputFormat();
outputFormat.setSOAP11(true);
outputFormat.setDoOptimize(true);
soapMessage.setOutputFormat(outputFormat);
}
};

WebServiceMessageExtractor responseExtractor = new WebServiceMessageExtractor() {
@SuppressWarnings("unchecked")
public Object extractData(WebServiceMessage message) throws IOException, TransformerException {
AxiomSoapMessage mensajeAxiom = (AxiomSoapMessage)message;
SOAPMessage mensaje = mensajeAxiom.getAxiomMessage();
SOAPEnvelope envelope = mensaje.getSOAPEnvelope();
SOAPBody body = envelope.getBody();

OMElement mensajeResponse = body.getFirstElement();
OMElement resultados = mensajeResponse.getFirstElement();

StringBuilder salida = new StringBuilder();
Iterator resultadosElement = resultados.getChildren();
QName atributoId = new QName("http://www.slcsccy.com.pe/pc/springws/calculadora","id");
while(resultadosElement.hasNext()){
OMElement elemento = resultadosElement.next();
salida.append("id:"+elemento.getAttributeValue(atributoId)+",valor:"+elemento.getText()+"\n");
}

logger.info("salida retorno:"+salida.toString());
return salida.toString();
}
};

@SuppressWarnings("unused")
String response = (String)getWebServiceTemplate().sendAndReceive(requestCallback,responseExtractor);
}
}



Una vez creado el proxy del web service ahora podemos conectarnos al web service y obtener los resultados esperados, veamos el log del cliente:


2010-07-27 23:35:27 (AbstractBeanFactory.java:241) - Returning cached instance of singleton bean 'clienteWebServiceSaaj'
2010-07-27 23:35:27 (WebServiceAccessor.java:110) - Opening [org.springframework.ws.transport.http.HttpUrlConnection@372a54] to [http://localhost:7001/springws/serviciosWeb]
2010-07-27 23:35:28 (WebServiceTemplate.java:581) - Sent request [SaajSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeRequest]
2010-07-27 23:35:35 (WebServiceTemplate.java:639) - Received response [SaajSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeResponse] for request [SaajSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeRequest]


Ahora veamos el log del web service:


2010-07-27 23:35:34 (WebServiceMessageReceiverObjectSupport.java:114) - Accepting incoming [org.springframework.ws.transport.http.HttpServletConnection@ea0dfc] to [http://localhost:7001/springws/serviciosWeb]
2010-07-27 23:35:34 (MessageDispatcher.java:167) - Received request [SaajSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeRequest]
2010-07-27 23:35:34 (AbstractMethodEndpointMapping.java:62) - Looking up endpoint for [{http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeRequest]
2010-07-27 23:35:34 (MessageDispatcher.java:256) - Endpoint mapping [org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping@3311c0] maps request to endpoint [public pe.com.slcsccy.pc.springws.schema.MensajeResponse pe.com.slcsccy.pc.springws.ws.CalculadoraEndpointWithAnnotation.calcular(pe.com.slcsccy.pc.springws.schema.MensajeRequest) throws javax.xml.datatype.DatatypeConfigurationException,pe.com.slcsccy.pc.springws.exception.OperandoInvalidoException,pe.com.slcsccy.pc.springws.exception.UnzipException]
2010-07-27 23:35:34 (AbstractValidatingInterceptor.java:179) - Request message validated
2010-07-27 23:35:34 (AbstractLoggingInterceptor.java:160) - Request: UEsDBBQAAAAIAE26+TxJUMN0JgAAACgAAAAPAAAAb3BlcmFjaW9uZXMudHh0PcixCQAgEATB/OEa0RV8T9D+K/Mjs2EaOVlsRf+qS2ysGJxbr3hQSwECFAAUAAAACABNuvk8SVDDdCYAAAAoAAAADwAAAAAAAAAAACAAAAAAAAAAb3BlcmFjaW9uZXMudHh0UEsFBgAAAAABAAEAPQAAAFMAAAAAAA==
2010-07-27 23:35:34 (MessageDispatcher.java:277) - Testing endpoint adapter [org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter@1d33c09]
2010-07-27 23:35:35 (MarshallingMethodEndpointAdapter.java:146) - Unmarshalled payload request to [pe.com.slcsccy.pc.springws.schema.MensajeRequest@1ea9700]
2010-07-27 23:35:35 (AbstractBeanFactory.java:241) - Returning cached instance of singleton bean 'calculadoraEndpoint'
2010-07-27 23:35:35 (MarshallingMethodEndpointAdapter.java:153) - Marshalling [pe.com.slcsccy.pc.springws.schema.MensajeResponse@1fcbeda] to response payload
2010-07-27 23:35:35 (AbstractLoggingInterceptor.java:160) - Response: 8016108968
2010-07-27 23:35:35 (AbstractValidatingInterceptor.java:221) - Response message validated
2010-07-27 23:35:35 (MessageDispatcher.java:178) - Sent response [SaajSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeResponse] for request [SaajSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeRequest]
2010-07-27 23:35:35 (FrameworkServlet.java:677) - Successfully completed request


Con Axion el log en el cliente es el siguiente:


2010-07-27 23:43:35 (AbstractBeanFactory.java:241) - Returning cached instance of singleton bean 'lifecycleProcessor'
2010-07-27 23:43:35 (AbstractBeanFactory.java:241) - Returning cached instance of singleton bean 'clienteWebServiceAxiom'
2010-07-27 23:43:35 (WebServiceAccessor.java:110) - Opening [org.springframework.ws.transport.http.HttpUrlConnection@1f4d2b] to [http://localhost:7001/springws/serviciosWeb]
2010-07-27 23:43:35 (WebServiceTemplate.java:581) - Sent request [AxiomSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeRequest]
2010-07-27 23:43:35 (OMOutputFormat.java:140) - Start getContentType: OMOutputFormat [ mimeBoundary =null rootContentId=null doOptimize=true doingSWA=false isSOAP11=true charSetEncoding=null xmlVersion=null contentType=null ignoreXmlDeclaration=false autoCloseWriter=false actionProperty=null optimizedThreshold=0]
2010-07-27 23:43:35 (OMOutputFormat.java:166) - getContentType= {multipart/related; boundary="MIMEBoundary_be673ed239be738d78bcea194265e824bd3e5e2b92766546"; type="application/xop+xml"; start="<0.ae673ed239be738d78bcea194265e824bd3e5e2b92766546@apache.org>"; start-info="text/xml"} OMOutputFormat [ mimeBoundary =MIMEBoundary_be673ed239be738d78bcea194265e824bd3e5e2b92766546 rootContentId=0.ae673ed239be738d78bcea194265e824bd3e5e2b92766546@apache.org doOptimize=true doingSWA=false isSOAP11=true charSetEncoding=null xmlVersion=null contentType=text/xml ignoreXmlDeclaration=false autoCloseWriter=false actionProperty=null optimizedThreshold=0]
2010-07-27 23:43:35 (MTOMXMLStreamWriter.java:91) - OutputStream =class org.springframework.ws.transport.AbstractSenderConnection$RequestTransportOutputStream
2010-07-27 23:43:35 (MTOMXMLStreamWriter.java:92) - OMFormat = OMOutputFormat [ mimeBoundary =MIMEBoundary_be673ed239be738d78bcea194265e824bd3e5e2b92766546 rootContentId=0.ae673ed239be738d78bcea194265e824bd3e5e2b92766546@apache.org doOptimize=true doingSWA=false isSOAP11=true charSetEncoding=null xmlVersion=null contentType=text/xml ignoreXmlDeclaration=false autoCloseWriter=false actionProperty=null optimizedThreshold=0]
2010-07-27 23:43:35 (StAXUtils.java:615) - About to create XMLOutputFactory implementation with classloader=java.net.URLClassLoader@32d985
2010-07-27 23:43:35 (StAXUtils.java:617) - The classloader for javax.xml.stream.XMLOutputFactory is: null
2010-07-27 23:43:35 (StAXDialectDetector.java:219) - StAX implementation at jar:file:/I:/repo-maven/org/codehaus/woodstox/wstx-asl/3.2.9/wstx-asl-3.2.9.jar!/ is:
Title: WoodSToX XML-processor
Symbolic name: null
Vendor: woodstox.codehaus.org
Version: 3.2.9
2010-07-27 23:43:35 (StAXDialectDetector.java:181) - Detected StAX dialect: Woodstox
2010-07-27 23:43:35 (StAXUtils.java:635) - Created XMLOutputFactory = class org.apache.axiom.util.stax.wrapper.ImmutableXMLOutputFactory for classloader=java.net.URLClassLoader@32d985
2010-07-27 23:43:35 (StAXUtils.java:637) - Size of XMLOutputFactory map =1
2010-07-27 23:43:35 (StAXUtils.java:352) - XMLStreamWriter is org.apache.axiom.util.stax.dialect.WoodstoxStreamWriterWrapper
2010-07-27 23:43:35 (OptimizationPolicyImpl.java:60) - Start MTOMXMLStreamWriter.isOptimizedThreshold()
2010-07-27 23:43:35 (OptimizationPolicyImpl.java:65) - DataHandler fetched, starting optimized Threshold processing
2010-07-27 23:43:35 (OptimizationPolicyImpl.java:71) - node should be added to binart NodeList for optimization
2010-07-27 23:43:35 (MTOMXMLStreamWriter.java:182) - Calling MTOMXMLStreamWriter.flush
2010-07-27 23:43:35 (MTOMXMLStreamWriter.java:190) - The XML writing is completed. Now the attachments are written
2010-07-27 23:43:35 (MTOMXMLStreamWriter.java:172) - close
2010-07-27 23:43:36 (StAXSOAPModelBuilder.java:278) - Build the OMElement Envelope by the StaxSOAPModelBuilder
2010-07-27 23:43:36 (StAXSOAPModelBuilder.java:278) - Build the OMElement Header by the StaxSOAPModelBuilder
2010-07-27 23:43:36 (StAXSOAPModelBuilder.java:278) - Build the OMElement Body by the StaxSOAPModelBuilder
2010-07-27 23:43:36 (StAXSOAPModelBuilder.java:278) - Build the OMElement mensajeResponse by the StaxSOAPModelBuilder
2010-07-27 23:43:36 (WebServiceTemplate.java:639) - Received response [AxiomSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeResponse] for request [AxiomSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeRequest]
2010-07-27 23:43:36 (WebServiceTemplate.java:639) - Received response [AxiomSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeResponse] for request [AxiomSoapMessage {http://www.slcsccy.com.pe/pc/springws/calculadora}mensajeRequest]
2010-07-27 23:43:36 (StAXSOAPModelBuilder.java:278) - Build the OMElement resultados by the StaxSOAPModelBuilder
2010-07-27 23:43:36 (StAXSOAPModelBuilder.java:278) - Build the OMElement resultado by the StaxSOAPModelBuilder
2010-07-27 23:43:36 (StAXSOAPModelBuilder.java:278) - Build the OMElement resultado by the StaxSOAPModelBuilder
2010-07-27 23:43:36 (StAXSOAPModelBuilder.java:278) - Build the OMElement resultado by the StaxSOAPModelBuilder
2010-07-27 23:43:36 (StAXSOAPModelBuilder.java:278) - Build the OMElement resultado by the StaxSOAPModelBuilder


El proyecto completo en eclipse te lo puedes bajar desde AQUI

No hay comentarios.:

Publicar un comentario

Es bueno comunicarnos, comenta!!.