Promoviendo Composite Services de ambientes de TEST a PROD

Una situación que siempre es clave en el control y gobernabilidad del Desarrollo que se hace alrededor de Servicios, es su promoción entre ambiente y ambiente.
En años pasados (2006-2008), en la SOA Suite 10g, tenía su reto hacer esto, pues tocaba programar tus propios Scripts de ANT. Si bien era lograble, no era tan simple como ahora en la versión 11g, y asumo se mejorará todavía mas en siguientes versiones.
En principio, lo mas simple que puede llegar a suceder es tener Compuestos que dependan de:
  • Adaptadores de Bases de Datos
  • Web Services HTTP/SOAP
  • Adaptadores hacia Servidores FTP
  • Llamadas a compuestos de la misma infraestructura
  • Llamadas a Servicios expuestos en Service Bus
  • etc
Desde el punto de vista de Desarrollo, estas dependencias se ubican y se tiene control sobre a qué sistema te estás conectando, pero para el rol que realiza los despliegues hacia Producción, esto no es necesariamente cierto.
Este rol, debe recibir el paquete a desplegar y tener una forma práctica de realizarlo sin necesidad de modificar el fuente del proyecto. Simplemente debería de ser capaz de tomar el paquete e indicar hacia que ambiente quiere promoverlo.
Bien, la SOA Suite tiene una opción de nombre: Configuration Plans. Estos sirven para indicar los cambios de nombres, ubicaciones, urls, puertos, etc, que se necesitan para diferenciar entre un ambiente y otro.



