martes, 14 de agosto de 2018

FN Project - Instalación y primera función

Intro

Fn es una plataforma cloud FaaS (Funtions-as-a-Service) de código abierto. Está basada en eventos y puede correr en cualquier nube (cloud agnostic serverless platform).

Entre otras, algunas características principales de éste proyecto son:
  • Código abierto
  • Docker native
  • Múltiples lenguajes de programación
  • Agnóstica a la nube (corre en cualquier nube)
  • De fácil uso (principalmente para desarrolladores y operadores)
  • Está escrita en Go


Instalación

Los pre-requisitos son simples:
  1. Tener instalado y corriendo Docker 17.10.0-ce o superior
  2. Tener una cuenta de Docker Hub
  3. Hacer login en la cuenta de Docker Hub
Instalar la línea de comandos de Fn (CLI)

Esto no es requerido, pero a nadie le cae mal una ayuda. Nos va a facilitar algunas cosas.

Estoy usando Linux, hay maneras de hacerlo en Windows y MacOS. Aquí vamos a mostrar cómo se hace en Linux.

Debemos descargar un shell y ejecutarlo. En caso de estar usando root, todo será transparente. En caso de estar utilizando algún otro usuario, nos va a pedir el password para invocar sudo.

curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh

Al finalizar la descarga e instalación, veremos lo siguiente en la línea de comandos. En este punto la herramienta de CLI estará instalada:


Podemos verificar que la instalación de CLI fue correcta ejecutando el comando: fn help


Ejecución del Fn Server

El siguiente paso es descargar el binario de Fn. Aquí van a encontrar las versiones disponibles, deberán descargar el que corresponde a su sistema operativo (en mi caso, Linux):


Una vez descargados los binarios, podemos ejecutar el comando para iniciar el fn server: fn start

Como era de esperarse, mi versión de docker era muy vieja. Entonces el primer intento no funcionó.


Pero no se agüiten. Sólo es necesario remover el docker-engine actual e instalar la versión más nueva y chévere de docker-ce (hay que agregar el repositorio correspondiente para poder instalar docker-ce).

Desinstalar docker-engine

sudo yum remove docker


Agregar repositorio de docker-ce e instalar la última versión

sudo yum -y install yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum -y install docker-ce


Verificar la instalación de docker-ce

docker version


Podemos ver un mensaje que nos indica que el Docker daemon no está iniciado. Como acabamos de instalar docker-ce, debemos iniciar manualmente el demonio y verificar nuevamente. Para poder iniciar el demonio con systemctl, nos va a solicitar el password de sudo:

systemctl start docker
docker version


Segundo intento, levantar el fn server

fn start


Primera función

fn init

Para escribir nuestra primera función, vamos a usar la herramienta CLI que instalamos al inicio. Esto va a permitir crear la primera versión de manera muy simple. Lo unico que debemos hacer es escribir: fn init --runtime go hello

Lo anterior, automáticamente va a generar una carpeta llamada hello y debajo de ella cuatro archivos correspondientes al código de nuestra función:


func.go

El archivo func.go contiene el código de la función. Es un simple hello world. Básicamente la función recibe un parámetro (name). En caso de que el parámetro esté vacío, devuelve "Hello World". En caso de que el parámetro contenga un valor, devuelve un saludo personalizado "Hello Leo".


func.yaml

El archivo func.yaml es llamado func file y es usado para la creación de las funciones de fn project. Lo que definimos en el archivo es: el nombre de la función, la versión de la función, el lenguaje de programación en tiempo de ejecución y el formato de los mensajes.


Gopkg.toml

El archivo Gopkg.toml es un archivo de configuración donde se definen las dependencias de la función.


test.json

El archivo test.json es un archivo utilizado para realizar pruebas de ejecución de la funcion, define entradas y salidas de la función. Esto nos ayudará a saber si la función está operando correctamente o no.


Ejecutar la función localmente

Una vez que está listo el código, vamos a ejecutarlo y a desplegarlo al Fn server local. Para el despliegue vamos a utilizar nuestro usuario de Docker Hub que comentamos al inicio, en los pre-requisitos del post. Vamos a hacer un export a la variable de ambiente FN_REGISTRY, con el usuario de Docker Hub. Una vez hecho esto, vamos a ejecutar la función localmente: fn run

Desplegar la función al Fn server local

Para desplegar la función a nuestro Fn server local, vamos a utilizar el comando: fn deploy --app myapp --local



Probar la función

Para poder probar la función en nuestro Fn server local, vamos a ejecutar alguna de las siguientes opciones:

  1. Probar en el navegador: http://localhost:8080/r/myapp/hello
  2. Probar usando curl: curl http://localhost:8080/r/myapp/hello
  3. Probar usando CLI: fn call myapp /hello
Navegador (usando Firefox):


CURL:


CLI:


HTTPie

Adicionalmente hice un par de pruebas usando HTTPie. Es una herramienta en modo línea de comandos que nos sirve para enviar requests a un endpoint usando los distintos métodos de HTTP. Esto me va a permitir ejecutar tanto un GET como un POST en el mismo endpoint y poder pasar el nombre a la función sin tener que armar a mano el JSON del payload.

HTTPie (GET):


HTTPie (POST):


miércoles, 7 de marzo de 2018

Automatización de pruebas de OSB usando SOAP UI.

En esta entrada voy a mostrar cómo es posible automatizar pruebas de servicios desplegados en OSB, haciendo uso de SOAP UI.

Los pasos a seguir son simples:

1. Construir un servicio y exponerlo en OSB.
2. Crear un proyecto de SOAP UI para probar el servicio.
3. Hacer uso de Maven para probar y desplegar el proyecto.

Imaginemos el siguiente escenario: tenemos un servicio en un entorno de desarrollo (desplegado) y lo queremos promover a un ambiente de pruebas. Previo a realizar esto, debemos asegurarnos que nuestro servicio funciona de manera adecuada y que hace lo que debe hacer.

Para ese propósito ocupamos SOAP UI, generamos algunos casos de prueba y los colocamos en una Test Suite y probamos. Una vez que aseguramos que todos los casos de prueba se ejecutan correctamente, podemos pasar a la automatización de esas pruebas.

En mi caso, creé un servicio simple que devuelve un saludo (cómo crear el servicio, esquemas, pipeline, etc., no es el objetivo de esta entrada pero pueden crear uno muy simple). Posteriormente, creé el proyecto en SOAP UI, una Test Suite (llamada Pruebas) y un Test Case (saludar TestCase). Agregué un par de pasos de ejecución para las pruebas y algunos assertions para cada paso. Ejecuté el test case y estos fueron mis resultados:


Al ejecutar cada uno de los pasos, mis resultados fueron los siguientes:



Como vemos, el servicio cumple con los casos de prueba diseñados. Esto podría significar que está listo para ser promovido a un ambiente de pruebas. Para asegurarnos que el código que estamos desplegando esté bien probado antes de ser promovido, y que esto se haga de forma automática, podemos hacer uso de un plugin de Maven. Esto es tan simple como agregar lo siguiente al POM del proyecto:

  <pluginRepositories>
    <pluginRepository>
      <id>smartbear-sweden-plugin-repository</id>
      <url>http://www.soapui.org/repository/maven2/</url>
    </pluginRepository>
  </pluginRepositories>
  <build>
    <plugins>
      <plugin>
        <groupId>com.smartbear.soapui</groupId>
        <artifactId>soapui-maven-plugin</artifactId>
        <version>4.6.1</version>
        <executions>
          <execution>
            <id>QClearanceTest</id>
            <goals>
              <goal>test</goal>
            </goals>
            <phase>test</phase>
          </execution>
        </executions>
        <configuration>
          <projectFile>${basedir}/Test/test-soapui-project.xml</projectFile>
          <testSuite>Pruebas</testSuite>
          <testCase>saludar TestCase</testCase>
          <endpoint>http://localhost:7001/v1/SOAPUI/TestSuite.svc</endpoint>
          <outputFolder>${basedir}/Reporte</outputFolder>
          <junitReport>true</junitReport>
          <printReport>true</printReport>
          <settingsFile>${basedir}/Test/soapui-settings.xml</settingsFile>
        </configuration>
      </plugin>
    </plugins>
  </build>

Lo que marco en naranja, es básicamente lo que tendría que cambiar de acuerdo a cómo hayan hecho la implementación del servicio. En mi caso:

- El endpoint de mi servicio está en localhost, por el puerto 7001
- La Test Suite de SOAP UI, la llamé Pruebas
- El Test Case de SOAP UI, lo llamé saludar TestCase
- En caso de haber un error en las pruebas, quiero que se genere un reporte debajo de la carpeta ${basedir}/Reporte (donde tengo mi proyecto de OSB, debajo de una carpeta llamada Reporte).
- Tanto el proyecto de SOAP UI, como el archivo de instalación del producto, los puse debajo de la carpeta Test.

Así quedó la estructura de mi proyecto de OSB:

- Reporte, es la carpeta donde el plugin va a almacenar el reporte de ejecución de las pruebas
- Test, es la carpeta donde coloqué el XML del proyecto de SOAP UI (test-soapui-project.xml) y el XML de la instalación del producto (soapui-settings.xml)

Hay algunas consideraciones respecto al proyecto de SOAP UI para que pueda funcionar bien el plugin:

- SOAP UI por default coloca "\r" al finalizar una línea en los payloads de prueba. Esto se ve en el XML del proyecto de SOAP UI. Simplemente hay que eliminar las "\r".
- SOAP UI por default coloca "No Authorization" cuando no tenemos algún tipo de autorización. Esto se valida en un enumeration de un esquema, y "No Authorization" no es parte de ese enumeration. Así es que hay que eliminarlo (o comentarlo en el código).

Entonces, el proyecto de SOAP UI que adjuntamos a nuestro proyecto de OSB, se debe corregir de la siguiente forma (izquierda: incorrecto, derecha: correcto):




Una vez corregido el proyecto de SOAP UI, lo podemos probar localmente ejecutando mvn test:



Lo más importante de haber logrado automatizar las pruebas, es que esto se incluya antes del despliegue. Para esto, debemos haber poblado nuestro repositorio local con los artefactos de Oracle, para así poder ejecutar: mvn pre-integration-test. La documentación de cómo hacer esto, la pueden encontrar aquí:


Lo anterior, realizará las pruebas previo al despliegue del servicio (en el ambiente indicado). Entonces, al ejecutar mvn pre-integration-test, tendremos lo siguiente (además del servicio probado y desplegado en el ambiente destino):


Podría concluir que el uso del plugin de SOAP UI es muy útil para validar que nuestros servicios se comporten de la manera en que se espera, previo al despliegue a un ambiente de calidad o productivo. En conjunto con los artefactos de Oracle, esto puede ser un buen inicio para automatizar las pruebas y despliegues, generando así los primeros pasos de un entorno de CI/CD.

Además nos obligamos a diseñar y ejecutar casos de prueba. Es muy importante entender que los defectos deben ser encontrados y corregidos (en su mayoría) por el desarrollador, no por el equipo encargado de realizar QA. Si diseñamos y ejecutamos esas pruebas previo al despliegue, minimizamos la cantidad de defectos que pudieran ser encontrados después. Entre más robusto sea el diseño de esos casos de prueba, entregaremos un producto de mejor calidad y con menor número de defectos. Hagamos ésta una práctica del equipo de desarrollo.

martes, 19 de diciembre de 2017

Primer Chatbot - Dialogflow (Google Platform)

Al finalizar la entrada anterior del blog, comenté que iba a hacer un ejemplo usando Dialogflow (antes API.AI). Dialogflow es una plataforma Cloud de Google para desarrollar chatbots.

Me ha sorprendido la facilidad de uso de la plataforma, es bastante intuitiva y simple de usar. Previamente hay que diseñar y establecer el flujo de la conversación que deseamos implementar con el chatbot. Y una vez entendidos los conceptos que describimos en la introducción de esta serie de posts, podemos saltar a construir nuestro primer ejercicio.

La consola.


Para poder acceder al servicio, primero debemos darnos de alta. Esto se puede realizar teniendo una cuenta de correo de Google. La consola es limpia, simple y se ve de la siguiente forma una vez que hacemos login a la plataforma.


El agente.


Un agente contiene intents, entities y responses para poder interactuar con un usuario. Hablaremos con los nombres de los conceptos en inglés, que es como se encuentran en la plataforma.

Para poder crear un nuevo agente, basta con seleccionar el siguiente botón en la consola de la plataforma.

Posteriormente, veremos una pantalla que nos permitirá realizar las primeras configuraciones (programación) de nuestro agente.


Aquí basta con colocar un nombre al agente y el idioma que vamos a utilizar. La plataforma ofrece ya varias opciones: alemán, inglés, francés, español, italiano, japonés, coreano, holandés, portugués, ruso, ucraniano y varios tipos de chino. Además permite definir la zona horaria. Una vez que realizamos las primeras configuraciones, podemos presionar en el botón Create que se encuentra en la parte superior derecha.


Los intents.


Lo primero que nos ofrece la plataforma, es la configuración de los intents. Por default, existen dos intents previamente creados en nuestro agente, estos los mantendremos como originalmente configurados. El primero de ellos es para saludar (Default Welcome Intent) y el segundo es utilizado para dar una respuesta en caso de no comprender la solicitud del usuario (Default Fallback Intent).


Mi primer intent, decidí hacerlo para hablar de fútbol. El fútbol es el tema preferido de muchos, y mucho más cuando se acerca la fecha del mundial de Rusia 2018. Además de que acabamos de tener campeón regio del fútbol mexicano. Así que configuré el siguiente intent.


En el ejemplo anterior, al agregar las posibilidades de interacción con el usuario (User says), podemos observar algunas palabras resaltadas en colores: México, Rusia y 2018. Esto significa que son anotadas como parámetros que son asignados a algunas entidades del sistema como fecha y ciudad. Estos parámetros nos ayudarán a entender otras ciudades y fechas proporcionadas por el usuario y no sólo las que configuramos en el intent.

A continuación presionamos el botón Save que se encuentra arriba a la derecha para poder probar por primera vez nuestro agente. Veamos qué sucede.

Los responses.


Debido a que no tenemos configuradas las respuestas a nuestro intent (al menos no para el del fútbol), el chatbot no devolverá respuesta alguna. Sin embargo, podrá reconocer los parámetros que se colocan en el mensaje de entrada del usuario. Por ejemplo, una de las frases que colocamos en la sección User say del intent fue: "Equipo más popular en México". El intent automáticamente reconocerá México o Brasil o Rusia o cualquier otro país como un parámetro que forma parte de las entidades del sistema (sys.geo-city) y devolverá un valor "Not available" como respuesta default. Esto está bien, pues no hemos configurado respuesta alguna todavía. También notaremos que el intent ejecutado es el que configuramos "Futbol Intent"


En caso de que coloquemos una frase sin sentido, el intent que se ejecutará es el "Default Fallback Intent" y devolverá alguna de las respuestas configuradas. Intentemos eso.

Finalmente, vamos a configurar algunos responses para nuestro intent. En mi caso coloqué los siguientes. Notemos que en las respuestas asocié los parámetros recibidos en la solicitud del usuario. Entonces, el chatbot tiene manera de asociar esos parámetros de entrada, a la respuesta de salida que va a elegir de la lista.


Por lo tanto, si le pregunto cuál es el campeón del mundo actual, no podrá nunca responderme con: "El campeón del siguiente mundial en Rusia 2018 será Perú", puesto que en la entrada no estoy usando entidades del sistema como parámetros, por lo tanto el chatbot no elegirá una respuesta que sí usa esa información en alguna de las salidas posibles.

Las primeras pruebas.


Estas son las respuestas que obtenemos de este ejercicio:





Siguientes pasos.

En la siguiente entrada del blog, vamos a hacer al chatbot un poco más inteligente. Se me ocurre que puedo publicar un API que reciba algunos parámetros y devuelva estadísticas del fútbol que tanto nos gusta. Así, de acuerdo a las entradas recibidas podremos obtener las estadísticas de un API y devolver una respuesta más coherente al usuario.

lunes, 18 de diciembre de 2017

Chatbots - Intro

Hace algunos meses, mi amigo Rolando Carrasco (@borland_c) se dio a la tarea de escribir un chatbot. El proyecto se desarrolló inicialmente a manera de demo, Posteriormente se convirtió en parte de algunas presentaciones en eventos de Oracle. Ahora lo hicimos realidad como parte de la implementación de un proyecto con uno de nuestros clientes.

Si bien el core de las cosas que hacemos tienen qué ver con Oracle, también tenemos un equipo que investiga algunas otras tecnologías. Esto nos ha hecho tener mucho valor para nuestros clientes, debido a que muchas veces nos expresan algunas inquietudes acerca de otras tecnologías que se encuentran evaluando. El entendimiento agnóstico de muchos de los conceptos que se relacionan con la tecnología, nos lleva a jugar un papel importante a la hora de ser seleccionados por nuestros clientes.

El chatbot del que hablo fue escrito en python y montado en diferentes infraestructuras: una propia y en Oracle Application Container. En ambos casos nos conectamos a Facebook que fue desde donde pudimos establecer la primer interacción con el chatbot prototipo.

Conceptos básicos.


Los chats existen desde hace mucho tiempo. Recuerdo en mi época de estudiante (por ahí de finales de los 90's y principios del 2000) una variedad de sitios web que ofrecían canales de chat para todos los gustos: música, películas, regiones del mundo, idiomas, ligue, había para todos los gustos. En aquel entonces la interacción era a distancia, pero persona-persona.

Hoy en día, distintos sitios web de algunas compañías nos ofrecen servicios de chat para interactuar con su equipo de atención a clientes: bancos, aseguradoras, empresas de manufactura, empresas de tecnología, por mencionar algunos. Algunos de estos chats establecen una conversación de persona-persona; pero en algunos otros la conversación es entre una persona y un programa que simula mantener esa conversación (llamemos a este tipo de interacción: persona-máquina).

Desde luego que establecer esta conversación no es algo mágico, aunque en el medio sigue habiendo muchas personas que confían en que el mundo del software es algo que tiene qué ver con la fe, la alquimia o la magia negra. Pero esa es harina de otro costal.

Para establecer este tipo de conversación deben tomarse en cuenta distintos factores: las frases a las que va a responder el chatbot, el idioma en que se lleva a cabo la conversación, la lógica y coherencia de la conversación, el tipo de interacción (pregunta-respuesta, conversación abierta, saludos, despedidas, recomendaciones, por mencionar algunos). Nadie habla con una persona y expresa la despedida antes del saludo, o las respuestas antes de las preguntas. ¿O sí? Pues aplican las mismas reglas para las conversaciones con las máquinas. Imaginen que un humano no puede entender de lo que hablamos, ¿por qué una máquina habría de hacerlo?

Flujo de la conversación.


En una conversación de bidireccional entre personas existe un emisor y un receptor. Esos roles se intercambian de vez en vez, de acuerdo a la dirección de la conversación. Entonces, cuando hablamos con alguien más, generalmente (supongamos el siguiente escenario):

1. Saludamos
2. Solicitamos algo (se inicia el contexto de una conversación)
3. El receptor entiende lo solicitado y hace lo necesario para emitir una respuesta.
4. El receptor (ahora emisor), da una respuesta.
5. Posterior a esto, se puede continuar con la conversación sin necesidad de iniciar de nuevo un contexto, pues se asume que se está hablando del mismo tema (algunas diferencias notarán cuando hablan con una persona que habla de uno y otro tema a la vez).
6. Una vez que se terminan de atacar los temas de interés en la conversación, se finaliza con una despedida.

Invocation, Agent, Intent, Entity, Fullfilment, Response y Context.


Cuando se establece una conversación con una máquina (chatbot), generalmente se sigue este flujo:

1. Invocación: el usuario invoca al agente para iniciar una conversación. Esto lo podríamos comparar con el saludo de una persona a otra. Así, el usuario solicita hablar con el agente en la forma en que el desarrollador definió el inicio de la conversación.
2. El usuario solicita algo al agente, posterior a iniciar la invocación. Esto se realiza a través de un intent (intención, en su traducción literal al español). Un intent almacena los elementos y lógica necesarios para interpretar la información que el usuario está proporcionando, para poder responder a la solicitud.
3. Con la información proporcionada, el agente intenta interpretar la solicitud del usuario. Para que el agente pueda interpretar esta información será necesario contar con algunos ejemplos de cómo el usuario puede hacer una solicitud determinara. Por ejemplo: preguntar la hora (puede haber muchas formas para preguntar la hora). El desarrollador deberá agregar el mayor número de estas posibilidades al intent. Entre más variaciones de la misma solicitud se agreguen al intent, el agente comprenderá mejor lo que se le está solicitando.
4. El agente necesita saber cuál es la información que pudiera resultar más útil para responder a la solicitud del usuario. Esta información generalmente es conocida como entity (entidad, en español). Algunas entidades son nativas en las plataformas de chatbots (las más comunes). Sin embargo, muchas otras tendrán que ser definidas por el desarrollador, dependiendo del contexto que se quiera abarcar. Por ejemplo: en el contexto de un banco podría definirse una entidad que se llame Cuenta Bancaria. Mientras que en el contexto de una tienda departamental podría definirse una entidad que se llame Item o Producto.
5. Una vez que el agente recopila las entidades que debe devolver al usuario, se formatean en un mensaje que el usuario pueda comprender (fullfilment request). A este mensaje formateado se le conoce como response (respuesta).
6. Al igual que en una conversación persona-persona, ésta conversación se lleva a cabo en un contexto. El contexto puede ser utilizado para almacenar algunos valores de los parámetros de la conversación y utilizarlos de un intent a otro. Una forma de reestablecer una conversación que se ha roto (por ejemplo: el usuario cierra el canal de la conversación o hay un error en la plataforma), es a través del contexto. Manteniendo este tipo de valores de los parámetros de la conversación en el contexto, es posible reparar una conversación rota. Otro uso del contexto, es cuando podemos tener múltiples ramas dentro de una conversación (por ejemplo: cuando el flujo de la conversación depende de las respuestas de alguno de los participantes).

Siguientes pasos.


Una vez que hemos descrito los conceptos claves involucrados en las plataformas comunes para desarrollar chatbots, los siguientes pasos incluyen utilizar estos conceptos para desarrollar y configurar un chatbot básico.

Para lo anterior, usaremos la plataforma que Google proporciona para este propósito: api.ai (ahora Dialogflow).

En la próxima entrada del blog vamos a crear nuestro primer agente usando Dialogflow. Será un agente básico que utilizará algunas respuestas definidas por el desarrollador. Una vez que tengamos eso listo, vamos a incluir un poco de complejidad haciendo llamadas a algunas APIs existentes. Aquí es donde se me ocurre que podríamos incluir algunos servicios expuestos en tecnología Oracle. Esto para ejemplificar cómo la integración de las plataformas no tiene restricciones en cuanto a tecnología se refiere, siempre y cuando utilicemos mecanismos y protocolos de comunicación estandarizados.

lunes, 3 de julio de 2017

Automatización de despliegue de un compuesto con Maven

En esta entrada del blog vamos a dar una mirada a algunos arquetipos que tenemos disponibles para la creación de compuestos de SOA/BPM en Oracle SOA Suite 12c. También vamos a abordar las tareas necesarias para automatizar el despliegue de estos compuestos hacia la SOA-INFRA.

La versión particular que estoy utilizando es 12.2.1.0.0; sin embargo, esto se encuentra disponible en 12.1.3.0.0 y 12.2.1.2.0. Así que pueden usar cualquier release de Oracle SOA Suite 12c.

Pre-requisitos


Hay algunas tareas previas que debemos ejecutar para tener en nuestro repositorio local de Maven los elementos necesarios para desplegar aplicaciones de Oracle SOA Suite. Los pre-requisitos son los siguientes:

  1. Instalar y configurar Maven (por obvio que esto parezca, habrá quien piensa que es magia)
  2. Configurar Maven para la automatización y configuración de dependencias de proyectos de Oracle SOA Suite 12c. Esto incluye: instalar y configurar el plug-in para la sicronización de Maven, ejecutar el plug-in para la sincronización del Repositorio de Maven, poblar el repositorio de Maven. La documentación oficial de Oracle para realizar esto, la pueden encontrar aquí:
https://docs.oracle.com/middleware/1221/core/MAVEN/config_maven.htm#MAVEN8853

Una vez realizado esto, podemos continuar.

Creación de una aplicación y proyecto de Oracle SOA Suite, utilizando el arquetipo de Maven


Para nuestra comodidad, ya existe un arquetipo que podemos utilizar para crear la estructura inicial de nuestro proyecto. Basta con ejecutar el siguiente comando para crear en nuestro sistema de archivos, la estructura de carpeta de nuestro proyecto:

mvn archetype:generate -DarchetypeGroupId=com.oracle.soa.archetype -DarchetypeArtifactId=oracle-soa-application -DarchetypeVersion=12.2.1-1-0 -DarchetypeRepository=local

El arquetipo usado lo estoy buscando en mi repositorio local, debido a que no existe en el repositorio central de Maven. Es por esto que uno de los pasos previos es poblar el repositorio de Maven siguiendo los pasos de la documentación mencionados arriba.


El resultado de la ejecución, será la creación de las carpetas del proyecto en el sistema de archivos. En mi caso particular voy a crear una aplicación que me sirva para exponer un API para el procesamiento de órdenes de compra que usaré en un futuro para algunas demostraciones. Dentro de esa aplicación, crearé un proyecto para la primer capacidad del API, que me servirá para validar algunos datos del pago, previo al procesamiento de las órdenes de compra.

En la estructura de las carpetas podemos observar lo necesario para crear algunos elementos típicos de un compuesto SOA: Events, Schemas, Transformations, WSDLs, etcétera. Hasta aquí no hemos creado ninguna aplicación (JWS) ni proyecto (PRJ) de JDeveloper. Sólo hemos generado la estructura de nuestras carpetas.


El arquetipo nos crea dos archivos POM: uno de aplicación y otro de proyecto.

Ejecución de comandos de Maven


En este punto podemos empaquetar el proyecto que hemos creado. Esto nos generará un JAR (evidentemente vacío, pues no hemos puesto código dentro del mismo). Para empaquetar el proyecto, ejecutamos el siguiente comando debajo de la carpeta de nuestra aplicación:

mvn package

Si es la primera vez que hacemos esto, vamos a observar un warning como el siguiente. Esto es debido a que la expresión version ya está deprecada; en lugar de esto deberíamos usar project.version.


Corregir lo anterior es muy simple, únicamente debemos abrir el POM que se encuentra debajo del proyecto (generado automáticamente por el arquetipo) y ubicar la expresión en las propiedades de configuración del proyecto.


Entonces reemplazamos version por project.version y guardamos el POM del proyecto. Algo importante es que esto se encuentra en el POM del proyecto, NO en el POM de la aplicación.


Si ejecutamos de nuevo el comando para empaquetar el proyecto, observaremos que el warning ha desaparecido.


El proyecto ha compilado y el paquete se ha generado correctamente.


Para poder validar lo anterior, vamos de nuevo al sistema de archivos generado por el arquetipo. Notamos que se ha creado una carpeta adicional debajo de la carpeta del proyecto. Esta nueva carpeta se llama target. Dentro de ella tendremos el JAR (paquete) generado por Maven.


Import del proyecto en JDeveloper


Dado que el proyecto no tiene código aún, vamos a abrirlo en JDeveloper y agregar algo de funcionalidad. Para realizar esto damos un click en New > Import y veremos un asistente que nos permite importar proyectos de Maven a JDeveloper.


En el directorio raíz, vamos a seleccionar la carpeta donde creamos la aplicación. El archivo de configuración de Maven (settings.xml) se selecciona de manera automática, lo vamos a conservar así.

En la estructura de proyectos debemos elegir tanto el POM de la aplicación, como el POM del proyecto. El resultado de esto es que JDeveloper va a crear el archivo de aplicación (JWS) y el archivo del proyecto (PRJ) debajo de la misma estructura de archivos donde estamos trabajando. En caso de que deseemos colocar el código debajo de otra carpeta (por ejemplo tu propio workspace de JDeveloper), debemos seleccionar la opción: Also import source files into application (no es mi caso, yo quiero trabajar en el mismo directorio).


A continuación, JDeveloper nos pedirá algunos datos adicionales para crear la aplicación. Probablemente les salga una advertencia de sobreescritura del archivo de la aplicación (JWS), debemos aceptar sin miedo (no puede sobreescribirse un archivo que ni siquiera ha sido creado todavía).


Observamos que en nuestra estructura de archivos se ha creado el archivo de la aplicación de JDeveloper (JWS).


También se ha creado el archivo del proyecto (PRJ).


En JDeveloper, ahora podemos ver ambas cosas: aplicación y proyecto.


Implementación del compuesto


Ahora voy a agregar un poco de código al proyecto (aquí pueden implementar lo que ustedes quieran). En el caso de mi ejemplo, agregué lo siguiente:


  1. Creé un esquema para definir el modelo canónico de mi proceso de negocio.
  2. Creé un BPEL que realiza la validación de la información un pago.
  3. Dentro del BPEL coloqué una validación: si el monto de la orden es menor o igual a 1000.00, el pago es aceptado; en caso contrario, el pago es rechazado. Esto a través de XSL.
  4. Expuse el compuesto en dos interfaces: SOAP y REST (JSON/XML).

Hasta este punto, podríamos compilar y desplegar el código como lo hacemos en forma tradicional, de manera manual.


Parent POM: sar-common 


Para poder automatizar las tareas de empaquetado y despliegue del código es necesario utilizar el parent POM: sar-common. Este debería estar previamente instalado en nuestro repositorio local al momento de ejecutar los pre-requisitos.

En el POM de sar-common, debemos hacer algunas modificaciones para la conexión al servidor a donde deseamos desplegar los compuestos. Esto evitará que en cada proyecto debamos de colocar los datos del servidor, así como las credenciales de conexión.

El POM a modificar se encuentra debajo de la siguiente ruta:

.m2\repository\com\oracle\soa\sar-common\12.2.1-1-0

Aquí debemos modificar lo siguiente:


  1. Usuario y contraseña para la conexión al servidor
  2. URL del servidor
  3. Nombre del servidor
  4. Ruta del Middleware Home



Despliegue desde JDeveloper (usando Maven)


Para la automatización de empaquetado y despliegue del compuesto, vamos a utilizar el goal de Maven llamado: pre-integration-test. Este goal no se encuentra disponible por default en JDeveloper, por lo que debemos agregarlo.

Para agregar este goal damos click derecho sobre el POM del proyecto > Run Maven > Manage Goal Profiles. Esto nos abrirá la siguiente vista:


Click sobre la cruz de color verde > Add Phases > Seleccionar pre-integration-test.


Una vez realizado lo anterior, debemos tener la fase disponible en el menú contextual. Al ejecutar pre-integration-test, el compuesto será desplegado hacia la SOA-INFRA.


Despliegue desde línea de comandos (usando Maven)


Si deseamos desplegar el compuesto desde la línea de comandos, lo primero que debemos hacer es settear la variable de ambiente ORACLE_HOME hacia una instalación válida de JDeveloper. Después ejecutar el siguiente comando:

mvn pre-integration-test

El script de Maven compilará el código.


Posteriormente creará el paquete.


Finalmente realizará el despliegue al servidor.


Validación del compuesto en Enterprise Manager


Una vez desplegado el compuesto, podemos validar el despliegue en Enterprise Manager. Al navegar hacia la vista de compuestos desplegados, podemos observar que el compuesto ya se encuentra en el servidor.


Pruebas del compuesto


A continuación, podemos ejecutar algunas pruebas básicas para validar el funcionamiento del código.

La primer prueba la ejecutamos utilizando un monto total de la orden igual a 100.00. Esto deberá responder Autorizado, de acuerdo a la implementación del XSL.



Ahora ejecutamos una prueba con un monto total de la orden de 2000.00. El pago deberá ser Rechazado.



Finalmente, podemos validar que ambas instancias fueron creadas y completadas de manera exitosa.


Algunas conclusiones



  1. Es posible automatizar tareas de compilación, empaquetado y despliegue de compuestos de Oracle SOA Suite. Este puede ser un primer paso para la implementación de una estrategia de DevOps y Continuous Integration.
  2. Oracle proveé de un plug-in para configurar y poblar nuestro repositorio local de Maven con los elementos necesarios para tareas de automatización de despliegues.
  3. A través de Maven (y sus arquetipos) podemos crear la estructura inicial de un proyecto de Oracle SOA Suite.
  4. JDeveloper nos permite importar proyectos de Maven previamente creados con algún arquetipo.
  5. Es posible desplegar compuestos de Oracle SOA Suite, de manera automática, desde JDeveloper y desde la línea de comandos.
  6. El automatizar el despliegue de los proyectos de Oracle SOA Suite, no implica realizar cambios en la forma en que tradicionalmente desarrollamos. Simplemente facilita las tareas del desarrollador al automatizar algunas tareas comunes.

Referencias

En la siguiente referencia pueden encontrar un video que muestra los pasos ejecutados en ésta entrada: