Download HERRAMIENTAS DE PRODUCTIVIDAD SOFIA2 SDK

Document related concepts
no text concepts found
Transcript
HERRAMIENTAS DE
PRODUCTIVIDAD
SOFIA2 SDK
JULIO 2014
Versión 3
1 INDICE
1
INDICE ............................................................................................................................................ 2
2
INTRODUCCIÓN .............................................................................................................................. 4
3
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
SOFIA2-CONSOLE: CREACIÓN DE KPS ............................................................................................. 7
3.1
COMANDO SOFIA2 CREARKP .................................................................................................. 7
3.2
COMANDO PARA GENERAR KP JAVA ........................................................................................ 8
3.2.1
3.3
COMANDO PARA GENERAR KP JAVASCRIPT ............................................................................. 12
3.3.1
3.4
Ejemplo de uso ....................................................................................................... 14
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
5
Ejemplo de uso ....................................................................................................... 12
COMANDO PARA GENERAR KP ARDUINO ............................................................................... 14
3.4.1
4
Ejemplo de uso ......................................................................................................... 9
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
KPS JAVA GESTIONADOS .............................................................................................................. 35
5.1
CONCEPTOS ...................................................................................................................... 35
5.2
LÓGICA DE FUNCIONAMIENTO .............................................................................................. 35
5.3
LANZADOR KPS .................................................................................................................. 36
Herramientas de Productividad SOFIA SDK
Página 2/76
5.3.1
5.4
6
El Lanzador de KP´s en Ejecución. .......................................................................... 38
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
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
Herramientas de Productividad SOFIA SDK
Página 3/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:
Herramientas de Productividad SOFIA SDK
Página 4/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 SOFIA2SDK.
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
Herramientas de Productividad SOFIA SDK
Página 5/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
Herramientas de Productividad SOFIA SDK
Página 6/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”
Herramientas de Productividad SOFIA SDK
Página 7/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:
Herramientas de Productividad SOFIA SDK
Página 8/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
Herramientas de Productividad SOFIA SDK
Página 9/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:
Herramientas de Productividad SOFIA SDK
Página 10/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.
Herramientas de Productividad SOFIA SDK
Página 11/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:
Herramientas de Productividad SOFIA SDK
Página 12/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.
Herramientas de Productividad SOFIA SDK
Página 13/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:
Herramientas de Productividad SOFIA SDK
Página 14/76

Creamos un directorio, “KPArduino”.

Abrimos la consola en ese directorio con \ArqSpring.bat

