INFRAESTRUCTURA KP JAVA GESTIONADO (KP MODELO) SEPTIEMBRE 2014 Versión 2 (27-08-2014) KPs Java Gestionados Página 2/35 1 INDICE 1 INDICE ............................................................................................................................................ 3 2 INTRODUCCIÓN .............................................................................................................................. 5 2.1 3 OBJETIVOS Y ALCANCE DEL PRESENTE DOCUMENTO .................................................................... 5 KPS JAVA GESTIONADOS ................................................................................................................ 6 3.1 CONCEPTOS ........................................................................................................................ 6 3.2 LÓGICA DE FUNCIONAMIENTO ................................................................................................ 6 3.3 LANZADOR KPS.................................................................................................................... 7 3.3.1 3.4 4 El Lanzador de KP´s en Ejecución. ............................................................................ 8 APP MODELO (KP MODELO) ................................................................................................ 9 3.4.1 Eventos ................................................................................................................... 11 3.4.2 Workers .................................................................................................................. 12 3.4.1 Suscripción ............................................................................................................. 19 3.4.2 Monitorización JMX ............................................................................................... 20 3.4.3 Ejemplo de Uso ...................................................................................................... 20 EJEMPLO FUNCIONAMIENTO APP MODELO ................................................................................. 22 4.1 ESTRUCTURA Y CONFIGURACION........................................................................................... 22 4.2 LANZAMIENTO ................................................................................................................... 25 4.3 COMPILACIÓN DE LOS FUENTES ............................................................................................ 27 4.4 ORGANIZACIÓN DE LAS CLASES ............................................................................................. 28 4.4.1 Workers StartApp y APPStop ................................................................................. 28 4.4.2 Worker DataInputLoop .......................................................................................... 30 4.4.3 Worker PrepareMessageToSend ........................................................................... 30 4.4.4 Worker SendServiceWrapper................................................................................. 31 4.4.5 Workers DataSendToSib y ErrorSendToSib ............................................................ 32 4.4.6 Worker SubscriptionListener ................................................................................. 32 4.4.7 Worker Connection ................................................................................................ 33 KPs Java Gestionados Página 3/35 5 4.4.8 Worker NoConnection ........................................................................................... 33 4.4.9 Worker Monitoring ................................................................................................ 34 4.4.10 Clases paquete negocio.......................................................................................... 34 ANEXOS ........................................................................................................................................ 35 5.1 INSTALACIÓN DEL SDK DE SOFIA2 (SOFIA2-SDK) .................................................................. 35 KPs Java Gestionados Página 4/35 2 INTRODUCCIÓN 2.1 Objetivos y alcance del presente documento El objetivo de este documento es describir el concepto de KP Modelo (Infraestructura de KP Java gestionado) así como explicar su funcionamiento a través de un ejemplo de uso. KPs Java Gestionados Página 5/35 3 KPS JAVA GESTIONADOS 3.1 Conceptos Lanzador KPs: Es la plataforma de ejecución de los KP´s Autogestionados, incluye un Servidor Lanzador KPs 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. 3.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 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. KPs Java Gestionados Página 6/35 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. 3.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. SW_RUTA Ruta donde se almacenarán los WAR del las AppModelo CONF_RUTA Ruta donde se almacenará configuración de las AppModelo KPs Java Gestionados Página 7/35 el properties de 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. 3.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. KPs Java Gestionados Página 8/35 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. 3.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. KPs Java Gestionados Página 9/35 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. KPs Java Gestionados Página 10/35 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. 3.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. KPs Java Gestionados Página 11/35 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()) 3.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. KPs Java Gestionados Página 12/35 3.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. KPs Java Gestionados Página 13/35 3.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; 3.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; KPs Java Gestionados Página 14/35 } @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); } } 3.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()); KPs Java Gestionados Página 15/35 } 3.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()); } 3.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. 3.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 KPs Java Gestionados Página 16/35 * ESTE METODO TRANSFORMA EL MENSAJE ERRORMESSAGE error EN UN MENSAJE 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){ KPs Java Gestionados Página 17/35 kPWorkerCfg.publish(InfraestructureEvents.MONITORING.name(), monitoringMessage); } } 3.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. KPs Java Gestionados Página 18/35 3.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. 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; KPs Java Gestionados Página 19/35 private String query; 3.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; } } 3.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. KPs Java Gestionados Página 20/35 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 KPs Java Gestionados Página 21/35 4 EJEMPLO FUNCIONAMIENTO APP MODELO Con la idea de aclarar los conceptos explicados en el punto anterior se incluye un ejemplo completo de Infraestructura KP Java gestionada (KP/App Modelo). Antes de seguir esta guía se recomienda leer la guía SOFIA2-Conceptos SOFIA2.doc e instalar el SDK de Sofia2 conforme se indica en el anexo de esta guía. El ejemplo descrito puede descargarse desde esta URL: http://sofia2.org/owncloud/public.php?service=files&t=956a786e3ac0a9cb804d185c6a70 aa7a La App Simplestat es una App Modelo utilizada en las pruebas de test de funcionamiento de un gateway real -un concentrador de señales de sensores, que corre sobre java y un sistema operativo debían wheezy. El test mide la capacidad de publicación y suscripción de un Kp, los tiempos de respuesta, la posible pérdida de mensajes, etc. Se centra en testear algunas de las capacidades del KP Modelo: La capacidad de lectura simulada de datos de un GPIO La capacidad de publicación/suscripción del KPModelo El guardado de mensajes en caso de error La capacidad de reconexión y reenvío Dejar un registro de todas la operaciones más el estado del SO (memoria, cpu) 4.1 Estructura y Configuracion Esta es la estructura de ficheros de la distribución del ejemplo Funcionará tal cual sobre el sistema objetivo, siempre que coincidan las rutas de java y de los ficheros de configuración. KPs Java Gestionados Página 22/35 En la raíz encontramos el jar principal de funcionamiento del KPModelo y un script run.sh para lanzarlo. En la carpeta config se hayan las configuraciones generales del KPModelo Los ficheros CONF_BASE y CONF_MODULO deben disponerse como se ha descrito. Es imprescindible apuntar correctamente las rutas y apuntar correctamente el SIB, puerto, token y kp por defecto. La base de datos por defecto esta en memoria, no requiere de modificación: En la carpeta CONF se dispone de las configuraciones propias de las APPs contenidas en el KPModelo. En este caso debe llamarse CONF_NombreDeApp: Dentro hemos persistido la base de datos a disco, para que no sature la memoria. Indicamos la ruta: KPs Java Gestionados Página 23/35 La creación es automática. Se puede ver un rastro de BBDD vacía de ejecuciones previas en el directorio temporal indicado: En la carpeta SW se ubican manualmente o mediante descarga del servidor, los wars de las APPs que se desplegarán el el KpModelo: Las librerías se han de ubicar al alcance del claspath de java, en este caso del script de lanzamiento run.sh en la raíz de la distribución: La carpeta netscript contiene dos utilidades- KPs Java Gestionados Página 24/35 El script runFile.sh altera aleatoriamente el contenido del fichero /var/ttp/gpio_sim.txt (es necesario crear dicho fichero) El propósito es el de utilizarlo como un origen de datos simulados de sensor GPIO por parte de la APP. El script runNet.sh cambia cada periodo aleatorio (por defecto de 5 minutos) entre servicios de red activos/inactivos. En cada ciclo es posible puede configurar el fichero sendmail.sh para que envie información a una dirección con los tiempos de actividad. Esto es interesante dado que durante una desconexión perderemos el acceso al Gateway. Finalmente en la carpeta outputs se escribirán las métricas y para realizar las estadísticas del estudio: 4.2 Lanzamiento Se hace desde el script run.sh en la raíz. Este script contiene: KPs Java Gestionados Página 25/35 echo 3>/proc/sys/vm/drop_caches Limpieza de caches del so para ofrecer métricas similares en cada prueba rm ./config/TMP/* Limpieza de temporales -Xmx192m Limite del stack. El Gateway tiene un límite de 256m -XX:MaxPermSize=24m Tamaño del perm -DCONF_BASE=./config Propiedad del entorno jvm que indica donde está la carpeta de configuraciones -classpath Cada una de las ubicaciones de las librerías java, separadas por dos puntos (en sistemas linux) com.indra.sofia2.kpmodelo.KpmModelo Clase principal java (con un main) del lanzador Se recomienda lanzar el script desde su propia carpeta como >sudo nohup ./run.sh & Los scripts de la carpeta de utilidades ./netscript funcionaran correctamente con las opciones por defecto, pero es muy sencillo editarlos y cambiarlos. Se recomienda su lanzamiento desde su carpeta, de la siguente manera: >sudo ./runFile.sh & No tiene salida de consola. Este script es imprescindible para que la APP envíe datos (no enviará nada si no cambia el contenido de la lectura de los datos GPIO simulados) >sudo nohup ./runNet.sh & Recordar configurar el comando mail del so y apuntar la dirección correcta en el script netscript/sendmail.sh si se quiere recibir correos con los tiempos de desconexión. Ejemplo de traza correcta: KPs Java Gestionados Página 26/35 4.3 Compilación de los Fuentes Es posible compilar desde las fuentes la APP Simplestat. Se provee el pom de maven para la descarga/actualización de las clases. Es necesario el acceso al repositorio public de sofia http://sofia2.org/nexus/content/groups/public/ para actualizar las dependencias de Sofia2. >mvn clean install La compilación de las fuentes generará en el directorio target el war del APP Modelo. Renombrar y mover el war a la parte indicada en la configuración para que sea incorporado al contenedor del KpModelo. KPs Java Gestionados Página 27/35 Después de compilar se pueden obtener los ficheros de configuración para el IDE eclipse mediante >mvn eclipse:eclipse Que posibilita la importación del proyecto en eclipse. 4.4 Organización de las Clases Esta es la estructura del proyecto SIMPLESTAT: A excepción de la carpeta negocio, toda la estructura de clases representa distintos workers que realizarán una tarea a lo largo del cilclo de vida del APP Modelo. A propósito informativo se han creado workers para cada tipo de tarea pero no todos implementan una funcionalidad. 4.4.1 Workers StartApp y APPStop Se ejecuta cuando se despliega el APP Modelo o se repliega (en caso de actualizaciones). En este APP concreto no tienen funcionalidad. KPs Java Gestionados Página 28/35 KPs Java Gestionados Página 29/35 4.4.2 Worker DataInputLoop Extiende de DataSendToSIBWorkerImpl. Ciclo periódico de lectura de datos del sensor. Es importante marcar los tiempos de lectura (200ms) y evaluar si el dato ha cambiado (fecha del fichero) para enviarlo al SIB en forma de objeto SensorData (si el método retorna null, no se produce el envío) 4.4.3 Worker PrepareMessageToSend Extiende de NewDataReceivedWorkerImpl. Transformación del objeto de propiedades de los datos SensorData a mensaje INSERT del protocolo SSAP. En el caso concreto del ejemplo, se lee una plantilla json y se reemplazan los valores clave: KPs Java Gestionados Página 30/35 4.4.4 Worker SendServiceWrapper Extiende de DataToSendWorkerImpl. Se compone de dos partes, el método preProcessSSAPMessage, por donde pasa el mensaje antes de ser enviado En este método añadimos el mensaje a un mapa, para comprobar más adelante si este mismo mensaje vuelve en forma de suscripción. Por el método postProcessMessage pasa el mensaje después de ser enviado, además de un mensaje con la respuesta del SIB con el estado de la operación de envío. Se escriben métricas con los tiempos de respuesta del mensaje y si fue enviado correctamente o no. KPs Java Gestionados Página 31/35 4.4.5 Workers DataSendToSib y ErrorSendToSib Workers no implementados. Se ejecuta DataSendToSIB cada vez que el SIB envía un mensaje sin problemas Y ErrorSentToSIB cada vez que hay un error con el mensaje (que es guardado automáticamente en la base de datos para posteriores reintentos de envío) 4.4.6 Worker SubscriptionListener Extiende de de Suscriber. Bean de suscripcion a ontología del APPModelo. El proceso de suscripción se hace en dos partes. Primero una inicialización donde se suscribe a una query de ontología, en este caso la misma ontología donde se publican los mensajes: La intención es la de recibir por suscripción el mismo mensaje publicado. Y un listener para los mensajes entrantes, donde se procesan: KPs Java Gestionados Página 32/35 En el caso del APP del ejemplo, se obtiene el id del mensaje y se borra este mensaje del mapa de mensajes publicados, asegurando que se ha recibido la suscripcion correspondiente. 4.4.7 Worker Connection Worker no implementado. Se ejecuta el método connected cada vez que se recupera la conexión de la red 4.4.8 Worker NoConnection Extiende de NoConnectionSibWorkerImpl. Se ejecuta el método noConnected cada vez que se pierde la conexión de la red. En estos casos el APP chequea si el mapa de guardado de mensajes tiene más de un mensaje guardado para emitir un registro de error en el fichero de métricas. Dado que se puede perder la conexión entre un envío y la suscripción (por el modelo de la prueba es casi imposible tener envíos concurrentes, dado que las lecturas no los son) se admite un error. El mapa se limpia acto seguido. KPs Java Gestionados Página 33/35 4.4.9 Worker Monitoring Workers no implementado. Se utiliza para monitorizar en caso de errores y seguimiento. 4.4.10 Clases paquete negocio Son clases propias de la obtención de las métricas, como la escritura del fichero de información, lanzamientos de comandos desde el sistema operativo (top), etc. KPs Java Gestionados Página 34/35 5 ANEXOS 5.1 Instalación del SDK de Sofia2 (SOFIA2-SDK) Para poder desarrollar aplicaciones SOFIA2 es necesario tener instalado el SDK de SOFIA2, para ello: Acceder http://sofia2.com/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: 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…) KPs Java Gestionados Página 35/35