76
HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK JULIO 2014 Versión 3

HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

  • Upload
    haque

  • View
    228

  • Download
    1

Embed Size (px)

Citation preview

Page 1: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

HERRAMIENTAS DE

PRODUCTIVIDAD

SOFIA2 SDK

JULIO 2014

Versión 3

Page 2: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 2/76

1 INDICE

1 INDICE ............................................................................................................................................ 2

2 INTRODUCCIÓN .............................................................................................................................. 4

2.1 OBJETIVOS Y ALCANCE DEL PRESENTE DOCUMENTO .................................................................... 4

2.2 INSTALACIÓN DEL SDK DE SOFIA2 (SOFIA2-SDK) ................................................................... 4

2.3 CONSOLA DEL SDK DE SOFIA2 (SOFIA2-CONSOLE) ................................................................. 5

3 SOFIA2-CONSOLE: CREACIÓN DE KPS ............................................................................................. 7

3.1 COMANDO SOFIA2 CREARKP .................................................................................................. 7

3.2 COMANDO PARA GENERAR KP JAVA ........................................................................................ 8

3.2.1 Ejemplo de uso ......................................................................................................... 9

3.3 COMANDO PARA GENERAR KP JAVASCRIPT ............................................................................. 12

3.3.1 Ejemplo de uso ....................................................................................................... 12

3.4 COMANDO PARA GENERAR KP ARDUINO ............................................................................... 14

3.4.1 Ejemplo de uso ....................................................................................................... 14

4 KPS JAVA: ESTRUCTURA Y CONFIGURACIÓN ................................................................................ 18

4.1 ESTRUCTURA DEL KP JAVA ................................................................................................... 18

4.1.1 Maven para la gestión de las dependencias .......................................................... 19

4.1.2 Spring como framework de soporte base .............................................................. 20

4.1.3 Soporte JMX ........................................................................................................... 21

4.2 CONFIGURAR NUESTRO KP .................................................................................................. 26

4.2.1 Creación de proyecto Eclipse de nuestro KP .......................................................... 26

4.2.2 Soporte persistencia local para nuestro KP ........................................................... 26

4.2.3 Soporte manejo JSON en nuestro KP .................................................................... 31

5 KPS JAVA GESTIONADOS .............................................................................................................. 35

5.1 CONCEPTOS ...................................................................................................................... 35

5.2 LÓGICA DE FUNCIONAMIENTO .............................................................................................. 35

5.3 LANZADOR KPS .................................................................................................................. 36

Page 3: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 3/76

5.3.1 El Lanzador de KP´s en Ejecución. .......................................................................... 38

5.4 APP MODELO (KP MODELO) .............................................................................................. 38

5.4.1 Eventos ................................................................................................................... 40

5.4.2 Workers .................................................................................................................. 41

5.4.1 Suscripción ............................................................................................................. 47

5.4.2 Monitorización JMX ............................................................................................... 49

5.4.3 Ejemplo de Uso ...................................................................................................... 49

6 ANEXOS ........................................................................................................................................ 51

6.1 UN POCO DE SPRING .......................................................................................................... 51

6.1.1 Inyección de dependencias .................................................................................... 53

6.1.2 Ejemplos: ................................................................................................................ 54

6.1.3 Ámbito de un Bean ................................................................................................. 64

6.1.4 Aplicando aspectos ................................................................................................ 65

6.1.5 Ecosistema/Portfolio Spring ................................................................................... 66

6.1.6 Enlaces de referencia ............................................................................................. 67

6.2 UN POCO DE MAVEN .......................................................................................................... 67

6.2.1 Conceptos básicos .................................................................................................. 67

6.2.2 Ciclo de vida ........................................................................................................... 68

6.2.3 Características ........................................................................................................ 68

6.2.4 Ejemplo de uso ....................................................................................................... 71

6.2.5 Enlaces de referencia: ............................................................................................ 73

6.3 UN POCO DE JUNIT ............................................................................................................ 73

6.3.1 Ejemplo .................................................................................................................. 75

6.3.2 Enlaces de referencia ............................................................................................. 76

Page 4: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 4/76

2 INTRODUCCIÓN

2.1 Objetivos y alcance del presente documento

El presente documento constituye la referencia para conocer el funcionamiento de las

herramientas que incluye el SDK de SOFIA2 y que nos ayudan a crear de forma más sencilla

aplicaciones cliente (KPs) de SOFIA2.

2.2 Instalación del SDK de SOFIA2 (SOFIA2-SDK)

Antes de seguir esta guía se recomienda leer la guía SOFIA2-Conceptos SOFIA2.doc

Para poder desarrollar aplicaciones SOFIA2 es necesario tener instalado el SDK de SOFIA2,

para ello:

Acceder http://scfront.cloudapp.net/desarrollador.html y en la sección de Descargas,

descargar el SDK de SOFIA2

Se trata de un fichero comprimido, que una vez descomprimido creará la siguiente estructura

de directorios:

Page 5: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 5/76

En el directorio SOFIA-RUNTIME tenemos un conjunto de herramientas para el desarrollo de

KPs (jdk, navegador) así como un KP Java y otro Javascript de ejemplo.

En el directorio SOFIA-SDK tenemos un conjunto de herramientas para el desarrollo de KPs

(IDEs, APIs, Repositorio Maven con librerías de dependencias de proyectos java…)

2.3 Consola del SDK de SOFIA2 (SOFIA2-Console)

La Consola de SOFIA2 es la pieza central de las herramientas de productividad de SOFIA2-

SDK.

Su nombre técnico es SOFIA2-Console.

Esta herramienta permite a través de una consola de comandos con ayuda contextual:

Crear clientes SOFIA2 (KPs) para diferentes lenguajes

Configurar capacidades sobre estos clientes

La forma de ejecutar la consola es:

1. Una vez instalado SOFIA2-SDK desde el directorio en el que lo he instalado ejecuto

SOFIA-START.bat

2. Sobre esta línea de comandos ejecuto el comando S:\>arqspring

Page 6: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 6/76

Este comando nos abre la consola de SOFIA2 en otra ventana independiente:

3. Desde esta consola ya puedo ejecutar los comandos que se muestran en los siguientes

capítulos del documento

Page 7: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 7/76

3 SOFIA2-CONSOLE: CREACIÓN DE KPS

Dentro de la consola de SOFIA2 el comando principal es el que nos permite crear KPs.

3.1 Comando sofia2 crearKp

El comando sofia2 crearKp permite generar esqueletos de KPs.

Se pueden generar tres tipos de KPs: Java, Javascript y Arduino.

sofia2 crearKp --nombreKp [NOMBREKP] --tipoKp [tipo] --token [TOKEN] --instancia

[INSTANCIA] --ip [IP] --puerto [PUERTO] --paquetebase [PAQUETE]

Parámetros obligatorios:

--nombreKp : nombre que tendrá el KP (obligatorio)

--tipoKP: tipo del KP a generar: JAVA, JAVASCRIPT o ARDUINO (obligatorio)

--token: token que junto con la instancia del KP permite conectar con el SIB (obligatorio)

--instancia: instancia del KP y permite junto con el token conectar con el SIB

(obligatorio)

Parámetros opcionales:

El resto de atributos dependerán del tipo de KP a generar. Son los siguientes:

--ip: IP del SIB al que se va a conectar al usar tipoKP = JAVA. El formato para

especificar la ip, se debe especificar separada por puntos, por ejemplo 192.112.12.121

--puerto: puerto del SIB al que se va a conectar al usar tipoKP = JAVA

--server: IP del servidor para el tipo Arduino (se debe especificar separada por puntos,

por ejemplo 192.112.12.121) y URL del servidor para el tipo de KP JavaScript (debe

ser una url completa, por ejemplo http://localhost:8080)

--mac: mac para establecer la conexión en un KP Arduino. El formato para especificar la

MAC debe seguir el patón 0xXX, por ejemplo 0x00.0xAA.0xBB.0xCC.0xDE.0x01.

--paquetebase: paquete base del proyecto Java, a utilizar con el tipoKP = JAVA. Si no

se indica por defecto e paquetebase será “src.sources”

Page 8: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 8/76

NOTA

Se recomienda lanzar el comando sobre un directorio vacío, y que la ruta al directorio no

contenga espacios en blanco

Ejemplo de ruta válida R:\Desarrollo\MiKP\

3.2 Comando para generar KP Java

Para generar un proyecto KP de tipo Java será necesario indicar el nombre del KP, token e

instancia de conexión, ip y puerto para conectar vía MQTT con el SIB. El comando quedará

definido del siguiente modo:

sofia2 crearKp --nombreKp [NOMBREKP] --tipoKp JAVA --token [TOKEN] --instancia

[INSTANCIA] --ip [IP] --puerto [PUERTO] --paquetebase [PAQUETE]

Al lanzar el comando se generará un proyecto web con las clases y recursos necesarios para

desarrollar un KP.

La estructura incluye:

Fichero pom.xml de Maven con las dependencias necesarias para compilar nuestro

proyecto KP:

<dependency> <groupId>com.indra.jee.arq.spring.sofia2.ssap</groupId> <artifactId>ssap-core</artifactId> <version>2.2.0</version> </dependency>

Estructura de Paquetes con conjunto de clases de utilidad

o Excepciones: 2 clases de excepción que nos ayudarán en el manejo de la

excepciones de nuestro proyecto de KP:

ExcepcionGateway.java

SensorExisteExcepcion.java

o ClienteSibServer.java. Clase que hace de proxy al SIB.

o GatewayLauncher.java. Clase que crea la conexión física con el SIB a través

de MQTT.

o ControladorLauncher.java. Para controlar la UI.

Ficheros de configuración:

Page 9: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 9/76

o monitorizacion.properties. Para monitorizar el KP vía JMX

UI Web básica que permite conectar y desconectar al KP del SIB

3.2.1 Ejemplo de uso

Veamos un ejemplo para crear un KP JAVA:

Creamos un directorio, “KPAnuncios”.

Abrimos la consola en ese directorio con \ArqSpring.bat

Lanzamos el comando:

sofia2 crearKp --nombreKp KPpubliAnuncios --tipoKp JAVA --token

d9e77d01d3c84f96994bfdcd428faa97 --instancia KPpubliAnuncios:KPpubliAnuncios01 --

ip localhost --puerto 1883 --paqueteBase com.sources

Page 10: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 10/76

NOTA

Es posible que en consola salga la siguiente traza, aunque no afecta al funcionamiento del

comando.En el caso de que salga, es necesario salir de la consola (con exit) y volver a entrar

(con arqspring).

Importamos el proyecto en el IDE donde podemos ver que se nos ha generado la siguiente

estructura:

Page 11: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 11/76

Si desplegamos la aplicación en un servidor de aplicaciones como Jetty y accedemos a la url,

podremos ver una UI como la siguiente:

Si la url y puerto para conectar por MQTT y el token e instancia son correctos podremos

conectar con el SIB.

A partir de esta estructura podemos extender nuestro KP.

Page 12: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 12/76

3.3 Comando para generar KP Javascript

Para generar un KP de tipo JavaScript será necesario indicar el nombre del KP, token e

instancia de conexión, ip del servidor:

sofia2 crearKp --nombreKp [NOMBREKP] --tipoKp JAVASCRIPT --token [TOKEN] --

instancia [INSTANCIA] --server [URL]

Al lanzar el comando se generarán los recursos necesarios para desarrollar un KP JavaScript.

La estructura incluye:

Directorio img: que contendrá las imágenes del KP

Directorio styles: que contendrá las hojas css con los estilos a utilizar en el KP.

Librerías JavaScript:

o kp-core : API Javascript que nos permitirá desarrollar nuestro KP

o jquery.min:

o dygraph-combined

o base64

o XXTEA

KP-javascript-[nombreKP].html: Que contiene esqueletos con las funciones javascript y

una vista para conectar y desconectar el KP.

3.3.1 Ejemplo de uso

Veamos un ejemplo para crear un KP JAVASCRIPT:

Creamos un directorio, “KPAnunciosJS”.

Abrimos la consola en ese directorio con \ArqSpring.bat

Lanzamos el comando:

sofia2 crearKp --nombreKp KPpubliAnuncios --tipoKp JAVASCRIPT --token

d9e77d01d3c84f96994bfdcd428faa97 --instancia KPpubliAnuncios:KPpubliAnuncios01 --

server http:localhost:8082

Si accedemos al directorio vemos que nos ha generado lo siguiente:

Page 13: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 13/76

Si abrimos el .html generado vemos que en la parte inicial se cargan las librerías.

En la imagen de arriba podemos ver que se han incuido varias líneas que carga DWR y las

librerías asociadas en DWR y que deben estar en el servidor.

A continuación se incluyen varias funciones Javascript para la conexión, desconexión,

suscripción, etc.

Page 14: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 14/76

3.4 Comando para generar KP Arduino

Para generar un KP de tipo Arduino será necesario indicar el nombre del KP, token e instancia

de conexión, ip, mac e ip del servidor

sofia2 crearKp --nombreKp [NOMBREKP] --tipoKp ARDUINO --token [TOKEN] --instancia

[INSTANCIA] --ip [IP] --server [IPSERVER] --mac [MAC]

Al lanzar el comando se generará dentro del directorio que hemos creado un fichero

arduino_[nombreKP].ino con la operativa.

3.4.1 Ejemplo de uso

Veamos un ejemplo para crear un KP ARDUINO:

Page 15: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 15/76

Creamos un directorio, “KPArduino”.

Abrimos la consola en ese directorio con \ArqSpring.bat

Lanzamos el comando:

sofia2 crearKp --nombreKp KPArduino --tipoKp ARDUINO --token

d9e77d01d3c84f96994bfdcd428faa97 --instancia KPArduino:KPArduino01 --ip

192.168.10.129 --server 192.168.10.128 --mac 0x00.0xAA.0xBB.0xCC.0xDE.0x01

Si abrimos el fichero con extensión .ino, podemos ver que se han incluido las librerías para

poder desarrollar KPs Arduino.

También se han incluido los datos de conexión

Definición de variables para la configuración del Arduino, para el envío de mensajes SSAP y

para la conexión física con el SIB a través de MQTT.

Page 16: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 16/76

Se incluye también los esqueletos con la operativa:

Page 17: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 17/76

Page 18: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 18/76

4 KPs JAVA: ESTRUCTURA Y CONFIGURACIÓN

En el punto 3.2 hemos hecho referencia al comando para crear KPs Java.

En este punto explicaremos con mayor detalle la estructura del código Java generado,

dependencias introducidas, frameworks propuestos,…

4.1 Estructura del KP Java

Al ejecutar el comando sofia2 crearKp con tipoKP JAVA se habrá generado en el directorio

desde el que lo ejecutemos esta estructura.

En esta estructura podemos observar:

Fichero pom.xml de Maven para gestión de las dependencias

Proyecto Eclipse (.project y .classpath)

Page 19: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 19/76

Ficheros de configuración de mi aplicación:

Aplicación Spring como contenedor IoC

Aplicación Web

Soporte JMX

4.1.1 Maven para la gestión de las dependencias

Los KPs Java generados usan Maven para la gestión de las dependencias.

Maven es básicamente una herramienta para la gestión y construcción de proyectos y puede

verse como la evolución de Ant.

Maven está basado en el concepto de un modelo de objetos del proyecto POM (Project Object

Model) en el que todos los productos (artifacts) generados por Maven son el resultado de

consultar un modelo de proyecto bien definido.

Page 20: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 20/76

Maven intenta hacer la vida del desarrollador sencilla proporcionando una estructura de

proyecto bien definida, unos procesos de desarrollo bien definidos a seguir, y una

documentación coherente que mantiene a los desarrolladores y clientes informados sobre lo

que ocurre en el proyecto.

Para más información sobre Maven puede consultarse el anexo Un poco de Maven.

4.1.2 Spring como framework de soporte base

Los KPs Java generados usan el framework Spring como tecnología base para el desarrollo y

ejecución. Es importante por tanto conocer qué ofrece Spring.

Spring es un framework ligero que ayuda en la estructuración de las aplicaciones permitiendo

usar de forma coherente diferentes productos, frameworks y soluciones.

La idea es que Spring se encarga de manejar la infraestructura, para que el desarrollador

centre su atención en el desarrollo del resto de la aplicación.

Spring permite construir aplicaciones a partir de POJOs “plain old java objects”, y dotándolas

de características propias de aplicaciones J2EE.

Spring permite hacer esto de una manera no intrusiva.

Los puntos principales que caracterizan a Spring son:

Es un estándar de facto en el mundo Java/JEE

Actúa como pegamento entre todas las Capas y componentes

Simplifica el desarrollo de aplicaciones JEE (Java) promoviendo buenas prácticas

Es portable entre Servidores de aplicaciones, en este contexto a Spring se le conoce como un framework ligero puesto que no usa EJBS para la implementación de Servicios.

No reinventa la rueda, reutiliza frameworks existentes y de amplio uso

Page 21: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 21/76

Proporciona al programador un “modo de trabajo”

Facilita la “colaboración”, puesto que estandariza el código, a nivel de componentes, permitiendo ahorrar tiempo e incrementando la calidad del software.

Para más información sobre Spring puede consultarse el anexo Un poco de Spring.

4.1.3 Soporte JMX

Los proyectos KPs JAVA creados ya vienen configurados para permitir la monitorización a

través de JMX.

Java Management Extensions (JMX) es la tecnología Java para administrar y/o supervisar

aplicaciones, objetos del sistema, dispositivos y redes orientadas al servicio. Equivalente a

SNMP. La entidad administrada/supervisada se representa mediante objetos llamados MBean

(del inglés "Managed Bean", bean administrado).

A través de JMX se puede interactuar con los componentes administrados (MBeans) de una

aplicación, bien de forma local o remota.

El soporte incluido en los KPs Java simplifica la creación de MBeans a través de anotaciones

Java que permiten:

Obtener el valor actual de los atributos de los objetos administrables que representan

parámetros de monitorización o configuración

Modificar el valor de los atributos de los objetos administrables que representan

parámetros de configuración.

Invocar operaciones de administración sobre objetos administrables, para realizar otro

tipo de tareas de administración.

4.1.3.1 Anotaciones JMX

Las anotaciones incluidas son:

@ManagedResource para definir un MBean. Este MBean debe ser un JavaBean

@ManagedAttribute para definir un atributo administrable en un MBean. Debe ser un

atributo de un JavaBean, con su get y su set.

@ManagedOperation para definir una operación administrable en un MBean

Conviene que los atributos y operaciones administrables sean de tipo primitivo, así como

arrays y collections de estos tipos. Estas pautas evitarán problemas de presentación en las

consolas de administración JMX.

Page 22: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 22/76

Definición de un Bean Monitorizable

@Component

@RooJavaBean

@ManagedResource(objectName =

"KPAnuncios:type=Monitorization,name=Connection", description =

"Connection Service")

public class ServiceImpl {

El parámetro objectName permite especificar el nombre jerárquico que tendrá el objeto.

Cada uno de los MBeans deberá disponer de un nombre jerárquico que deberá ser único entre

todos los objetos administrables que se ejecuten en la máquina virtual java.

[dominio]:[parámetro=valor], [parámetro=valor], …

El dominio típicamente identifica a la organización que especifica los objetos de configuración,

así como la categoría a la que pertenezcan los objetos de configuración, aunque pueden

usarse otros convenios.

Los parámetros y sus valores permiten dar más información acerca de los objetos de

configuración, facilitando búsquedas. Cuando la aplicación se encuentre en ejecución y se

acceda a estos objetos mediante JMX, se mostrará un árbol con todos los objetos disponibles,

organizados por su nombre.

Definición de un método get o set Monitorizable

@ManagedAttribute(description = "Active Connection")

public boolean getActiveConnection() {

return connection;

}

Los métodos de acceso a los atributos deben anotarse de la siguiente forma, bien en los

métodos get o bien en los set:

Definición de una operación Monitorizable

@ManagedOperation(description = "Añade un nuevo dato")

@ManagedOperationParameters({

Page 23: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 23/76

@ManagedOperationParameter(name = "data", description = "Data")

})

public void addData(String data)

4.1.3.2 Acceso a MBeans a través de JConsole

Una vez en ejecución, los objetos de configuración o monitorización de la aplicación podrán ser

observados y administrados a través de JMX, tanto de forma local como de forma remota.

Para la administración local se puede hacer uso de la herramienta jconsole.exe que incluye el

JDK de SOFIA-RUNTIME) y que permite operar sobre los objetos administrables:

El primer paso será elegir el PID del proceso asociado a la máquina virtual java que se

desea administrar:

Una vez elegida la máquina virtual en la que se ejecuta la aplicación, pueden

observarse todos los objetos de administración disponibles, clasificados según su

nombre.

Page 24: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 24/76

El elemento Attributes contiene el valor actual de los diferentes atributos del objeto

administrable:

El elemento Operations muestra las operaciones que es posible invocar sobre el objeto

de administración para modificar la configuración:

Page 25: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 25/76

4.1.3.3 Acceso a MBeans vía web:

El KP JAVA también soporta el acceso a los MBeans a través de una consola Web que adapta

el protecolo JMX a HTTP.

Por defecto este acceso no está habilitado, para habilitarlo es preciso modificar el fichero

monitorizacion.properties de nuestra aplicación, para elegir la dirección y puerto concretos

sobre los que se desea que se lance:

Tras esto arrancaré la aplicación y colocaré un navegador sobre la url en la que

configuré el adaptador JMX-HTTP:

Seleccionando el MBean concreto podré administrarlo:

Page 26: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 26/76

4.2 Configurar nuestro KP

4.2.1 Creación de proyecto Eclipse de nuestro KP

El SDK de SOFIA2 incluye una versión de Eclipse personalizada para el desarrollo de KPs.

Para poder cargar, depurar y ejecutar un proyecto generado con el comando crearKp se puede

ejecutar desde la consola de SOFIA2 el comando

>perform eclipse

Que genera el proyecto de Eclipse.

4.2.2 Soporte persistencia local para nuestro KP

En muchas ocasiones el KP a desarrollar necesitará almacenar en local información,

normalmente si se pierde temporalmente la conexión con el nodo central.

Desde la consola de comandos se puede añadir fácilmente a nuestro KP la capacidad de

almacenar información.

El comando a ejecutar desde la consola es:

>sofia2 configurarKp persistencia

Este comando debe ejecutarse sobre un proyecto de tipo KP JAVA, como resultado de su

ejecución se incluirá:

Page 27: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 27/76

Dependencias necesarias en el pom.xml (H2 y ORMLite)

Generar un Test y clases necesarias para simplificar el uso

4.2.2.1 Tecnologías involucradas: H2 y ORMLite

El soporte a la persistencia local a los KPs Java se basa en estas tecnologías:

H2 como base de datos local funcionando en modo embebido (se lanza desde el propio

KP)

ORMLite como motor de mapeo objeto-relacional para simplificar el uso de la base de

datos

Spring como framework de “glue” que simplifica el uso de estas tecnologías bajo su

framework IoC

Base de datos SQL Java H2:

Ofrece funcionalidades similares a HSQLDB (pero con más rendimiento)

Es una base de datos muy rápida y adecuada a entornos embebidos

Open Source

Ofrece diversos modos de funcionamiento: en memoria, embebido y Servidor

Tamaño pequeño: 1 JAR de 1 Mb

ORMLite como motor java de mapeo objeto-relacional

Más ligero que JPA (sin dependencias) y adecuado a entornos embebidos

Autoconfigurable

Se compone sólo de 2 jars

Configuración de clases con anotaciones Java simples

Soporte DAO

QueryBuilder para queries simples y complejas

Soporta varias bases de datos: MySQL, Postgres, H2, Derby, etc.

Soporte básico para transacciones

Soporte configuración sobre Spring

Soporte nativo Android SQLite API

Page 28: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 28/76

4.2.2.2 Ejemplo de Uso

Sobre el proyecto del KP Java Anuncios creado en el punto 3.2.1 lanzamos el comando que

configurará la persistencia:

>sofia2 configurarKp persistencia

Tras ejecutar el comando se habrá generado:

La clase TablaKp corresponde con la clase Java anotada que representa la tabla y

campos de la tabla. Se ha creado a modo de ejemplo e incluye como campos un id,

fecha y datos a insertar.

Page 29: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 29/76

La clase FillTableKp que muestra cómo manejar el soporte de persistencia:

La clase TestPersistenciaKP: en el test se valida que la tabla de base de datos

contiene datos tras ejecutarse las operacions de FillTableKp.

Page 30: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 30/76

El fichero applicationContext-Persistencia.xml que contiene toda la configuración de

la base de datos se encuentra en el fichero. Veamos con más detalle que incluye este

fichero.

Los beans para la definición del transaction manager para H2 y ORMLite.

Page 31: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 31/76

Bean para la creación de los Daos asociados a la clase Java que representa la tabla de

base de datos.

Bean para la creación automática de la tabla.

Bean que representa nuestro DAO de ejemplo.

Fichero database.properties con los datos de conexión:

4.2.3 Soporte manejo JSON en nuestro KP

Al crear un proyecto KP Java automáticamente ya se incluye la dependencia a la librería

FlexJson para manejar JSON desde Java.

Además de esto la consola ofrece un comando que simplifica el uso de esta librería permitiendo

de forma sencilla mapear Java-JSON y JSON-Java.

El comando que permite esta funcionalidad es el siguiente:

>sofia2 configurarKp mapperJSON

No requiere de ningún parámetro adicional.

Se debe lanzar sobre un proyecto sobre el que se haya creado previamente un KP

Java.

Como resultado se incluirán las dependencias necesarias, un JSON de ejemplo y se

generará un test que muestra cómo utilizar esta funcionalidad.

4.2.3.1 Clase JsonToJAva

Existe una clase JsonToJava.java que incluye un método jsonToJava que permite

generar las clases Java a partir del Json.

Page 32: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 32/76

public final static void jsonToJava(String outputdirectory, String

packageName, String fileJson, String className)throws IOException,

ClassNotFoundException, JsonParseException,JsonMappingException

Como parámetros de entrada:

- String outputdirectory: Ruta del proyecto donde se van a generar las clases

- String packageName: Paquete para la generación de las clases

- String fileJson: Ruta donde se encuentra el JSON

- String className: Nombre de la clase Java.

4.2.3.2 Ejemplo de Uso

Sobre el proyecto del KP Java Anuncios lanzamos el comando que configurará el mapperJSON

>sofia2 configurarKp mapperJSON

Que genera:

La clase de Test TestJson que muestra cómo a partir del JSON de ejemplo incluido

(SensorHumedad.json) se obtienen las clases Java asociadas a él y cómo mapear el

json al objeto Java generado.

NOTA: Para evitar problemas de compilación hasta que se generen las clases Java, se

ha dejado comentado el segundo método de test.

Page 33: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 33/76

Al ejecutar el test (hacemos refresh sobre el proyecto) vemos que se han generado la

clase Java MyOntology y una serie de clases Java que representan el JSON.

Si ahora descomentamos el método JavaToJson y lo lanzamos vemos que es posible

mappear el Json al objeto Java MyOntology, haciendo uso de ObjectMapper.

Page 34: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 34/76

Page 35: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 35/76

5 KPS JAVA GESTIONADOS

Aparte del soporte para la creación de KPs en Java, Javascript y Arduino dentro de las

herramientas de productividad se ofrece soporte para la creación de KPs Java gestionados,

esto significa que siguen un patrón de desarrollo y que ofrecen funcionalidades avanzadas

como la capacidad de autodespliegue y autoconfiguración.

5.1 Conceptos

Lanzador KPs: Es la plataforma de ejecución de los KP´s Autogestionados, incluye un

Servidor Web Jetty Embebido que ejecuta las diferentes AppModelo, gestiona su

configuración y actualización en función de los requisitos indicados desde el SIB.

AppModelo = KP Modelo: Son los KP desarrollados siguiendo la metodología y

requisitos establecidos por el Lanzador KPs, abstrae al desarrollador de la lógica de

actualización, configuración y perdida de conectividad.

Evento: Son las diferentes acciones que un KP puede ejecutar (Captación sensórica,

transformación de la información, envío y recepción de datos a y desde el SIB )

Worker: Son la tareas que interceptan los diferentes eventos que son generados por los

KP.

5.2 Lógica de Funcionamiento

El lanzador se conecta con el SIB y recupera.

La información proporcionada por el SIB con el listado de los KP que debe tener

desplegado y su configuración.

Se comprueba si la versión de SW o Configuración es la indicada por el SIB

Page 36: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 36/76

Se realiza copia de seguridad de la configuración y SW de los KP que han de ser

actualizados.

Se actualiza la Configuración y/o SW de los KP cuya versión difiere de la notificada por

el SIB, tanto si es una versión superior como inferior.

El lanzador arranca cada uno de los KP que tiene configurados.

Los KP funcionan de forma autónoma accediendo a la infraestructura gestionada por el

Lanzador de KP y que les proporcionan capacidades de comunicación con el SIB,

monitorización, persistencia…

El Lanzador interroga al SIB cada x tiempo por la configuración de los KP que debe tener

desplegados, si el SIB le notifica una nueva versión de Software o Configuración, se detiene la

aplicación y es actualizada.

5.3 Lanzador Kps

Como hemos dicho el Lanzador KPs es el encargado de la ejecución y gestión de los KPs de la

plataforma SOFIA2.

Establece un marco de ejecución con un estricto ciclo de vida que facilita el desarrollo de

clientes (APPModelo). La finalidad es permitir el mantenimiento remoto de las AppModelo,

centralizando su configuración y gestión de versiones en el SIB, facilitar el desarrollo de

clientes aportando mecanismos para el control de errores, persistencia, monitorización, .

El Lanzador de KP´s es un JAR que levanta un contenedor Web donde despliega las

AppModelo con la configuración que el SIB le notifica. Es un contenedor que permite ejecutar

simultáneamente distintas implementaciones de KP sobre la misma máquina virtual. Utiliza un

modelo de Workers para ofrecer un marco de funcionalidades básicas comunes a los KPs de

SOFIA (herramientas de conexión, envío y recepción de mensajes, suscripciones,

monitorización, persistencia local de mensajes, reintento de envío de mensajes fallidos,

actualización/versionado automático de KPs,…)

Requiere de una configuración básica para su funcionamiento, el fichero

CONF_BASE.properties

PROPIEDADES BASICAS DEL LANZADOR DE KP´s

TIMEOUT TimeOut para comunicaciones con el SIB

TIME_4_NEWVERSION Indica en minutos cada cuanto tiempo se comprueba la

configuración de las AppModelo que han de estar

desplegadas en el KPModelo.

Page 37: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 37/76

SW_RUTA Ruta donde se almacenarán los WAR del las

AppModelo

CONF_RUTA Ruta donde se almacenará el properties de

configuración de las AppModelo

TMP_RUTA Ruta donde se almacenarán las copias de seguridad

SIB IP : PUERTO de comunicación MQTT con el SIB

PORT Puerto donde se levanta el servidor Web del KPModelo

KP KP utilizado para comunicarse con el SIB

INSTANCIA_KP Instancia KP utilizada para comunicarse con el SIB

TOKEN Token utilizado para comunicarse con el SIB

Estas propiedades son las mínimas necesarias para la ejecución del Lanzador de KP´s, y son

accesibles desde las AppModelo, siempre y cuando estas últimas no las sobrescriban en su

fichero de configuración.

Su estructura es la siguiente

LIB Donde se almacenan las dependencias para la ejecución del KPMODELO

SW Directorio donde se almacenan los WAR APPModelo

CFG Directorio donde se almacena la configuración de cada APPModelo

TMP Directorio donde se almacena la copia de seguridad de las APPModelo que van ha

ser actualizadas.

El Lanzador de KP´s ha de ser ejecutado con el parámetro -DCONF_BASE= [DIRECTORIO

DONDE SE UBICA CONF_BASE.properties]

El script arranca la aplicación.

Si no arrancamos el Lanzador de KP´s con esta configuración buscará el fichero

CONF_BASE.properties en el directorio usr.

Page 38: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 38/76

5.3.1 El Lanzador de KP´s en Ejecución.

Cuando se arranca el Lanzador de KP´s a través del comando START-KP-MODELO.

Lo primero que hace es conectarse al SIB con la configuración establecida en el fichero

CONF_BASE.properties, solicitando la configuración asociada a él. A nivel de KP y de Instancia

de KP.

El SIB devolverá por un lado la configuración global del KP.

Configuración de Ontologías

Configuración de Assets

El listado de las aplicaciones que ha de desplegar con su información a nivel de.

Firmware

Configuración

Cualquiera de estos datos está versionado, por lo que si el Firmware o la Configuración tienen

una versión diferente (Inferior o Superior) a la desplegada se actualizará en el Lanzador de

KP´s. Previo a realizar una actualización de firmware o configuración se guarda una copia en el

directorio indicado en el parámetro de configuración TMP_RUTA.

Una vez actualizado el APPModelo se despliega en el Lanzador de KP´s.

IMPORTANTE

Las aplicaciones ya desplegadas en el Lanzador de KP´s y que no son notificadas por el

SIB son eliminadas. Si se encuentran en ejecución serán detenidas y eliminadas.

5.4 APP Modelo (KP Modelo)

Las aplicaciones que se despliegan en el Lanzador de KP´s reciben el nombre de APPModelo,

estas aplicaciones son creadas con el comando sofia2 crearAppModelo --id [NOMBRE

APPMODELO] –paquetebase [PAQUETE APLICACION], La Herramienta de Productividad

crea una estructura y las implementaciones por defecto para empezar a desarrollar el negocio

específico.

Page 39: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 39/76

El proyecto Maven generado tiene las dependencias necesarias para compilar las AppModelo.

<dependency>

<groupId>com.indra.sofia2</groupId>

<artifactId>launcher</artifactId>

<version>1.0</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>com.mycila</groupId>

<artifactId>mycila-pubsub</artifactId>

<version>5.0.ga</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>com.indra.sofia2</groupId>

<artifactId>ssap</artifactId>

<version>2.5.0</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>com.jsontojava</groupId>

<artifactId>jsontojava</artifactId>

<version>1.0</version>

<scope>provided</scope>

</dependency>

Todas estas dependencias tiene scope provided, pues en tiempo de ejecución será el Lanzador

de KP´s el que nos proporcione las versiones adecuadas de todas las librerias necesarias para

la ejecución de las diferentes APPModelo.

Page 40: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 40/76

IMPORTANTE

Cuando se despliegan multiples wars es necesario que estos dispongan del identificador como una propiedad context-param en el web.xml, para diferenciar unívocamente cada aplicacion <context-param>

<param-name>webAppRootKey</param-name>

<param-value>NOMBREAPP MODELO</param-value>

</context-param>

A partir de la versión 2.8.0 del SDK cuando se crea una nueva AppModelo esta propiedad es

creada de forma automática.

5.4.1 Eventos

Los KPs gestionados funcionan en base a unos Eventos, estos Eventos se producen cuando

se desencadena alguna opción.

Los siguientes eventos están predefinidos en la infraestructura del Lanzador de KP´s.

START_APP Evento que se genera cuando se arranca la aplicación.

STOP_APP Evento que se genera cuando se solicita la detención de la aplicación.

APP_STOPED Evento que se genera cuando la aplicación ha sido detenida.

PREPARE_TO_RECEIVED Evento que se genera una vez que se ha arrancado la

aplicación, se han lanzado los Workers asociados al evento START_APP.

NEW_DATA_RECEIVED Evento que se genera cada vez que se recibe datos desde un

sensor.

DATA_TO_SEND Evento que se genera cuando los datos recibidos por el sensor son

convertidos a un mensaje SSAP para ser enviados al SIB

CONNECTION_TO_SIB Evento que se genera cuando se existe conectividad con el

SIB.

NO_CONNECTION_TO_SIB Evento que se genera cuando se pierde la conectividad

con el SIB.

DATA_SEND_TO_SIB Evento que se genera cuando se ha enviado un mensaje SSAP

al SIB.

ERROR_ON_SENT_TO_SIB Evento que se genera cuando se produce un error al

enviar un SSAP al SIB.

Page 41: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 41/76

Además el desarrollador puede registrar nuevos eventos de esta forma:

Los eventos deben ser registrados a través del Bean KPWorkerCfg, para poder registrar

nuevos eventos deberemos obtener una referencia a este objeto

@Autowired

protected KPWorkerCfg kPWorkerCfg;

e invocar el método public void addEvent(String event, Class message, Subscriber worker) al cual

debemos informarle el EVENTO que no es más que un String que lo identifica, la clase del

objeto que recibe el Worker que intercepta ese evento y el propio Worker, que es la

implementación de la interface Subscriber que define lo que haremos cada vez que se genere

ese evento.

public class StartAppWorker extends Subscriber<LifeCicleMessage> {

public void onEvent(Event<LifeCicleMessage> event) throws Exception{

Para una implementación como la anterior, la invocación al método addEvent quedaría de la

siguiente forma.

kPWorkerCfg.addEvent(“MI_EVENTO”, LifeCicleMessage.class, new StartAppWorker())

5.4.2 Workers

La forma de trabajo está basada en Workers a traves de un modelo Pub/Subcribe a nivel de

JVM. Estos Workers definen el siguiente ciclo de vida.

Page 42: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 42/76

5.4.2.1 PrepareToReceived.

@Component

public class PrepareToReceived extends PrepareToReceivedWorkerImpl {

@Override

public SensorMessage reveivedDataSensor (LifeCicleMessage lifeCicleMessage) {

/*

* METODO QUE ES EJECUTADO DE FORMA CICLICA ES EL ENCARGADO DE LEER LA INFORMACION

* SENSORICA HA DE DEVOLVER UN OBJETO SensorMessage CON LA INFORMACIN DE LOS

* SONSORES.

*/

//TODO

return new SensorMessage();

}

}

Este Worker es ejecutado de forma automática cuando arranca la APPModelo, en su interior

ejecuta un Bucle que envía constantemente la información recogida en el método

reveivedDataSensor al evento NEW_DATA_RECEIVED.

Page 43: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 43/76

5.4.2.2 NewDataReceived.

@Component

public class NewDataReceived extends NewDataReceivedWorkerImpl {

@Override

public SSAPMessage generateSSAPMessage(SensorMessage sensorData) {

/*

* METODO QUE ES EJECUTADO CUANDO EL CAPTADOR DE DATOS SENSORICOS LOS NOTIFICA

* ESTE METODO HA DE TRANFORMAR LOS DATOS CAPTADOS DE LOS SENSORES EN UN SSAP

VALIDO

* SI ESTE METODO DEVUELVE UN OBJETO DISTINTO DE NULO LO ENVIA AUTOMATICAMENTE A

LA CLASE

* DataToSend EL SESSION KEY NO ES NECESARIO PUES LA PLATAFORMA LO RELLENARA

AUTOMATICAMENTE

*/

//TODO

return new SSAPMessage();

}

}

Es el Worker que debemos Invocar cuando recibimos datos del sensor, su finalidad es convertir

el SensorMessage que contiene la información que hemos recibido de los sensores en un

SSAPMessage.

Cuando retornamos el SSAPMessage la clase abstracta de la que extendemos se encargará

de enviar el mensaje al siguiente Worker.

public void onEvent(Event<SensorMessage> event) throws Exception{

SSAPMessage ssapMessage = generateSSAPMessage(event.getSource());

if (ssapMessage!=null){

kPWorkerCfg.publish(SensorEvents.DATA_TO_SEND.name(), ssapMessage);

}

}

IMPORTANTE

Para que los datos del sensor lleguen al Worker NewDataReceived, debemos notificarlo con el

siguiente código.

kPWorkerCfg.publish(SensorEvents.NEW_DATA_RECEIVED.name(), sensorMessage);

El objeto kpWorkerCfg lo recuperaremos del contexto de Spring, la manera mas sencilla será

con un Autowired en un Bean de Spring.

@Autowired

protected KPWorkerCfg kPWorkerCfg;

5.4.2.3 DataToSend.

@Component

public class DataToSend extends DataToSendWorkerImpl {

@Override

public SSAPMessage preProcessSSAPMessage(SSAPMessage requestMessage) {

/*

* METODO QUE ES EJECUTADO JUSTO ANTES DE ENVIAR EL SSAP CREADO EN NewDataReceived

AL SIB

* EL MENSAJE ENVIADO SERA EL QUE DEVUELVA ESTE METODO PARA ENVIAR EL MENSAJE

GENERADO PREVIAMENTE

* DEVOLVER EL OBJETO DE ENTRADA requestMessage SIN MODIFICAR

*/

//TODO

return requestMessage;

Page 44: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 44/76

}

@Override

public void postProcessSSAPMessage(SSAPMessage requestMessage, SSAPMessage

responseMessage) {

/*

* METODO QUE ES EJECUTADO DESPUES DE ENVIAR EL SSAP AL SIB LOS PARAMETROS QUE SON

EL requestMessage

* MENSAJE ENVIADO Y EL requestMessage MENSAJE DE RESPUESTA DEL SIB

*/

//TODO

}

}

Es el Worker encargado de enviar el SSAP al SIB, tiene dos métodos en los que implementar el

código de pre preProcessSSAPMessage y post postProcessSSAPMessage procesamiento

del envío. La clase abstracta de la que extendemos se encargará de enviar el mensaje al

siguiente Worker.

public void onEvent(Event<SSAPMessage> event) throws Exception{

SSAPMessage requestMessage = preProcessSSAPMessage(event.getSource());

SSAPMessage responseMessage = sib.send(requestMessage);

if (requestMessage!=null){

postProcessSSAPMessage(requestMessage, responseMessage);

}

}

5.4.2.4 DataSendToSib.

@Component

public class DataSendToSib extends DataSendToSIBWorkerImpl {

@Override

public void sended(SibMessage message) {

/*

* METODO QUE ES EJECUTADO CUANDO SE HAN ENVIADO DATOS AL SIB DE FORMA CORRECTA SI

EL MESAJE

* ENVIADO ESTA EN LA BASE DE DATOS DE ERRORES LO BORRA DE ESTA

*/

//TODO

}

}

Es el Worker notificado cuando un envío al SIB se ha procesado correctamente, El método que

debemos implementar, recibe un SibMessage que tiene el mensaje enviado y la respuesta del

SIB. La clase abstracta de la que extendemos se encargará de comprobar si el mensaje

enviado está en la tabla de fallidos de la base de datos y en de ser así de borrarlo.

public void onEvent(final Event<SibMessage> event) throws Exception{

try{

persistence.getTransactionManager().callInTransaction(new Callable<Void>()

{

public Void call() throws Exception {

Table table =

persistence.findById(event.getSource().getRequest().toJson());

if (table!=null){

persistence.delete(table);

}

return null;

}

});

}catch (Exception e){

e.printStackTrace();

}

sended(event.getSource());

Page 45: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 45/76

}

5.4.2.5 Connection.

@Override

public void connected(SibMessage connected) {

/*

* METODO QUE ES EJECUTADO CUANDO SE HA REALIZADO UNA CONEXION CON EL SIB PREVIO A

ESTE METODO

* LA CLASE COMPRUEBA SI EXISTEN SSAP NO ENVIADOS O CON ERRORES EN LA BASE DE

DATOS LOS VUELVE

* A ENVIAR Y LOS BORRA DE LA BASE DE DATOS

*/

//TODO

}

Es el Worker notificado cuando se tiene conectividad con el SIB. La clase abstracta de la que

extendemos se encargará de recuperar todos los mensajes que han fallado al ser enviados y

volver a intentar su envío.

public void onEvent(final Event<SibMessage> event) throws Exception{

try{

persistence.getTransactionManager().callInTransaction(new Callable<Void>()

{

public Void call() throws Exception {

List<Table> tables = persistence.findAll();

for (Table table : tables){

kPWorkerCfg.publish(SensorEvents.DATA_TO_SEND.name(),

SSAPMessage.fromJsonToSSAPMessage(table.getSsapMesssage()));

}

return null;

}

});

}catch (Exception e){

e.printStackTrace();

}

connected(event.getSource());

}

5.4.2.6 NoConnection.

@Component

public class NoConnection extends NoConnectionToSIBWorkerImpl {

@Override

public void noConnected(ErrorMessage error) {

/*

* METODO QUE ES EJECUTADO CUANDO NO DE PUEDE CONECTAR CON EL SIB

*/

//TODO

}

}

Es el Worker notificado cuando no se tiene Conectividad con el SIB, este evento provoca

también ErrorSendToSib.

5.4.2.7 ErrorSendToSib.

@Component

public class ErrorSendToSib extends ErrorSendToSIBWorkerImpl {

@Override

public MonitoringMessage toMonitoring(ErrorMessage error) {

/*

* METODO QUE ES EJECUTADO CUANDO SE HAN ENVIADO DATOS AL SIB Y SE PRODUCE UN

ERROR EN EL ENVIO

* ESTE METODO TRANSFORMA EL MENSAJE ERRORMESSAGE error EN UN MENSAJE

Page 46: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 46/76

MonitoringMessage QUE SERA

* INTERCEPTADO POR LA CLASE Monitoring

*

* SI EL MENSAJE DEVUELTO ES DISTINTO DE NULL PUBLICA

publish(InfraestructureEvents.MONITORING.name(), monitoringMessage);

*/

//TODO

return new MonitoringMessage(error);

}

@Override

public void onError(ErrorMessage error) {

/*

* METODO QUE ES EJECUTADO CUANDO SE HAN ENVIADO DATOS AL SIB Y SE PRODUCE UN

ERROR EN EL ENVIO

* ANTES DE EJECUTAR ESTE METODO DE FORMA AUTOMATICA SE ALMACENA EL SSAP ENVIADO

EN LA BASE DE DATOS

* CONFIGURADA PARA SU POSTERIOR REENVIO

*

* ESTE METODO PODRIA A PARTE DE ESCRIBIR EL LOG ADECUADO ELIMINAR DE LA BASE DE

DATOS EL SSAP SI SE DETECTA

* QUE LO HA PROVOCADO UN ERROR SEMANTICO O SINTACTICO

*/

//TODO

}

}

Es el Worker notificado cuando no se produce un error en el envío de un SSAP al SIB, los

métodos que debemos implementar reciben parámetros de tipo ErrorMessage.

public class ErrorMessage extends Exception{

/**

*

*/

private static final long serialVersionUID = -8835699096763715136L;

private SSAPMessage ssapRequestMessage;

private SSAPMessage ssapResponseMessage;

private Throwable exception;

Este tipo de objetos pueden contienen el mensaje enviado al SIB, la respuesta del SIB y la

excepción originada.

IMPORTANTE

No todos los atributos tiene por que estar informados, si se produce un error antes de

preparar el mensaje a enviar únicamente tendremos la excepción que lo ha originado.

La clase abstracta de la que extendemos se encargará de almacenar el Mensaje SSAP en la

base de datos para su posterior envío al SIB.

public void onEvent(final Event<ErrorMessage> event) throws Exception{

persistence.getTransactionManager().callInTransaction(new Callable<Void>() {

public Void call() throws Exception {

Table table = new

Table(event.getSource().getSsapRequestMessage().toJson());

persistence.create(table);

return null;

}

});

onError(event.getSource());

MonitoringMessage monitoringMessage = toMonitoring(event.getSource());

if (monitoringMessage!=null){

kPWorkerCfg.publish(InfraestructureEvents.MONITORING.name(),

Page 47: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 47/76

monitoringMessage);

}

}

5.4.2.8 StopApp.

@Component

public class StopApp extends StopAppWorkerImpl {

@Autowired

private KPWorkerCfg cfg;

@Autowired

private PropertyPlaceHolder property;

@Override

public void stopApp(LifeCicleMessage message) {

/*

* METODO QUE ES EJECUTADO CUANDO SE SOLICITA LA DETENCION DE LA APLICACION MODELO

* EN ESTE METODO SE DEBERIA DE DETENER LA LECTURA SENSORICA Y REALIZAR LOS

PROCESOS

* ADECUADOS PARA DETENER DE FORMA SEGURA LA APLICACION

*/

//TODO

}

}

Es un Worker notificado por el KPModelo cuando se solicita la detención de una aplicación, en

el método que debemos implementar hemos de añadir las medidas necesarias para una

detención inminente de la aplicación. La clase abstracta de la que heredamos se encarga de

notificar al KPModelo que puede detener la aplicación.

public void onEvent(final Event<ErrorMessage> event) throws Exception{

persistence.getTransactionManager().callInTransaction(new Callable<Void>() {

public Void call() throws Exception {

Table table = new

Table(event.getSource().getSsapRequestMessage().toJson());

persistence.create(table);

return null;

}

});

onError(event.getSource());

MonitoringMessage monitoringMessage = toMonitoring(event.getSource());

if (monitoringMessage!=null){

kPWorkerCfg.publish(InfraestructureEvents.MONITORING.name(),

monitoringMessage);

}

}

IMPORTANTE

El resto de Clases pueden ser implementadas sin necesidad de heredar de la clase

abstracta, haciendo uso de las interfaces, Para este Worker es obligatorio que se

implemente una clase que herede de ErrorSendToSibWorkerImpl, en caso de no existir,

se utiliza la implementación por defecto del KPModelo, que directamente notifica a este

la posibilidad de detención de la aplicación.

5.4.1 Suscripción

La suscripción a eventos del SIB notificados por el SIB se realiza a través de un

encapsulamiento del mecanismo de Listener que proporciona el API Java de SOFIA2.

Page 48: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 48/76

Los Subscriptores serán los encargados de atender las notificaciones de la subscripción a la

que están asociados, para crear un subscriptor, debemos extender de la clase

com.indra.sofia2.kpmodelo.infraestructure.subscription.Subscriber.

@Component

public class SubscriptionListener extends Subscriber {

@Override

@PostConstruct

public void init() throws SubscriptionException {

/*

* METODO EN EL QUE ESTABLECEMOS QUE SUSCRIPCION ATENDERA ESTE LISTENER

subscribe(ontology, query, SSAPQueryType);

*/

//TODO

}

@Override

public void onEvent(SSAPMessage arg0) {

/*

* METODO QUE ES EJECUTADO CUANDO SE NOTIFICA LA INFORMACION A LA QUE NOS HEMOS

* SUSCRITO EN EL INIT

* DE LA CLASE

*/

//TODO

}

}

Definiremos la clase como un bean de Spring anotándola con @Component y el método init lo

anotaremos con @PostConstruct, con lo que nos aseguramos que se ejecutará cuando se

registre el Bean.

Al extender de la clase Subscriber tenemos disponibles los métodos.

void subscribe(String ontology, String query, SSAPQueryType queryType) throws

SubscriptionException

void unsubscribe() throws SubscriptionException

que nos permiten subscribirnos a una ontología y anular esa subscripción. Cuando el SIB

notifique la información referente a nuestra subscripción el método

void onEvent(SSAPMessage arg0)

recibirá el mensaje SSAP enviado por el SIB y podremos manipularlo, adicionalmente

podremos obtener la información relativa a la subscripción con el método.

SubscriptionData getSubscriptionData()

Que dispone de la siguiente estructura de información.

private String subscriptionId;

private String ontology;

private SSAPQueryType queryType;

private String query;

Page 49: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 49/76

5.4.2 Monitorización JMX

Al igual que pasa con la Suscripción, la monitorización a través de JMX implica el registro de

los MBean en el servidor de MBeans, para ello la plataforma identifica todos los Beans que

implementan la interface JmxSelfNaming y los registra como MBeans para poder explotar su

información debemos anotar los Beans con las anotaciones de Mycila JMX que se encarga de

registrar la información según nuestra parametrización en el servidor MBean.

http://code.mycila.com/jmx/#documentation

@JmxBean("com.company:type=MyService,name=main")

public final class MyService {

private String name;

@JmxField

private int internalField = 10;

@JmxProperty

public String getName() { return name; }

public void setName(String name) { this.name = name; }

@JmxMethod(parameters = {@JmxParam(value = "number", description = "put a big number please

!")})

void increment(int n) {

internalField += n;

}

}

5.4.3 Ejemplo de Uso

El Comando >sofia2 crearAppModelo crea la estructura de aplicación AppModelo con la

configuración básica y los Workers predefinidos para ser modificados por los desarrolladores.

>sofia2 crearAppModelo --id appEjemplo --paquetebase com.ejemplo

Que genera el proyecto directamente importable en eclipse.

Page 50: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 50/76

IMPORTANTE

En el fichero applicationContext.xml

<bean id="properyPlaceHolder"

class="com.indra.sofia2.kpmodelo.infraestructure.loader.PropertyPlaceHolder">

<constructor-arg value="APPEJEMPLO"/>

</bean>

En el bean properyPlaceHolder viene indicado el Identificador de la aplicación, este valor no puede

ser modificado pues es el contrato entre el KPModelo y AppModelo.

El nombre del WAR y el fichero de configuración han de ser denominados con el valor de este

identificador.

Recordar que el identificador de la aplicación es necesario en el fichero web.xml como propiedad

context-param cuando se despliegan múltiples aplicaciones

Page 51: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 51/76

6 ANEXOS

6.1 Un poco de Spring

Spring es un Framework Open Source, creado con la finalidad de facilitar el desarrollo de

aplicaciones empresariales. Spring es un contenedor ligero con soporte para aspectos y la

inyección de dependencias.

Las principales características de Spring son:

Inyección de dependencias: Spring consigue un débil acoplamiento gracias a la inyección de dependencias (DI). El contenedor inyecta las dependencias durante la instanciación de los objetos que gestiona, de ésta forma, éstos no tienen que buscar las referencias de los otros objetos que usen, por lo que se reduce el acoplamiento, facilitando el mantenimiento y las pruebas.

Orientación a aspectos: La AOP nos permite separar la lógica de negocio de los servicios de sistema transversales, tales como la auditoría, el logging y la gestión de transacciones. De esta manera, los objetos de aplicación únicamente contienen lógica de negocio, y mediante aspectos, definimos de manera externa los servicios transversales.

Contenedor: Spring es un contenedor puesto que contiene, gestiona el ciclo de vida y gestiona las configuraciones de los objetos de aplicación. Permite declarar cómo será la instanciación de un objeto (singleton, un nuevo objeto por cada llamada, etc.), la configuración de los mismos (propiedades) así como la asociación existente entre los objetos.

Framework: Spring es un Framework compuesto por diversos módulos permitiendo así la creación de aplicaciones empresariales.

No reinventar la rueda: reutilizando librerías y productos existentes.

Spring Framework está compuesto por un conjunto de 17 módulos:

Page 52: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 52/76

Core Container

Se encuentra compuesto por los módulos Core, Beans, Context y Expression Language.

o Core y Beans: son las piezas fundamentales del Framework, ya que garantizan el IoC y la inyección de dependencias.

o Context: este módulo añade soporte para la internacionalización, propagación de eventos, carga de recursos estáticos y la creación transparente de contextos.

o Expression Language: permite acceder/modificar valores de propiedades, invocar métodos, acceder al contexto de los arrays, colecciones e indexadores, operadores lógicos y aritméticos…

Data Access/Integration

Se encuentra compuesto por los módulos JDBC, ORM, OXM, JMS y Transaction.

o JDBC: facilita una capa de abstracción eliminando la necesidad de escribir y parsear códigos de error específicos por proveedor de base de datos.

o ORM: Spring ofrece un amplio soporte para el trabajo con diferentes motores de persistencia (Hibernate, TopLink, IBatis) y también para trabajar con JPA permitiendo configurar estos contenedores y su transaccionalidad desde el contexto de Spring.

o OXM: capa abstracta que facilita el mapeo entre objetos y XML usando JAXB, Castor, XMLBeans, JiBX y XStream.

o JMS: éste módulo permite las funcionalidades de envío y recepción de mensajes de Queues y Topics.

o Transaction: el módulo soporta la gestión de transacciones de manera tanto programática como declarativa (en base a configuración o anotaciones). Puede ser usado en combinación con ORM y con JDBC.

Web: Ofrece funcionalidades web tales como la subida de archivos multiparte desde formularios, la inicialización del contenedor IoC usando servlet listeners… Contiene

Page 53: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 53/76

también las partes relacionadas con el soporte de invocación remota de los servicios basados en web.

AOP

El módulo de Spring AOP ofrece una implementación de programación orientada a

aspectos (AOP Alliance-compliant), también ofrece soporte para AspectJ.

Aspects: El módulo de Spring Aspects, proporciona integración con AspectJ

Instrumentation: da soporte al Api de JMX

Test: Ofrece soporte para testar los componentes de Spring con JUnit y TestNG. También ofrece mock objects para poder probar el código de manera aislada.

6.1.1 Inyección de dependencias

Spring es un contenedor que basa su modelo de programación en el Patrón Inversion of

Control (Ioc), también llamado Inyección de Dependencias.

Este patrón permite un menor acoplamiento entre componentes de una aplicación y fomenta

así la reutilización de los mismos.

Muchas veces, un componente tiene dependencias de servicios u otros componentes, cuyos

tipos concretos son especificados en tiempo de diseño.

La solución del Patrón delega la selección de una implementación concreta de las

dependencias a un componente externo. Esto implica:

El control de cómo un objeto A obtiene la referencia de un objeto B es invertido.

El objeto A no es responsable de obtener una referencia al objeto B sino que es el Componente Externo el responsable de esto. Esta es la base del patrón IoC.

Page 54: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 54/76

Una dependencia entre un componente y otro, puede establecerse estáticamente (en tiempo

de compilación), o bien dinámicamente (en tiempo de ejecución).

Es en éste último escenario es donde cabe el concepto de inyección, y para que esto fuera

posible, debemos referenciar interfaces y no implementaciones directas.

En general, las dependencias son expresadas en términos de interfaces en lugar de clases

concretas. Esto permite un rápido reemplazo de las implementaciones dependientes sin

modificar el código fuente de la clase.

Lo que propone entonces la inyección de dependencias es no instanciar las dependencias

explícitamente en su clase, sino expresarlas declarativamente en la definición de la clase. La

esencia de la inyección de dependencias es contar con un componente capaz de obtener

instancias válidas de las dependencias de un componente, e inyectárselas durante su creación

o inicialización, para que éste pueda utilizarlas.

6.1.2 Ejemplos:

6.1.2.1 Ejemplo básico

La configuración de Spring consiste en la definición de uno o más ficheros XML que serán

administrados por el contenedor.

En nuestro ejemplo, construiremos un objeto e inyectaremos dependencias sobre él usando

Spring. El aspecto inicial del fichero de configuración “applicationContext.xml”, aún sin

contenido, será el siguiente:

Definición inicial de fichero applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

Page 55: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 55/76

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springfrmework.org/schema/beans/spring-beans-

3.0.xsd">

</beans>

A continuación crearemos la clase del componente que queremos definir. En este caso

se creará una clase llamada Connection, que será un JavaBean con tres atributos:

user, password y connectionManager. La clase queda de la siguiente manera:

Clase Connection

package springtest;

public class Connection {

private String user;

private String password;

private ConnectionManager manager;

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public String getUser() {

return user;

}

public void setUser(String user) {

this.user = user;

}

public void setConnectionManager(

ConnectionManager connectionManager) {

this.connectionManager = manager;

}

public ConnectionManager getConnectionManager() {

Page 56: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 56/76

return connectionManager;

}

}

También debemos definir el administrador de conexiones al que hace referencia esta

clase. Se trata de un JavaBean con dos atributos: host y port.

Clase ConnectionManager

package springtest;

public class ConnectionManager {

private String host;

private int port;

public String getHost() {

return host;

}

public void setHost(String host) {

this.host = host;

}

public int getPort() {

return port;

}

public void setPort(int port) {

this.port = port;

}

public String toString() {

return "ConnectionManager [host=" + host + ", port=" +

port + "]";

}

}

Page 57: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 57/76

Ahora que ya disponemos de las clases, completaremos el fichero de configuración

declarándolas como componentes, y definiendo sus dependencias. Lo primero que hay

que hacer es definir nuestros objetos como beans:

Definición de fichero applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springfrmework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="connection" class="springtest.Connection">

</bean>

<bean id="manager" class="springtest.ConnectionManager">

</bean>

</beans>

Para ello definimos en el fichero de configuración dos elementos <bean>, indicando los

atributos id y class. El atributo id servirá para definir el nombre del componente, el cual

deberá ser único. El atributo class indica el nombre cualificado de la clase

A continuación definiremos el valor de las propiedades de cada componente, creándose

de esta forma la estructura de dependencias necesaria para nuestro ejemplo.

Definición de fichero applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springfrmework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="connection" class="springtest.Connection">

<property name="user" value="Test"/>

<property name="password" value="password123"/>

<property name="connectionManager" ref="manager"/>

Page 58: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 58/76

</bean>

<bean id="manager" class="springtest.ConnectionManager">

<property name="host" value="localhost"/>

<property name="port" value="8080"/>

</bean>

</beans>

Mediante el uso de elementos <property>, definimos el valor de las propiedades de

cada uno de nuestros componentes. El atributo name indica el nombre de la propiedad.

El atributo value indica el valor de la propiedad. El atributo ref indica una referencia a

otro componente, mediante el nombre de éste.

Una vez definido el fichero de configuración, se debe utilizar una implementación de

contenedor Spring para crear la estructura de componentes. Existen varias

implementaciones disponibles. Una de ellas es

org.springframework.beans.factory.BeanFactory, que proporciona un mecanismo de

configuración avanzada capaz de manejar cualquier tipo de objeto. Otra posibilidad es

org.springframework.context.ApplicationContext, la cual agrega una integración

más fácil con algunas de las características más interesantes de Spring, como su

módulo de Programación Orientada a Aspectos, manejo de recursos de mensajes (para

la internacionalización), publicación de eventos, y contextos específicos para ciertas

capas de aplicaciones (como aplicaciones web), entre otras.

En este ejemplo usaremos ClassPathXmlApplicationContext. En este caso, el

constructor recibe una cadena (o cadenas) indicando la ubicación de este archivo (o

archivos):

Inicialización de contenedor Spring

ApplicationContext context = new

ClassPathXmlApplicationContext("/springtest/applicationContext.xml");

Con este ApplicationContext creado, y que representa el contenedor de componentes,

ahora podemos recuperar el componente que necesitemos, usando el método getBean:

Obtención de beans del contenedor

Connection connection = context.getBean(Connection.class);

Page 59: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 59/76

Y teniendo la instancia de Connection, proporcionada por el contenedor, se puede

hacer uso normal de sus métodos:

Utilización de beans obtenidos del contenedor

System.out.println("El nombre de usuario es: " +

connection.getUser());

A continuación se muestra la clase que instancia el contenedor Spring y que muestra los datos

en consola para comprobar que efectivamente nuestro objeto ha sido inyectado con sus

dependencias:

Ejemplo completo

package springtest;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

public static void main(String[] args) {

// crea el contenedor

ApplicationContext context = new

ClassPathXmlApplicationContext(

"/springtest/applicationContext.xml");

// obtiene el bean con sus dependecias ya inyectadas

Connection connection = context.getBean(Connection.class);

// muestra en consola los datos

System.out.println("El nombre de usuario es : " +

connection.getUser());

System.out.println("El password es: " +

connection.getPassword());

System.out.println("El manager es: " +

connection.getConnectionManager());

}

}

Page 60: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 60/76

Ahora si ejecutamos el proyecto podremos ver en consola los resultados:

Resultado de ejecución

El nombre de usuario es: Test

El password es: password123

El manager es: ConnectionManager[host=localhost, port=8080]

6.1.2.2 Ejemplo basado en anotaciones

Spring también permite definir componentes y dependencias mediante el uso de anotaciones.

En el próximo ejemplo definiremos un componente que realizará la función de observable, así

como otros dos componentes que actuarán como observadores.

En primer lugar, debemos habilitar el uso de anotaciones en el fichero XML de definición de

contexto, applicationContext.xml:

Definición de fichero applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:context="http://www.springframework.org/schema/context"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springfrmework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:component-scan base-package="springtest"/>

</beans>

Mediante el elemento <context:component-scan> indicaremos a Spring que, en tiempo de

creación del contenedor, busque componentes escaneando las clases del classpath de la

aplicación, que estén ubicadas bajo el paquete indicado en el atributo base-package. La

manera en que Spring identifica que debe instanciar un componente es mediante la anotación

@Component en la clase Java que implementa éste.

Page 61: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 61/76

De esta forma, no tendremos que definir nuestros componentes en el fichero

applicationContext.xml, aunque si queremos hacerlo, también es posible combinar las dos

formas de definir componentes.

Una vez habilitada la definición de componentes mediante anotaciones, vamos a definir el

código de las clases que necesitamos para continuar con nuestro ejemplo. En primer lugar

definiremos una clase que modelará un Evento, que el Observador enviará a cada uno de los

Observables:

Evento.java

package springtest;

import java.util.Date;

public class Evento {

public Date fecha;

public Object datos;

public Evento(Object datos) {

this.fecha = new Date();

this.datos = datos;

}

public Date getFecha() {

return fecha;

}

public Object getDatos() {

return datos;

}

@Override

public String toString() {

return "Evento [fecha=" + fecha + ", datos=" + datos + "]";

}

}

A continuación crearemos un interfaz que nos permitirá definir distintos Observadores:

Observador.java

package springtest;

public interface Observador {

public void notificar(Evento e);

Page 62: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 62/76

}

El paso siguiente será definir el Observable:

Observable.java

package springtest;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Component;

@Component

public class Observable {

@Autowired

private List<Observador> observadores;

public void notificar(Evento e) {

if ( observadores == null ) return;

for ( Observador observador : observadores ) {

observador.notificar(e);

}

}

}

Observamos que la clase está decorada con la anotación @Component. Cuando se

inicie nuestro contenedor Spring, se creará una instancia de esta clase y se definirá

como componente. El identificador de este componente será observable (generado

automáticamente a partir del nombre de la clase), aunque también podemos definir el

identificador especificándolo en la anotación.

Como podemos observar, la clase dispone de un atributo decorado con @Autowired, y

ya no dispone de métodos get y set, puesto que trabajando con anotaciones ya no son

imprescindibles. La anotación @Autowired sirve para indicar a Spring que el valor del

atributo es una dependencia que Spring deberá resolver automáticamente. En nuestro

caso, el atributo es una lista de Observadores, por lo que Spring deberá buscar todos

los componentes que implementen este interfaz, insertarlos en una lista, e inyectar

dicha lista sobre el atributo. El método notificar recibirá un evento que será entregado a

todos y cada uno de los observadores que se encuentren en la lista.

Page 63: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 63/76

Cuando Spring resuelve dependencias automáticamente, puede seguir varias

estrategias. Una de ellas consiste en buscar componentes cuyo nombre sea igual al

nombre del atributo decorado con @Autowired. Otra de ellas es buscar componentes

cuyo tipo de datos sea asignable al tipo de datos del atributo. Si no se encuentra ningún

componente para una dependencia, Spring lanzará una excepción.

A continuación definiremos dos implementaciones de Observador:

ObservadorSystemOut y ObservadorSystemErr. El primero de ellos escribirá el

evento recibido en la salida estándar. El segundo, lo escribirá en la salida de error.

ObservadorSystemOut.java

package springtest;

import org.springframework.stereotype.Component;

@Component

public class ObservadorSystemOut implements Observador {

@Override

public void notificar(Evento e) {

System.out.println(e);

}

}

ObservadorSystemErr.java

package springtest;

import org.springframework.stereotype.Component;

@Component

public class ObservadorSystemErr implements Observador {

@Override

public void notificar(Evento e) {

System.err.println(e);

}

}

Ambas clases están decoradas con la anotación @Component, con lo que se definirá

un componente de cada una de las dos clases en tiempo de arranque del contenedor.

Page 64: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 64/76

Finalmente ya solo restaría arrancar el contenedor, obtener el componente observable

e invocar su método notificar, entregando como argumento un determinado evento. Al

hacerlo, se escribirá tanto por la salida estándar como por la salida de error el resultado

de invocar el método toString del evento entregado.

6.1.3 Ámbito de un Bean

Por defecto, los beans definidos en Spring son Singleton, es decir que siempre devuelven la

misma instancia del bean. Sin embargo, Spring define otros posibles ámbitos:

Ámbito Qué hace

Singleton Extiende la definición del bean a una única instancia por contexto de

Spring

Prototype Permite a un bean ser instanciado un número de veces N (una por uso)

request Extiende la definición del bean a un http request (sólo válido para contexto

web de Spring como Spring MVC)

Session Extiende la definición de un bean a una sesión HTTP (sólo válido para

contexto web de Spring como Spring MVC)

Global-session Extiende la definición de un bean a una sesión HTTP global (sólo válido

cuando se usa un contexto de portlets).

Para especificar el ámbito en la definición del componente mediante fichero XML, se ha de

utilizar el atributo scope:

Definición del ámbito de un componente en XML

<bean id="miBean1"

class="com.bbva.arqspring.ejemplos.MiBean1"

scope="prototype"/>

Para especificar el ámbito en la definición del componente mediante anotaciones, se ha de

utilizar la anotación @Scope. El ámbito singleton es el ámbito por defecto, de modo que si no

se indica esta anotación, nuestro componente será un singleton:

Page 65: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 65/76

Definición del ámbito de un componente mediante anotaciones

@Component

@Scope("session")

public class Componente {

}

6.1.4 Aplicando aspectos

La Inyección de dependencias permite descoplar el interfaz de la implementación.

La Programación orientada a aspectos se define a menudo como una técnica de programación

que promueve la separación de conceptos dentro de un sistema de software.

Los sistemas están compuestos de varios componentes, cada uno responsable de una parte

específica de la funcionalidad. A menudo estos componentes también tienen la responsabilidad

adicional más allá de su núcleo funcionalidad.

Sistema de servicios transversales tales como el logging, la gestión de transacciones y la

seguridad a menudo están distribuidos por los componentes.

AOP permite modularizar estos servicios y declarar a que componentes que afectar.

En Spring se define de esta forma:

En la configuración Spring añado el soporte:

Declaro en la clase que es una Aspecto con:

Page 66: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 66/76

Declaro un PointCut: es decir qué métodos voy a interceptar

Un Aspecto interesante podría ser este, que detectaría en qué capa estamos:

6.1.5 Ecosistema/Portfolio Spring

Spring ofrece un completo ecosistema de soluciones. Este portfolio abarca varias frameworks y

bibliotecas que se basan en el núcleo de Spring Framework. En conjunto, el ecosistema de

Spring constituye un marco para casi todas las facetas del desarrollo Java.

Spring Web Flow: permite modelar flujos de navegación en aplicaciones Web.

Page 67: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 67/76

Spring Security: es un proveedor de seguridad que permite la autenticación y la autorización de los usuarios, es independiente del Servidor de aplicaciones, fácilmente ampliable y con soporte para CAS, OpenID, certificados…

Spring Batch: es el framework para procesamiento de lotes, provee servicios comunes para los programas Batch.

Spring Integration: es una extensión para soportar los Patrones de Integración Corporativos Permite integrar con sistemas externos a través de adaptadores.

Spring Social: facilita el desarrollo de aplicaciones con soporte para las redes sociales, con Twitter y Facebook, utilizando OAuth (con Spring Security Oauth).

Spring Mobile: es una extensión de Spring MVC, para desarrollar aplicaciones web para móviles.

Spring AMQP, Spring Data, Spring GemFire, Spring .Net,…

6.1.6 Enlaces de referencia

Sitio oficial: http://www.springsource.org/

Documentación de Referencia: http://www.springsource.org/documentation

6.2 Un poco de Maven

Maven es básicamente una herramienta para la gestión y construcción de proyectos y puede

verse como la evolución de Ant.

6.2.1 Conceptos básicos

Un artefacto es un componente que se puede incluir en un proyecto como dependencia, pero también se le llama por el mismo nombre al componente generado por esta herramienta (jar, war, ear).

Un grupo es un conjunto de artefactos. Los grupos se usan para organizar los diferentes artefactos disponibles.

El scope indica el alcance de la dependencia, y puede ser de los siguientes tipos:

o Compile: La dependencia es necesaria a la hora de compilar y ésta se propaga a los proyectos dependientes. Esta opción es la que viene por defecto si no se especifica el scope.

o Provided: Esta dependencia no es transitiva y es necesaria para compilar, pero en este caso se espera que en el proyecto ya esté el JDK o el contenedor que provea la dependencia. Esta opción es aconsejable en proyectos en los que se usen muchas librerías.

o Runtime: La dependencia no es necesaria a la hora de compilar, pero sí lo es en tiempo de ejecución.

o Test: La dependencia no es necesaria para el uso normal de la aplicación, pero si lo es para las fases de compilación y ejecución de los tests.

o System: Este scope es similar al de provided, excepto porque se tiene que proveer el contenedor que contenga explícitamente. El artefacto siempre está disponible y no se busca en el repositorio.

Un archetype (arquetipo) es una plantilla que es necesaria especificar cuando se crea un proyecto. Este arquetipo crea la estructura del proyecto.

Page 68: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 68/76

6.2.2 Ciclo de vida

Las partes del ciclo de vida principal del proyecto Maven son:

compile

test

package

install

deploy

La idea es que, para cualquier meta, todas las metas anteriores han sido completadas

satisfactoriamente

Por ejemplo, cuando se ejecuta mvn install Maven verificará si mvn package ha sido ejecutado

exitosamente (el archivo jar existe en target/), en cuyo caso no será ejecutado otra vez.

También existen algunas metas que están fuera del ciclo de vida que pueden ser llamadas,

pero Maven asume que estas metas no son parte del ciclo de vida por defecto (no tienen que

ser siempre realizadas). Estas metas son:

1. clean

2. assembly:assembly

3. site

4. site-deploy

5. etc.

Pero estas metas pueden ser añadidas al ciclo de vida a través del Project Object Model

(POM).

6.2.3 Características

El modelo de objetos del proyecto POM (pom.xml) es la base de cómo Maven trabaja. El desarrollo y gestión del modelo está controlado desde el modelo del proyecto.

Page 69: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 69/76

En el pom.xml se define toda la metainformación necesaria para el proyecto (nombre del artefacto a generar, rutas fuentes, JDK de compilación, dependencias,…):

o Nombre y versión de artefacto a generar

o Dependencias:

o Versión JDK compilación:

Maven tiene un funcionamiento basado en Repositorios. Los Repositorios son Servidores (en general Servidores Web) en los que están accesibles las diferentes versiones de las librerías organizadas jerárquicamente. Ejemplo:

Maven contempla 2 tipos de Repositorios:

Page 70: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 70/76

o Remotos: existen repositorios públicos de Maven (como http://maven.springframework.org/release) que contienen las diferentes versiones

de las librerías.

o Local: contiene una copia de la parte del Repositorio remoto necesaria para trabajar con las aplicaciones en una estructura local (en la Arquitectura en w:\SOFTWARE\Maven\M2_REPO\)

Los Repositorios remotos que se usan en una aplicación se definen en el pom.xml del proyecto. A la hora de realizar una tarea sobre un proyecto (compilar, ejecutar tests,…) se busca en estos repositorios de forma secuencial.

Al realizar una tarea de Maven (mvn install por ejemplo) se descargan al repositorio local las dependencias necesarias desde los repositorios remotos para funcionar. Ejemplo:

Estructura estándar de todos los proyectos, por ejemplo, para una estructura de un módulo WAR, la configuración sería:

Está listo para ser utilizado en red. Uso de repositorios centrales de librerías, utilizando un mecanismo que permite descargar automáticamente aquellas necesarias en el proyecto, lo que permite a los usuarios de Maven reutilizar librerías entre proyectos y facilita la comunicación entre proyectos para asegurar que la compatibilidad entre distintas versiones es correctamente tratada.

Maven provee soporte no sólo para obtener archivos de su repositorio, sino también para subir artefactos al repositorio al final de la construcción de la aplicación, dejándola

Page 71: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 71/76

al acceso de todos los usuarios. Una caché local de artefactos actúa como la primera fuente para sincronizar la salida de los proyectos a un sistema local.

Maven está construido usando una arquitectura basada en plugins que permite que utilice cualquier aplicación controlable a través de la entrada estándar. En teoría, esto podría permitir a cualquiera escribir plugins para su interfaz con herramientas como compiladores, herramientas de pruebas unitarias, etcétera, para cualquier otro lenguaje

6.2.4 Ejemplo de uso

Vamos a crear un proyecto Java, compilarlo, chequearlo, empaquetarlo y subirlo al repositorio.

Dicho proyecto va a ser creado con el siguiente arquetipo en la línea de comandos:

mvn archetype:generate -

DarchetypeGroupId=org.apache.maven.archetypes -

DgroupId=com.mycompany.app -DartifactId=my-app

Éste es un comando interactivo, por lo que Maven nos pedirá cierta información antes de crear

la estructura del proyecto. A continuación se muestran las trazas generadas:

...

Choose a number: 112: 112

Choose version:

1: 1.0-alpha-1

2: 1.0-alpha-2

3: 1.0-alpha-3

4: 1.0-alpha-4

5: 1.0

6: 1.1

Choose a number: 6: 6

[INFO] Using property: groupId = com.mycompany.app

[INFO] Using property: artifactId = my-app

Define value for property 'version': 1.0-SNAPSHOT:

[INFO] Using property: package = com.mycompany.app

Confirm properties configuration:

groupId: com.mycompany.app

artifactId: my-app

version: 1.0-SNAPSHOT

package: com.mycompany.app

Y: Y

[INFO] -------------------------------------------------------------------------

[INFO] Using following parameters for creating project from Old (1.x) Archetype:

maven-archetype-quickstart:1.1

[INFO] -------------------------------------------------------------------------

[INFO] Parameter: groupId, Value: com.mycompany.app

[INFO] Parameter: packageName, Value: com.mycompany.app

[INFO] Parameter: package, Value: com.mycompany.app

[INFO] Parameter: artifactId, Value: my-app

[INFO] Parameter: basedir, Value: W:\DESARROLLO\prueba

[INFO] Parameter: version, Value: 1.0-SNAPSHOT

[INFO] ********************* End of debug info from resources from generated POM

***********************

[INFO] project created from Old (1.x) Archetype in dir: W:\DESARROLLO\MavenDemo\my-app

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESSFUL

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 1 minute 46 seconds

Page 72: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 72/76

[INFO] Finished at: Wed Jul 27 10:33:36 CEST 2011

[INFO] Final Memory: 11M/28M

[INFO] ------------------------------------------------------------------------

Maven habrá creado un directorio my-app, y este directorio contendrá un fichero pom.xml:

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0

http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.mycompany.app</groupId>

<artifactId>my-app</artifactId>

<version>1.0-SNAPSHOT</version>

<packaging>jar</packaging>

<name>my-app</name>

<url>http://maven.apache.org</url>

<properties>

<project.build.sourceEncoding>UTF-

8</project.build.sourceEncoding>

</properties>

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>3.8.1</version>

<scope>test</scope>

</dependency>

</dependencies>

</project>

La estructura de ficheros generada será la siguiente:

my-app

|-- pom.xml

`-- src

|-- main

| `-- java

| `-- com

| `-- mycompany

| `-- app

| `-- App.java

`-- test

`-- java

`-- com

`-- mycompany

`-- app

`-- AppTest.java

Page 73: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 73/76

En la cual se nos habrán generado dos clases:

Una principal: App.java

Una de prueba de JUnit: AppTest.java

Una vez que se hayan modificado las clases (en este caso maven ha creado un ejemplo

básico, por lo que no es necesario modificar el código), se pueden compilar y ejecutar las

pruebas con el siguiente comando desde el directorio my-app que ha creado:

mvn test-compile

Y posteriormente empaquetarlo en un jar y subirlo al repositorio:

mvn package

mvn install

El comando “mvn install” instala el artefacto creado en el repositorio local de la máquina. El

comando copia tanto el jar como el pom a nuestro repositorio.

Al instalar el artefacto en el repositorio local, este proyecto está disponible para incluirlo como

dependencia en otro proyecto maven, mejorando así la portabilidad y modularidad de los

proyectos creados.

6.2.5 Enlaces de referencia:

Sitio oficial: http://maven.apache.org

Tutorial en Castellano: http://login.osirislms.com/offline/maven

Tutorial en castellano: http://www.juntadeandalucia.es/xwiki/bin/view/MADEJA/Maven2

6.3 Un poco de JUnit

JUnit es un Framework de pruebas que usa anotaciones para identificar los métodos que

contienen pruebas.

Para escribir un test con JUnit deberemos anotar un método con la anotación @Test

y deberemos usar un método proporcionado por JUnit para poder evaluar si el

funcionamiento de cada uno de los métodos de la clase se comporta como se espera.

En función de algún valor de entrada se evalúa el valor de retorno esperado; si la clase cumple con la especificación, entonces JUnit devolverá que el método de la

clase pasó exitosamente la prueba; en caso de que el valor esperado sea diferente

Page 74: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 74/76

al que regresó el método durante la ejecución, JUnit devolverá un fallo en el método

correspondiente.

Permite la ejecución de dos o más test que pueden ejecutarse sobre el mismo o similar conjunto de datos.

Permita la ejecución de test y recolectar sus resultados.

JUnit es también un medio de controlar las pruebas de regresión, necesarias cuando una parte

del código ha sido modificado y se desea ver que el nuevo código cumple con los

requerimientos anteriores y que no se ha alterado su funcionalidad después de la nueva

modificación.

Las siguientes anotaciones están presentes en JUnit 4.x:

Anotacion Descripción

@Test public void method() La annotation @Test identifica que este

método es un método de prueba.

@Before public void method() Ejecutara el método antes de cada

prueba.

@After public void method() Ejecutara el método después de cada

prueba

@BeforeClass public void method() Ejecutará el método antes del comienzo

de todas las pruebas

@AfterClass public void method() Ejecutará el método después de haber

ejecutado todas las pruebas.

@Ignore Se ignorará este método en la

ejecución de las pruebas

@Test(expected=IllegalArgumentException.class) Comprueba si el método lanza la

excepción especificada.

@Test(timeout=100) Falla si el método tarda más de los

milisegundos indicados.

Aquí pasamos a resumir algunos métodos de pruebas:

Anotacion Descripción

Page 75: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 75/76

fail(String) La comprobación falla con el texto de salida

indicado.

assertTrue(true); True

assertsEquals([String message], expected,

actual)

Comprueba si los valores son los mismos.

assertsEquals([String message], expected,

actual, tolerance)

Mismo que el anterior pero para los tipos float

y double.

assertNull([message], object) Comprueba si el objeto es null.

assertNotNull([message], object) Comprueba si el objeto no es null.

assertSame([String], expected, actual) Comprueba si ambas variables se refieren al

mismo objeto.

assertNotSame([String], expected, actual) Comprueba si ambas variables no se refieren

al mismo objeto.

assertTrue([message], boolean condition) Comprueba si la condición es verdadera.

Las herramientas de desarrollo como Eclipse cuentan con plug-ins que permiten ejecutar de

forma gráfica test unitarios.

6.3.1 Ejemplo

Suponiendo que nos hemos creado una clase que contiene un método que se encarga de

multiplicar dos números:

package com.bbva.ejemplos;

public class MyClass {

public int multiply(int x, int y) {

return x / y;

}

}

Para comprobar que realmente el método multiplicador realiza correctamente la operación,

vamos a ejecutar una prueba, en la cual vamos a multiplicar 10 x 5 y vamos a evaluar que el

resultado sea 50. Dicha clase de prueba con JUnit sería la siguiente:

Page 76: HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Herramientas de Productividad SOFIA SDK Página 76/76

package com.bbva.ejemplos;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class MyClassTest {

@Test

public void testMultiply() {

MyClass tester = new MyClass();

assertEquals("Result", 50, tester.multiply(10, 5));

}

}

Alrededor de JUnit han surgido una serie de librerías especializadas en un tipo de Test

especiales:

DBUnit: permite realizar tests sobre bases de datos, insertando datos antes de la ejecución de los tests y comprobando los datos tras ella. También permite importar y exportar los datos desde y hacia ficheros xml o xls (Excel).

JMock: Librería que permite realizar tests utilizando objetos simulados (mock objects) dinámicos. El objetivo es aislar los objetos que se testean sustituyendo los objetos con los que se relacionan por objetos simulados en los que podemos definir su estado y los resultados de los métodos.

6.3.2 Enlaces de referencia

Sitio oficial: http://www.junit.org/

Tutorial en Ingles: http://www.vogella.de/articles/JUnit/article.html

Libro: http://java.sun.com/developer/Books/javaprogramming/ant/ant_chap04.pdf

Sitio oficial DBUnit: http://www.dbunit.org/

Tutorial DBUnit: http://www.oreillynet.com/onjava/blog/2005/10/dbunit_made_easy.html

Sitio oficial JMock: http://www.jmock.org/

Tutorial JMock: http://www.jmock.org/cookbook.html