WSO2 Guest Webinar: Creando un Backend de Servicios y/o API con WSO2

 

 

WSO2 Webinar – WSO2 Guest Webinar: Creando un Backend de Servicios y/o API con WSO2

 

Complex Event Processor 3.1  Released

WSO2 Guest Webinar:
Creando un Backend de Servicios y/o API con WSO2

Date: Thursday, July 17, 2014

Time: 16:00 p.m. – GMT

Presenters: Roger Carhuatocto, Consultor Técnico, Chakray |
Isabelle Mauny, jefe de producto, WSO2

Introduction and Reference Architecture of IoT

Después de haber definido nuestra Arquitectura de Referencia SOA, el siguiente paso es crear servicios, en otras palabras, crear la capa de servicios y/o API de la que consultaremos para crear Aplicaciones de Negocio completas.

La creación de Aplicaciones de Negocio modernas están compuestas de 3 capas generalmente, la capa de presentación, encargada de mostrar información y sirve como interfaz de interacción con el usuario; la capa de orquestación, que es la que define el flujo u orden de ejecución de las funcionalidades y por último la capa de negocio, que en el escenario SOA será una capa donde se exponen las funcionalidades o lógica de negocio como servicios y/o API. Es en esta situación donde WSO2 nos provee de diferentes herramientas para construir nuestra Aplicación de Negocio de manera completa, destacamos la ayuda de WSO2 en la creación de la capa de funcionalidades o lógica de negocio como un backend de servicios y/o API, e ir más allá, es decir, crear de manera ágil Servicios y/o API, gestionarlas, aplicar seguridad, monitorizarla, QoS, etc.

En esta sesión exploraremos las diferentes estrategias para crear Servicios y/o API, conoceremos las funcionalidades de WSO2 ESB, WSO2 API Manager y WSO2 Data Service Server para crear rápidamente Servicios y/o API, además de gestionarlas y aplicar aspectos de QoS y Seguridad.

Register Now

Presenters

Roger Carhuatocto

Roger Carhuatocto

Consultor Técnico

Chakray

Isabelle Mauny

Isabelle Mauny

jefe de producto

WSO2

shadow
WSO2Con-USA-2014
Learn how WSO2 can accelerate
your SOA deployments
Find out how WSO2
can support your projects
Connect with the WSO2
community
Contact Us Get Support
WSO2Blog Facebook Twitter LinkedIn Youtube Meetup

 

 

MTOM en WSO2 ESB para optimizar la transferencia de datos binarios sobre SOAP (Parte 2/2)

En la anterior entrada explorábamos los beneficios del uso de MTOM en WSO2 ESB, ahora explicaremos cómo integrar esta funcionalidad en nuestras aplicaciones web, es decir, cómo invocar el mismo servicio desde una página web tradicional.


wso2-esb

I. Escenario.


Una vez implementado MTOM sobre SOAP empleando WSO2, subir ficheros es sumamente fácil desde SoapUI, pero lo sería también desde un formulario HTML?. Pues, en principio no lo es debido a que ambos implementan maneras diferentes de hacerlo, a pesar de que ambos envían información sobre el mismo protocolo HTTP.

Un formulario HTML envía ficheros sobre HTTP codificándolo en “multipart/form-data”, mientras que en el servidor se decodifica. Hay que decirlo, “multipart/form-data” es una especificación nada reciente, es la forma de envio de ficheros más usada equiparable al FTP.

MTOM sobre SOAP, es una especificación relativamente joven, cubre la necesidad de envio de fichero sobre el protocolo SOAP, pero el valor añadido es que el envio es optimizado, esto requiere implementar un cliente SOAP que use MTOM. SoapUI es una buena herramienta de prueba para estos fines, pero dentro de tu proyecto tarde o temprano tendrás que implementar un cliente SOAP con MTOM.

Entonces, sacando ventaja de los mecanismos de mediación que WSO2 ESB ofrece, podríamos crear un Proxy_01 que exponga un servicio de transferencia de fichero usando MTOM y SOAP, luego podríamos crear otro Proxy_02 que nos facilite enviar ficheros desde un formulario HTML. En el fondo el Proxy_02 haría la traducción de “multipart/form-data” a “MTOM”.

Si tenemos un cliente MTOM/SOAP que nos permita subir ficheros, lo enviaremos a Proxy_01, pero si tenemos un formulario HTML para subir ficheros, éste apuntará a Proxy_02, que hará la traducción y que luego lo enviará a Proxy_01.

HTTP Multipart/form-data a MTOM SOAP en WSO2 ESB

HTTP Multipart/form-data a MTOM SOAP en WSO2 ESB

II. Implementando el escenario.


