martes, 25 de abril de 2017

Spring Adapter SOA 12c - aprende a usarlo!


Hace unos días, se precisaba una funcionalidad de negocio para validar un número a través de un proceso particular usando Java. Se podria utilizar Java Embedding en el proceso BPEL, pero hay formas más elegantes de hacer esto, ya que no se desea contaminar la capa de orquestación con funcionalidad de negocio. Una forma más agradable y elegante, en mi opinión, es hacer uso del adaptador Spring. Al utilizar este componente, se puede exponer un Java Bean tan simple como se lo haría llamando a otro webservice. De esta manera la funcionalidad del negocio se puede empaquetar en un .JAR más bonito que se podria también probar por separado del resto del composite. Veamos cómo funciona todo esto:



Comenzando con la Prueba de Concepto (PoC)

En primer lugar, se deberá crear un archivo JAR simple que contenga la función que se desea utilizar con una interfaz apropiada. Para este ejemplo se creará una clase FactorialNum, una interfaz  IFactorialNum y una clase simple TestFactorialNum para comprobar si la función hace lo que tiene que hacer. Notar que la clase de Interface se diferencia por su I mayuscula como prefijo en el nombre de la misma. Luego de probar la función con la clase TestFactorialNum, eliminarla.

Crear un proyecto en NetBeans de tipo Maven EJB Module y copiar el siguiente código para cada clase:



IFactorialNum

package com.ejemplo.factorial;

public interface IFactorialNum {
    int getFactorial(int num);
}



FactorialNum

package com.ejemplo.factorial;

public class FactorialNum implements IFactorialNum {
    public FactorialNum() {
        super();
    }
   
    public int getFactorial(int num) {
       
        int resultado = 1;
       
        for (int i = 1; i <= num; i++) {
            resultado *= i;
        }
       
        return resultado;
    }
}



TestFactorialNum

package com.ejemplo.factorial;

public class TestFactorialNum {
   
    public static void main (String[] args) {
       
        System.out.println ("Factorial: " + new FactorialNum().getFactorial(4));
       
    }
   
}


Clic derecho sobre la clase TestFactorialNum y vemos que funciona correctamente:




Ahora en JDeveloper!

Crear una aplicación SOA y un proyecto, llamarlo: FactorialWithSpring






Soltar un componente BPEL y configurarlo asi:




Luego cambiar el tipo de datos de las variables de entrada y salida para que la PoC funcione correctamente, para ello editar el esquema FactorialProcess.xsd de la siguiente forma:

















Llegado este punto, añadir el JAR del EJB creado anteriormente para obtener el Factorial de un Numero, para esto clic derecho sobre el proyecto, elegir "Project Properties", dirijirse a "Libraries and Classpath" y hacer clic en "Add JAR/Directory":



Añadir tambien el archivo JAR a mano en la carpeta SCA-INF/lib dentro de la carpeta del Proyecto.


¡Ahora la parte interesante!

Lo que se desea es obtener el Factorial de un número desde el proceso BPEL. Desde la vista del composite, arrastrar y solar un Spring Adapter en el carril "Components":



Llamarlo FactorialUtil y hacer clic en OK:



Un archivo Spring Context se ha creado, abrir el archivo Spring/FactorialUtil.xml y dirigirse a la sección Weblogic SCA en el panel derecho de componentes:



Arrastrar y soltar el componente Service en el contenido del archivo Spring/FactorialUtil.xml:



Completar los campos name y tarjet como se muestra en la siguiente figura y hacer clic en el icono con el simbolo de engranaje:




Buscar la clase IFactorialNum que es la que define la Interfaz del Java Bean y seleccionarla:



Guardar el archivo Spring/FactorialUtil.xml y cerrar la pestaña. Cuando se regresa al composite se puede ver que el componente Spring ya tiene una interface ahora, prestar atencion:



Es necesario ralizar unos ajustes más al archivo Spring/FactorialUtil.xml sino al tratar de deployar el composite fallará.

Abrir nuevamente el archivo Spring/FactorialUtil.xml (de ahora en más, Archivo Spring Context), ya que es necesario añadir la declaración del Bean que es la que definirá la implementación de la interfaz.

Para ello, añadir un elemento <bean/> debajo del elemento <sca:service/> y un elemento extra <interface.java/> dentro del elemento <sca:service/>, como se muestra en la siguiente figura:




Hacer clic en Editar y buscar la clase en lugar de la Interfaz:



Finalmente el codigo del archivo Spring Context debería quedar de la siguiente forma: 

<?xml version="1.0" encoding="windows-1252" ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util"
       xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:sca="http://xmlns.oracle.com/weblogic/weblogic-sca" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://xmlns.oracle.com/weblogic/weblogic-sca META-INF/weblogic-sca.xsd">
  <!--Spring Bean definitions go here-->
  <sca:service name="FactorialNumBeanService" target="FactorialNumBean" type="com.ejemplo.factorial.IFactorialNum">
    <interface.java interface="com.ejemplo.factorial.IFactorialNum"/>
  </sca:service>
  <bean name="FactorialNumBean" class="com.ejemplo.factorial.FactorialNum"/>
</beans>


Si prestamos atención, tanto el atributo type del elemento <sca:service/> como el atributo interface del elemento <interface.java/> comparten la misma interfaz que define el JAR creado anteriormente. Además el atributo target del elemento <sca:service/> hace referencia al nombre del bean definido al final del archivo Spring Context (esa es la relacion de sus nombres, y puede elegirse cualquiera que se desee).

Por ultimo, el atributo class del elemento <bean/> contiene la clase definida en el JAR creado anteriormente.

De esta manera queda demostrado como se usan las dos clases Java (la Interfaz IFactorialNum y la clase FactorialNum).


¡Atención!

Como se ve en el codigo del archivo Spring Context que se muestra mas arriba, el namespace xsi:schemaLocation ha cambiado, es imperioso cambiarlo o remplazarlo ya que sino fallara al tratar de hacer el deploy del composite. El namespace por el cual deberia cambiarse debe ser el siguiente:

http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://xmlns.oracle.com/weblogic/weblogic-sca META-INF/weblogic-sca.xsd

comprobar que sea ese el namespace final.




Ahora si, conectar el proceso BPEL y el adaptador Spring:



Si aparece el siguiente cartel, aceptarlo con clic en OK:




Como se puede apreciar, se han crado 2 WSDLs dentro de la Carpeta WSDLs, IFactorialNum.wsdl y IFactorialNumWrapper.wsdl. Ahora se puede llamar al Java Bean como cualquier otro Partner Link: 




¡Importante!

Es necesario también, dejar el JAR creado para el Java Bean en la carpeta lib de WebLogic, esto es en: %MW_HOME%\wlserver\server\lib

Es necesario para que a la hora de deployar, el composite encuentre su JAR para el Java Bean en WebLogic.

Asegurarse reiniciar el ambiente completo para que WebLogic tome este nuevo archivo JAR.



¡Hora de Probar!

Deployar el composite y probarlo desde la consola del Enterprise Manager (a.k.a. EM Console).



y el resultado es:



Trace/Log




Ahi está. Una forma bonita y sencilla de implementar funcionalidad de negocio que es reutilizable y no desordena la capa de orquestación.

No hay comentarios:

Publicar un comentario