lunes, 6 de octubre de 2014

En la entrada anterior vimos cómo implementar usando el ESB de WSO2 un problema planteado en StackOverFlow. En esta entrada veremos con más nivel de detalle la solución propuesta y terminaremos la implementación pues nos faltó realizar la transformación para que el mensaje de salida cumpliera con el WSDL del servicio proxy desarrollado.

El WSDL del servicio proxy visto a través del editor gráfico del Eclipse luce como sigue (nos centraremos en los mensajes de entrada y salida):

Mensaje de entrada
mensaje_entrada

Mensaje de salida:
mensaje_salida

Como se puede apreciar la salida debe ser un listado de direcciones y cada dirección debe tener los elementos del complexType addressType.

La parte que nos interesa del servicio proxy que se implementó es la del flujo de salida, que es donde se reciben los mensajes y estos son agregados para luego pasar a una transformación.
De la entrada anterior a esta se hicieron pequeños cambios en la secuencia así que la mostramos nuevamente.


<outSequence>
 <property name="root" scope="default">
 <root:rootelement xmlns:root="http://ws.wso2.org/dataservice"/>
 </property>
 <aggregate id="iterate1">
 <completeCondition>
    <messageCount min="-1" max="-1"/>
 </completeCondition>
 <onComplete xmlns:s12="http://www.w3.org/2003/05/soap-envelope"
    xmlns:add="http://ws.wso2.org/dataservice"
    xmlns:s11="http://schemas.xmlsoap.org/soap/envelope/"
    expression="//add:Addresses/add:Address"
    enclosingElementProperty="root">
    <log level="full"/>
 </onComplete>
 </aggregate>
 <xslt key="conf:/xslt/Tranformacion_DS_to_ESB.xsl"/>
 <send/>
</outSequence>


Lo primero diferente que se puede apreciar es que hemos creado una property de nombre root que está asociada a un namespace y que posee un elemento rootelement. Esta property la necesitaremos pues cuando los mensajes son agregados el resultado del mediador aggregate no posee un nodo raíz, así que se lo ponemos usando esta propiedad y el parámetro enclosingElementProperty="root" que pueden ver en el mediador aggregate. Ambos nos permiten generar un XML válido para que sea procesado sin problemas por la transformación. Para más información pueden ver esta pregunta en stackoverflow.


La transformación entonces sería la siguiente:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:a="http://ws.wso2.org/dataservice" xmlns:b="http://www.example.org/Address/" exclude-result-prefixes="a fn xs">
 <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
 <xsl:template match="/">
  <b:getAddressResponse>
   <xsl:for-each select="//a:rootelement/a:Address">
     <address>
      <address>
       <xsl:value-of select="a:address"/>
      </address>
      <partybranchid>
       <xsl:value-of select="a:partybranchid"/>
      </partybranchid>
      <clientid>
       <xsl:value-of select="a:clientid"/>
      </clientid>
     </address>
   </xsl:for-each>
  </b:getAddressResponse>
 </xsl:template>
</xsl:stylesheet>


Como pueden observar a la hora de obtener los nodos ya tenemos en cuenta que existirá un elemento raíz “rooelement” y basicamente lo que hacemos es iterar por cada nodo Address y generar nodos address los cuales estarán contenidos dentro de un nodo raíz getAddressResponse.


Ya con esta transformación se logra que el mensaje de salida cumpla con el WSDL del servicio proxy, lo cual pueden comprobar usando el SOAPUI y validando contra el Schema del servicio.


Espero les sea de utilidad.