Para implementar este escenario necesitamos lo siguiente:

  1. WSO2 ESB 4.8.1 (http://wso2.com/products/enterprise-service-bus)
  2. Proxy_01, similar al “Sample 51″ (MTOM and SwA Optimizations and Request/Response Correlation) desplegado en WSO2 ESB.
  3. Proxy_02 que reciba la petición de envio de fichero codificada en “multipart/form-data” realizada desde un formulario HTML.
  4. El formulario HTML para enviar el fichero.
  5. Modificar la implementación del servicio MTOM SOAP en el lado del Axis2 Server.

 

II.1. Proxy_01 para el envio de ficheros usando MTOM y SOAP.


En la anterior entrada implementamos un proxy para el envio de ficheros usando MTOM y SOAP. Entonces, vamos a reutilizar el mismo proxy y añadiremos unos pequeños cambios.Este proxy es un proxy actualizado a partir del proxy publicado en la entrada anterior “MTOM en WSO2 ESB para optimizar la transferencia de datos binarios sobre SOAP (Parte 1/2)“. Sabemos que en el lado servidor tenemos que desplegar la implementación de este servicio para que todo funcione. Más adelante explicaré que es necesario tocar algunas líneas de código.

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="MTOMSwASampleService_proxy"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <log level="custom">
            <property name="======== Proxy-MTOMSwASampleService" value="====== inSeq - ini"/>
         </log>
         <filter source="get-property('Action')" regex="urn:oneWayUploadUsingHTTP">
            <then>
               <log level="custom">
                  <property name="...calling " value="oneWayUploadUsingHTTP"/>
               </log>
               <property name="OUT_ONLY" value="true"/>
               <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
               <property name="example" value="onewayhttp"/>
               <send>
                  <endpoint>
                     <address uri="http://localhost:9000/services/MTOMSwASampleService"/>
                  </endpoint>
               </send>
            </then>
            <else/>
         </filter>
         <filter source="get-property('Action')" regex="urn:uploadFileUsingMTOM">
            <then>
               <log level="custom">
                  <property name="...calling " value="uploadFileUsingMTOM"/>
               </log>
               <header name="Action" scope="default" action="remove"/>
               <property name="SOAPAction" scope="default" action="remove"/>
               <property name="example" value="mtom"/>
               <property name="Action" value="urn:uploadFileUsingMTOM" scope="default"/>
               <header name="Action" scope="default" value="urn:uploadFileUsingMTOM"/>
               <send>
                  <endpoint>
                     <address uri="http://localhost:9000/services/MTOMSwASampleService"
                              optimize="mtom"/>
                  </endpoint>
               </send>
            </then>
            <else/>
         </filter>
         <filter source="get-property('Action')" regex="urn:uploadFileUsingSwA">
            <then>
               <log level="custom">
                  <property name="...calling " value="uploadFileUsingSwA"/>
               </log>
               <property name="example" value="swa"/>
               <send>
                  <endpoint>
                     <address uri="http://localhost:9000/services/MTOMSwASampleService"
                              optimize="swa"/>
                  </endpoint>
               </send>
            </then>
            <else/>
         </filter>
         <filter source="get-property('Action')" regex="urn:oneWayUploadUsingMTOM">
            <then>
               <log level="custom">
                  <property name="...calling " value="oneWayUploadUsingMTOM"/>
               </log>
               <property name="OUT_ONLY" value="true"/>
               <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
               <property name="example" value="onewaymtom"/>
               <send>
                  <endpoint>
                     <address uri="http://localhost:9000/services/MTOMSwASampleService"
                              optimize="mtom"/>
                  </endpoint>
               </send>
            </then>
            <else/>
         </filter>
         <log level="custom">
            <property name="======== Proxy MTOMSwASampleService" value="====== inSeq - fin"/>
         </log>
      </inSequence>
      <outSequence>
         <log level="custom">
            <property name="======== Proxy MTOMSwASampleService" value="====== outSeq - ini"/>
         </log>
         <filter source="get-property('example')" regex="onewayhttp">
            <property name="enableMTOM" value="true" scope="axis2"/>
         </filter>
         <filter source="get-property('example')" regex="onewaymtom">
            <property name="enableMTOM" value="true" scope="axis2"/>
         </filter>
         <filter source="get-property('example')" regex="mtom">
            <property name="enableMTOM" value="true" scope="axis2"/>
         </filter>
         <filter source="get-property('example')" regex="swa">
            <property name="enableSwA" value="true" scope="axis2"/>
         </filter>
         <send/>
         <log level="custom">
            <property name="======== Proxy MTOMSwASampleService" value="====== outSeq - fin"/>
         </log>
      </outSequence>
   </target>
   <publishWSDL uri="http://localhost:9000/services/MTOMSwASampleService?wsdl"/>
   <parameter name="enableMTOM">true</parameter>
   <description>MTOMSwASampleService (Sample 51) updated</description>
</proxy>

La URL http://localhost:9000 representa al Axis2 server, donde desplegamos el servicio. Es Axis2 server que auto-genera el WSDL asociado al backend service.
Es importante iniciar primero el Axis2 server, luego iniciar WSO2 ESB ya que desde el ESB hacemos referencia al WSDL alojado en Axis2 server. Esto es lo que en WSO2 ESB se llamada “WSDL inline”.

 

II.2. Proxy_02 que reciba el fichero en “multipart/form-data” y lo envie a Proxy_01.


Aquí básicamente, el Proxy_02 transformará la cabecera y el cuerpo del mensaje para adaptarlo al formato que el Proxy_01 lo necesita.
Evidentemente, deberás conocer cómo “multipart/form-data” y MTOM codifican para implementar este proxy.

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="MTOMSwASampleService_http"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <log level="custom">
            <property name="****** MTOMSwASampleService - HTTP" value="***** inSeq - ini"/>
         </log>
         <property name="DISABLE_CHUNKING" value="true"/>
         <property name="Action" value="urn:oneWayUploadUsingHTTP" scope="default"/>
         <header name="Action" scope="default" value="urn:oneWayUploadUsingHTTP"/>
         <send>
            <endpoint>
               <address uri="http://localhost:8281/services/MTOMSwASampleService_proxy"
                        format="soap11"/>
            </endpoint>
         </send>
         <log level="custom">
            <property name="****** MTOMSwASampleService - HTTP" value="***** inSeq - fin"/>
         </log>
      </inSequence>
      <outSequence>
         <log level="custom">
            <property name="******* MTOMSwASampleService - HTTP" value="***** outSeq - ini"/>
         </log>
         <property name="OUT_ONLY" value="true"/>
         <property name="FORCE_SC_ACCEPTED" value="true"/>
         <send/>
         <log level="custom">
            <property name="******* MTOMSwASampleService - HTTP" value="***** outSeq - fin"/>
         </log>
      </outSequence>
   </target>
   <description>Proxy Upload File using Multipart Form Data</description>
</proxy>

 

II.3. Formulario HTML para el envio de ficheros.


Implementar un formulario de este tipo es muy fácil, sólo hay que usar enctype con el siguiente valor "multipart/form-data". Tal como se muestra a continuación:

<html>
    <head>
        <title>Sending Binary Data by SOAP with MTOM using WSO2 ESB</title>
    </head>
    <body>
        <h2>Sending Binary Data by SOAP with MTOM using WSO2 ESB</h2>

        <form action="http://localhost:8283/services/MTOMSwASampleService_http" method="POST" enctype="multipart/form-data">
            Binary file: <input type="file" name="myimagefile" size="50" multiple>
            <br/>
            <input type="submit" value="Submit">
        </form>

    </body>
 </html>

 

Las 3 partes a prestar atención aquí son:

  1. El Action del form apunta al Proxy_02, asegurarse que el puerto sea el correcto y corresponda al del WSO2 ESB.
  2. El enctype debe indicar la codificación con el que se enviará el fichero.
  3. El input del form es de tipo file y debe tener un nombre, como en este caso myimagefile, con el que podamos luego leerlo para hacer la transformación.

Finalmente, recordar que no será necesario un Servidor Web para invocar este formulario HTML, basta con abrir el formulario desde cualquier navegador y elegir el fichero que queremos enviar desde nuestro disco duro.

 

II.4. Modificar el servicio de backend que implementa el envio y recepción de ficheros.


Como indiqué líneas arriba, será necesario actualizar la implementación del servicio de backend del “Sample 51″ para nuestro escenario, ya que en principio sólo está preparado para trabajar con MTOM y SwA sobre SOAP.

Lo que haremos es básicamente añadir una nueva operación SOAP que recoja el mensaje y sepa decodificarlo para guardarlo en el lado servidor.

package samples.services;

import org.apache.axiom.om.OMText;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.util.base64.Base64Utils;
import org.apache.axiom.attachments.Attachments;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.wsdl.WSDLConstants;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.xml.namespace.QName;
import java.io.*;

public class MTOMSwASampleService {

    private static final int BUFFER = 2048;

    public OMElement uploadFileUsingMTOM(OMElement request) throws Exception {

        /*
        <soapenv:Envelope
               xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:ser="http://services.samples">
           <soapenv:Header/>
           <soapenv:Body>
              <ser:uploadFileUsingMTOM>
                 <ser:request>
                    <ser:image>cid:tux-grenade.png</ser:image>
                 </ser:request>
              </ser:uploadFileUsingMTOM>
           </soapenv:Body>
        </soapenv:Envelope>
        */

        OMText binaryNode = (OMText) request.
            getFirstChildWithName(new QName("http://services.samples", "request")).
            getFirstChildWithName(new QName("http://services.samples", "image")).
            getFirstOMChild();
        DataHandler dataHandler = (DataHandler) binaryNode.getDataHandler();
        InputStream is = dataHandler.getInputStream();

        File tempFile = File.createTempFile("mtom-", ".gif");
        FileOutputStream fos = new FileOutputStream(tempFile);
        BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);

        byte data[] = new byte[BUFFER];
        int count;
        while ((count = is.read(data, 0, BUFFER)) != -1) {
            dest.write(data, 0, count);
        }

        dest.flush();
        dest.close();
        System.out.println("Wrote MTOM content to temp file : " + tempFile.getAbsolutePath());

        OMFactory factory = request.getOMFactory();
        OMNamespace ns = factory.createOMNamespace("http://services.samples", "m0");
        OMElement payload  = factory.createOMElement("uploadFileUsingMTOMResponse", ns);
        OMElement response = factory.createOMElement("response", ns);
        OMElement image    = factory.createOMElement("image", ns);

        FileDataSource fileDataSource = new FileDataSource(tempFile);
        dataHandler = new DataHandler(fileDataSource);
        OMText textData = factory.createOMText(dataHandler, true);
        image.addChild(textData);
        response.addChild(image);
        payload.addChild(response);

        MessageContext outMsgCtx = MessageContext.getCurrentMessageContext().getOperationContext().getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
        outMsgCtx.setProperty(
            org.apache.axis2.Constants.Configuration.ENABLE_MTOM,
            org.apache.axis2.Constants.VALUE_TRUE);

        return payload;
    }

    public OMElement uploadFileUsingSwA(OMElement request) throws Exception {

        String imageContentId = request.
            getFirstChildWithName(new QName("http://services.samples", "request")).
            getFirstChildWithName(new QName("http://services.samples", "imageId")).
            getText();

        MessageContext msgCtx   = MessageContext.getCurrentMessageContext();
        Attachments attachment  = msgCtx.getAttachmentMap();
        DataHandler dataHandler = attachment.getDataHandler(imageContentId);
        File tempFile = File.createTempFile("swa-", ".gif");
        FileOutputStream fos = new FileOutputStream(tempFile);
        dataHandler.writeTo(fos);
        fos.flush();
        fos.close();
        System.out.println("Wrote SwA attachment to temp file : " + tempFile.getAbsolutePath());

        MessageContext outMsgCtx = msgCtx.getOperationContext().getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
        outMsgCtx.setProperty(
            org.apache.axis2.Constants.Configuration.ENABLE_SWA,
            org.apache.axis2.Constants.VALUE_TRUE);

        OMFactory factory = request.getOMFactory();
        OMNamespace ns = factory.createOMNamespace("http://services.samples", "m0");
        OMElement payload  = factory.createOMElement("uploadFileUsingSwAResponse", ns);
        OMElement response = factory.createOMElement("response", ns);
        OMElement imageId  = factory.createOMElement("imageId", ns);

        FileDataSource fileDataSource = new FileDataSource(tempFile);
        dataHandler = new DataHandler(fileDataSource);
        imageContentId = outMsgCtx.addAttachment(dataHandler);
        imageId.setText(imageContentId);
        response.addChild(imageId);
        payload.addChild(response);

        return payload;
    }

    public void oneWayUploadUsingMTOM(OMElement element) throws Exception {

        /*
        <soapenv:Envelope
               xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:ser="http://services.samples">
           <soapenv:Header/>
           <soapenv:Body>
              <ser:oneWayUploadUsingMTOM>cid:chilcano.jpg</ser:oneWayUploadUsingMTOM>
           </soapenv:Body>
        </soapenv:Envelope>
        */

        OMText binaryNode = (OMText) element.getFirstOMChild();
        System.out.println("contentID   : " + binaryNode.getContentID() );
        System.out.println("isBinary    :" + binaryNode.isBinary() );
        System.out.println("isOptimized :" + binaryNode.isOptimized() );
        DataHandler dataHandler = (DataHandler) binaryNode.getDataHandler();
        InputStream is = dataHandler.getInputStream();

        File tempFile = File.createTempFile("mtom-", ".gif");
        FileOutputStream fos = new FileOutputStream(tempFile);
        BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);

        byte data[] = new byte[BUFFER];
        int count;
        while ((count = is.read(data, 0, BUFFER)) != -1) {
            dest.write(data, 0, count);
        }

        dest.flush();
        dest.close();
        System.out.println("Wrote to file : " + tempFile.getAbsolutePath());
    }

    public void oneWayUploadUsingHTTP(OMElement element) throws Exception {

        /*
        <?xml version="1.0" encoding="UTF-8"?>
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
          <soapenv:Body>
            <mediate>
              <myimagefile>...content in base64...</myimagefile>
            </mediate>
          </soapenv:Body>
        </soapenv:Envelope>
        */

        String imageContentB64 = element.getFirstElement().getText();
        File tempFile = File.createTempFile("1wayhttp-", ".gif");
        byte[] byteImageContent = Base64Utils.decode(imageContentB64);
        try (OutputStream ostream = new FileOutputStream(tempFile)) {
            ostream.write(byteImageContent);
        }
        System.out.println("Wrote 1WayHTTP attachment to temp file : " + tempFile.getAbsolutePath());
    }

}

Veréis que he implementado una nueva operación al servicio (método java) llamada oneWayUploadUsingHTTP que recibe como un parámetro de tipo OMElement.

Si deseas añadir más código para efectuar acciones más complejas te recomiendo que crees un proyecto nuevo desde WSO2 Studio haciendo uso de Maven, luego importes esta clase.

 

Una vez actualizado, debemos compilarlo y desplegarlo en Axis2 Server. El WSDL será actualizado automáticamente.
Sólo seguir los siguientes pasos:

  1. Editar el fichero %ESB_HOME%/samples/axis2Server/src/MTOMSwASampleService/src/samples/servicesMTOMSwASampleService.java, dejarlo como se indica líneas arriba.
  2. Grabar servicesMTOMSwASampleService.java para preservar los cambios.
  3. Desde la línea de comandos, ejecutar ANT para compilar el servicio y desplegarlo en el Axis2 server.
  4. Si todo ha ido bien, iniciemos Axis2 server.
  5. Para verificar que hemos implementado una nueva operación, podemos consultar el actualizado WSDL en la siguiente dirección: http://localhost:9000/services/MTOMSwASampleService?wsdl
Chilcano@Pisc0 $ cd ~/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService
Chilcano@Pisc0 $ ant
Buildfile: /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService/build.xml

clean:
   [delete] Deleting directory /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService/temp

init:
    [mkdir] Created dir: /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService/temp
    [mkdir] Created dir: /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService/temp/classes

compile-all:
    [javac] /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService/build.xml:47: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService/temp/classes

build-service:
    [mkdir] Created dir: /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService/temp/MTOMSwASampleService
    [mkdir] Created dir: /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService/temp/MTOMSwASampleService/META-INF
     [copy] Copying 1 file to /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService/temp/MTOMSwASampleService/META-INF
     [copy] Copying 1 file to /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/src/MTOMSwASampleService/temp/MTOMSwASampleService
      [jar] Building jar: /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/repository/services/MTOMSwASampleService.aar

BUILD SUCCESSFUL
Total time: 2 seconds

 

III. Ejecutando todo esto.


Finalmente, después de desplegar satisfactoriamente el servicio de backend, iniciar Axis2 server, iniciar WSO2 ESB, crear Proxy_01 y Proxy_02, estamos a punto de poder ejecutar el form HTML para hacer el upload de un fichero.

wso2esb-mtom-part2-http2soap-02form

Después del envío de un fichero a través del form HTML, tu verás que en el lado de Axis2 server se recuperará el fichero enviado para guardarlo en el disco del servidor.

[...]
14/05/26 22:43:07 INFO nhttp.HttpCoreNIOSender: HTTPS Sender starting
14/05/26 22:43:07 INFO nhttp.HttpCoreNIOSender: HTTP Sender starting
14/05/26 22:43:07 INFO jms.JMSSender: JMS Sender started
14/05/26 22:43:07 INFO jms.JMSSender: JMS Transport Sender initialized...
14/05/26 22:43:07 INFO deployment.DeploymentEngine: Deploying Web service: FastStockQuoteService.aar - file:/Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/repository/services/FastStockQuoteService.aar
14/05/26 22:43:07 INFO deployment.DeploymentEngine: Deploying Web service: LBService1.aar - file:/Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/repository/services/LBService1.aar
14/05/26 22:43:07 INFO deployment.DeploymentEngine: Deploying Web service: LBService2.aar - file:/Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/repository/services/LBService2.aar
14/05/26 22:43:07 INFO deployment.DeploymentEngine: Deploying Web service: MTOMSwASampleService.aar - file:/Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/repository/services/MTOMSwASampleService.aar
14/05/26 22:43:07 INFO deployment.DeploymentEngine: Deploying Web service: ReliableStockQuoteService.aar - file:/Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/repository/services/ReliableStockQuoteService.aar
14/05/26 22:43:07 INFO deployment.DeploymentEngine: Deploying Web service: SecureStockQuoteService.aar - file:/Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/repository/services/SecureStockQuoteService.aar
14/05/26 22:43:07 INFO deployment.DeploymentEngine: Deploying Web service: SimpleStockQuoteService.aar - file:/Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/repository/services/SimpleStockQuoteService.aar
14/05/26 22:43:08 INFO nhttp.HttpCoreNIOListener: HTTPS Listener started on 0:0:0:0:0:0:0:0:9002
14/05/26 22:43:08 INFO nhttp.HttpCoreNIOListener: HTTP Listener started on 0:0:0:0:0:0:0:0:9000
14/05/26 22:43:08 INFO util.SampleAxis2ServerManager: [SimpleAxisServer] Started

Wrote 1WayHTTP attachment to temp file : /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/../../tmp/sampleServer/1wayhttp-1767851362396795349.gif

En el lado de WSO2 ESB verás las siguientes trazas:

sourcecode language=”text” gutter=”true” wraplines=”false”]
[...]
[2014-05-25 11:48:59,110] INFO – PassThroughHttpSSLListener Pass-through HTTPS Listener started on 0:0:0:0:0:0:0:0:8246
[2014-05-25 11:48:59,110] INFO – PassThroughHttpListener Starting Pass-through HTTP Listener…
[2014-05-25 11:48:59,112] INFO – PassThroughHttpListener Pass-through HTTP Listener started on 0:0:0:0:0:0:0:0:8283
[2014-05-25 11:48:59,114] INFO – NioSelectorPool Using a shared selector for servlet write/read
[2014-05-25 11:48:59,328] INFO – NioSelectorPool Using a shared selector for servlet write/read
[2014-05-25 11:48:59,343] INFO – RegistryEventingServiceComponent Successfully Initialized Eventing on Registry
[2014-05-25 11:48:59,379] INFO – JMXServerManager JMX Service URL : service:jmx:rmi://localhost:11114/jndi/rmi://localhost:10002/jmxrmi
[2014-05-25 11:48:59,379] INFO – StartupFinalizerServiceComponent Server : WSO2 Enterprise Service Bus-4.8.1
[2014-05-25 11:48:59,380] INFO – StartupFinalizerServiceComponent WSO2 Carbon started in 22 sec
[2014-05-25 11:48:59,599] INFO – CarbonUIServiceComponent Mgt Console URL : https://192.168.56.1:9446/carbon/
[2014-05-25 11:49:06,594] INFO – CarbonAuthenticationUtil ‘admin@carbon.super [-1234]‘ logged in at [2014-05-25 11:49:06,594+0200]
[2014-05-25 11:51:28,952] INFO – ProxyService Building Axis service for Proxy service : MTOMSwASampleService_http
[2014-05-25 11:51:28,952] INFO – ProxyService Adding service MTOMSwASampleService_http to the Axis2 configuration
[2014-05-25 11:51:28,954] INFO – DeploymentInterceptor Deploying Axis2 service: MTOMSwASampleService_http {super-tenant}
[2014-05-25 11:51:28,978] INFO – ProxyService Successfully created the Axis2 service for Proxy service : MTOMSwASampleService_http
[2014-05-26 22:43:51,296] INFO – CarbonAuthenticationUtil ‘admin@carbon.super [-1234]‘ logged in at [2014-05-26 22:43:51,296+0200]

[2014-05-26 22:47:15,938] INFO – LogMediator ****** MTOMSwASampleService – HTTP = ***** inSeq – ini
[2014-05-26 22:47:15,945] INFO – LogMediator ======== Proxy-MTOMSwASampleService = ====== inSeq – ini
[2014-05-26 22:47:15,945] INFO – LogMediator …calling = oneWayUploadUsingHTTP
[2014-05-26 22:47:15,946] INFO – LogMediator ======== Proxy MTOMSwASampleService = ====== inSeq – fin
[2014-05-26 22:47:15,954] INFO – LogMediator ****** MTOMSwASampleService – HTTP = ***** inSeq – fin
[/sourcecode]

IV. Conclusiones.


  • Hemos demostrado que WSO2 ESB nos permite transformar tanto la estructura del mensaje como el protocolo de transporte (de HTTP a SOAP) de manera fácil creando únicamente 2 Proxies.
  • Hemos implementado un patrón de integración llamado Content-Based Router (CBR) todo ello gracias a la capacidades de Mediation de WSO2 ESB.
  • El uso de MTOM directamente desde un form HTML no es posible, es necesario usar otro proxy que transforme la petición multipart/form-data a MTOM.

Espero que os haya servido!.

MTOM en WSO2 ESB para optimizar la transferencia de datos binarios sobre SOAP (Parte 1/2)

Hace poco estaba explorando las características de WSO2 ESB para el envío óptimo de datos binarios sobre nuestros servicios implementados en SOAP y me encontré que WSO2 ESB implementa MTOM y SwA. Hice unas pruebas rápidas y pude comprobar que la transferencia de datos binarios, que por lo general son más grandes que datos de tipo textual, usando SOAP con MTOM es realmente muy potente y veloz, luego me puse a profundizar y aquí os muestro mis resultados.

 

wso2esb-soapui-mtom

 

I. Casos de Uso MTOM en WSO2 ESB.


WSO2 ESB viene con más de 102 ejemplos de Proxy de Apache Synapse, cada uno de ellos implementa diferentes casos de usos necesarios para integrar aplicaciones con diferencias estrategias.

El ejemplo “Sample 51″ implementa MTOM y SwA sobre SOAP y esta entrada al blog usa esta implementación.

Requisitos:

 

II. Desplegar los servicios de back-end (Sample 51) en Axis2 server.


Para trabajar con los ejemplos de cualquier producto WSO2 es necesario ANT. Basta con añadir ANT a la variable del sistema PATH, en mi caso será:

 
PATH = %PATH%;C:\01bizlife\apache-ant-1.9.3\bin

WSO2 ESB viene con Axis2 server y con los servicios de back-end ya implementados. Para sólo es necesario compilarlos y desplegarlos en el Axis2 server. Para ello hacer lo siguiente:

 
C:\> cd <ESB_HOME>/samples/axis2Server/src/MTOMSwASampleService
 
C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\src\MTOMSwASampleService>ant

Buildfile: C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\src\MTOMSwASampleService\build.xml
clean:
init:
    [mkdir] Created dir: C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\src\MTOMSwASampleService\temp
    [mkdir] Created dir: C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\src\MTOMSwASampleService\temp\classes
    [mkdir] Created dir: C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\repository\services
compile-all:
    [javac] C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\src\MTOMSwASampleService\build.xml:47: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 1 source file to C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\src\MTOMSwASampleService\temp\classes
build-service:
    [mkdir] Created dir: C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\src\MTOMSwASampleService\temp\MTOMSwASampleService
    [mkdir] Created dir: C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\src\MTOMSwASampleService\temp\MTOMSwASampleService\META-INF
     [copy] Copying 1 file to C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\src\MTOMSwASampleService\temp\MTOMSwASampleService\META-INF
     [copy] Copying 1 file to C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\src\MTOMSwASampleService\temp\MTOMSwASampleService
      [jar] Building jar: C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server\repository\services\MTOMSwASampleService.aar

BUILD SUCCESSFUL
Total time: 1 second

Sólo comentar que “MTOMSwASampleService” implementa el servicio de back-end y tiene 3 operaciones:

  • uploadFileUsingMTOM (in-out): Acepta una imagen en binario desde el request SOAP como MTOM y devuelve esta misma imagen como response SOAP.
  • uploadFileUsingSwA (in-out): Acepta una imagen en binario desde el request SOAP como SwA y devuelve esta misma imagen as response SOAP.
  • oneWayUploadUsingMTOM (in-only): Guarda el mensaje de request al disco.

III. Iniciar Axis2 server.


Axis2 server usa HTTP listener en el puerto 9000 y el HTTPS 9002 por defecto.

 
C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Server>axis2server.bat	

"Starting Sample Axis2 Server ..."
Using AXIS2_HOME:        C:\01BIZL~1\WSO2ES~1.1-D\samples\AXIS2S~1\
Using JAVA_HOME:       C:\Program Files\Java\jdk1.7.0_51
14/04/30 12:31:36 INFO util.SampleAxis2ServerManager: [SimpleAxisServer] Starting
[SimpleAxisServer] Using the Axis2 Repository : C:\01BIZL~1\WSO2ES~1.1-D\samples\AXIS2S~1\repository
[SimpleAxisServer] Using the Axis2 Configuration File : C:\01BIZL~1\WSO2ES~1.1-D\samples\AXIS2S~1\repository\conf\axis2.xml
14/04/30 12:31:36 INFO deployment.ModuleDeployer: Deploying module: addressing - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/repository/modules/addressing.mar
14/04/30 12:31:36 INFO deployment.ModuleDeployer: Deploying module: rampart - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/repository/modules/rampart.mar
14/04/30 12:31:36 INFO deployment.ModuleDeployer: Deploying module: sandesha2 - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/repository/modules/sandesha2.mar
14/04/30 12:31:36 INFO deployment.ModuleDeployer: Deploying module: addressing - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.addressing_4.2.0.jar
14/04/30 12:31:36 INFO deployment.ModuleDeployer: Deploying module: wso2caching - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.caching.core_4.2.0.jar
14/04/30 12:31:36 INFO deployment.ModuleDeployer: Deploying module: ComponentMgtModule - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.feature.mgt.services_4.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: wso2mex - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.mex_4.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: pagination - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.registry.server_4.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: relay - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.relay.module_4.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: sandesha2 - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.rm_4.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: POXSecurityModule - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.security.mgt_4.2.2.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: ServerAdminModule - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.server.admin_4.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: wso2statistics - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.statistics_4.2.2.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: wso2throttle - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.throttle.core_4.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: usagethrottling - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.throttling.agent_2.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: wso2tracer - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.tracer_4.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: metering - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.usage.agent_2.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: wso2xfer - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/org.wso2.carbon.xfer_4.2.0.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: rampart - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/rampart-core_1.6.1.wso2v12.jar
14/04/30 12:31:37 INFO deployment.ModuleDeployer: Deploying module: rahas - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/./../../repository/components/plugins/rampart-trust_1.6.1.wso2v12.jar
14/04/30 12:31:37 ERROR sandesha2.SandeshaModule: Could not load module policies. Using default values.
14/04/30 12:31:37 INFO config.ClientConnFactoryBuilder: HTTPS Loading Identity Keystore from : ../../repository/resources/security/wso2carbon.jks
14/04/30 12:31:37 INFO config.ClientConnFactoryBuilder: HTTPS Loading Trust Keystore from : ../../repository/resources/security/client-truststore.jks
14/04/30 12:31:37 INFO nhttp.HttpCoreNIOSender: HTTPS Sender starting
14/04/30 12:31:37 INFO nhttp.HttpCoreNIOSender: HTTP Sender starting
14/04/30 12:31:37 INFO jms.JMSSender: JMS Sender started
14/04/30 12:31:37 INFO jms.JMSSender: JMS Transport Sender initialized...
14/04/30 12:31:37 INFO deployment.DeploymentEngine: Deploying Web service: MTOMSwASampleService.aar - file:/C:/01BIZL~1/WSO2ES~1.1-D/samples/AXIS2S~1/repository/services/MTOMSwASampleService.aar
14/04/30 12:31:37 INFO nhttp.HttpCoreNIOListener: HTTPS Listener started on 0.0.0.0:9002
14/04/30 12:31:37 INFO nhttp.HttpCoreNIOListener: HTTP Listener started on 0.0.0.0:9000
14/04/30 12:31:37 INFO util.SampleAxis2ServerManager: [SimpleAxisServer] Started

Si es necesario abrir varias instancias de Axis2 server, hay que iniciarlos en puertos diferentes como se indica a continuación:

./axis2server.sh -http 9001 -https 9005 -name MyServer1
./axis2server.sh -http 9002 -https 9006 -name MyServer2
./axis2server.sh -http 9003 -https 9007 -name MyServer3

 

IV. Cargar la configuración synapse de “Sample 51″ en WSO2 ESB.


Es posible cargar “Sample 51″ por defecto cuando WSO2 ESB inicie, esto hará que se cargue el fichero synapse, mientras que los proxies antes creados no se cargarán, al volver a iniciar WSO2 ESB de la forma normal dichos Proxies volverán a cargarse.

Iniciemos WSO2 ESB con <ESB_HOME>\repository\samples\synapse_sample_51.xml pre-cargado, de esta forma:

 
C:\01bizlife\wso2esb-4.8.1-dev\bin>wso2esb-samples.bat -sn 51

JAVA_HOME environment variable is set to C:\Program Files\Java\jdk1.7.0_51
CARBON_HOME environment variable is set to C:\01BIZL~1\WSO2ES~1.1-D\bin\..
[2014-04-30 12:53:51,708]  INFO - CarbonCoreActivator Starting WSO2 Carbon...
[2014-04-30 12:53:51,708]  INFO - CarbonCoreActivator Operating System : Windows XP 5.1, x86
[2014-04-30 12:53:51,708]  INFO - CarbonCoreActivator Java Home        : C:\Program Files\Java\jdk1.7.0_51\jre
[2014-04-30 12:53:51,708]  INFO - CarbonCoreActivator Java Version     : 1.7.0_51
[2014-04-30 12:53:51,718]  INFO - CarbonCoreActivator Java VM          : Java HotSpot(TM) Client VM 24.51-b03,Oracle Corporation
[...]
[2014-04-30 12:54:08,162]  INFO - PassThroughHttpSSLListener Pass-through HTTPS Listener started on 0.0.0.0:8246
[2014-04-30 12:54:08,162]  INFO - PassThroughHttpListener Starting Pass-through HTTP Listener...
[2014-04-30 12:54:08,172]  INFO - PassThroughHttpListener Pass-through HTTP Listener started on 0.0.0.0:8283
[2014-04-30 12:54:08,172]  INFO - JMSListener JMS listener started
[2014-04-30 12:54:08,172]  INFO - NioSelectorPool Using a shared selector for servlet write/read
[2014-04-30 12:54:08,382]  INFO - NioSelectorPool Using a shared selector for servlet write/read
[2014-04-30 12:54:08,412]  INFO - RegistryEventingServiceComponent Successfully Initialized Eventing on Registry
[2014-04-30 12:54:08,462]  INFO - JMXServerManager JMX Service URL  : service:jmx:rmi://localhost:11114/jndi/rmi://localhost:10002/jmxrmi
[2014-04-30 12:54:08,462]  INFO - StartupFinalizerServiceComponent Server           :  WSO2 ESB (DEV)-4.8.1
[2014-04-30 12:54:08,462]  INFO - StartupFinalizerServiceComponent WSO2 Carbon started in 24 sec
[2014-04-30 12:54:08,853]  INFO - CarbonUIServiceComponent Mgt Console URL  : https://10.0.2.15:9446/carbon/

 

V. Ejecutar el ejemplo desde un cliente Axis2.


Para ejecutar este ejemplo debemos emplear un cliente Axis2 e invocar el Proxy correspondiente al “Sample 51″.
WSO2 ESB viene con cliente Axis2 implementado (OptimizeClient) para este ejemplo. Este cliente enviará una petición a WSO2 ESB en el puerto 8280, pero mi ESB tiene el offset puesto a 3 por lo que tendré que redirigir las peticiones del puerto 8280 al 8283, para ello usaré TCPMon, una herramienta muy útil para debugging que hará todo este trabajo, además podemos inspeccionar los mensajes SOAP de request y response, y modificarlos en tiempo real.

Entonces, iniciar TCPmon y crear un Listener en 8280 y reenviarlo a 8283:

 
C:\> cd <ESB_HOME>\bin
C:\01bizlife\wso2esb-4.8.1-dev\bin>tcpmon.bat

Usar estos valores en TCPmon:

Listen Port #: 8280
Target Hostname: 127.0.0.1
Target Port #: 8283

Ahora, ejecutar el cliente Axis2. Seguir estos pasos para ejecutarlo:

 
C:\> cd <ESB_HOME>\samples\axis2Client
C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Client>ant optimizeclient -Dopt_mode=mtom

Buildfile: C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Client\build.xml

init:
      [jar] Building jar: C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Client\pathing.jar

compile:

optimizeclient:
     [java] Sending file : ./../../repository/samples/resources/mtom/asf-logo.gif as MTOM
     [java] 14/04/30 13:57:33 INFO deployment.DeploymentEngine: No services directory was found under C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Client\client_repo.
     [java] 14/04/30 13:57:33 INFO deployment.ModuleDeployer: Deploying module: addressing - file:/C:/01bizlife/wso2esb-4.8.1-dev/samples/axis2Client/client_repo/modules/addressing.mar
     [java] 14/04/30 13:57:33 INFO deployment.ModuleDeployer: Deploying module: rampart - file:/C:/01bizlife/wso2esb-4.8.1-dev/samples/axis2Client/client_repo/modules/rampart.mar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: sandesha2 - file:/C:/01bizlife/wso2esb-4.8.1-dev/samples/axis2Client/client_repo/modules/sandesha2.mar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: addressing - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.addressing_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: wso2caching - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.caching.core_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: ComponentMgtModule - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.feature.mgt.services_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: wso2mex - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.mex_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: pagination - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.registry.server_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: relay - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.relay.module_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: sandesha2 - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.rm_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: POXSecurityModule - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.security.mgt_4.2.2.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: ServerAdminModule - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.server.admin_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: wso2statistics - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.statistics_4.2.2.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: wso2throttle - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.throttle.core_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: usagethrottling - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.throttling.agent_2.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: wso2tracer - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.tracer_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: metering - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.usage.agent_2.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: wso2xfer - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/org.wso2.carbon.xfer_4.2.0.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: rampart - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/rampart-core_1.6.1.wso2v12.jar
     [java] 14/04/30 13:57:34 INFO deployment.ModuleDeployer: Deploying module: rahas - file:/C:/01bizlife/wso2esb-4.8.1-dev/repository/components/plugins/rampart-trust_1.6.1.wso2v12.jar
     [java] 14/04/30 13:57:34 ERROR sandesha2.SandeshaModule: Could not load module policies. Using default values.
     [java] 14/04/30 13:57:34 INFO mail.MailTransportSender: MAILTO Sender started
     [java] 14/04/30 13:57:34 INFO jms.JMSSender: JMS Sender started
     [java] 14/04/30 13:57:34 INFO jms.JMSSender: JMS Transport Sender initialized...
     [java] Saved response to file : C:\01bizlife\wso2esb-4.8.1-dev\samples\axis2Client\.\..\..\tmp\sampleClient\mtom-7597224514139522188.gif

BUILD SUCCESSFUL
Total time: 3 seconds

Según los logs, se ha podido enviar satisfactoriamente una imagen ubicada en C:>1bizlife\wso2esb-4.8.1-dev\repository\samples\resources\mtom\asf-logo.gif, además, la imagen recibida ha sido guardada en el lado servidor en esta ruta C:>1bizlife\wso2esb-4.8.1-dev\tmp\sampleClient\mtom-7597224514139522188.gif
 

VI. Revisando el request y response SOAP MTOM.


Gracias al uso de TCPmon hemos podido interceptar el request y el response, aunque sólo serán legibles las cabeceras SOAP mientras que parte de los payloads no ya que contienen información en formato binario.

MTOM SOAP request message:

 
POST /services/MTOMSwASampleService HTTP/1.1
Content-Type: multipart/related; boundary="MIMEBoundary_6b43ce2cbb2f537bc614ca2667f80dd0906a861a70931f26"; type="application/xop+xml"; start="<0.1b43ce2cbb2f537bc614ca2667f80dd0906a861a70931f26@apache.org>"; start-info="text/xml"
SOAPAction: "urn:uploadFileUsingMTOM"
User-Agent: Axis2
Host: 127.0.0.1:8280
Transfer-Encoding: chunked

210e
--MIMEBoundary_6b43ce2cbb2f537bc614ca2667f80dd0906a861a70931f26
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <0.1b43ce2cbb2f537bc614ca2667f80dd0906a861a70931f26@apache.org>

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
	<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
		<wsa:To>http://localhost:8280/services/MTOMSwASampleService</wsa:To>
		<wsa:MessageID>urn:uuid:526d38f6-510c-4e9e-9a0b-93ff70c8d0eb</wsa:MessageID>
		<wsa:Action>urn:uploadFileUsingMTOM</wsa:Action>
	</soapenv:Header>
	<soapenv:Body>
		<m0:uploadFileUsingMTOM xmlns:m0="http://services.samples">
			<m0:request>
				<m0:image>
					<xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:1.0b43ce2cbb2f537bc614ca2667f80dd0906a861a70931f26@apache.org">
					</xop:Include>
				</m0:image>
			</m0:request>
		</m0:uploadFileUsingMTOM>
	</soapenv:Body>
</soapenv:Envelope>
--MIMEBoundary_6b43ce2cbb2f537bc614ca2667f80dd0906a861a70931f26
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-ID: <1.0b43ce2cbb2f537bc614ca2667f80dd0906a861a70931f26@apache.org>

GIF89a ...<<binary-content>>
...
--MIMEBoundary_6b43ce2cbb2f537bc614ca2667f80dd0906a861a70931f26--

0

MTOM SOAP response message:

 
HTTP/1.1 200 OK
messageType: multipart/related
Content-Type: multipart/related; boundary="MIMEBoundary_1773747b8c9584bd1c67c2029eb620e46671585360cbb85a"; type="application/xop+xml"; start="<0.0773747b8c9584bd1c67c2029eb620e46671585360cbb85a@apache.org>"; start-info="text/xml"
Date: Wed, 30 Apr 2014 11:57:35 GMT
Server: WSO2-PassThrough-HTTP
Transfer-Encoding: chunked

1ff4
--MIMEBoundary_1773747b8c9584bd1c67c2029eb620e46671585360cbb85a
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <0.0773747b8c9584bd1c67c2029eb620e46671585360cbb85a@apache.org>

<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><m0:uploadFileUsingMTOMResponse xmlns:m0="http://services.samples"><m0:response><m0:image><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:1.3773747b8c9584bd1c67c2029eb620e46671585360cbb85a@apache.org"></xop:Include></m0:image></m0:response></m0:uploadFileUsingMTOMResponse></soapenv:Body></soapenv:Envelope>
--MIMEBoundary_1773747b8c9584bd1c67c2029eb620e46671585360cbb85a
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-ID: <1.3773747b8c9584bd1c67c2029eb620e46671585360cbb85a@apache.org>

GIF89a ...<<binary-content>>
...
--MIMEBoundary_1773747b8c9584bd1c67c2029eb620e46671585360cbb85a--

0

 

VII. Usando SoapUI para envio de mensajes MTOM SOAP directamente a Axis2 server.


Para poder usar un cliente SOAP como SoapUI en este ejemplo, necesitamos el endpoint que representa al servicio expuesto a través del Axis2 server, la acción/operación a invocar y un mensaje SOAP MTOM de ejemplo. En otras palabras, necesitamos el WSDL.
Sabemos que los servicios de back-end están desplegados sobre Axis2 server, pues si accedemos a la web de Axis2 server nos mostrará los servicios expuestos y sus respectivos WSDL, si los tienen.

Las URLs de la web de Axis2 server son:
* HTTP: http://localhost:9000/services
* HTTPS: https://localhost:9002/services

En el caso que no exista WSDL o necesitemos exponer el mismo servicio usando otro contrato, pues podemos crear un Proxy nuevo de tipo Pass Through en WSO2 ESB a partir del fichero synapse <ESB_HOME>\repository\samples\synapse_sample_51.xml, en dicho Proxy nuevo debemos indicarle el nuevo WSDL que vamos a emplear.

Entonces, el WSDL para el back-end servicio MTOMSwASampleService estará en esta URL:

 

http://localhost:9000/services/MTOMSwASampleService?wsdl

Recordar que deberá existir 3 operaciones disponibles y que SoapUI deberá generar automáticamente 3 request:
* oneWayUploadUsingMTOM
* uploadFileUsingMTOM
* uploadFileUsingSwA

MTOMSwASampleService operaciones

MTOMSwASampleService operaciones

Desde SoapUI hacemos “request SOAP” para la operación uploadFileUsingMTOM indicando como endpoint a http://localhost:9000/services/MTOMSwASampleService, el mensaje SOAP es el siguiente:

 
<soapenv:Envelope 
       xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
       xmlns:ser="http://services.samples">
   <soapenv:Header/>
   <soapenv:Body>
      <ser:uploadFileUsingMTOM>
         <ser:request>
         	<ser:image>cid:chilcano.jpg</ser:image>
         </ser:request>
      </ser:uploadFileUsingMTOM>
   </soapenv:Body>
</soapenv:Envelope>

Debemos habilitar en SoapUI las “Request Properties” para MTOM:

 
Enable MTOM = true

Luego en la pestaña “Attachments” (ubicado al pie de la ventana Request en el SoapUI) anexar el fichero que deseamos enviar junto al mensaje SOAP.
En este caso el fichero será “chilcano.jpg”.

Ahora, ya estamos listos para lanzar la petición a la implementación del servicio “MTOMSwASampleService” alojado en Axis2 server.
Al final, siguiendo el comportamiento de la acción/operación “uploadFileUsingMTOM”, el fichero “chilcano.jpg” debe ser enviado por SoapUI y recibido por Axis2 server, el mismo fichero debe ser retornado como fichero anexado al response MTOM SOAP message, para verificarlo basta con comprobar si existe algún fichero anexado en la pestaña “Attachments” del Response.

Haciendo MTOM SOAP request a uploadFileUsingMTOM

Haciendo MTOM SOAP request a uploadFileUsingMTOM

 

VIII. Usando SoapUI para envio de mensajes MTOM SOAP a través de un Pass Through Proxy en WSO2 ESB.


En este caso implementaremos un Proxy, pero para fines demostrativos mantendremos el contrato original.
Y según dicho contrato, el servicio tendrá 3 acciones/operaciones (oneWayUploadUsingMTOM, uploadFileUsingMTOM y uploadFileUsingSwA).

El Proxy que crearemos en WSO2 ESB será el siguiente y usará el WSDL expuesto desde Axis2:

 
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="proxy_MTOMSwASampleService"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <log level="custom">
            <property name="====== Proxy-MTOMSwASampleService" value="====== inSeq - ini"/>
         </log>
         <property name="POST_TO_URI" value="true" scope="default" type="STRING"/>
         <filter source="get-property('Action')" regex="urn:uploadFileUsingMTOM">
            <then>
               <header name="Action" scope="default" action="remove"/>
               <property name="SOAPAction" scope="default" action="remove"/>
               <property name="example" value="mtom"/>
               <property name="Action" value="urn:uploadFileUsingMTOM" scope="default"/>
               <header name="Action" scope="default" value="urn:uploadFileUsingMTOM"/>
               <send>
                  <endpoint>
                     <address uri="http://localhost:9001/services/MTOMSwASampleService"
                              optimize="mtom"/>
                  </endpoint>
               </send>
            </then>
            <else/>
         </filter>
         <filter source="get-property('Action')" regex="urn:uploadFileUsingSwA">
            <then>
               <property name="example" value="swa"/>
               <send>
                  <endpoint>
                     <address uri="http://localhost:9000/services/MTOMSwASampleService"
                              optimize="swa"/>
                  </endpoint>
               </send>
            </then>
            <else/>
         </filter>
         <filter source="get-property('Action')" regex="urn:oneWayUploadUsingMTOM">
            <then>
               <property name="OUT_ONLY" value="true"/>
               <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
               <property name="example" value="onewaymtom"/>
               <send>
                  <endpoint>
                     <address uri="http://localhost:9001/services/MTOMSwASampleService"
                              optimize="mtom"/>
                  </endpoint>
               </send>
            </then>
            <else/>
         </filter>
         <log level="custom">
            <property name="Proxy MTOMSwASampleService" value="================ inSeq - fin"/>
         </log>
      </inSequence>
      <outSequence>
         <log level="custom">
            <property name="====== Proxy MTOMSwASampleService" value="====== outSeq - ini"/>
         </log>
         <filter source="get-property('example')" regex="onewaymtom">
            <property name="enableMTOM" value="true" scope="axis2"/>
         </filter>
         <filter source="get-property('example')" regex="mtom">
            <property name="enableMTOM" value="true" scope="axis2"/>
         </filter>
         <filter source="get-property('example')" regex="swa">
            <property name="enableSwA" value="true" scope="axis2"/>
         </filter>
         <send/>
         <log level="custom">
            <property name="====== Proxy MTOMSwASampleService" value="====== outSeq - fin"/>
         </log>
      </outSequence>
   </target>
   <publishWSDL uri="http://localhost:9000/services/MTOMSwASampleService?wsdl"/>
   <parameter name="enableMTOM">true</parameter>
   <description>MTOMSwASampleService (Sample 51)</description>
</proxy>

En este caso, el nuevo WSDL estará servido desde el WSO2 ESB cuando despleguemos el Proxy, será la siguiente URL:

 

http://localhost:8283/services/proxy_MTOMSwASampleService?wsdl

La ventaja de usar un Pass Through Proxy es porder mediar (manipular, transformar, ruteo, etc.) el request/response, y también para un debugging más exacto empleando el mediador de LOG.

Si ahora creamos un nuevo proyecto con el Proxy, el proyecto sería el siguiente:

Proyecto SoapUI: Proxy MTOMSwASampleService

Proyecto SoapUI: Proxy MTOMSwASampleService

Los request message para cada operación son los siguientes.

Request message para oneWayUploadUsingMTOM:

 
<soapenv:Envelope 
       xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
       xmlns:ser="http://services.samples">
   <soapenv:Header/>
   <soapenv:Body>
      <ser:oneWayUploadUsingMTOM>cid:chilcano.jpg</ser:oneWayUploadUsingMTOM>
   </soapenv:Body>
</soapenv:Envelope>

Request message SOAP para uploadFileUsingMTOM:

 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
   <soapenv:Body>
      <m0:uploadFileUsingMTOMResponse xmlns:m0="http://services.samples">
         <m0:response>
            <m0:image>
               <xop:Include href="cid:1.c83f1f7b0058d225ca82b4f9a5875be65b9d20debd92abe8@apache.org" xmlns:xop="http://www.w3.org/2004/08/xop/include"/>
            </m0:image>
         </m0:response>
      </m0:uploadFileUsingMTOMResponse>
   </soapenv:Body>
</soapenv:Envelope>

El mensaje request SOAP para uploadFileUsingSwA usado es:

 
<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ser="http://services.samples">
   <soapenv:Header/>
   <soapenv:Body>
      <ser:uploadFileUsingSwA>
         <ser:request>
         	<ser:imageId>tux-mario.jpg</ser:imageId>
         </ser:request>
      </ser:uploadFileUsingSwA>
   </soapenv:Body>
</soapenv:Envelope>

Y en el lado de Axis2 Server veremos las siguientes trazas:

$ ./axis2server.sh 
 Using JAVA_HOME:   /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home
 Using AXIS2 Repository :   /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/repository
 Using AXIS2 Configuration :   /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/repository/conf/axis2.xml
14/05/12 15:46:47 INFO util.SampleAxis2ServerManager: [SimpleAxisServer] Starting
[...]
14/05/12 15:46:48 INFO nhttp.HttpCoreNIOListener: HTTPS Listener started on 0:0:0:0:0:0:0:0:9002
14/05/12 15:46:48 INFO nhttp.HttpCoreNIOListener: HTTP Listener started on 0:0:0:0:0:0:0:0:9000
14/05/12 15:46:48 INFO util.SampleAxis2ServerManager: [SimpleAxisServer] Started
[...]
Wrote to file : /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/../../tmp/sampleServer/mtom-6291717480475442754.gif
Wrote MTOM content to temp file : /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/../../tmp/sampleServer/mtom-7105409971701841709.gif
Wrote SwA attachment to temp file : /Users/Chilcano/0dev-env/2srv/wso2esb-4.8.1/samples/axis2Server/../../tmp/sampleServer/swa-5320928313738320843.gif

 

IX. Enviando BinaryData desde un Form HTML a servicio SOAP.


SOAP usa comúnmente HTTP como transporte, SOAP MTOM también usa lo mismo y el ejemplo “Sample 51″ también. En lugar de usar SoapUI por qué no empleamos un formulario HTML para enviar el un fichero pero usando un formulario del tipo multipart/form-data?.
Creo que sería la forma más natural para enviar ficheros, además sabiendo que la especificación HTTP desde inicios implementa el envío vía multipart/form-data, por qué no seguir haciéndolo?.

Dicho esto, vamos a implementar un formulario HTML para este propósito, luego, aprovechando que tenemos desplegado el “Sample 51″ en WSO2 ESB y “MTOMSwASampleService” desplegado en Axis2 Server, vamos a crear un simple Form HTML con “mutipart/form-data”, crearemos un nuevo Pass Through Proxy que recibirá la petición del Form HTML y reenviará una petición SOAP al Proxy creado al inicio de esta entrada pero con unas pequeñas modificaciones.

También será necesario modificar la implementación de “MTOMSwASampleService” para implementar una nueva operación que sepa decondificar la nueva petición efectuada desde un Form HTML.

El siguiente gráfico representa la situación final:

[HTML Form]=>[ msg HTTP]=>[Proxy 01]=>[msg-soap]=>[Proxy 02]=>[msg SOAP]=>[  SOAP req  ]
             |multipart|  [WSO2 ESB]  [ base64 ]  [WSO2 ESB]  | base64 |  [Axis2 Server]
             [form-data]                                      [or MTOM ]  

Pues los proxies de WSO2 ESB nuevos y actualizados, el Form HTML, el servicio “MTOMSwASampleService” modificado los publicaré en un segundo post en este blog.
Asi que siga sintonizado :)

X. Conclusiones.


  • En un escenario SOA lo más probable es que todo sean servicios implementados en SOAP y si se requiere enviar de manera optimizada ficheros en formato binario de manera óptima y de una forma estándar, lo recomendable es usar MTOM sobre SOAP.
  • Si estamos fuera de un proyecto SOA, podemos disponer de opciones como FTP, VFS o Formulario HTML con CGI en el lado servidor.
  • Hay que destacar que el uso de MTOM sobre SOAP es un forma de envio de ficheros en binario de una manera óptima y eficiente, además el envío de ficheros grandes también sigue siendo de una manera óptima. Si estáis buscando el envío de grandes volúmenes de ficheros grandes, considerar MTOM sobre SOAP como una buena opción.

 

XI. Referencias.


Revisión del libro “Activiti 5.x Business Process Management”

Packt Publishing me ha solicitado revisar el libro “Activiti 5.x Business Process Management: Beginner’s Guide“, escrito por Dr. Zakir Laliwala y Irshad Mansuri.

Activiti BPM

Activiti BPM

Particularmente destaco la importancia de los libros para productos Open Source como Activiti, por lo general se trata de contenido muy actual y práctico para los que quieran iniciarse rápidamente en este mundo y evitar leer y revisar información y documentación muy dispersa e inexacta.

Activiti 5.x Business Process Management Beginner's Guide

Activiti 5.x Business Process Management Beginner’s Guide

En fin, aquí va mi revisión.

Para empezar, el libro está orientado a principiantes y no requiere tener conocimientos previos técnicos, por este motivo, si alguien quiere iniciarse en mundo del BPM, este libro es el medio adecuado.

Cabe destacar también que Activiti es una Suite BPM “centrado a humano” (Human-Centric BPMS) y no es una Suite BPM “centrada a integración” (Integration-Centric BPMS o System-Centric BPMS), esto quiere decir que Activiti es un herramienta que da soporte a la interacción humana en los procesos de negocio de la Organización, por este motivo que este libro en el Capítulo 1 inicia con la Instalación y configuración de un Entorno de trabajo con Activiti, luego, en el Capítulo 2 nos dá una visión rápida de la notación BPMN para diseñar nuestros procesos de negocio siguiendo las buenas prácticas y patrones de modelamiento.

Después de aprender BPMN, en el Capítulo 3, “Designing Your Process Using the Activiti Designer”, se emplea Activiti Designer para modelar los procesos de negocios, también se explica cómo integrar Activiti Designer con Eclipse.

En el Capítulo 4, Management and Monitoring Using the Activiti Explorer, se explica cómo emplear Activiti Explorer, aplicación web, para explorar sobre los recursos asociados a los procesos de negocios, desde tareas, instancias de procesos y usuarios. Además nos permitirá generar reportes de actividad de nuestros procesos de negocios.

Llegado a este punto tendrás el conocimiento necesario para definir y modelar todos tus procesos de negocio sin necesidad de conocimientos técnicos previos.

En los siguientes capítulos (Capítulos 5, 6, 7 y 8) se explica aspectos más profundos y técnicos de Activiti, desde el ciclo de desarrollo de aplicaciones siguiendo BPMN, hasta aspectos de integración con Servicios externos, además se enseña cómo interactuar con Activiti a través de su REST API.

Finalmente, en el Capítulo 9, Implementing Advanced Workflows, se explica cómo implementar procesos de negocio complejos (sub-procesos, procesos de multiple instancias, gateway paralelos, etc.)

En conclusión, con este libro podemos iniciar a personas en el mundo del desarrollo de aplicaciones usando BPM de manera fácil y rápida.

Creando rápidamente un “Business Ecosystem” en las Organizaciones usando WSO2

Este es mi primer screencast, así que pido disculpas por si no se entiende, os agradezco vuestros comentarios al respecto y así ir mejorando en los siguientes posts.

En esta entrada os explico BizLife.org, es una PoC (Proof of Concept) resultado de la Creación de manera ágil de un Ecosistema Empresarial usando WSO2 stack como herramienta de integración de sistemas y aplicaciones existentes en la Empresa.

A fecha de hoy (2014/Marzo), WSO2 también pone foco en los “Connected Business” o “Business Ecosystem” y lo explica en el Asia 2014 WSO2Con. Esto quiere decir que estamos realizando proyectos que apuntan a la misma dirección de WSO2. Con ello nuestra relación como Partner Oficial de WSO2 se ve fortalecida.

WSO2 - Build a Connected Business

WSO2 – Build a Connected Business

Muestro BizLife.org, diferentes escenarios y estrategias de integración y cómo cada producto de WSO2 se ajusta en cada escenario de integración.

Un Ecosistemas Empresarial (Business Ecosystem) es la agrupación de Sistemas y Aplicaciones existentes (ERP, CRM, ECM, etc.) en la Organización, pudiendo estar integrados o funcionar de manera aislada, que sería lo más común. En ese escenario, el stack WSO2 es el conjunto de herramientas que nos permite integrar de manera rápida los sistemas existentes.

Bien, aquí os dejo el screencast y la presentación:

Parte 1: “BizLife – Introducción”

Parte 2: “BizLife – Demostraciones”

Y aquí la presentación:

Saludos.

Business Activity Monitoring aplicado a Openbravo ERP usando WSO2 ESB y WSO2 BAM

Mi colega Luis Peñarrubia ha publicado un detallado post de cómo usar WSO2 BAM, WSO2 ESB para monitorizar la capa de servicio de Openbravo ERP (Data Access Layer).

Aquí os dejo el documento que explica cómo hacerlo paso a paso:

Por otro lado, al desplegarlo en mi entorno, WSO2 BAM mostraba errores de autenticación de Apache Thrift con Apache Cassandra, como este:

 

[2014-03-20 17:31:16,112]  INFO {org.wso2.carbon.ntask.core.service.impl.TaskServiceImpl} -  Task service starting in STANDALONE mode...
[2014-03-20 17:31:16,285] ERROR {org.wso2.carbon.bam.notification.task.internal.NotificationDispatchComponent} -  InvalidRequestException(why:You have not logged in)
me.prettyprint.hector.api.exceptions.HInvalidRequestException: InvalidRequestException(why:You have not logged in)
	at me.prettyprint.cassandra.service.ExceptionsTranslatorImpl.translate(ExceptionsTranslatorImpl.java:45)
	at me.prettyprint.cassandra.service.ThriftCluster$6.execute(ThriftCluster.java:164)
	at me.prettyprint.cassandra.service.ThriftCluster$6.execute(ThriftCluster.java:151)
	at me.prettyprint.cassandra.service.Operation.executeAndSetResult(Operation.java:103)
	at me.prettyprint.cassandra.connection.HConnectionManager.operateWithFailover(HConnectionManager.java:258)
	at me.prettyprint.cassandra.service.ThriftCluster.addKeyspace(ThriftCluster.java:168)

[...]

[2014-03-20 17:31:16,471]  INFO {org.wso2.carbon.databridge.core.DataBridge} -  admin connected
[2014-03-20 17:31:16,473] ERROR {org.wso2.carbon.databridge.core.internal.authentication.Authenticator} -  wrong userName or password
[2014-03-20 17:31:16,475] ERROR {org.wso2.carbon.bam.notification.task.NotificationDispatchTask} -  Error executing notification dispatch task: Cannot borrow client for TCP,10.10.10.24:7613,TCP,10.10.10.24:7713
org.wso2.carbon.databridge.agent.thrift.exception.AgentException: Cannot borrow client for TCP,10.10.10.24:7613,TCP,10.10.10.24:7713
	at org.wso2.carbon.databridge.agent.thrift.internal.publisher.authenticator.AgentAuthenticator.connect(AgentAuthenticator.java:58)
	at org.wso2.carbon.databridge.agent.thrift.DataPublisher.start(DataPublisher.java:273)
	at org.wso2.carbon.databridge.agent.thrift.DataPublisher.<init>(DataPublisher.java:211)
	at org.wso2.carbon.bam.notification.task.NotificationDispatchTask.initPublisherKS(NotificationDispatchTask.java:103)
	at org.wso2.carbon.bam.notification.task.NotificationDispatchTask.execute(NotificationDispatchTask.java:188)
	at org.wso2.carbon.ntask.core.impl.TaskQuartzJobAdapter.execute(TaskQuartzJobAdapter.java:67)
	at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
	at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
	at java.util.concurrent.FutureTask.run(FutureTask.java:166)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
	at java.lang.Thread.run(Thread.java:679)
Caused by: org.wso2.carbon.databridge.commons.exception.AuthenticationException: Thrift Authentication Exception
	at org.wso2.carbon.databridge.agent.thrift.internal.publisher.authenticator.ThriftAgentAuthenticator.connect(ThriftAgentAuthenticator.java:49)
[...]

Esto se debe a que no he actualizado los ficheros de conexión con Apache Cassandra con las nuevas credenciales de WSO2 BAM, en mi caso no es admin/admin. Entonces, hay actualizar los siguientes ficheros:

 
$ nano /opt/wso2bam-2.4.0/repository/conf/etc/cassandra-auth.xml 
$ nano /opt/wso2bam-2.4.0/repository/conf/datasources/master-datasources.xml 

Saludos.

Message Brokering y recolección de datos para Big Data con WSO2

Message Brokering es el conjunto de mecanismos por el cual se gestiona la recepción y la entrega de mensajes entre sistemas distribuidos. El propósito final con los Message Broker Systems son:

  • Desacoplar: En tiempo, en espacio y a nivel de sincronización.
  • Confiabilidad: A nivel de transacción y de persistencia.

1. Casos de uso y beneficios

Los beneficios son palpables, como por ejemplo:

  • Comunicación Síncrona/Asíncrona/Colas: Hacer una solicitud (enviar un mensaje) y que te respondan después de cierto tiempo.
  • Persistencia de mensajes: Hacer una solicitud y que la petición siga viva a pesar de que los sistemas no hayan estado operativos después de haber realizado la solicitud, almacenar de manera persistente los mensajes de las solicitudes excedentes efectuadas a un servicio o simplemente, almacenar con gran rapidez y garantía los mensajes de las solicitudes realizadas.
  • Publicación/Suscripción: Publicar un mensaje de cierto tópico y que sólo ciertos clientes reciban el mensaje.

Hay diferentes casos de uso o escenarios donde son necesarios los Message Brokers, pero los más representativos están definidos en los Enterprise Integration Patterns, estos son:

Message Broker - Colas y Persistencia de mensajes

Message Broker – Colas y Persistencia de mensajes

Message Broker - Publicación y Suscripción

Message Broker – Publicación y Suscripción

2. Message Brokers en el mundo real: Big Data

Dependiendo del tipo de mensaje y del tipo de clientes existen muchos tipos de Message Brokers, algunos por ejemplo:

  • Sensores (clientes MB)
  • Monitorización (cliente suscriptor MB)
  • Vigilancia (cliente suscriptor MB)
  • Business Activity Monitoring (BAM)
  • Scheduling Systems
  • Redes Sociales

Hay que destacar que su uso ahora es más frecuente en sectores inimaginables, sobretodo en los Sistemas de Información Críticos, donde fallar no es una opción, son escenarios muy diferentes al tradicional, en otras palabras, son escenarios relacionados a Internet of Things y comunicación Machine-to-Machine que con mucha innovación promueve el uso de este tipo de Message Brokers y por consecuencia la re-definición de protocolos y especificaciones, esto se da por los mismos beneficios que arriba indicábamos.

Entre los productos free/open source más usados tenemos:

  1. WSO2 Message Broker: basado en Apache Qpid (http://qpid.apache.org) e implementa el “Advanced Message Queueing Protocol” (AMQP – http://www.amqp.org) y otros estándares relacionados como JMS y WS-Eventing. Es rápido, potente y muy ligero, la persistencia de mensaje se logra con el uso de Apache Cassandra y en combinación con Apache Zookeper nos permite coordinar colas distribuidas. Los complementos perfectos son WSO2 ESB (mediation), WSO2 BAM (streams) y WSO2 CEP (eventing).
  2. Storm MQ (http://stormmq.com): implementa también AMQP, provee un Message Broker y Message Store en la nube accesible a través de un API.
  3. ActiveMQ (http://activemq.apache.org): proyecto de Apache, implementa muchos Enterprise Integration Patterns (EIP) a través de Apache Camel (http://camel.apache.org). Implementa una variedad de protocolos como JMS y MQTT (machine-to-machine / “Internet of Things” connectivity binary protocol – http://mqtt.org).
  4. Rabbit MQ (http://www.rabbitmq.com): a diferencia de los anteriores implementa muchos protocolos a nivel de transporte y mensaje, entre ellos AMQP, STOMP (text-based messaging protocol emphasising simplicity – http://stomp.github.io), MQTT  y HTTP.
  5. Mosquitto  (http://mosquitto.org): Message Broker para el protocolo MQTT muy potente y veloz, muy usado en IoT / M2M.
  6. Paho (http://eclipse.org/paho): altamente escalable, optimizado para equipos de reducida potencia y para redes muy restringidas, junto a Mosquitto son los brokers más usados en IoT / M2M, ambos poseen muchos clientes desde C++ a JavaScript, como tal implementa también el protocolo MQTT.
  7. ActiveMQ Apollo (http://activemq.apache.org/apollo): es la nueva generación de Apache ActiveMQ que soporte protocolos como STOMP, AMQP, MQTT, Openwire, SSL y WebSockets.

3. Escalando los Message Broker Systems

Para escalar un Broker debemos considerar 3 dimensiones:

  • Número de mensajes soportados
  • Número de colas soportadas
  • Tamaño de los mensajes

Considerando estas dimensiones, podríamos indicar que nuestro Broker es potencialmente escalable, aunque su implementación, sobretodo para Colas Distribuidas, se convierte en un reto.

Más información aquí:

4. Implementando Message Store EIP con WSO2

En mi opinión, el uso de Message Broker para controlar la persistencia de mensajes es vital en Sistemas de Información Críticos. ¿De qué sirve si podemos recibir y/o entregar mensajes de manera muy rápida, si por algún problema de conectividad algunos mensajes se perderían?. Como indiqué líneas arriba, esto no es admitible en Sistemas de Información Críticos, por lo que lo el uso de Message Broker y sus características como la persistencia de mensajes es vital.

En fin, a continuación implementaremos Message Store EIP con WSO2.

Enterprise Integration Pattern - Message Store

Enterprise Integration Pattern – Message Store

5. Arquitectura de Referencia para Message Brokering y estrategias de integración

Existen dos posibilidades de implementar Message Store EIP con WSO2, la primera únicamente con WSO2 ESB y la segunda con WSO2 ESB y WSO2 MB (Message Broker). En ambas configuraciones podemos implementar Message Store EIP con algunas pequeñas diferencias técnicas, aprovechando que WSO2 ESB está basado en Apache Synapse (https://synapse.apache.org), podemos mediar las peticiones y los mensajes haciendo que se persistan en diferentes tipos de medios (WSO2 ESB Store – Mediator), como:

Durante mis pruebas con WSO2 ESB 4.8.1 me he encontrado que la funcionalidad de explorar los mensajes almacenados en el Message Store cuando usamos cualquier JMS Broker ha sido quitada desde la versión 4.7.0 (más información aquí: https://wso2.org/jira/browse/ESBJAVA-2529), así que implementaremos 3 escenarios para explorar los mensajes almacenados en el lado del WSO2 ESB y del WSO2 MB:

  • Escenario 1: Hacer una petición a un HTTP Proxy y almacenar el mensaje en un Message Store de tipo in memory.
  • Escenario 2: Hacer una petición a un HTTP Proxy y almacenar el mensaje en una Cola del WSO2 MB.
  • Escenario 3: Hacer una petición a un HTTP Proxy que hace de interfaz de un JMS Proxy.

Antes de desarrollar cada escenarios, vamos a explicar cómo configurar WSO2 ESB con WSO2 MB.

5.1. Instalación y configuración de WSO2 ESB y WSO2 MB

Para poder conectar WSO2 ESB con los Brokers, es necesario que estos implementen Java Message Service (JMS), conectando un Broker facilita comunicación desacoplada, confiable y asíncrona entre los diferentes componentes de un sistema distribuido.

WSO2 ESB puede conectarse con:

  • ActiveMQ
  • IBM WebSphere MQ
  • IBM WebSphere Application Server
  • JBossMQ
  • Microsoft Message Queuing (MSMQ)
  • Tibco EMS
  • SwiftMQ
  • Oracle WebLogic 10.3.4.0
  • Y WSO2 Message Broker

Emplearemos WSO2 MB 2.1.0 (con offset 4) y WSO2 ESB 4.8.1 (con offset 2), ambos sobre Mac OSX 10.9.1 y Java 7.x. Descargarlos y descomprimirlos. Luego configurar WSO2 MB para que no tenga conflictos con WSO2 ESB, para ello cambiar los puertos (offset) de ambas aplicaciones.

Configuración de WSO2 MB:

1) Actualizar offset en \repository\conf\carbon.xml

2) Actualizar puertos de Apache Cassandra en \repository\conf\advanced\qpid-virtualhosts.xml

3) Con Mac OS X (Mavericks) y Java 7.x hay que actualizar la librería Java Snappy ya que si no se hace, WSO2 MB o WSO2 BAM no funcionaría ya que ambos embeben Apache Cassandra (https://code.google.com/p/snappy-java/issues/detail?id=39). Sólo hay que descargar snappy-java-1.0.5.jar, luego extraer snappy-java-1.0.5/org/xerial/snappy/native/Mac/x86_64/libsnappyjava.jnilib y copiarlo a /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/ con este nombre libsnappyjava.dylib. Más información aquí: https://github.com/thinkaurelius/titan/issues/62

$ sudo cp libsnappyjava.jnilib /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home/jre/lib/libsnappyjava.dylib

4) Iniciar WSO2 MB

5) Finalmente, no funcionará WSO2 MB ya que después de solucionar este error salen 2 más, uno durante el inicio y otro relacionado a JMX:

[2014-03-05 14:14:24,270]  INFO {org.wso2.carbon.core.transports.http.HttpTransportListener} -  HTTP port        : 9763
java(682,0x1111b8000) malloc: *** error for object 0x1111a3ff0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
./wso2server.sh: line 299:   682 Abort trap: 6           $JAVACMD -Xbootclasspath/a:"$CARBON_XBOOTCLASSPATH" -Xms256m -Xmx1024m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath="$CARBON_HOME/repository/logs/heap-dump.hprof" -javaagent:"$CARBON_HOME/repository/components/plugins/jamm_0.2.5.wso2v2.jar" $JAVA_OPTS -DandesConfig=qpid-config.xml -Ddisable.cassandra.server.startup=true -Dcom.sun.management.jmxremote -classpath "$CARBON_CLASSPATH" -Djava.endorsed.dirs="$JAVA_ENDORSED_DIRS" -Djava.io.tmpdir="$CARBON_HOME/tmp" -Dcatalina.base="$CARBON_HOME/lib/tomcat" -Dwso2.server.standalone=true -Dcarbon.registry.root=/ -Djava.command="$JAVACMD" -Dcarbon.home="$CARBON_HOME" -Djava.util.logging.config.file="$CARBON_HOME/repository/conf/log4j.properties" -Dcarbon.config.dir.path="$CARBON_HOME/repository/conf" -Dcomponents.repo="$CARBON_HOME/repository/components/plugins" -Dconf.location="$CARBON_HOME/repository/conf" -Dcom.atomikos.icatch.file="$CARBON_HOME/lib/transactions.properties" -Dcom.atomikos.icatch.hide_init_file_path=true -Dorg.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true -Dcom.sun.jndi.ldap.connect.pool.authentication=simple -Dcom.sun.jndi.ldap.connect.pool.timeout=3000 -Dorg.terracotta.quartz.skipUpdateCheck=true -Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF8 org.wso2.carbon.bootstrap.Bootstrap $*
[2014-03-05 15:26:15,064]  INFO {org.wso2.carbon.core.transports.http.HttpTransportListener} -  HTTP port        : 9763
[2014-03-05 15:27:15,492] ERROR {org.wso2.carbon.core.init.JMXServerManager} -  Could not initialize RMI server
java.io.IOException: Cannot bind to URL [rmi://localhost:9999/jmxrmi]: javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
	java.net.SocketTimeoutException: Read timed out]

6) Dejo Mac OS X y paso a Windows. En este caso no es necesario actualizar la librería java snappy, sólo cambiar los puertos.

Configuración de WSO2 ESB:

1) Actualizar offset en \repository\conf\carbon.xml

2) Habilite JMS para configurarlo con el WSO2 MB externo editando el fichero /repository/conf/axis2/axis2.xml. Luego identifique el bloque para WSO2 MB 2.x y descomente el bloque.

3) En el mismo fichero, descomente el bloque para JMSSender.

4) Copiar los JAR bajo /clent-lib/ al directorio /repository/components/lib/ :

  • andes-client-0.13.wso2v8.jar
  • geronimo-jms_1.1_spec-1.1.0.wso2v1.jar

5) Una vez WSO2 ESB y WSO2 MB (con Apache Cassandra embebida) iniciados, explore ambos servicios. Más información sobre configuración seguir la documentación oficial: https://docs.wso2.org/display/ESB481/Configure+with+WSO2+Message+Broker

5.2. Implementación de escenarios

Los escenarios a implementar serán:

  • Escenario #1: Hacer una petición a un HTTP Proxy y almacenar el mensaje en un Message Store de tipo in memory.
  • Escenario #2: Hacer una petición a un HTTP Proxy y almacenar el mensaje en una Cola del WSO2 MB.
  • Escenario #3: Hacer una petición a un HTTP Proxy que hace de interfaz de un JMS Proxy.

WSO2 ESB viene con muchos ejemplos, entre ellos los relacionados a persistencia y entrega de mensajes. Toda la información para ejecutar los ejemplos puede ser encontrado aquí: https://docs.wso2.org/display/ESB481/Store+and+Forward+Messaging+Patterns+with+Message+Stores+and+Processors.

5.2.1. Escenario #1: Petición a un HTTP Proxy y almacenamiento del mensaje en un In Memory Message Store

En este escenario almacenaremos el mensajes en un Message Store de tipo In Memory, es un almacenamiento muy rápido pero tiene la desventaja de que es volatil, es decir, si reiniciamos WSO2 ESB, los mensajes se perderán.

Message Store EIP with WSO2 ESB

Message Store EIP with WSO2 ESB

Pasos:

1) En WSO2 ESB crear un Message Store de tipo In Memory, tal como se muestra en la figura siguiente:

WSO2 ESB - Creating Message Store

WSO2 ESB – Creating Message Store

2) Crear un Address Endpoint:

<endpoint name="openbravo1_dal_soap_ep_external">
   <address uri="http://api.bizlife.org/services/proxy_openbravo1.proxy_openbravo1HttpSoap12Endpoint"/>
</endpoint>

3) Crear un HTTP Proxy Service que recoja el mensaje enviado al Address Endpoint antes creado y luego almacenarlo en el In Memory Message Store.

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="proxy_openbravo_msgstore_inmemory"
       transports="http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
         <property name="OUT_ONLY" value="true"/>
         <property name="target.endpoint" value="openbravo1_dal_soap_ep_external"/>
         <log level="full"/>
         <store messageStore="messagestorage_openbravo_inmemory"/>
      </inSequence>
   </target>
   <description>HTTP Proxy para almacenar msg en Message Store In Memory</description>
</proxy>

4) Invocar el HTTP Proxy antes creado (para fines demostrativos usar cualquier mensaje XML SOAP) varias veces, usar TryIt o SoapUI.

WSO2 ESB - Calling Proxy using TryIt

WSO2 ESB – Calling Proxy using TryIt

5) En WSO2 ESB explorar los mensajes almacenados en el Message Store.

WSO2 ESB - Browsing stored messages

WSO2 ESB – Browsing stored messages

5.2.2. Escenario #2: Petición a un HTTP Proxy y almacenamiento del mensaje en WSO2 MB

En este escenario introduciremos WSO2 MB para que sea él que gestione los mensajes, peticiones y entrega. En este caso configuraremos WSO2 ESB indicándole que el nuevo Broker será WSO2 MB.

Message Store EIP with WSO2 ESB and WSO2 Message Broker

Message Store EIP with WSO2 ESB and WSO2 Message Broker

Pasos:

1) Detenga WSO2 ESB.

2) Edite el fichero /repository/conf/jndi.properties y apunte al WSO2 MB (considere el port offset). Usar carbon como virtualhost en lugar de test. Comente el topic si no es usado, pero para evitar el error javax.naming.NameNotFoundException: TopicConnectionFactory, también configurar TopicConnectionFactory apuntando al Message Broker de igual forma que QueueConnectionFactory. El fichero quedaría así:

# register some connection factories
# connectionfactory.[jndiname] = [ConnectionURL]
connectionfactory.QueueConnectionFactory = amqp://admin:admin@clientID/carbon?brokerlist='tcp://localhost:5677'

# register some queues in JNDI using the form
# queue.[jndiName] = [physicalName]
queue.proxy_openbravo1_qpid_queue = proxy_openbravo1_qpid_queue
queue.msgstore_openbravo_wso2mb = msgstore_openbravo_wso2mb

# register some topics in JNDI using the form
# topic.[jndiName] = [physicalName]
connectionfactory.TopicConnectionFactory = amqp://admin:admin@clientID/carbon?brokerlist='tcp://localhost:5677'
# topic.MyTopic = example.MyTopic

Donde:

  • proxy_openbravo1_qpid_queue es una cola que usaremos en el escenario #3
  • msgstore_openbravo_wso2mb es la cola que nos permitirá almacenar los mensajes en WSO2 MB

3) Iniciar WSO2 ESB.

4) En WSO2 ESB crear un Message Store de tipo In Memory, tal como se muestra en la figura siguiente:

WSO2 ESB - Creating a JMS Message Store

WSO2 ESB – Creating a JMS Message Store

5) Si no lo habéis creado antes, crear un Address Endpoint, como sigue:

<endpoint name="openbravo1_dal_soap_ep_external">
   <address uri="http://api.bizlife.org/services/proxy_openbravo1.proxy_openbravo1HttpSoap12Endpoint"/>
</endpoint>

6) Crear un HTTP Proxy como sigue:

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="proxy_openbravo_msgstore_wso2mb"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <log level="full"/>
         <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
         <property name="OUT_ONLY" value="true"/>
         <property name="target.endpoint" value="openbravo1_dal_soap_ep_external"/>
         <store messageStore="msgstore_openbravo_wso2mb"/>
         <log level="custom">
            <property name="==[ proxy_openbravo_msgstore_wso2mb ]" value="+++++++++"/>
         </log>
      </inSequence>
   </target>
   <description>HTTP Proxy - envia msg al Message Store</description>
</proxy>

7) Crear un Message Processor, éste servirá para consumir los mensajes alojados en la cola de WSO2 MB y enviarlas al Endpoint correspondiente. Por el momento, la crearemos en estado inactivo y así poder observar el contenido de estos mensajes.

<messageProcessor name="proxy_openbravo_processor" class="org.apache.synapse.message.processor.impl.forwarder.ScheduledMessageForwardingProcessor" targetEndpoint="openbravo1_dal_soap_ep_external" messageStore="msgstore_openbravo_wso2mb" xmlns="http://ws.apache.org/ns/synapse">
   <parameter name="interval">1000</parameter>
   <parameter name="client.retry.interval">1000</parameter>
   <parameter name="is.active">false</parameter>
</messageProcessor>

8) Ya estamos listos para invocar al Proxy. Usar TryIt o SoapUI. Cualquier tipo de mensaje SOAP es válido, se trata de ver que el mensaje se almacena en la cola del WSO2 MB.

WSO2 ESB - Calling HTTP Proxy using TryIt

WSO2 ESB – Calling HTTP Proxy using TryIt

9) Ahora, si activamos el Message Processor antes creado, veremos que el contador de mensajes se decrementa y en el lado del Servicio de backend (en mi caso Openbravo ERP) se verá que el servicio se está siendo consultado.

WSO2 MB - Queue storting messages

WSO2 MB – Queue storting messages

Si exploramos algún mensaje almacenado en esta cola, veremos que no podemos visualizarlo correctamente ya que dicho mensaje está serializado. Será el Message Processor del WSO2 ESB quién lo deserializará para enviarlo al Endpoint.

WSO2 MB - Browsing stored messages in Queue

WSO2 MB – Browsing stored messages in Queue

5.2.3. Escenario #3: Petición a un HTTP Proxy que hace de interfaz de un JMS Proxy.

Este escenario nos permite usar WSO2 ESB como un cliente JMS, es decir, que si queremos interactuar con un JMS Broker, basta con crear un JMS Proxy en WSO2 ESB, luego desde cualquier cliente SOAP (TryIt o SoapUI) podemos interactuar con el JMS Broker sin necesidad de programar un cliente JMS.

Pasos a seguir:

1) En el escenario #2 ya creamos una cola llamada proxy_openbravo1_qpid_queue que usaremos ahora para crear un JMS Proxy.

2) Detener WSO2 ESB, luego habilitar el transport JMS (sender y receiver), para ello edite el fichero /repository/conf/axis2/axis2.xml. Luego identifique el bloque para WSO2 MB 2.x y descomente el bloque. En el mismo fichero, descomente el bloque para JMSSender.

3) Reiniciar WSO2 ESB, luego crear 2 Proxies en WSO2 ESB (HTTP Proxy que recibirá petición SOAP, que luego reenviará el mismo mensaje al Queue Proxy usando transporte JMS).

proxy_openbravo1_qpid_proxy:

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="proxy_openbravo1_qpid_proxy"
       transports="https,http"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <log level="custom">
            <property name="==[ proxy_openbravo1_qpid_proxy ]==" value="ini - inSequence"/>
         </log>
         <log level="full"/>
         <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
         <property name="OUT_ONLY" value="true"/>
         <send>
            <endpoint>
               <address uri="jms:/proxy_openbravo1_qpid_queue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&amp;java.naming.factory.initial=org.wso2.andes.jndi.PropertiesFileInitialContextFactory&amp;java.naming.provider.url=repository/conf/jndi.properties&amp;transport.jms.DestinationType=queue"/>
            </endpoint>
         </send>
         <log level="custom">
            <property name="==[ proxy_openbravo1_qpid_proxy ]==" value="fin - inSequence"/>
         </log>
      </inSequence>
   </target>
   <description>HTTP Proxy - envia msg al Queue Proxy via JMS transport</description>
</proxy>

proxy_openbravo1_qpid_queue:

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse"
       name="proxy_openbravo1_qpid_queue"
       transports="jms"
       statistics="disable"
       trace="disable"
       startOnLoad="true">
   <target>
      <inSequence>
         <log level="custom">
            <property name="==[ proxy_openbravo1_qpid_queue ]==" value="ini - inSequence"/>
         </log>
         <log level="full"/>
         <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
         <property name="OUT_ONLY" value="true"/>
         <send>
            <endpoint>
               <address uri="http://api.bizlife.org/services/proxy_openbravo1.proxy_openbravo1HttpSoap12Endpoint"/>
            </endpoint>
         </send>
         <log level="custom">
            <property name="==[ proxy_openbravo1_qpid_queue ]==" value="fin - inSequence"/>
         </log> 
      </inSequence>
   </target>
   <description>JMS Proxy - recibe msg y lo envia a proxy_openbravo1_qpid_queue</description>
</proxy>

4) Ahora, usando cualquier cliente SOAP hacer una consulta al proxy.

WSO2 ESB - Calling JMS Proxy

WSO2 ESB – Calling JMS Proxy

En las trazas de WSO2 ESB veremos los log de la ejecución de los 2 proxies anteriores.

WSO2 ESB - Logs when calling JMS Proxy

WSO2 ESB – Logs when calling JMS Proxy

Conclusiones

  • Si requieres una comunicación desacoplada, confiable, con capacidad de persistencia de los mensajes, pues el uso de un Message Broker es la mejor opción.
  • Para entornos o Sistemas de Información Críticos es recomendable el uso de Message Brokers por su capacidad de gestionar grandes volúmenes de mensajes y su capacidad de persistencia de mensajes.
  • Para entornos Big Data, WSO2 Message Broker es capaz de escalar en las 3 dimensiones siguientes: volumen de mensajes, tamaño de mensajes y número de colas.
  • Hay una tendencia en el uso de Message Brokers para entornos Internet of Things (IoT), por ser entornos muy restrictivos (red lentas o con mucha latencia, potencia de los sensores, mensajes pequeños, etc.) se opta por protocolos más adecuados como MQTT en lugar de JMS/AMQP. Se suele usar MQTT para la “primera milla”, mientras que AMQP se usa para mover los datos (también es óptimo, preparado para mensajes grandes, etc.) por resto de los sistemas distribuídos.
  • El complemento perfecto para WSO2 ESB es WSO2 Message Broker, mientras que el ESB crea interfases para nuestros servicios, WSO2 Message Broker se encarga de dar persistencia y entrega de los mensajes de manera eficiente.
  • Java Message Service (JMS) es el estándar más usado a pesar de que no define el formato del mensaje a emplear o cómo hay que interactuar con el Message Broker. AMQP es el estándar que cubre dicho “gap”.