viernes, 30 de enero de 2015

image

En una entrada anterior, vimos cómo implementar un escenario donde se debía cargar la información de un fichero CSV ubicado en un FTP y procesar dicha información(órdenes de compra) en el WSO2 ESB para notificar a los clientes de las órdenes y guardar las mismas en BD.

En esta solución teníamos que implementar un componente en JAVA encargado de recibir el fichero y convertirlo en XML para que sirviera como entrada al ESB y otro componente para formatear el mensaje de correo a enviarle a los clientes.

Buscando minimizar la cantidad de código java hemos actualizado esta solución sustituyendo el “CSVFile Builder” por un mediador dentro del ESB, que nos permite de forma muy fácil lleva de un fichero csv a un XML.

Para lograr lo anterior, en esta otra entrada mostramos cómo hacer uso del framework Smooks para llevar de un formato XML a otro y además notamos que entre sus funcionalidades está la de llevar de CSV a XML y en esta entrada podemos ver como combinar el framework smooks con el WSO2 ESB para llevar de CSV a XML.

Los pasos son los siguientes:
  1. Elaborar en el Developer Studio la configuración smooks para llevar de un csv al XML deseado.
  2. Remover del ESB los elementos incluidos para usar el componente java que parsea el fichero y carga los datos en un xml.
  3. Incluir en el servicio proxy a través de un mediador smooks la configuración del paso 1 y probar.

Paso 1:
Lo primero es abrir el WSO2 Developer Studio y desde su Dashboard crear un “Registry Resources Project”.
img1
Luego creamos un nuevo “Registry Resource”
img2
Y le especificamos que usaremos el template para Smooks.
img4
Una vez creado el fichero de configuración seleccionamos el tipo de entrada como CSV y definimos los nombres de los campos que se corresponden con los datos a cargar, así como el separador y el nombre del nodo que contendrá cada record así como el elemento raíz.
img5 
Tener en cuenta que el fichero csv que emplearemos tiene esta data:
img6

Para definir los ficheros de entrada y salida creamos una carpeta que los contendrá e incluímos estos ficheros en dicha carpeta.

img8

Como pueden observar en la siguiente imagen, el fichero que contiene la estructura de salida es un reflejo del mensaje que está esperando el ESB.
img9

 Cargamos este fichero en el input data y ya estamos listos para realizar la transformación.
img10

La transformación quedaría de la siguiente manera:
img12
Como pueden ver es muy sencilla y para probarla solo deben añadir las dependencias de smooks al proyecto usando la librería de WSO2/Smooks y probar tal como hicimos en la entrada introductoria a smooks.
img13

Paso2: vamos a eliminar del fichero axis2.xml en el ESB la carga del componente java para que no procese el fichero cuando sea detectado y también podemos eliminar el jar que lo implementa.

Paso 3:
En este punto debemos crear un entrada local en el ESB(local entry) con nombre "orderIncommingTransfer.xml" y agregamos el fuente del fichero de configuración del paso 1 tal cual se generó.


<?xml version="1.0" encoding="UTF-8"?>
<localEntry xmlns="http://ws.apache.org/ns/synapse" key="orderIncommingTransformer">
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd" xmlns:csv="http://www.milyn.org/xsd/smooks/csv-1.2.xsd" xmlns:edi="http://www.milyn.org/xsd/smooks/edi-1.2.xsd" xmlns:ftl="http://www.milyn.org/xsd/smooks/freemarker-1.1.xsd">
  <params>
    <param name="stream.filter.type">SAX</param>
    <param name="inputType">input.csv</param>
    <param name="input.csv" type="input.type.actived">Workspace://MyRegistryResources/models/incomming_csv.csv</param>
    <param name="default.serialization.on">false</param>
  </params>
  <csv:reader fields="orderid,customerid,date,price" recordElementName="AddOrder" rootElementName="AddOrder_batch_req" separator=","/>
  <ftl:freemarker applyOnElement="#document">
    <ftl:template><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <soapenv:Body>
        <#list .vars["AddOrder_batch_req"] as AddOrder_batch_req>
        <ns1:AddOrder_batch_req xmlns:ns1="http://wso2.org/sample/shop/order">
            <#list .vars["AddOrder_batch_req"]["AddOrder"] as AddOrder>
            <ns1:AddOrder>
                <ns1:orderID>${.vars["AddOrder"]["orderid"]}</ns1:orderID>                
                <ns1:customerID>${.vars["AddOrder"]["customerid"]}</ns1:customerID>                
                <ns1:date>${.vars["AddOrder"]["date"]}</ns1:date>                
                <ns1:price>${.vars["AddOrder"]["price"]}</ns1:price>                
            </ns1:AddOrder>
            </#list>            
        </ns1:AddOrder_batch_req>
        </#list>        
    </soapenv:Body>    
</soapenv:Envelope>]]></ftl:template>
    <param name="modelSrc">Workspace://MyRegistryResources/models/outgoing_xml_from_csv.xml</param>
    <param name="modelSrcType">XML</param>
    <param name="messageType">XML</param>
    <param name="templateDataProvider">input</param>
  </ftl:freemarker>
  <resource-config selector="#document">
    <resource>org.milyn.delivery.DomModelCreator</resource>
  </resource-config>
</smooks-resource-list>

</localEntry>



En el proxy service añadimos el mediador al inicio y modificamos la carga del fichero para hacer las pruebas localmente, luego se pueden volver a cambiar para el ftp sin problema.

<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="OrderProcessorv2" transports="https http vfs" startOnLoad="true" trace="disable">
    <target>
        <inSequence>
   <smooks config-key="orderIncommingTransformer">
   <input type="text"/>
   <output type="xml"/>
   </smooks>
            <log level="full"/>
            <property name="OUT_ONLY" value="true"/>
            <clone continueParent="true" sequential="true">
                <target>
                    <sequence>
                        <iterate xmlns:sn="http://wso2.org/sample/shop/order" id="orderIterator" expression="//sn:AddOrder_batch_req/sn:AddOrder" sequential="true">
                            <target>
                                <sequence>
                                    <log level="full"/>
                                    <dblookup>
                                        <connection>
                                            <pool>
                                                <password>tupass</password>
                                                <user>postgres</user>
                                                <url>jdbc:postgresql://localhost:5432/SHOP_DB</url>
                                                <driver>org.postgresql.Driver</driver>
                                            </pool>
                                        </connection>
                                        <statement>
                                            <sql>select "EMAIL_C","NAME_C" from "CUSTOMER_T" where "CUSTOMER_ID_C" = ?</sql>
                                            <parameter expression="//sn:AddOrder/sn:customerID" type="VARCHAR"/>
                                            <result name="email" column="EMAIL_C"/>
                                            <result name="name" column="NAME_C"/>
                                        </statement>
                                    </dblookup>
                                    <log level="custom">
                                        <property name="email" expression="get-property('email')"/>
                                        <property name="name" expression="get-property('name')"/>
                                    </log>
                                    <xslt key="orderTransformer">
                                        <property name="email" expression="get-property('email')"/>
                                        <property name="name" expression="get-property('name')"/>
                                    </xslt>
                                    <log level="full"/>
                                    <property name="messageType" value="text/csv" scope="axis2"/>
         <property name="Subject" expression="fn:concat('Customer Data: ', get-property('name'))" scope="transport"/>
                                    <header name="To" expression="fn:concat('mailto:', get-property('email'))"/>
                                    <send/>
                                </sequence>
                            </target>
                        </iterate>
                    </sequence>
                </target>
            </clone>
            <log level="full"/>
            <property name="messageType" value="application/soap+xml" scope="axis2"/>
            <send>
                <endpoint>
                    <address uri="http://localhost:9765/services/OrderService"/>
                </endpoint>
            </send>
            <property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
        </inSequence>
    </target>
    <parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
    <parameter name="transport.PollInterval">5</parameter>
    <!--parameter name="transport.vfs.FileURI">vfs:ftp://ftpuser:ftppass@localhost/projects/WSO2/data</parameter-->
    <!--parameter name="transport.vfs.MoveAfterProcess">vfs:ftp://ftpuser:ftppass@localhost/projects/WSO2/data/processed</parameter-->
    <!--parameter name="transport.vfs.MoveAfterFailure">vfs:ftp://ftpuser:ftppass@localhost/projects/WSO2/data/failure</parameter-->
    <parameter name="transport.vfs.Locking">disable</parameter>
    <parameter name="transport.vfs.MoveAfterProcess">E:\Work\WSO2\sample_8\sample\data\processed</parameter>
    <parameter name="transport.vfs.FileURI">E:\Work\WSO2\sample_8\sample\data\</parameter>
    <parameter name="transport.vfs.MoveAfterFailure">E:\Work\WSO2\sample_8\sample\data\failure</parameter>
    <parameter name="transport.vfs.FileNamePattern">.*.txt</parameter>
    <parameter name="transport.vfs.ContentType">text/plain</parameter>
    <parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
</proxy>



Eso es todo lo que se requiere. Puede parecer un poco extenso por lo detallado de cada paso pero el trabajo no lleva más de 5 minutos.

0 comentarios:

Publicar un comentario