Para generarlo, basta con que des click derecho sobre el composite.xml y escojas la opción de: Generate Config Plan.
Un ejemplo de un Config Plan, es el siguiente:
<?xml version="1.0" encoding="UTF-8"?>
<SOAConfigPlan xmlns:jca="http://platform.integration.oracle/blocks/adapter/fw/metadata"
               xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
               xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy"
               xmlns:edl="http://schemas.oracle.com/events/edl"
               xmlns="http://schemas.oracle.com/soa/configplan">
   <composite name="COMPUESTO_EJEMPLO">
      <!--Add search and replace rules for the import section of a composite
    Example:
    <searchReplace>
        <search>http://my-dev-server</search>
        <replace>http://my-test-server</replace>
    <searchReplace>
    <searchReplace>
        <search>8888</search>
        <replace>8889</replace>
    <searchReplace>-->
      <import>
         <searchReplace>
            <search>maquinaTest.com</search>
            <replace>maquinaProd.com</replace>
         </searchReplace>
         <searchReplace>
            <search>7777</search>
            <replace>80</replace>
         </searchReplace>
         <searchReplace>
            <search>maquinaOSBTest</search>
            <replace>maquinaOSBPROD</replace>
         </searchReplace>
         <searchReplace>
            <search>8888</search>
            <replace>80</replace>
         </searchReplace>
      </import>
      <service name="ObtieneArchivo">
         <binding type="jca"/>
      </service>
      <!--Add search and replace rules for the component properties
    For components and service/reference bindings, you can add policy references.
    Example:
    <component name="*">
        <wsp:PolicyReference orawsp:category="management" orawsp:status="enabled" URI="oracle/log_policy"/>
    </component>-->
      <component name="COMPUESTO_EJEMPLO">
         <property name="activationAgent.ValidaEjecucionConcurrente.className">
            <replace>oracle.tip.adapter.fw.agent.jca.JCAActivationAgent</replace>
         </property>
         <property name="activationAgent.ValidaEjecucionConcurrente.portType">
            <replace>BPEL_NOTIFICA_ERRORES_APPACallback</replace>
         </property>
      </component>
      <!--Add search and replace rules for the reference properties
    Example:
    <searchReplace>
        <search>http://my-dev-server</search>
        <replace>http://my-test-server</replace>
    <searchReplace>
    <searchReplace>
        <search>8888
        <replace>8889</replace>
    <searchReplace>
    or provide a new replace value like:
    <replace>http://my-new-server:8889/myservice</replace>-->
      <reference name="ejemploSvc3">
         <property name="jca.retry.count">
            <replace>4</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>1</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>2</replace>
         </property>
         <property name="jca.retry.maxInterval">
            <replace>120</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="insertaCabecera_AP">
         <property name="jca.retry.count">
            <replace>1</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>60</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>1</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="insertaLinea_AP">
         <property name="jca.retry.count">
            <replace>1</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>60</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>1</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="NotificaViaEmail">
         <!--Add search and replace rules for the binding properties-->
         <binding type="ws">
            <attribute name="port">
               <replace>http://xmlns.oracle.com/BPM_ejemplo_COMERCIAL_jws/BPEL_ejemplo_SEND_EMAIL/BPEL_ejemplo_SEND_EMAIL#wsdl.endpoint(bpel_ejemplo_send_email_client_ep/BPEL_ejemplo_SEND_EMAIL_pt)</replace>
            </attribute>
            <attribute name="location">
               <searchReplace>
                  <search>auohsejemplo20.oracleoutsourcing.com</search>
                  <replace>auohsejemplo27.oracleoutsourcing.com</replace>
               </searchReplace>
               <searchReplace>
                  <search>40513</search>
                  <replace>40013</replace>
               </searchReplace>
            </attribute>
            <property name="weblogic.wsee.wsat.transaction.flowOption">
               <replace>WSDLDriven</replace>
            </property>
            <property name="weblogic.wsee.wsat.transaction.flowOption">
               <replace>WSDLDriven</replace>
            </property>
            <property name="weblogic.wsee.wsat.transaction.flowOption">
               <replace>WSDLDriven</replace>
            </property>
         </binding>
      </reference>
      <reference name="ejemploSvc3PRJ_TASK">
         <property name="jca.retry.count">
            <replace>3</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>60</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>1</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="ejecutaConcurrente">
         <property name="jca.retry.count">
            <replace>4</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>1</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>2</replace>
         </property>
         <property name="jca.retry.maxInterval">
            <replace>120</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="ejemploSvc1">
         <property name="jca.retry.count">
            <replace>2</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>1</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>2</replace>
         </property>
         <property name="jca.retry.maxInterval">
            <replace>120</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="ejemploSvc2">
         <property name="jca.retry.count">
            <replace>2</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>1</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>2</replace>
         </property>
         <property name="jca.retry.maxInterval">
            <replace>120</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="INSERT_HEADER">
         <property name="jca.retry.count">
            <replace>4</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>1</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>2</replace>
         </property>
         <property name="jca.retry.maxInterval">
            <replace>120</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="INSERT_LINEAS">
         <property name="jca.retry.count">
            <replace>4</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>1</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>2</replace>
         </property>
         <property name="jca.retry.maxInterval">
            <replace>120</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="ejemploSvc4_interface_rejections">
         <property name="jca.retry.count">
            <replace>2</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>1</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>2</replace>
         </property>
         <property name="jca.retry.maxInterval">
            <replace>120</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="ejemploSvc4_invoice_lines_interface">
         <property name="jca.retry.count">
            <replace>2</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>1</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>2</replace>
         </property>
         <property name="jca.retry.maxInterval">
            <replace>120</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="DELETE_ATT">
         <property name="jca.retry.count">
            <replace>3</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>1</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>2</replace>
         </property>
         <property name="jca.retry.maxInterval">
            <replace>120</replace>
         </property>
         <binding type="jca"/>
      </reference>
      <reference name="ValidaEjecucionConcurrente">
         <!--Add search and replace rules for the binding properties-->
         <binding type="ws">
            <attribute name="port">
               <replace>http://xmlns.oracle.com/SOA_ejemplo_INTERFACES_FII_jws/ejemplo_BPEL_SUELDOS_SALARIOS_REPORTA_ERRORES_APPA/ejemplo_BPEL_NOTIFICA_ERRORES_APPA#wsdl.endpoint(ejemplo_bpel_notifica_errores_appa_client_ep/ejemplo_BPEL_NOTIFICA_ERRORES_APPA_pt)</replace>
            </attribute>
            <attribute name="location">
               <searchReplace>
                  <search>auohsejemplo20.oracleoutsourcing.com</search>
                  <replace>auohsejemplo27.oracleoutsourcing.com</replace>
               </searchReplace>
               <searchReplace>
                  <search>40513</search>
                  <replace>40013</replace>
               </searchReplace>
            </attribute>
            <property name="weblogic.wsee.wsat.transaction.flowOption">
               <replace>WSDLDriven</replace>
            </property>
            <property name="weblogic.wsee.wsat.transaction.flowOption">
               <replace>WSDLDriven</replace>
            </property>
            <property name="weblogic.wsee.wsat.transaction.flowOption">
               <replace>WSDLDriven</replace>
            </property>
         </binding>
         <callback>
            <binding type="ws">
               <attribute name="port">
                  <replace>http://xmlns.oracle.com/SOA_ejemplo_INTERFACES_FII_jws/ejemplo_BPEL_SUELDOS_SALARIOS_REPORTA_ERRORES_APPA/ejemplo_BPEL_NOTIFICA_ERRORES_APPA#wsdl.endpoint(ejemplo_bpel_notifica_errores_appa_client_ep/ejemplo_BPEL_NOTIFICA_ERRORES_APPACallback_pt)</replace>
               </attribute>
            </binding>
         </callback>
      </reference>
      <reference name="inserta_Datos_Reporte_AP">
         <property name="jca.retry.count">
            <replace>4</replace>
         </property>
         <property name="jca.retry.interval">
            <replace>1</replace>
         </property>
         <property name="jca.retry.backoff">
            <replace>2</replace>
         </property>
         <property name="jca.retry.maxInterval">
            <replace>120</replace>
         </property>
         <binding type="jca"/>
      </reference>
   </composite>
   <!--To configure monitor.config:
    <property name="enabled"><replace>true</replace></property>
    <property name="dataObjectsFolder"><searchReplace><search>mydev</search><replace>myproduction</replace></searchReplace></property>
   
    sample properties to configure for file/ftp adapter:
    <jca:property name="PhysicalDirectory"><replace>c:\temp</replace></jca:property>
    <jca:property name="DeleteFile"><replace>true</replace></jca:property>
    <jca:property name="PollingFrequency"><replace>3</replace></jca:property>
   
    To add search and replace rules for wsdls, xsd and jca files
    Example:
    <searchReplace>
        <search>http://my-dev-server</search>
        <replace>http://my-test-server</replace>
    <searchReplace>
    <searchReplace>
        <search>8888</search>
        <replace>8889</replace>
    <searchReplace>
    -->
   <wsdlAndSchema name="ejemploSvc1.wsdl|ejemploSvc1_db.jca|ejemploSvc2.wsdl|ejemploSvc2_db.jca|
BPEL_ejemplo_SEND_EMAIL.wsdl|BPEL_ejemplo_SEND_EMAIL.xsd|bpel_ejemplo_send_email_client_ep.wsdl|ejemploSvc3.wsdl|
ejemploSvc3PRJ_TASK.wsdl|
ejemploSvc3PRJ_TASK_db.jca|ejemploSvc3_db.jca|ejemploSvc4_interface_rejections.wsdl|
ejemploSvc4_interface_rejections_db.jca|ejemploSvc4_invoices_interface_attribute15_db.jca|
ejemploSvc4_invoice_lines_interface.wsdl|ejemploSvc4_invoice_lines_interface_db.jca|
Delete_At15_db.jca|DELETE_AtQ_db.jca|DELETE_ATT.wsdl|DELETE_ATT_db.jca|deploy/sca_COMPUESTO_EJEMPLO_rev1.5/ejemploSvc1.wsdl|deploy/
sca_COMPUESTO_EJEMPLO_rev1.5/ejemploSvc1_db.jca|deploy/
sca_COMPUESTO_EJEMPLO_rev1.5/ejemploSvc2.wsdl|
xsd/ejemplo_BPEL_LECTURA_ARCHIVO_AP.xsd|xsd/COMPUESTO_EJEMPLO.xsd|
xsd/ejemploSvc3.xsd|xsd/ejemploSvc3PRJ_TASK.xsd|xsd/DATOS_ENTRADA.xsd|xsd/DATOS_ENTRADA_PSFT_AP.xsd|
xsd/ejemploSvc4_interface_rejections.xsd|xsd/ejemploSvc4_invoices_interface_attribute15.xsd|
xsd/ejemploSvc4_invoice_lines_interface.xsd|xsd/Delete_At15.xsd|xsd/DELETE_AtQ.xsd|xsd/DELETE_ATT.xsd|
xsd/insertaCabecera_AP_table.xsd|xsd/insertaLinea_table.xsd|xsd/inserta_Datos_Reporte_table.xsd|xsd/INSERT_HEADER_table.xsd|
xsd/INSERT_LINEAS_table.xsd|xsd/mensajeEmail.xsd">
      <searchReplace>
         <search>maquinaTest.com</search>
         <replace>maquinaProd.com</replace>
      </searchReplace>
      <searchReplace>
         <search>7777</search>
         <replace>80</replace>
      </searchReplace>
      <searchReplace>
         <search>eis/DB/TestejemploNonXA</search>
         <replace>eis/DB/ProdnonXA</replace>
      </searchReplace>
      <searchReplace>
         <search>eis/DB/EBS</search>
         <replace>eis/DB/ProdEBS</replace>
      </searchReplace>
      <searchReplace>
         <search>eis/DB/TestnonXA</search>
         <replace>eis/DB/ProdnonXA</replace>
      </searchReplace>
      <searchReplace>
         <search>eis/DB/TesteUsuarioInterface</search>
         <replace>eis/DB/ProdXA</replace>
      </searchReplace>
   </wsdlAndSchema>
</SOAConfigPlan>

Las secciones que se pueden identificar en el Config Plan, son:
      <!--Add search and replace rules for the import section of a composite
    Example:
    <searchReplace>
        <search>http://my-dev-server</search>
        <replace>http://my-test-server</replace>
    <searchReplace>
    <searchReplace>
        <search>8888</search>
        <replace>8889</replace>
    <searchReplace>—>

Esta es la parte de hasta arriba del Plan. Y como lo indica la documentación, está enfocado a la substitución de datos en la Sección de Importe del Compuesto en cuestión.
Posteriormente, vienen las entradas de cada referencia que se tenga en el Compuesto: Servicios, Adapters, etc.
Cada una de las referencias, tiene sus propias características que pueden ser intercambiadas, por ejemplo, en el caso de un WS tradicional:
<reference name="AltaCliente">
   <!--Add search and replace rules for the binding properties-->
   <binding type="ws">
      <attribute name="port">
         <replace>http://xmlns.oracle.com/SOA_ejemplo/ejemplo_BPEL/ejemplo_BPEL#wsdl.endpoint(ejemplo_bpel_client_ep/ejemplo_BPEL_pt)</replace>
      </attribute>
      <attribute name="location">
         <searchReplace>
            <search>maquinaTest</search>
            <replace>maquinaProd</replace>
         </searchReplace>
         <searchReplace>
            <search>7777</search>
            <replace>80</replace>
         </searchReplace>
      </attribute>
      <property name="weblogic.wsee.wsat.transaction.flowOption">
         <replace>WSDLDriven</replace>
      </property>
      <property name="weblogic.wsee.wsat.transaction.flowOption">
         <replace>WSDLDriven</replace>
      </property>
      <property name="weblogic.wsee.wsat.transaction.flowOption">
         <replace>WSDLDriven</replace>
      </property>
   </binding>
   <callback>
      <binding type="ws">
         <attribute name="port">
            <replace>http://xmlns.oracle.com/SOA_ejemplo/ejemplo_BPEL_/ejemplo_BPEL_APPA#wsdl.endpoint(ejemplo_bpel_client_ep/ejemplo_BPEL_Callback_pt)</replace>
         </attribute>
      </binding>
   </callback>
</reference>
Se puede ver cómo en el atributo Location se hace el intercambio hacia la máquina de Producción.
Finalmente, en la parte final del Plan, se encuentra una sección dónde se puede intercambiar cualquier valor que se encuentre en los archivos listados. Esto es en wsdls, xsds, etc:
   <wsdlAndSchema name="ejemploSvc1.wsdl|ejemploSvc1_db.jca|ejemploSvc2.wsdl|ejemploSvc2_db.jca|BPEL_ejemplo_SEND_EMAIL.wsdl|BPEL_ejemplo_SEND_EMAIL.xsd|bpel_ejemplo_send_email_client_ep.wsdl|ejemploSvc3.wsdl|ejemploSvc3PRJ_TASK.wsdl|ejemploSvc3PRJ_TASK_db.jca|ejemploSvc3_db.jca|ejemploSvc4_interface_rejections.wsdl|ejemploSvc4_interface_rejections_db.jca|ejemploSvc4_invoices_interface_attribute15_db.jca|ejemploSvc4_invoice_lines_interface.wsdl|ejemploSvc4_invoice_lines_interface_db.jca|Delete_At15_db.jca|DELETE_AtQ_db.jca|DELETE_ATT.wsdl|DELETE_ATT_db.jca|deploy/sca_COMPUESTO_EJEMPLO_rev1.5/ejemploSvc1.wsdl|deploy/sca_COMPUESTO_EJEMPLO_rev1.5/ejemploSvc1_db.jca|deploy/sca_COMPUESTO_EJEMPLO_rev1.5/ejemploSvc2.wsdl||xsd/ejemplo_BPEL_LECTURA_ARCHIVO_AP.xsd|xsd/COMPUESTO_EJEMPLO.xsd|xsd/ejemploSvc3.xsd|xsd/ejemploSvc3PRJ_TASK.xsd|xsd/DATOS_ENTRADA.xsd|xsd/DATOS_ENTRADA_PSFT_AP.xsd|xsd/ejemploSvc4_interface_rejections.xsd|xsd/ejemploSvc4_invoices_interface_attribute15.xsd|xsd/ejemploSvc4_invoice_lines_interface.xsd|xsd/Delete_At15.xsd|xsd/DELETE_AtQ.xsd|xsd/DELETE_ATT.xsd|xsd/insertaCabecera_AP_table.xsd|xsd/insertaLinea_table.xsd|xsd/inserta_Datos_Reporte_table.xsd|xsd/INSERT_HEADER_table.xsd|xsd/INSERT_LINEAS_table.xsd|xsd/mensajeEmail.xsd">
      <searchReplace>
         <search>maquinaTest.com</search>
         <replace>maquinaProd.com</replace>
      </searchReplace>
      <searchReplace>
         <search>7777</search>
         <replace>80</replace>
      </searchReplace>
      <searchReplace>
         <search>eis/DB/TestejemploNonXA</search>
         <replace>eis/DB/ProdnonXA</replace>
      </searchReplace>
      <searchReplace>
         <search>eis/DB/EBS</search>
         <replace>eis/DB/ProdEBS</replace>
      </searchReplace>
      <searchReplace>
         <search>eis/DB/TestnonXA</search>
         <replace>eis/DB/ProdnonXA</replace>
      </searchReplace>
      <searchReplace>
         <search>eis/DB/TesteUsuarioInterface</search>
         <replace>eis/DB/ProdXA</replace>
      </searchReplace>
   </wsdlAndSchema>
</SOAConfigPlan>
De esta manera , al realizar un deployment, se adjunta el Config Plan, y el Engine por si solo realiza el intercambio de Datos.
Otro punto relevante es que se pueden realizar pruebas del Config Plan, para validar que realmente haga los cambios necesario. Esto se hace en el JDEV, dando click derecho sobre el archivo del Config Plan y escogiendo la opción de: Validate Config Plan.
Esto generará un informe con los cambios que esperas se realicen al utilizar el Plan.
Hay muchas mas opciones, pero eso se explicará en un artículo que estoy preparando para el OTN en español.