Lanzamos el comando:
sofia2
crearKp
--nombreKp
KPArduino
d9e77d01d3c84f96994bfdcd428faa97
--instancia
--tipoKp
ARDUINO
--token
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.
Herramientas de Productividad SOFIA SDK
Página 15/76
Se incluye también los esqueletos con la operativa:
Herramientas de Productividad SOFIA SDK
Página 16/76
Herramientas de Productividad SOFIA SDK
Página 17/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)
Herramientas de Productividad SOFIA SDK
Página 18/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.
Herramientas de Productividad SOFIA SDK
Página 19/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
Herramientas de Productividad SOFIA SDK
Página 20/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.
Herramientas de Productividad SOFIA SDK
Página 21/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({
Herramientas de Productividad SOFIA SDK
Página 22/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.
Herramientas de Productividad SOFIA SDK
Página 23/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:
Herramientas de Productividad SOFIA SDK
Página 24/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:
Herramientas de Productividad SOFIA SDK
Página 25/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á:
Herramientas de Productividad SOFIA SDK
Página 26/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
Herramientas de Productividad SOFIA SDK
Página 27/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.
Herramientas de Productividad SOFIA SDK
Página 28/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.
Herramientas de Productividad SOFIA SDK
Página 29/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.
Herramientas de Productividad SOFIA SDK
Página 30/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.
Herramientas de Productividad SOFIA SDK
Página 31/76
public
final
packageName,
static
String
void
jsonToJava(String
fileJson,
String
outputdirectory,
className)throws
String
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.
Herramientas de Productividad SOFIA SDK
Página 32/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.
Herramientas de Productividad SOFIA SDK
Página 33/76
Herramientas de Productividad SOFIA SDK
Página 34/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
Herramientas de Productividad SOFIA SDK
Página 35/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.
Herramientas de Productividad SOFIA SDK
Página 36/76
SW_RUTA
Ruta
donde
se
almacenarán
los
almacenará
el
WAR
del
las
properties
de
AppModelo
CONF_RUTA
Ruta
donde
se
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.
Herramientas de Productividad SOFIA SDK
Página 37/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.
Herramientas de Productividad SOFIA SDK
Página 38/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.
Herramientas de Productividad SOFIA SDK
Página 39/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.
Herramientas de Productividad SOFIA SDK
Página 40/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.
Herramientas de Productividad SOFIA SDK
Página 41/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.
Herramientas de Productividad SOFIA SDK
Página 42/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;
Herramientas de Productividad SOFIA SDK
Página 43/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());
Herramientas de Productividad SOFIA SDK
Página 44/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
Herramientas de Productividad SOFIA SDK
Página 45/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(),
Herramientas de Productividad SOFIA SDK
Página 46/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.
Herramientas de Productividad SOFIA SDK
Página 47/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
private
private
private
String subscriptionId;
String ontology;
SSAPQueryType queryType;
String query;
Herramientas de Productividad SOFIA SDK
Página 48/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.
Herramientas de Productividad SOFIA SDK
Página 49/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
Herramientas de Productividad SOFIA SDK
Página 50/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:
Herramientas de Productividad SOFIA SDK
Página 51/76

Core Container
Se encuentra compuesto por los módulos Core, Beans, Context y Expression Language.
o
o
o

Core y Beans: son las piezas fundamentales del Framework, ya que garantizan
el IoC y la inyección de dependencias.
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.
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
Herramientas de Productividad SOFIA SDK
Página 52/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.
Herramientas de Productividad SOFIA SDK
Página 53/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"
Herramientas de Productividad SOFIA SDK
Página 54/76
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springfrmework.org/schema/beans/spring-beans3.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() {
Herramientas de Productividad SOFIA SDK
Página 55/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 + "]";
}
}
Herramientas de Productividad SOFIA SDK
Página 56/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"/>
Herramientas de Productividad SOFIA SDK
Página 57/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);
Herramientas de Productividad SOFIA SDK
Página 58/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());
}
}
Herramientas de Productividad SOFIA SDK
Página 59/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.
Herramientas de Productividad SOFIA SDK
Página 60/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);
Herramientas de Productividad SOFIA SDK
Página 61/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.
Herramientas de Productividad SOFIA SDK
Página 62/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.
Herramientas de Productividad SOFIA SDK
Página 63/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:
Herramientas de Productividad SOFIA SDK
Página 64/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:
Herramientas de Productividad SOFIA SDK
Página 65/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.
Herramientas de Productividad SOFIA SDK
Página 66/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.
Herramientas de Productividad SOFIA SDK
Página 67/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.
Herramientas de Productividad SOFIA SDK
Página 68/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:
Herramientas de Productividad SOFIA SDK
Página 69/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

Herramientas de Productividad SOFIA SDK
Página 70/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
Herramientas de Productividad SOFIA SDK
Página 71/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>UTF8</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
Herramientas de Productividad SOFIA SDK
Página 72/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:
6.3

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
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
Herramientas de Productividad SOFIA SDK
Página 73/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
Herramientas de Productividad SOFIA SDK
Descripción
Página 74/76
fail(String)
La comprobación falla con el texto de salida
indicado.
assertTrue(true);
True
assertsEquals([String message], expected, Comprueba si los valores son los mismos.
actual)
assertsEquals([String message], expected, Mismo que el anterior pero para los tipos float
actual, tolerance)
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:
Herramientas de Productividad SOFIA SDK
Página 75/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
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
Herramientas de Productividad SOFIA SDK
Página 76/76
DBUnit: