71
ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA 44 PROPUESTA DE SOLUCIÓN 3. PROPUESTA DE SOLUCIÓN La migración de la arquitectura del sistema de movilidad al completo queda fuera del alcance del presente proyecto. La finalidad del proyecto era sentar las bases de esta migración, motivo por el cual se llevará a cabo una Prueba de Concepto con uno de los servicios que la empresa quiere ofrecer a sus empleados a través de los dispositivos BlackBerry (BB). En concreto, se quiere que sea accesible desde los dispositivos móviles la aplicación web de gestión de procesos de negocios (BPM) BizAgi. Tras la Prueba de Concepto sería necesario ampliar la solución para poder incluir todos los servicios que la empresa quiera ofrecer a sus usuarios a través de los dispositivos BlackBerry. A continuación se describe la estructuración del capítulo. En primer lugar se comienza describiendo la prueba de concepto y los casos de uso de los que se compone, describiendo cómo funciona en la actualidad y cómo será la arquitectura con la utilización del ESB. Después se pasará a tratar la arquitectura funcional, exponiendo el entorno de la Prueba de Concepto y el catálogo de servicios empleado. El último apartado, el más técnico, consistirá en la implementación de la solución. Se comentará los detalles de la implementación. 3.1. DISEÑO Cómo ya se comentó en la introducción del capítulo a continuación se pasará a describir la prueba de concepto y los casos de uso que la componen. Se explicará cómo realiza en la actualidad el sistema de movilidad las operaciones necesarias y cómo se diseñará la nueva arquitectura para conseguir los objetivos mediante la orientación a servicios. Además de detallar el entorno en el que se desarrolla la prueba de concepto y el catálogo de servicios que se ofrece. 3.1.1. DESCRIPCIÓN DE LA PRUEBA DE CONCEPTO La Prueba de Concepto consiste en hacer accesible a las BlackBerry la aplicación web de gestión de procesos de negocios BizAgi. Los procesos constan de una serie de actividades cuyo número y tipo dependerán del proceso en cuestión. Algunas actividades son realizadas por el propio gestor de procesos, mientras que otras requieren de la intervención de un empleado. La forma que tienen de interactuar los usuarios con esta aplicación es a través de formularios que tienen que ser cumplimentados, así mediante la cumplimentación de un formulario se completa una actividad del proceso. Por tanto, ¿qué hay que ofrecer a los usuarios de BlackBerry y a la aplicación web de BizAgi? En primer lugar, a la aplicación web se le debe ofrecer una forma de

3. PROPU STA SOLUIÓNbibing.us.es/proyectos/abreproy/11966/fichero...3.1.1. DESCRIPCIÓN DE LA PRUEBA DE CONCEPTO La Prueba de Concepto consiste en hacer accesible a las BlackBerry

  • Upload
    others

  • View
    20

  • Download
    0

Embed Size (px)

Citation preview

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

44 PROPUESTA DE SOLUCIÓN

3. PROPUESTA DE SOLUCIÓN La migración de la arquitectura del sistema de movilidad al completo queda fuera del alcance del presente proyecto. La finalidad del proyecto era sentar las bases de esta migración, motivo por el cual se llevará a cabo una Prueba de Concepto con uno de los servicios que la empresa quiere ofrecer a sus empleados a través de los dispositivos BlackBerry (BB). En concreto, se quiere que sea accesible desde los dispositivos móviles la aplicación web de gestión de procesos de negocios (BPM) BizAgi. Tras la Prueba de Concepto sería necesario ampliar la solución para poder incluir todos los servicios que la empresa quiera ofrecer a sus usuarios a través de los dispositivos BlackBerry. A continuación se describe la estructuración del capítulo. En primer lugar se comienza describiendo la prueba de concepto y los casos de uso de los que se compone, describiendo cómo funciona en la actualidad y cómo será la arquitectura con la utilización del ESB. Después se pasará a tratar la arquitectura funcional, exponiendo el entorno de la Prueba de Concepto y el catálogo de servicios empleado. El último apartado, el más técnico, consistirá en la implementación de la solución. Se comentará los detalles de la implementación.

3.1. DISEÑO Cómo ya se comentó en la introducción del capítulo a continuación se pasará a describir la prueba de concepto y los casos de uso que la componen. Se explicará cómo realiza en la actualidad el sistema de movilidad las operaciones necesarias y cómo se diseñará la nueva arquitectura para conseguir los objetivos mediante la orientación a servicios. Además de detallar el entorno en el que se desarrolla la prueba de concepto y el catálogo de servicios que se ofrece.

3.1.1. DESCRIPCIÓN DE LA PRUEBA DE CONCEPTO

La Prueba de Concepto consiste en hacer accesible a las BlackBerry la aplicación web de gestión de procesos de negocios BizAgi. Los procesos constan de una serie de actividades cuyo número y tipo dependerán del proceso en cuestión. Algunas actividades son realizadas por el propio gestor de procesos, mientras que otras requieren de la intervención de un empleado. La forma que tienen de interactuar los usuarios con esta aplicación es a través de formularios que tienen que ser cumplimentados, así mediante la cumplimentación de un formulario se completa una actividad del proceso. Por tanto, ¿qué hay que ofrecer a los usuarios de BlackBerry y a la aplicación web de BizAgi? En primer lugar, a la aplicación web se le debe ofrecer una forma de

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

45 PROPUESTA DE SOLUCIÓN

hacer llegar un formulario a un dispositivo BlackBerry cuando se requiera la intervención del empleado para completar una determinada actividad. A su vez se debe ofrecer ciertas funcionalidades a los usuarios de los dispositivos móviles. Por un lado, se debe hacer llegar el formulario que rellenen a la aplicación web para que ésta pueda realizar la tramitación de la actividad. También hay que permitir al usuario de la BlackBerry la posibilidad de poder crear un proceso, además de poder delegar una actividad a otro usuario. Con esto quedan definidos los cuatro casos de uso de los que constará el proyecto:

Movilizar una actividad Tramitar una actividad Iniciar un proceso Delegar una actividad

Ahora se describirá cómo el sistema actual de movilidad lleva a cabo estas cuatro tareas y cómo se van a tratar con la arquitectura orientada a servicios.

3.1.2. FUNCIONAMIENTO DEL ACTUAL SISTEMA DE MOVILIDAD

En el capítulo anterior se vio la arquitectura completa del sistema, así que ahora el estudio se centrará en la aplicación BizAgi. Quedando el subsistema mostrado en la Figura B.3.1.

Figura B.3.1 - Arquitectura del sistema de movilidad: BizAgi

Los componentes que forman este subsistema son:

Movilizador BizAgi: Se trata de un servicio web que expone cuatro métodos: movilizaActividad, tramitarActividad, delegaActividad e iniciaProceso.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

46 PROPUESTA DE SOLUCIÓN

Servicio De Usuarios: Es un servicio web que expone una serie de métodos destinados a obtener información sobre los usuarios de movilidad.

Sistema Central: Se trata de un servlet que está a la escucha de peticiones POST y que se encarga de despachar los mensajes.

En concreto habrá que sustituir la parte punteada. Se reutilizará el Servicio De Usuarios, hay que recordar que la reutilización de servicios es uno de los principios básicos de SOA. Ahora se pasará a describir brevemente el funcionamiento de este sistema.

Movilización de Actividad

La movilización de la actividad comienza cuando la aplicación de BizAgi consume el método movilizaActividad del servicio web expuesto por el movilizador BizAgi. El movilizador, con el usuarioLDAP indicado por la aplicación BizAgi, hace una llamada al servicio web Servicio De Usuarios, concretamente al método getUsuarioDeUsuarioLDAP. De esta manera obtiene toda la información que necesita del usuario para realizar sus gestiones, como pueden ser el PIN de la BB, el idioma configurado en la misma… Una vez llamado al Servicio De Usuarios, se consume el método getActivityForm del servicio web RenderSOA ofrecido por BizAgi. La respuesta a esta petición es el formulario a cumplimentar por la BB. Una vez recibido el formulario, el movilizador BizAgi hace una serie de transformaciones para adaptar el formulario a la BB. Realizada esta transformación se pasa el mensaje a enviar a la BB a una Base de Datos (Bandeja). Aquí termina el trabajo del movilizador y comienza el del Sistema Central. El Sistema Central se compone de una serie de tareas, que periódicamente recorren las bandejas de mensajes (Tablas en la Base de Datos) y despachan los mensajes mandándolos a los BES oportunos.

Tramitar una Actividad

Desde la aplicación SIM se puede cumplimentar un formulario recibido y una vez rellenado marcar ‘procesar’. Cuando se hace esto, la aplicación SIM se encarga de enviar un mensaje con el formulario al Sistema Central. El Sistema Central, al ver los campos de la cabecera, sabe que se trata de un formulario de BizAgi, por lo que debe enviárselo al movilizador BizAgi, consumiendo el método tramitarActividad.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

47 PROPUESTA DE SOLUCIÓN

La capa SOA de BizAgi ofrece el servicio web WorkflowEngineSOA.asmx. El movilizador consume el método performActivityAsString, al cual pasa como parámetro el formulario cumplimentado desde la BlackBerry. Una vez realizada la tramitación por parte de la aplicación BizAgi, ésta da como resultado al movilizador un mensaje en el que da información de cómo ha sido desarrollada la actividad. En función del resultado de la tramitación de la actividad, el movilizador tendrá que mandar un mensaje de error o éxito a la BlackBerry. Para ello actúa de la misma manera que cuando se mandó el formulario y deja el mensaje a enviar en la Base de Datos del Sistema Central. El Sistema Central se encarga la despachar los mensajes que tiene almacenados en la Base de Datos. La aplicación SIM, al recibir el mensaje, se encarga de marcar con una o una según cómo haya sido el resultado de la tramitación.

Iniciar un Proceso

En la aplicación SIM el usuario tiene la opción de iniciar un proceso, para lo que tendrá que indicar la sociedad a la que pertenece el proceso y el proceso en cuestión. Una vez seleccionados, la aplicación SIM se encarga de mandar un mensaje al Sistema Central indicando el proceso que desea crear. El Sistema Central procesa la cabecera del mensaje y descubre que se trata de un mensaje relacionado con la aplicación BizAgi. Además por los parámetros mandados sabe que se trata de una petición de inicio de proceso. Por lo que el Sistema Central consumirá el método iniciaProceso expuesto por el movilizador de BizAgi. Para crear el proceso, el movilizador BizAgi hace uso de un método del servicio web WorkflowEngineSOA.asmx. En concreto del método createCasesAsString, el cual como respuesta indica si la creación fue realizada correctamente o no. Según la respuesta, el movilizador tendrá que mandar un mensaje de error o de confirmación a la BlackBerry. Para ello, como ya se vio con anterioridad, guarda el mensaje en una base de datos. Y es el Sistema Central el encargado del envío del mensaje al BES para que éste lo remita a la BlackBerry oportuna.

Delegar una Actividad

Otra opción que se le ofrece al usuario es delegar una actividad a otro usuario. Cuando recibimos el formulario de una actividad en la BlackBerry, la aplicación SIM da la opción ‘delegar’. Esta opción ofrece un buscador en el que encontrar al usuario al que delegar la actividad. Una vez seleccionado el usuario al que delegar la actividad, la aplicación SIM manda un mensaje al Sistema Central con información sobre la actividad a delegar y el nombre del usuario al que se va a delegar. El Sistema Central procesará el mensaje y

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

48 PROPUESTA DE SOLUCIÓN

descubrirá que se trata de una petición de delegación de actividad para BizAgi. Después invocará el método delegaActividad expuesto por el movilizador de BizAgi. El movilizador hace uso del método getEntitiesAsString del servicio web EntityMan.asmx, para obtener el identificador LDAP del usuario al que hay que delegar la actividad. Si no se encuentra el usuario, se indica un mensaje de error en el LOG. Si se ha obtenido el identificador LDAP con éxito, el siguiente paso a realizar por el movilizador es, usando este identificador y la información recibida en la petición sobre la actividad, llamar al método assignActivityAsString del servicio web WorkflowEngineSOA.asmx. Este método realiza la delegación de la actividad al nuevo usuario. El servicio web devuelve el resultado de la operación, indicando si ha podido realizar la operación o no. Al igual que en el caso del inicio del proceso, el movilizador tendrá que mandar un mensaje de error o de confirmación a la BlackBerry según cómo haya sido la respuesta. Este mensaje es enviado al Sistema Central para que se lo haga llegar al BES correspondiente, el cual enviará el mensaje a la BlackBerry destino.

3.1.3. FUNCIONAMIENTO DE LA NUEVA ARQUITECTURA

En la nueva arquitectura se eliminarán tanto los movilizadores como el Sistema Central. Todo ello será sustituido por el ESB, quedando un esquema como el mostrado en la Figura B.3.2. El ESB se encargará de todo, tanto de las tareas de transformación de XML como del enrutado de mensajes. De esta manera se hará un procesamiento de los mensajes “al vuelo”. Los mensajes a enviar no serán guardados en Base de Datos, y podrán ser gestionados de forma más cómoda gracias a la gestión de colas. Se establecerán tres puntos de entrada al ESB. En uno de ellos se expondrá un servicio web con un método movilizarActividad que reciba exactamente los mismos parámetros que recibía el antiguo movilizador. De esta manera evitamos tener que modificar en exceso la aplicación BizAgi, únicamente será necesario modificar la url en la que se encuentra alojada el servicio web. Los otros dos puntos de entrada se tratan de endpoints Jetty21. Estos estarán a la espera de peticiones HTTP. Uno de ellos recibirá información de los BES sobre el resultado del envío de mensajes a las BlackBerry, mientras que el otro está a la escucha de mensajes enviados directamente desde las BlackBerry. 21

http://www.eclipse.org/jetty/

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

49 PROPUESTA DE SOLUCIÓN

Figura B.3.2 - Nueva arquitectura de movilidad: BizAgi

Cuando los mensajes son recibidos desde los endpoints son conducidos por rutas Camel a diferentes endpoints donde se llevarán a cabo tareas de transformación de mensajes o llamadas a servicios web. En el apartado de implementación básica se dará una explicación más detallada de los procesos que se ejecutan en el ESB y las rutas seguidas por los mensajes. Antes de comenzar a comentar detalles de la implementación, hay que describir el entorno en el que se desarrolla la Prueba de Concepto y exponer el catálogo de servicios del que se dispone.

3.1.4. ARQUITECTURA FUNCIONAL

La Prueba de Concepto debe ejecutarse en un entorno de desarrollo, que permita trabajar con cierta libertad sin miedo a poder poner en peligro la integridad del sistema de movilidad. En concreto el servidor de BizAgi es srv-desbizagi, el servidor de desarrollo que tiene la empresa para BizAgi. Obviamente también usaremos el BES de desarrollo, en lugar de alguno de los otros nueve. Por último también se dispone de un Servicio De Usuarios de desarrollo, cuya diferencia con el de producción radica en el hecho que accede a una Base de Datos en la que únicamente existen usuarios de prueba empleados para este tipo de tareas. Para el desarrollo de las pruebas se creó un usuario en esta Base de Datos asociado a mi perfil en la empresa, a su vez este usuario de prueba fue ligado al PIN de una de las BlackBerry disponibles en el departamento de movilidad para el desarrollo de pruebas en el sistema.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

50 PROPUESTA DE SOLUCIÓN

Los datos de interés relacionados al usuario en esta Base de Datos son los comentados a continuación:

PIN: El pin de la BlackBerry asociada al usuario, necesario para que el BES sepa a qué dispositivo debe enviar los mensajes.

url del BES: Cada BlackBerry está asociada a uno de los nueve BES, este parámetro indica el BES al que está asociada la BlackBerry. En el entorno de interés, al trabajar en desarrollo, este valor siempre será el mismo: SRV-DESBLACKBE, aunque en el desarrollo del proyecto se tiene en cuenta que pueda cambiar adaptando la aplicación a un posible paso a producción.

Idioma: Otra información útil es el idioma en el que está configurada la BlackBerry. Según este idioma se puede pedir a BizAgi que nos mande el formulario en el idioma adecuado.

Identificadores de usuario: Existen distintos tipos de identificadores como Notes, LDAP, movilidad…, siendo los de interés en la Prueba de Concepto el usuario LDAP (el que usa BizAgi) e identificador de usuario que da movilidad (por razones evidentes)

Catálogo de servicios

Servicios Ofrecidos

El servicio que se ofrecerá al usuario, en este caso la aplicación BizAgi, consiste en un único método dentro del servicio web SistemaCentralSOAWSService. El método se llama movilizarActividad y se invoca por medio de un mensaje SOAP enviado a la url http://172.28.70.197:15633/SC_SOA, siendo 172.28.70.197 la IP de mi equipo en la empresa y 15633 el puerto que se le asignó a este servicio web, aunque podía haber sido cualquier otro. El mensaje SOAP se muestra en la Figura B.3.3, y cuenta con los siguientes parámetros:

idActividad e idProceso: Identifican la actividad de BizAgi a movilizar, y a qué proceso pertenece.

usuarioLDAP: Usuario a cuya BlackBerry necesitamos mandar la actividad. tipoActualización: Indica que hay que movilizar la actividad. codigoSociedad: Código que asigna la empresa a cada una de las sociedades

que la componen. dominio: Siempre será ABG, aunque de momento es un parámetro que no está

en uso.

Servicios Consumidos

Del Servicio De Usuarios se consumen dos métodos, ambos para conseguir la información del usuario. Uno de ellos lo obtiene a partir del PIN, getUsuarioDePIN, y el otro a partir del usuarioLDAP, getUsuarioDeUsuarioLDAP.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

51 PROPUESTA DE SOLUCIÓN

En las Figura B.3.4 y Figura B.3.5 se muestran los mensajes SOAP que hay que enviar a la url del servicio web para invocar ambos métodos. En la Figura B.3.4 se muestra el mensaje de petición del método getUsuarioDeUsuarioLDAP, mientras que en la Figura B.3.5 el del método getUsuarioDePIN. También se presenta un ejemplo de respuesta que es común a las dos invocaciones en la Figura B.3.6. La url del servicio es:

http://srv-wasdes/servicio-de-usuarios/ws/ServicioDeUsuarios

Figura B.3.3 - Mensaje SOAP: movilizarActividad

Figura B.3.4 - Mensaje SOAP: getUsuarioDeUsuarioLDAP

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/

soap/envelope/" xmlns:ws="http://ws.soa.sim.abengoa.com/">

<soapenv:Header/>

<soapenv:Body>

<ws:movilizarActividad>

<!-- Optional -->

<idActividad>776928</idActividad>

<!-- Optional -->

<idProceso>75711</idProceso>

<!-- Optional -->

<usuarioLDAP>INJBO</usuarioLDAP>

<!-- Optional -->

<tipoActualizacion>I</tipoActualizacion>

<!-- Optional -->

<codigoSociedad>C09</codigoSociedad>

<!-- Optional -->

<dominio>ABG</dominio>

</ws:movilizarActividad>

</soapenv:Body>

</soapenv:Envelope>

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/

soap/envelope/" xmlns:ws="http://ws.usuarios.servicios.sim.

telvent.abengoa.com/">

<soapenv:Header/>

<soapenv:Body>

<ws:getUsuarioDeUsuarioLDAP>

<!-- Optional -->

<usuarioLDAP>INJBO</usuarioLDAP>

</ws:getUsuarioDeUsuarioLDAP>

</soapenv:Body>

</soapenv:Envelope>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

52 PROPUESTA DE SOLUCIÓN

Figura B.3.5 - Mensaje SOAP: getUsuarioDePIN

Se consumirán además el método getActivityFormXML del servicio web

RenderSOA.asmx, el método getEntitiesAsString del servicio web EntityMan.asmx y los métodos performActivityAsString, createCasesAsString y assignActivityAsString del servicio web WorkflowEngineSOA.asmx. En este caso la invocación de los métodos se hará mediante peticiones GET en lugar de usar el protocolo SOAP. El por qué se explicará cuando demos detalles de la implementación de la solución.

El método getActivityFormXML requiere del parámetro requestInfoData, cuyo contenido debe ser como el mostrado en la Figura B.3.7. Por su parte el método performActivityAsString necesita el parámetro activityInfo, el cual tiene un contenido como el de la Figura B.3.8. El método createCasesAsString necesita el parámetro casesInfo mostrado en la Figura B.3.9, mientras que assignActivityAsString necesita el parámetro info mostrado en la Figura B.3.10. Finalmente el método getEntitiesAsString necesita el parámetro entitiesInfo mostrado en la Figura B.3.11.

3.2. IMPLEMENTACIÓN BÁSICA

Antes de comenzar a dar detalles de la implementación se recordará en que consistía la Prueba de Concepto. Ésta consistente en la migración del actual sistema de movilidad, una arquitectura mallada, al nuevo sistema basado en una arquitectura orientada a servicios. Esto está únicamente centrado en una de las aplicaciones: la aplicación de gestión de procesos de negocio BizAgi. La Prueba consistía en cuatro Casos de Uso: la movilización, tramitación y delegación de actividades y la creación de procesos. Se comenzará este apartado dando una idea global de la solución, para posteriormente estudiar cada uno de los casos de uso por separado. Estos casos de uso serán comentados en detalle mediante la referencia a fragmentos de código (el código completo puede consultarse en los archivos adjuntos al proyecto).

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/

soap/envelope/" xmlns:ws="http://ws.usuarios.servicios.sim.

telvent.abengoa.com/">

<soapenv:Header/>

<soapenv:Body>

<ws:getUsuarioDePIN>

<!-- Optional -->

<usuarioPin>21369C5E</usuarioPin>

</ws:getUsuarioDePIN>

</soapenv:Body>

</soapenv:Envelope>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

53 PROPUESTA DE SOLUCIÓN

Figura B.3.6 - Ejemplo respuesta a getUsuarioDePIN

<soap:Envelope xmlns:soap=”http://schemas.xmlsoap.org/soap/

envelope/”>

<soap:Body>

<ns2:getUsuarioDePINResponse xmlns:ns2=”http://ws.

usuarios.servicios.sim.telvent.abengoa.com”>

<return>

<propiedades>

<entry>

<key>movilidad.modeloBB</key>

<value>8520</value>

</entry>

<entry>

<key>movilidad.pinBB</key>

<value>21369C5E</value>

</entry>

<entry>

<key>movilidad.usuarioMovilidadId</key>

<value>6801</value>

</entry>

<entry>

<key>movilidad.urlBes</key>

<value>SRV-DESBLACKBE</value>

</entry>

<entry>

<key>movilidad.idiomaId</key>

<value>2</value>

</entry>

<entry>

<key>movilidad.sistemaOperativoBB</key>

<value>4.2.0.118</value>

</entry>

<entry>

<key>movilidad.locale</key>

<value>EN</value>

</entry>

<entry>

<key>movilidad.versionApp</key>

</entry>

</propiedades>

<usuarioLDAP>INJBO</usuarioLDAP>

<usuarioNotes>

CN=Jesus Burgers Onate/OU=SimosaIT/O=Abengoa

</usuarioNotes>

</return>

</ns2:getUsuarioDePINResponse>

</soap:Body>

</soap:Envelope>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

54 PROPUESTA DE SOLUCIÓN

Figura B.3.7 - getActivityFormXML: requestInfoData

Figura B.3.8 - performActivityAsString: activityInfo

Figura B.3.9 - createCasesAsString: casesInfo

<BizAgiWSParam>

<domain>ABG</domain>

<userName>INJBO</username>

<idLanguage>es-ES</idLanguage>

<Case>

<idCase>75956</idCase>

<idWorkItem>77737</idWorkItem>

</Case>

</BizAgiWSParam>

<BizAgiWSParam>

<domain>ABG</domain>

<userName>INVGD</userName>

<ActivityData>

<radNumber>E81-ABR02-4054</radNumber>

<taskId>2017</taskId>

<idCase>23573</idCase>

<idWorkItem>86024</idWorkItem>

</ActivityData>

<Entities>

</Entities>

</BizAgiWSParam>

<BizAgiWSParam>

<domain>ABG</domain>

<userName>INJBO</username>

<Cases>

<Case>

<Process>pPRL110_EntEspConf</Process>

<Entities>

<idSociedad businessKey=”sCodigo=C10”/>

</Entities>

</Case>

</Cases>

</BizAgiWSParam>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

55 PROPUESTA DE SOLUCIÓN

Figura B.3.10 - assignActivityAsString: info

Figura B.3.11 - getEntitiesAsString: entitiesInfo

3.2.1. ESQUEMA DE LA SOLUCIÓN

En la Figura B.3.12 se puede ver una primera aproximación de la solución adoptada. Consiste en un bundle OSGi, dentro del cual se ha definido un contexto de camel. Además en el bundle se ha definido una serie de beans que cubrirá ciertas necesidades que los componentes de camel no fueron capaces de satisfacer. Dentro del contexto de camel se han definido unas rutas por las cuales serán encaminados los mensajes. En concreto se han definido nueve rutas, las cuales se describirán para tener una idea del funcionamiento del bundle:

Una de las rutas tiene como punto de entrada el servicio web en el que se definió el método movilizarActividad. Esta ruta tiene como función identificar el método del servicio web al que se está invocando y actuar en consecuencia. Aunque en nuestro caso sólo tenemos definido un método, tenemos preparada esta ruta por si se añaden nuevos métodos. [1]

Otra de las rutas es la encargada de realizar la movilización de la actividad

propiamente dicha. Esta ruta finaliza mandando el mensaje a la ruta que se encarga de mandar los push. [2]

Como se ha visto, existe una ruta que se encarga de realizar los push para

mandar los mensajes a las BlackBerry. [3]

<BizAgiWSParam>

<CaseInfo>

<userName>INJBO</username>

<IdCase>23573</IdCase>

<IdWorkItem>86024</IdWorkItem>

</CaseInfo>

</BizAgiWSParam>

<BizAgiWSParam>

<EntityData>

<EntityID>1</EntityID>

<Filters> fullname like ‘Jesus Burgers Onate’</Filters>

</EntityData>

</BizAgiWSParam>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

56 PROPUESTA DE SOLUCIÓN

Otra ruta recibe la respuesta asíncrona que mandan los BES para indicar el resultado del envío. [4]

Figura B.3.12 - Solución ESB: simplificada

Existe también una ruta que se encarga de recibir los mensajes que mandan las

BlackBerry y meterlos en una cola para que sean procesados. [5]

Habrá por tanto una ruta que tome los mensajes de la anterior cola, los procese y en función del contenido del mensaje mandarlo a la ruta oportuna. [6]

También se crearon las rutas encargadas de tramitar la actividad [7], iniciar el proceso [8] y delegar la actividad [9].

En la Figura B.3.13 se puede ver un diagrama en el que se ven las rutas Camel y los caminos que pueden seguir los mensajes. Se clasificarán las rutas en dos grupos: las correspondientes a cada uno de los casos de uso y las rutas de uso común.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

57 PROPUESTA DE SOLUCIÓN

Figura B.3.13 - Esquema rutas Camel

3.2.2. RUTAS: COMUNES

En primer lugar se verán las rutas comunes a los cuatro casos de usos: la ruta encargada de exponer el servicio web y recibir las peticiones, las rutas encargadas de enviar los push y de recibir la respuesta de los BES, y la ruta encargada de recibir los mensajes de las BlackBerry y de procesarlos.

Ruta Servicio Web

En primer lugar se verá la ruta que se encarga de exponer el servicio web con el método movilizarActividad. Para exponerlo se usará un endpoint CXF, el cual habrá que configurar. En primer lugar habrá que configurar el interfaz del servicio web, para el cual se usará una clase de Java. En la Figura B.3.14 se muestra el código que se ha usado para definir la interfaz. Se ha mantenido el nombre que tenía el antiguo movilizador para el método encargado de realizar la movilización de la actividad. De esta manera no habrá

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

58 PROPUESTA DE SOLUCIÓN

que tocar en exceso la aplicación web de BizAgi, sólo habrá que modificar la url en la que se encuentra alojado el servicio web.

Figura B.3.14 - Interfaz servicio Web

Una vez definido el interfaz de nuestro servicio web ya se puede configurar el endpoint CXF. Para ello se usará el siguiente fragmento de código:

Con la etiqueta cxfEndpoint se indica que se quiere crear un endpoint CXF. Esta etiqueta tiene tres atributos:

El id es un identificador que se usará cuando se definan las rutas para hacer referencia a este endpoint.

El atributo address indica la dirección en la que se expondrá el servicio. Finalmente, serviceClass es la clase en la que está definida la interfaz del

servicio web. Dentro de la etiqueta de propiedades se ha configurado la propiedad dataFormat. Se ha ajustado al valor MESSAGE, que es el que interesa para el servicio que se quiere exponer. Con esto queda configurado el servicio web, lo cual se hace fuera del contexto de Camel. Ahora se pasará a comentar la ruta propiamente dicha.

@WebService

public interface SistemaCentralSOA {

public String movilizarActividad(

@WebParam(name = "idActividad") String idActividad,

@WebParam(name = "idProceso") String idProceso,

@WebParam(name = "usuarioLDAP") String usuarioLDAP,

@WebParam(name = "tipoActualizacion") String tipoActualizacion,

@WebParam(name = "codigoSociedad") String codigoSociedad,

@WebParam(name = "dominio") String dominio );

}

<cxf:cxfEndpoint id="sistemaCentralSOAEndpoint" address="http://

localhost:15633/SC_SOA" serviceClass="com.abengoa.sim.soa.ws.

SistemaCentralSOA">

<cxf:properties>

<entry key="dataFormat" value="MESSAGE"/>

</cxf:properties>

</cxf:cxfEndpoint>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

59 PROPUESTA DE SOLUCIÓN

A la ruta se le asignará como punto de entrada un endpoint CXF que haga referencia al servicio web que se ha configurado. Esto se hace con la siguiente línea de código:

Una vez recibido un mensaje (petición) habrá que procesarlo. El procesado se limitará a analizar los mensajes y mandarlos a la ruta adecuada, que es donde se realizará la movilización de la actividad BizAgi (u otra operación si se integran otras aplicaciones). En este procesado se puede distinguir uno de los EIP. Se trata del Content Based Router (Enrutado basado en contenido). Es decir, en función del mensaje recibido, o más bien de su contenido, el mensaje se manda por una u otra ruta. A continuación se ve el código que se encarga del procesado:

Las etiquetas ‘choice’, ‘when’ y ‘otherwise’ permiten hacer el enrutado basado en contenido. Para ver la condición que debe cumplir el mensaje para ser mandado a una u otra ruta se usa la etiqueta ‘xpath’. En este caso estamos diciendo que si existe el nodo ‘movilizarActividad’, dentro del nodo ‘Body’, dentro del nodo raíz ‘Envelope’, entonces el mensaje se manda por la ruta que se encarga de movilizar la actividad. El caso otherwise se dará cuando no se cumpla ninguna de las otras condiciones, en cuyo caso se asigna al cuerpo del mensaje el valor “Invalid operation” para indicar al cliente del servicio web que no existe la operación que está tratando de ejecutar. Si se recibe el mensaje mostrado en la Figura 4.6, este será mandado a la ruta que realiza la movilización porque el mensaje SOAP contiene el nodo movilizarActividad.

<from uri="cxf:bean:sistemaCentralSOAEndpoint"/>

<choice>

<when>

<xpath>

/soapenv:Envelope/soapenv:Body/ws:movilizarActividad

</xpath>

<to uri="direct:movilizarActividad"/>

</when>

<otherwise>

<setBody>

<constant>Invalid operation</constant>

</setBody>

</otherwise>

</choice>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

60 PROPUESTA DE SOLUCIÓN

Ruta Servicio De Escucha

Esta ruta de momento se dedica a estar a la escucha de la respuesta asíncrona de los BES e imprimir en el LOG el código de la misma. De esta forma nos sirve para saber si había problemas en el envío del push. En un futuro podría usarse esta ruta para reenviar mensajes en el caso de que algo fallase. Para recibir los mensajes se ha empleado un endpoint Jetty como punto de entrada a la ruta. Este endpoint es mucho más sencillo de utilizar que el de CXF pues no requiere ninguna configuración. Únicamente hay que indicar en la uri la dirección en la que el servlet estará a la espera de peticiones:

Cualquier mensaje mandado a esta uri entrará a nuestra ruta. En concreto los mensajes que llegarán son los de respuesta asíncrona del BES que son como los ya mostrados en la Figura A.4.3. El código se encuentra almacenado en el atributo ‘code’ del nodo ‘resultnotificaiton-message’. Para obtenerlo se usará XPath, con el que se indica la ruta del nodo y luego el atributo de interés como se muestra a continuación.

Se ve cómo se ha extraído con XPath el atributo ‘code‘ y se ha guardado como cabecera del mensaje que va por la ruta. Sin embargo si se ejecuta esto sin más se produce un error debido a que XPath tiene problemas con el elemento <!DOCTYPE… del mensaje anterior. Por lo que hay que hacer un procesado previo para eliminarlo. Como Camel no dispone de un componente para hacer algo parecido hay que generar código Java para obtener la funcionalidad deseada. En concreto se generó la clase ProcesaXML. Esta clase tiene varios métodos, pero el que interesa en este momento es el método eliminaDoctype. En el método se obtiene el cuerpo del mensaje y se guarda en un BufferReader. Luego se lee línea a línea y se van concatenando ignorando las dos primeras líneas, que son las que no

<from uri="jetty:http://0.0.0.0:15844/respuestasBES/"/>

<setHeader headerName="codeBes">

<xpath resultType="java.lang.String">/pap/resultnotification

-message/@code</xpath>

</setHeader>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

61 PROPUESTA DE SOLUCIÓN

interesan. Finalmente se añaden saltos de línea entre nodos para que el XML tenga un buen formato. El código del método se muestra a continuación.

Para acceder a este método se usa el componente bean que proporciona Camel. Al que se le indica el identificador del bean y el método a llamar del bean:

El identificador del bean es ‘procesaXml’, que debe coincidir con el que se le asigna al definir el bean fuera del contexto Camel. Para definir el bean hay que asignar un identificador e indicar a qué clase de Java se quiere instanciar:

public String eliminaDoctype(Exchange exchange)

throws IOException{

String xmlOriginal = (String) exchange.getIn().getBody();

InputStream is =

new ByteArrayInputStream(xmlOriginal.getBytes());

InputStreamReader converter = new InputStreamReader(is);

BufferedReader in = new BufferedReader(converter);

String xmlProcesado = in.readLine();

String linea = in.readLine();

linea = in.readLine();

while(linea != null){

xmlProcesado = xmlProcesado.concat(linea);

linea = in.readLine();

}

xmlProcesado = xmlProcesado.replaceAll(">", ">\n");

return xmlProcesado;

}

<to uri="bean:procesaXml?method=eliminaDoctype"/>

<bean id="procesaXml"

class="com.abengoa.sim.soa.utils.ProcesaXML"/>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

62 PROPUESTA DE SOLUCIÓN

Si se hace este procesado ya no hay ningún problema en obtener el atributo ‘code’ y guardarlo como cabecera ‘codeBes’. Una vez obtenido el código se puede imprimir un mensaje en el LOG para indicarlo. El código usado para generar el LOG no es de gran importancia. Se remite al lector interesado al código fuente anexo al proyecto.

Ruta Recepción Mensajes BB

Las BlackBerry mandaban sus mensajes al antiguo Sistema Central mediante una petición POST a un servlet expuesto por dicho sistema. Ahora se volverá a hacer hincapié en uno de los principios de SOA: la reutilización. Se podría pensar que una buena solución podría ser, como se hizo en la recepción de peticiones de BizAgi, exponer un servicio web con su correspondiente contrato de servicio (WSDL). Sin embargo esto nos llevaría irremediablemente a la modificación de la aplicación SIM, y el objetivo era únicamente modificar el middleware. Por tanto la solución a adoptar será la exposición de un servlet para recibir los mensajes como ya hiciera el Sistema Central. Esto sólo supondría modificar en la BlackBerry la url a la que enviar los mensajes. Esto se puede hacer fácilmente gracias a que la aplicación SIM permite hacerlo como se ve en la Figura B.3.15. Para exponer el servlet se ha empleado un endpoint Jetty. Este endpoint ha sido expuesto en el puerto 15367, siendo la url:

http://172.28.70.197:15367/Recepcion_Mensajes/

Se tiene entonces una ruta con este endpoint como punto de entrada y que recibirá mensajes con el formato de la Figura B.3.16. El mensaje tiene una cabecera ‘c’ y un campo de información ‘info’. La cabecera contendrá una serie de atributos y el nodo ‘info’ contiene una serie de nodos ‘c’ que contienen información útil. Si el nodo ‘info’ va vacío quiere decir que se trata de un mensaje de asentimiento. El mensaje recibido se pasa ahora a una cola de la que posteriormente lo extraerá la ruta encargada de discriminar los mensajes. Para implementar la cola se usa el componente de Camel SEDA, que sirve para crear colas dentro de un mismo contexto de Camel.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

63 PROPUESTA DE SOLUCIÓN

Figura B.3.15 - Modificación de url en la aplicación SIM

Figura B.3.16 - Formato de un mensaje enviado por una BlackBerry

Para mandar el mensaje a la cola únicamente hay que indicar el nombre de la cola como se muestra a continuación:

<xml>

<c …></c>

<info>

<c e="…">…</c>

<c e="…">…</c>

<c e="…">…</c>

</info>

</xml>

<to uri="seda:mensajesBlackBerry"/>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

64 PROPUESTA DE SOLUCIÓN

Ruta Discriminación de Mensajes

Esta ruta comenzará sacando mensajes de la cola en la que con anterioridad se guardan los mensajes recibidos de las BlackBerry. Ahora se verá qué tipo de mensajes podemos recibir, esto nos ayudará a ver cómo discriminarlos y procesarlos de diferente manera. Se pueden recibir cinco tipos de mensajes. Cuatro de ellos relacionados con BizAgi y un quinto que manda la BlackBerry para preguntar si hay alguna actualización disponible de la aplicación SIM. Este último tipo de mensaje no se procesará, pues no está dentro del contexto de la Prueba de Concepto. Se procesarán únicamente los mensajes relacionados con la aplicación BizAgi. En las Figuras B.3.32, B.3.37 y B.3.42 se pueden ver ejemplos de mensajes de petición de tramitación de una actividad BizAgi, de petición de inicio de un proceso y de petición de delegación de una actividad. En la Figura B.3.17 se muestra un mensaje de asentimiento y en la Figura B.3.18 un mensaje de comprobación de actualización.

Figura B.3.17 - Mensaje Asentimiento de BlackBerry

Figura B.3.18 - Mensaje Actualización de BlackBerry

<xml>

<c fecbbtz="2011-03-10T12:08:44+0100"

fecbbrtz="2011-03-10T11:08:44+0000"

PIN="21369c5e" fec="10/03/2011"

fecbb="10/03/2011 12:08:44" par="-1" td="a" iu="" ac="16"

idso="785322~77834" men="" tas="Actividad" sub="25"

app="12" us="6801" sc="NO"

orig="SistemaCentralSOA:e1985052-ebbd-1b738bb2d3" tp="1">

</c>

<info/>

</xml>

<xml>

<c tp="0" app="1" tas="en" us="-1" sc="SI" ac="111"

fecbb="10/03/2011 12:33:02" fecbes="" PIN="21369c5e"

iu="1.21.93" />

<info>

<c e="servicio">GPRS</c>

<c e="tipo">6</c>

<c e="plataforma">4.2.0.118</c>

<c e="nombreDispositivo">8520</c>

<c e="nombreRed">214016.50.108071.1</c>

</info>

</xml>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

65 PROPUESTA DE SOLUCIÓN

Si se observan los mensajes con detenimiento se pueden establecer una serie de reglas para discriminarlos, las cuales se pueden ver en la Figura B.3.19 y que se describirán a continuación:

En primer lugar se mira si el mensaje está relacionado con algún servicio de la empresa o si se trata de un mensaje de actualización de la aplicación SIM. Éstos últimos son fácilmente reconocibles debido a que en su campo de cabecera (‘c’) no existe el atributo ‘sub’. Por lo que si no se encuentra este atributo se sabe que el mensaje es de actualización y se descartará.

Si la cabecera contiene el atributo ‘sub’ sabemos que es un mensaje

relacionado con algún servicio. Los mensajes de BizAgi están caracterizados por tener el atributo ‘app’ de la cabecera con valor 12. Por lo que si llega algún mensaje con un atributo ‘app’ distinto de 12 se descarta el mensaje (en un futuro si se incluyen más aplicaciones de la empresa habría que empezar a procesarlos también).

Si ya se sabe que se trata de un mensaje de BizAgi, el siguiente paso será saber

si se trata de un asentimiento o de una petición. Los asentimientos se reconocen porque el nodo ‘info’ está vacío, por lo que si llega un mensaje con el nodo ‘info’ vacío se imprime en el LOG que hemos recibido un asentimiento. No se hará ningún otro procesado para el asentimiento.

Si el nodo ‘info’ tiene contenido se está entonces ante una petición. Se puede identificar en primer lugar el mensaje de petición de inicio de proceso. Este mensaje contiene un atributo en su cabecera que no contienen las otras peticiones. Este atributo es ‘iu’ y contiene el nombre del proceso que se quiere iniciar. Por lo tanto si se recibe una petición que tiene este atributo en la cabecera, se manda el mensaje a la ruta encargada del inicio de procesos.

Si no contiene este atributo se trata de una petición de tramitación o delegación de actividad. Estos mensajes difieren en el contenido del nodo ‘c’ hijo del nodo ‘info’. El contenido es el parámetro que hay que pasar a BizAgi para que realice la tramitación o la delegación de la actividad. En el caso de la delegación de actividad existe un nodo ‘CaseInfo’ dentro del nodo ‘BizAgiWSParam’, por lo que habrá que basarse en la existencia o no de ese nodo ‘CaseInfo’ para saber si se trata de una petición de delegación o de tramitación.

No merece la pena poner el código que realiza la discriminación. Sólo comentar que se ha vuelto a hacer uso de las etiquetas ‘choice’, ‘when’ y ‘otherwise’, y que se ha usado XPath para establecer las condiciones de discriminación. En XPath destaca el uso de varias funciones como pueden ser: node(), que indica si el nodo al que acompaña entre corchetes contiene un nodo hijo; not(), que es una función lógica para negar; e in:header() que sirve para obtener el contenido de una cabecera del mensaje.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

66 PROPUESTA DE SOLUCIÓN

Figura B.3.19 - Esquema Discriminación de Mensajes

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

67 PROPUESTA DE SOLUCIÓN

Hay una parte del código que necesita explicación y es cuando ya se sabe a qué ruta hay que mandar el mensaje (Tramitación de actividad, Inicio de proceso o Delegación de actividad). Hasta ahora cuando se quería mandar un mensaje a otra ruta se usaba la etiqueta ‘to’, como se hizo en la ruta del servicio web cuando se mandaba el mensaje a la ruta encargada de movilizar la actividad. Pero si uno se fija en el código de esta ruta se usa la etiqueta ‘wireTap’ en lugar de ‘to’:

¿Por qué? Porque si se usa una etiqueta ‘to’ no se obtiene un correcto intercambio de mensajes. Esto se debe al funcionamiento que tienen las rutas. Si se llamara a la ruta encargada de procesar el mensaje (tramitar, iniciar o delegar), la ruta de discriminación quedaría esperando al mensaje de respuesta de la ruta llamada. Una vez procesado el mensaje se obtendría una respuesta y se podría llegar al final de esta ruta de discriminación, tras lo cual se respondería a la ruta de recepción de mensajes (que es la que la llamó). Una vez que la ruta de recepción reciba esta respuesta podrá acabar su ejecución y el endpoint Jetty podrá devolver un 200 OK (o un código de error si algo fue mal) al cliente que lo llamó. Por lo tanto se mandaría el 200 OK tras haber tramitado la actividad, iniciado el proceso o delegado la actividad y habérselo indicado a la BlackBerry, pero el dispositivo BlackBerry espera el 200 OK inmediatamente después de haber mandado la petición. Si se usa ‘wireTap’ se permite que el mensaje llegue al final de la ruta de discriminación, con lo que se responderá inmediatamente a la ruta de recepción de mensajes y el endpoint Jetty mandará el 200 OK. Mientras que lo que se manda a la ruta encargada del procesado será una copia del mensaje original. Esto se ve mejor en el esquema de la Figura B.3.20 con un ejemplo en el caso de que llegue una petición de tramitación de actividad.

Ruta Envío Push

Esta ruta será la encargada de hacer llegar los mensajes a las BlackBerry mediante el envío de Push a los BES. La ruta tendrá como punto de entrada una cola en las que las rutas de movilización, tramitación, delegación e inicio introducirán los mensajes que quieran mandar a las BlackBerry. Se trata de una ruta de envío común pues todos los mensajes que se manden a las BlackBerry tendrán el mismo formato. Únicamente varía el contenido del cuerpo del mensaje y algunas cabeceras en las que se indica la aplicación con la que se relaciona el mensaje. El formato de los mensajes es el mostrado en la Figura B.3.21.

<wireTap uri=direct:nombreRuta"/>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

68 PROPUESTA DE SOLUCIÓN

Figura B.3.20 - to vs wireTap

Figura B.3.21 - Formato mensaje enviados a BlackBerry

El mensaje consta de un nodo raíz, ‘mensaje’, que sirve de envoltorio de un mensaje que consta de una etiqueta ‘cabecera’ y otra ‘cuerpo’. En la etiqueta ‘cuerpo’ ira el contenido del mensaje, mientras que la etiqueta ‘cabecera’ cuenta con una serie de atributos que sirven a la aplicación SIM para tener información de donde viene ese mensaje. Algunos de estos atributos son:

fechaderecepcion: Indica la fecha y hora en el que el sistema recibe la petición de movilizar.

idaplicación, idsubsistema, idtipodesubsistema: Son códigos numéricos que identifican la aplicación y el subsistema del que viene el mensaje. En el caso de BizAgi los valores son: 12, 1225 y 25.

<?xml version="1.0" encoding="ISO-8859-1"?>

<mensaje xmlns=http://abengoa.com/sim

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

xsi:schemaLocation="http://abengoa.com/sim/bpmbizagi.xsd">

<cabecera esconfiguracion=… fechaderecepcion=… idaplicacion=…

idmensaje=… idpush=… idsubsistema=…

idtipodesubsistema=…

idusuario=… nombreabreviadotiposubsistema=…

nombretiposubsistema=… tipodeactualizacion=…"/>

<cuerpo>

</cuerpo>

</mensaje>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

69 PROPUESTA DE SOLUCIÓN

idpush: Es un identificador único de mensaje. Lo asignamos nosotros. Cuando la aplicación SIM de la BlackBerry responda a algún mensaje lo hará con el idpush del mensaje al que responde. Este dato también es usado por los BES.

idusuario: Identificador que asigna el equipo de movilidad a cada uno de los usuarios.

tipodeactualizacion: Indica la operación que la Blackberry debe realizar sobre el mensaje.

Por tanto los mensajes que lleguen a la cola de envío tendrán que contener el cuerpo del mensaje que se va a enviar a la BlackBerry así como información adicional almacenada en cabeceras para rellenar campos de la cabecera del mensaje que se enviará a la BlackBerry. También es necesaria información adicional para generar el push, como puede ser el Pin del usuario al que se quiere mandar el mensaje. Una vez sacado un mensaje de la cola de envío, lo que se debería hacer en primer lugar es generar el mensaje de la BlackBerry mediante una plantilla velocity. Sin embargo no se hace así. Como hay que generar el push también con una plantilla velocity, se aprovechará y se hará todo a la vez. Cuando llega un mensaje a esta ruta, se comienza por generar el mensaje (push) que hay que enviar al BES para que éste haga llegar el mensaje a la BlackBerry. Para generar el push se usa la plantilla velocity que se observa en la Figura B.3.22 (ver los archivos anexos al proyecto para verla completa).

Figura B.3.22 - papPushBB.vm

--asdlfkjiurwghasf

Content-Type: application/xml; charset=ISO-8859-1

<?xml version="1.0"?>

<!DOCTYPE pap PUBLIC "-//WAPFORUM//DTD PAP 2.0//EN"

"http://www.wapforum.org/DTD/pap_2.0.dtd"

[<?wap-pap-ver supported-versions="2.0"?>]>

<pap>

<push-message push-id="${headers.pushId}" ppg-notify-requested-

to="http://172.28.70.197:15844/respuestasBES/">

<address address-value="WAPPUSH=${headers.movilidadPinBB}%3A…

…${headers.portBB} /[email protected]"/>

<quality-of-service delivery-method="unconfirmed"/>

</push-message>

</pap>

--asdlfkjiurwghasf

Content-Type: text/plain

<?xml version="1.0" encoding="ISO-8859-1"?>

<mensaje …><cabecera …/><cuerpo>${body}</cuerpo></mensaje>

--asdlfkjiurwghasf--

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

70 PROPUESTA DE SOLUCIÓN

Se destacan a continuación algunos puntos importantes. En primer lugar con el atributo ‘to’ del nodo ‘push-message’ se indica al BES que la respuesta asíncrona debe ser enviada a la dirección http://172.28.70.197:15844/respuestasBES/, que es en la que se expuso el endpoint Jetty del servicio de escucha. Otro dato de interés es el puerto establecido en el ‘address-value’. Se trata del puerto de la BlackBerry en el que la aplicación SIM estará a la espera de mensajes entrantes. En este punto ya está preparado el push. Ahora queda mandarlo y para ello se hará una petición POST al BES correspondiente. La petición tendrá como cuerpo el push a enviar, y además habrá que asignar las siguientes cabeceras HTTP:

Content-Type: indica como es el cuerpo del mensaje. Se le asigna el valor ‘multipart/related; type=\"application/xml\"; boundary=asdlfkjiurwghasf‘.

X-Wap-Application-Id: Irá siempre con valor ‘/’ X-Rim-Push-Dest-Port: Puerto destino, tomará también el valor ‘100’

Además de estas cabeceras propias de los protocolos HTTP y WAP, hay que añadir cabeceras que serán interpretadas por el endpoint HTTP. Hay que tocar dos de estas cabeceras. Una de ellas es CamelHttpMethod al que habrá que asignar el valor POST, y la segunda de ellas es CamelHttpUri. Es necesario el uso de la cabecera CamelHttpUri porque la uri a la que se le mandará la petición POST depende del BES al que esté asignada la BlackBerry. Por tanto al ser dinámica no se puede poner directamente en la llamada al endpoint.

Por lo que no importa lo que escribamos en la uri de la etiqueta ‘to’, pues será sustituido por el contenido de la cabecera CamelHttpUri. Además también se puede comprobar que el BES al que mandaremos el push viene guardado como cabecera en el mensaje que llegó a la cola de envío. Una vez hecho esto el push queda mandado al BES y es este último el que se encargará de hacer llegar el mensaje a la BlackBerry del Pin correspondiente al usuario.

<setHeader headerName="CamelHttpMethod">

<constant>POST</constant>

</setHeader>

<setHeader headerName="CamelHttpUri">

<simple>http://${in.header.movilidadUrlBes}:8080/pap</simple>

</setHeader>

<to uri="http://mandapushalbes"/>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

71 PROPUESTA DE SOLUCIÓN

Con esto finaliza la exposición de las rutas comunes a todos los casos de uso. A continuación se explicarán las rutas que se encargan de realizar el procesado correspondiente a los cuatro casos de uso.

3.2.3. RUTAS: CASOS DE USO

Ruta Movilización Actividad

Se entiende por movilizar una actividad de BizAgi al enviar un formulario a la BlackBerry del usuario relacionado con la actividad. Cuando la aplicación web de BizAgi quiere movilizar una actividad, ésta consumirá el servicio movilizarActividad. El mensaje SOAP que debe enviar es el que ya se vio en la Figura B.3.3. Una vez recibida la petición por parte del servicio web, la ruta del servicio web se encargará de encaminar la petición a la ruta de movilización. Cuando se tiene el mensaje, hay que averiguar qué idioma tiene configurada la BlackBerry del usuario. Para ello se consume el método getUsuarioDeUsuarioLDAP del servicio web Servicio De Usuarios, pues el UsuarioLDAP es la única información de la que se dispone sobre el usuario en concreto. Una vez hecho esto hay pedir el formulario en un idioma que entienda el usuario del dispositivo móvil. Cuando se recibe el formulario hay que procesarlo y añadir unas cabeceras para adaptarlo al formato que entiende la aplicación SIM instalada en las BlackBerry. Finalmente se prepara el mensaje para el push y se envía a la ruta encargada del envío del push. En la Figura B.3.23 se muestra un esquema en el que se plasma el funcionamiento de la ruta.

Obtención de información de usuario La ruta del servicio web ya ha procesado la petición, ha detectado que se trata de una petición de movilización de actividad y ha encaminado el mensaje a esta ruta encargada de llevar a cabo la movilización. El siguiente paso, como ya se vio, es obtener la información que tiene movilidad de los usuarios. En concreto interesan los siguientes datos:

movilidad.pinBB: Hay que averiguar el PIN de la BlackBerry del usuario para poder mandarle los mensajes necesarios.

movilidad.urlBes: Indica el BES al que está asignado la BlackBerry del usuario.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

72 PROPUESTA DE SOLUCIÓN

Figura B.3.23 - Esquema Ruta Movilización Actividad

movilidad.usuarioMovilidadId: Hará falta este identificador de usuario cuando

se creen las cabeceras de los mensajes que se mandarán a las BlackBerry. movilidad.locale: Indica el idioma configurado en la BlackBerry, se usará para

pedir a BizAgi el formulario en el idioma oportuno. Hay que generar el mensaje SOAP de la Figura B.3.4 para hacer la llamada al método getUsuarioDeUsuarioLDAP del Servicio De Usuarios y así obtener los datos del usuario.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

73 PROPUESTA DE SOLUCIÓN

Para generar este mensaje hace falta conocer el usuarioLDAP. Éste viene en la petición que nos hizo BizAgi, por lo que en un primer paso hay que extraer esta información del mensaje. Hay que tener en cuenta una consecuencia importante del uso de Camel. Cuando se crea el mensaje SOAP, en realidad no se crea un nuevo mensaje sino que se modifica el cuerpo del mensaje que va circulando por la ruta. Por tanto se perderá el mensaje de petición de movilización de actividad. Por ello cuando se extraiga el usuarioLDAP de la petición, también se extraerá el resto de parámetros y se guardarán como propiedades del mensaje. De esta forma se evita perder estos parámetros que serán de utilidad más adelante en la ruta.

A continuación se ve un fragmento de código en el que se muestra cómo se extrae el usuarioLDAP del mensaje. El resto de propiedades se extraerán de la misma manera.

Con XPath se selecciona el nodo ‘usuarioLDAP’ y mediante la función text() se indica que debe obtener el texto que hay contenido en el nodo. El atributo ‘resultType’ de la etiqueta ‘xpath’ está indicando que se devuelva el resultado como un objeto String de Java.

Antes de generar el mensaje SOAP con el que se invocará al Servicio De Usuarios, se realizan dos operaciones. Se llaman a dos beans Java, en concreto los que instancian las clases HoraLocal y Push. Estas dos clases se usan para obtener la fecha y hora en que se recibe el mensaje y para generar un identificador único de mensaje.

Se explicará ahora brevemente que hacen estas clases, empezando por HoraLocal. La clase HoraLocal consta de un único método que se encargará de devolver en un String la fecha y hora del instante en que se llama al método. A continuación se muestra el código del método getHoraLocal:

<setProperty propertyName="usuarioLDAP">

<xpath resultType="java.lang.String">

/soapenv:Envelope/soapenv:Body/ws:movilizarActividad/

usuarioLDAP/text()

</xpath>

</setProperty>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

74 PROPUESTA DE SOLUCIÓN

Al crear un objeto de la clase Date se obtiene la hora y fecha, y usando la clase SimpleDateFormat se pone la fecha en el formato que interese. Por su parte la clase Push también tiene un único método que devuelve un String con un identificador único de mensaje. El código de getPushId es el siguiente:

Se usa el método randomUUID de la clase UUID para generar el identificador pseudo-aleatorio.

Ahora, para poder acceder a los beans Java desde el contexto de camel,

primero hay declarar estos beans fuera del mismo mediante el siguiente código:

Se usa la etiqueta bean, la cual contiene el atributo class que indica la clase java que instanciará el bean y el atributo id que es el identificador con el que se hace referencia al bean. Se ha puesto el ejemplo para la clase HoraLocal, para el resto de clases se operará de idéntica manera. Finalmente se pueden hacer llamadas a los métodos de estos beans desde la ruta camel. Para hacer esto se opera como se muestra a continuación:

public String getHoraLocal(){

Date fechaActual = new Date();

SimpleDateFormat formatoFecha;

formatoFecha = new SimpleDateFormat("dd:MM:yyyy HH:mm:ss");

String horaActual = formatoFecha.format(fechaActual);

return horaActual;

}

public String getPushId(){

return "SistemaCentralSOA:" + UUID.randomUUID().toString();

}

<bean id="obtenHora"

class="com.abengoa.sim.soa.utils.HoraLocal"/>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

75 PROPUESTA DE SOLUCIÓN

Vemos que se manda el mensaje (etiqueta ‘to’) al primer bean (obtenHora). Mediante la opción method se indica el método del bean que invocamos. Cómo el método getHoraLocal no recibe parámetros simplemente ignorará el mensaje entrante. El mensaje que es devuelto contiene en el cuerpo el String con la fecha y hora. Se usa ‘setProperty’ para guardar la fecha como una propiedad. En este caso la etiqueta hija de ‘setProperty’ no es ‘xpath’, sino ‘simple’. Usamos simple para indicar que queremos que la propiedad guardada sea el cuerpo del mensaje, lo cual es indicado con ${in.body}. Se opera de idéntica manera con el segundo bean. En este punto ya están guardados los parámetros de la petición BizAgi, así como otros dos valores de interés generados y almacenados en propiedades del mensaje. Ahora ya se puede pasar a modificar el cuerpo del mensaje para convertirlo en el mensaje SOAP de la Figura B.3.4. Para generar el mensaje se usará la plantilla velocity que se muestra en el siguiente cuadro de texto.

Figura B.3.24 - getUsuarioDeUsuarioLDAP.vm

Con ${headers.usuarioLDAP} se indica al componente velocity que debe sustituir esa cadena por la cabecera de nombre usuarioLDAP del mensaje que le llegue. Por tanto, antes de pasar el mensaje al componente de velocity hay que crearle una cabecera con nombre usuarioLDAP y asignarle la propiedad usuarioLDAP que se almacenó con anterioridad. Para hacer esto se usa el código:

<to uri="bean:obtenHora?method=getHoraLocal"/>

<setProperty propertyName="fechaDeRecepcion">

<simple>${in.body}</simple>

</setProperty>

<to uri="bean:pushBean?method=getPushId"/>

<setProperty propertyName="pushId">

<simple>${in.body}</simple>

</setProperty>

<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/

soap/envelope/ xmlns:ws="http://ws.usuarios.servicios.sim.

telvent.abengoa.com/">

<soapenv:Header/>

<soapenv:Body>

<ws:getUsuarioDeUsuarioLDAP>

<usuarioLdap>${headers.usuarioLDAP}</usuarioLdap>

</ws:getUsuarioDeUsuarioLDAP>

</soapenv:Body>

</soapenv:Envelope>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

76 PROPUESTA DE SOLUCIÓN

El cuerpo del mensaje no es importante pues será eliminado para crear el

nuevo cuerpo. Una vez creada la cabecera ya se puede llamar al componente velocity para que

pueda crear el mensaje. Al componente velocity hay que indicarle qué plantilla debe usar de la siguiente manera:

Ya está creado el mensaje, luego ya solo queda hacer la petición al Servicio De Usuarios mandando el mensaje SOAP. Para poder hacer esto hay que configurar un endpoint CXF como ya se hizo con nuestro propio servicio, solo que ahora tendremos que cambiar los atributos de la etiqueta cxfEndpoint:

id: Lo llamaremos usersEndpoint. address: Este servicio está alojado en el servidor de desarrollo:

http://srv-wasdes/servicio-de-usuarios/ws/ServicioDeUsuarios serviceClass: La clase que define la interfaz es:

com.abengoa.telvent.sim.servicios.usuarios.ws.ServicioDeUsuariosWS

Se usa una clase de un paquete que no es de creación propia, por lo que habrá que añadirlo como dependencia a nuestro proyecto.

Estando ya definido el endpoint, solo queda hacerle llegar el mensaje SOAP:

En la Figura B.3.6 se mostraba un ejemplo de respuesta, lo que queda hacer es sacar la información que interesa y guardarla como propiedades. Si uno se fija en la Figura B.3.6 puede observar que existen múltiples nodos ‘entry’ dentro del nodo ‘propiedades’. Los nodos ‘entry’ tienen dos nodos hijo: ‘key’ y ‘value’. El nodo hijo ‘key’ indica el nombre de la propiedad y el nodo ‘value’ su valor. Se ve ahora un ejemplo de cómo obtener el nodo ‘entry’ que contiene el dato movilidad.urlBes:

<setHeader headerName="usuarioLDAP">

<property>usuarioLDAP</property>

</setHeader>

<to uri="velocity:getUsuarioDeUsuarioLDAP.vm"/>

<to uri="cxf:bean:usersEndpoint"/>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

77 PROPUESTA DE SOLUCIÓN

Para acceder al valor de una propiedad hay que escribir en el XPath: …/return/propiedades/entry/value/text(). Pero esto no es suficiente, hay que indicarle cual es el ‘entry’ que nos interesa. Para ello le decimos que queremos el que tenga el key correspondiente mediante: …/entry[key='movilidad.urlBes']/… Con esto ya se ha terminado de obtener la información del usuario. Ahora nos queda pedir el formulario a BizAgi, procesarlo y mandárselo a la BlackBerry.

Petición del formulario a la aplicación de BizAgi Llegó el momento de hacer la petición al servicio web RenderSOA.asmx expuesto por BizAgi y de explicar el porqué del hacer uso de una petición GET en lugar de seguir usando SOAP. Se trata de una decisión forzada usar GET en lugar de SOAP. Cuando se vio la configuración de los endpoints CXF se pudo observar que uno de los atributos que hay que indicar es serviceClass, que hacía referencia a la clase en la que está definida la interfaz del servicio web. Un dato a tener en cuenta y no comentado aún es que hay que proporcionar este atributo obligatoriamente. Pero a diferencia del Servicio De Usuarios, no tenemos acceso a esa clase. Esto se debe a que el Servicio De Usuarios fue creado por el grupo de movilidad, mientras que RenderSOA.asmx queda fuera de nuestro alcance. Había que buscar una solución, y esta fue usar un endpoint HTTP en lugar de un endpoint CXF gracias a que también se ofrece el equivalente servicio REST de RenderSOA.asmx. El porqué del uso de una petición GET en lugar de POST no tiene ningún motivo particular, era indiferente realizar una u otra. Se accede al método getActivityFormXML de RenderSOA.asmx mediante GET a través de la url: http://srv-desbizagi.abg.corp/bizagi_des/WebServices/RenderSOA.asmx/GetActivityFo rmXML?requestInfoData=... Para realizar la petición GET se usa el componente HTTP. A este componente se le pasan dos cabeceras (en este caso el cuerpo del mensaje no es importante al tratarse de una petición GET):

<setProperty propertyName="movilidadUrlBes">

<xpath resultType="java.lang.String">/soap:Envelope/soap:Body/ns2:g

etUsuarioDeUsuarioLDAPResponse/return/propiedades/entry[key='movilidad

.urlBes']/value/text()</xpath>

</setProperty>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

78 PROPUESTA DE SOLUCIÓN

CamelHttpMethod: Tendrá el valor GET para indicar que se quiere hacer ese tipo de petición.

CamelHttpQuery: Esta cabecera contendrá los parámetros requeridos por el método invocado. Debe llevar codificación URL. En nuestro caso solo hay que mandar el parámetro requestInfoData.

En primer lugar se genera la cabecera CamelHttpQuery, para lo que se usa el siguiente código:

Vemos como se asigna a la cabecera el cuerpo del mensaje que llegue a este punto. Por lo que antes se usará una plantilla velocity para asignar al cuerpo del mensaje el parámetro requestInfoData. Recordar que el contenido de requestInfoData debe contener lo mostrado en la Figura B.3.7, sin embargo hay que adaptarlo a la codificación URL. Para ello se eliminarán espacios y se sustituirán ‘<’ y ‘>’ por %3C y %3E respectivamente.

Figura B.3.25 - getActivityForm.vm

Se puede observar que, como ya se hizo antes, se pasan al componente velocity los datos que debe usar para rellenar la plantilla por medio de cabeceras en el mensaje. Así que antes de llamar al componente de velocity debemos asignar las cabeceras: dominio, movilidadLocale, idProceso e idActividad. Hay que recordar que estos datos estaban guardados como propiedades por lo que hay que proceder como ya se hizo con la cabecera usuarioLDAP. Para asignar la otra cabecera, CamelHttpMethod, simplemente hay que hacer:

<setHeader headerName="CamelHttpQuery">

<simple>${in.body}</simple>

</setHeader>

requestInfoData=%3CBizAgiWSParam%3E%3Cdomain%3E${headers.dominio

}%3C/domain%3E%3CuserName%3E${headers.usuarioLDAP}%3C/userName%3

E%3CidLanguage%3E${headers.movilidadLocale}%3C/idLanguage%3E%3CC

ase%3E%3CidCase%3E${headers.idProceso}%3C/idCase%3E%3CidWorkItem

%3E${headers.idActividad}%3C/idWorkItem%3E%3C/Case%3E%3C/BizAgiW

SParam%3E

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

79 PROPUESTA DE SOLUCIÓN

Ya establecidas las cabeceras se pasa a mandar el mensaje al componente HTTP. Este componente se encarga de añadir los parámetros dados en la cabecera CamelHttpQuery a la uri que se indique en la etiqueta ‘to’, y de realizar la petición GET.

Los parámetros que se pasan con la petición GET pueden ser puestos directamente en la uri de la etiqueta ‘to’, pero sólo si se pasa siempre el mismo parámetro. Se ha usado la cabecera CamelHttpQuery porque el parámetro a pasar depende de la actividad y el usuario. Tras esto se recibe la respuesta de BizAgi, la cual puede ser el formulario si todo ha ido correctamente o un mensaje de error si no. Por tanto habrá que procesar esta respuesta.

Procesado respuesta de la aplicación BizAgi La respuesta de BizAgi vendrá en el cuerpo del mensaje, así que el siguiente objetivo será comprobar si ha habido error o no durante la petición del formulario. Si la petición ha ido bien, el resultado devuelto por BizAgi será el formulario a cumplimentar que tiene la forma que se observa en la Figura B.3.26. Mientras que si ha habido algún tipo de error el mensaje devuelto por BizAgi será como el mostrado:

El mensaje de error consta de la etiqueta ‘errorMessage’, que siempre contendrá texto e indica el error que se ha producido, y de la etiqueta

<setHeader headerName="CamelHttpMethod">

<constant>GET</constant>

</setHeader>

<to uri="http://srv-desbizagi.abg.corp/bizagi_des/WebServices/

RenderSOA.asmx/GetActivityFormXML"/>

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

<processError>

<errorMessage>???</errorMessage>

<innerException />

</processError>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

80 PROPUESTA DE SOLUCIÓN

‘innerException’, que según sea el error contendrá texto o será una etiqueta vacía. Un ejemplo de ‘errorMessage’ es:”Invalid Workitem. The work ítem does not exist or is closed for the given idCase and user”.

Por lo tanto para identificar si ha habido error o no lo que se hará es examinar el nodo raíz del XML devuelto por BizAgi. Si el nodo raíz es ‘processError’ será que se ha producido un error, para identificarlo se volverá a hacer uso de XPath. En el código de la Figura B.3.27 se observa cómo se comprueba con XPath si existe error. En el caso que exista se comprueba si la etiqueta ‘innerException’ contiene texto mediante “not(string(/processError/innerException))”. Según tenga o no texto esta etiqueta, se imprimirá en el log un mensaje de error distinto. Si se ha recibido un formulario válido. Ahora hay que procesarlo para adaptarlo a la BlackBerry. El procesado que hay que hacer es simple, únicamente hay que quitar la etiqueta ‘BizAgiResponse’ que envuelve el formulario. Para quitar esta etiqueta lo que se hará es usar XPath para quedarnos con todos los nodos hijos del nodo raíz ‘BizAgiResponse’. El código que hace esto es el siguiente:

Ya está preparado el formulario, ahora hay que encapsularlo en un mensaje que es que lo que habrá que enviar al BES para que éste lo haga llegar a la BlackBerry adecuada.

Preparación cuerpo mensaje BlackBerry En la Figura B.3.21 ya se mostró el formato de mensaje que emplea la aplicación SIM de las BlackBerry de la empresa. Lo que hay que hacer en este momento es generar el cuerpo del mensaje. Este cuerpo se muestra en la Figura B.3.28. La etiqueta ‘actividad’ da información sobre la actividad BizAgi, la única aclaración que merece es que el atributo ‘infoUsuario’ se refiere al usuarioLDAP mientras que el atributo ‘usuario’ se refiere al identificador de movilidad del usuario. El nodo hijo ‘formulario’ contendrá el formulario BizAgi al que previamente hemos eliminado la etiqueta ‘BizAgiResponse’.

<setBody>

<xpath>BizAgiResponse/*</xpath>

</setBody>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

81 PROPUESTA DE SOLUCIÓN

Figura B.3.26 - Respuesta BizAgi con formulario

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

<BizAgiResponse>

<Form RenderId="1896" Editable="True"… >

<Tab DisplayName="Información del proceso">

<Group DisplayName="Datos Solicitud">

<Text RenderId="12172" DisplayName="Tipo de formulario"… />

<Form RenderId="3371" Editable="False"… >

<Form RenderId="3370" Editable="False">

<DateTime RenderId="19485"… />

</Form>

</Form>

<Text RenderId="9061" DisplayName="Creado por"… />

<Form RenderId="1740" Editable="True"… >

<Text RenderId="8083" DisplayName="Sociedad"… />

</Form>

<Form RenderId="1741" Editable="True" DisplayName="(DG_1)">

<Form RenderId="1900" Editable="True"… >

… </Form>

</Form>

</Group>

</Tab>

</Form>

<CaseInfo>

<IdCase>76414</IdCase>

<IdWorkItem>778588</IdWorkItem>

<RadicationNumber>C10-PRL05-23791</RadicationNumber> <SolutionDate>2011-03-02T09:30:41.0000000+01:00</SolutionDate>

<Creator>

<Id>276</Id>

<UserName>INJBO</UserName>

<Domain>ABG</Domain>

<FullName>Jesus Burgers Onate</FullName>

</Creator>

<Activity>

<Id>960</Id>

<Name>PRLWF01_Cuestionario</Name>

<DisplayName>Cumplimentar Formulario</DisplayName>

<AllowsReassign>False</AllowsReassign>

</Activity>

<Process>

<Id>54</Id>

<Name>pPRL05_EspacioConfinado</Name>

<DisplayName>PRL05 Trabajo en Espacios Confinados</DisplayName>

</Process>

</CaseInfo>

</BizAgiResponse>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

82 PROPUESTA DE SOLUCIÓN

Figura B.3.27 - Comprobación si Error en Obtención de Formulario BizAgi

Figura B.3.28 - Cuerpo Mensaje BlackBerry para BizAgi

<choice>

<when>

<xpath>/processError/*</xpath>

<setHeader headerName="errorMessage">

<xpath resultType="java.lang.String">/processError/error

Message</xpath>

</setHeader>

<choice>

<when>

<xpath>not(string(/processError/innerException))</xpath>

<to uri="bean:obtenHora?method=getHoraLocal"/>

<setBody>

<simple>ERROR - ${in.body} -

${in.headers.errorMessage}</simple>

</setBody>

</when>

<otherwise>

<setHeader headerName="innerException">

<xpath resultType="java.lang.String">/processError/in

nerException</xpath>

</setHeader>

<to uri="bean:obtenHora?method=getHoraLocal"/>

<setBody>

<simple>ERROR - ${in.body} - ${in.headers.errorMessage}

: ${in.headers.innerException}</simple>

</setBody>

</otherwise>

</choice>

</when>

<otherwise>

<!-- Procesar formulario -->

</otherwise>

</choice>

<actividad dominio=… idActividad=… idProceso=… idTipoSubsistema=…

infoUsuario=… tipoActualizacion=… usuario=… >

<formulario>

</formulario>

</actividad>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

83 PROPUESTA DE SOLUCIÓN

Para generar el mensaje se ha vuelto a recurrir a una plantilla velocity (Figura B.3.29), a la que se pasa el formulario en el cuerpo del mensaje que recorre la ruta de Camel y los atributos del nodo ‘actividad’ mediante cabeceras (todos datos que se recibieron en su momento en la petición de BizAgi).

Figura B.3.29 - actividadBizAgi.vm

Una vez que se tiene el cuerpo del mensaje preparado solo queda envolver el cuerpo según el formato de la Figura B.3.21 y enviar el push. Como el formato de la Figura B.3.21 es común a todas las aplicaciones, se creará el mensaje a mandar a la BlackBerry en la ruta que se encargue de mandar el push. Por tanto el mensaje que es mandado a esa ruta deberá contener como cuerpo el cuerpo del mensaje que se quiere enviar a la BlackBerry, y deberá contener las cabeceras necesarias para completar los atributos del nodo ‘cabecera’ de la Figura B.3.21. Hay que destacar un problema surgido durante la implementación. Este problema es que la aplicación SIM solo era capaz de entender el mensaje si este iba contenido en una sólo línea y no en varias como se muestra en la Figura B.3.21. Para solucionar el problema se procedió de la siguiente manera: En primer lugar se modificaron las plantillas velocity que creaban tanto el mensaje BlackBerry como el cuerpo del mismo. Ahora están como puede observarse en los archivos anexos actividadBizAgi.vm y papPushBB.vm. Se han puesto en una única línea. En segundo lugar hay que realizar al formulario BizAgi un procesado adicional ya que éste llega como se vio en el apartado anterior y hay que ponerlo en una sola línea. Para conseguir esto se creó un nuevo bean Java que instancia la clase ProcesaXML. La clase contiene varios métodos que se han creado para solventar más problemas que fueron surgiendo durante la elaboración del proyecto. El método que se creó para el problema que nos ocupa es eliminaTabulaciones, cuyo código puede verse en la Figura B.3.30.

<actividad dominio="${headers.dominio}"

idActividad="${headers.idActividad}"

idProceso="${headers.idProceso}"

idTipoSubsistema="25"

infoUsuario="${headers.usuarioLDAP}"

tipoActualizacion="${headers.tipoActualizacion}"

usuario="${headers.movilidadUsuarioMovilidadId}">

<formulario>${body}</formulario>

</actividad>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

84 PROPUESTA DE SOLUCIÓN

Este método recibe como parámetro de entrada el mensaje que va recorriendo la ruta Camel, del cual se coge el cuerpo y se guarda en un String. Se irá leyendo línea a línea el XML original. De cada línea se cogerá la información útil eliminando cualquier tipo de espacio o tabulación al principio de la línea, y se irá concatenando las líneas en un nuevo String que es el que devolverá el método. Para ejecutar el método se usa la siguiente línea:

Figura B.3.30 - Clase: ProcesXML, Método: eliminaTabulaciones

Preparación para mandar push

Como ya se ha comentado en varias ocasiones, será otra ruta la que se encargue de mandar el push al BES. Como se dijo en el apartado anterior, esta ruta también se encargará de crear el mensaje BlackBerry. Por lo tanto antes de mandar el mensaje a la ruta Camel encargada del push, se tienen que añadir las cabeceras que se usarán para establecer los atributos del nodo ‘cabecera’ del mensaje BlackBerry.

<to uri="bean:procesaXml?method=eliminaTabulaciones"/>

public String eliminaTabulaciones(Exchange exchange)

throws IOException{

int ind;

String xmlOriginal = (String) exchange.getIn().getBody(); String xmlProcesado = "";

InputStream is =

new ByteArrayInputStream(xmlOriginal.getBytes()); InputStreamReader converter = new InputStreamReader(is); BufferedReader in = new BufferedReader(converter);

String linea = in.readLine();

while(linea != null){ ind = linea.indexOf('<'); linea = linea.substring(ind); xmlProcesado = xmlProcesado.concat(linea); linea = in.readLine(); }

return xmlProcesado;

}

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

85 PROPUESTA DE SOLUCIÓN

Estas cabeceras son:

fechaderecepcion: Se genera al comienzo de la ruta mediante el bean obtenHora.

idaplicacion, idsubsistema, idtipodesubsistema, nombretiposubsistema, nombreabreviadotiposubsistema: Tienen un valor fijo: “12”, “1225”, “25”, “Actividades Bizagi” y “Act. Bizagi”

idusuario: Dato que se obtuvo del servicio web ServicioDeUsuarios. idpush: Se generó al comienzo de la ruta mediante el bean pushBean. tipodeactualizacion: Será el que nos pasa BizAgi en su petición.

Los atributos ‘idmensaje’ y ‘esconfiguracion’ no se usan. ‘idmensaje’ irá vacío (“”) y ‘esconfiguracion’ lleva siempre valor 0. Si se observa la plantilla velocity usada para generar el push (Figura B.3.22), se puede ver que hay añadir otras cabeceras adicionales antes de mandar el mensaje a esta ruta. Hay que añadir el pin de la BlackBerry a la que se tiene que enviar el mensaje y el puerto en el que estará escuchando la aplicación SIM, cuyo puerto es el 100. Una vez creadas las cabeceras se manda el mensaje Camel a la ruta encargada del push mediante el código:

Una vez enviado el push por medio de la ruta de envío de push, será tarea de los BES el hacer llegar el mensaje a la BlackBerry correspondiente y será tarea de la aplicación SIM de las BlackBerry el procesar ese mensaje y presentárselo a través del display al usuario. Con esto queda finalizado el primero de los dos casos de uso que componen la Prueba de Concepto. Una vez que el usuario reciba el formulario en su BlackBerry lo rellenará y querrá que se lleve a cabo la tramitación. Empieza así el segundo caso de uso, que llevará en este caso la comunicación en sentido inverso, del dispositivo móvil a la aplicación web.

Ruta Tramitación Actividad

Se comenzará este apartado con un breve resumen en el que se explica en qué consiste la tramitación de una actividad y qué tareas hay que llevar a cabo para conseguir alcanzar nuestro objetivo. Para tramitar una actividad hay que llevar el formulario cumplimentado por el usuario desde su dispositivo móvil hasta la aplicación web de BizAgi. La aplicación ya se

<to uri="direct:mandaPushBB"/>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

86 PROPUESTA DE SOLUCIÓN

encargará de tramitar la actividad. Además de trasladar el formulario, se tiene que realizar una serie de tareas adicionales como transformaciones de XML, llamadas a servicios web, comprobación de errores… Cuando se reciba una petición de tramitación por parte de la ruta de discriminación de mensajes, se cogerá el formulario cumplimentado que contiene la petición y habrá que hacérselo llegar a BizAgi para que lo tramite. El resultado de esta tramitación hay que hacérselo saber al dispositivo móvil, por lo que habrá que mandar de nuevo un push a la BlackBerry para hacerle saber el resultado. Debido a la necesidad de mandar un push se tiene que volver a obtener información sobre el usuario como ya se hizo al movilizar la actividad. En la Figura B.3.31 se muestra un esquema en el que se pueden ver las tareas a realizar por la ruta.

Formato petición de Tramitación de Actividad En la Figura B.3.32 se ve un ejemplo de petición de tramitación mandada por una BlackBerry. En primer lugar se comentarán algunos de los campos de la cabecera que son de interés:

app, sub: Dicen la aplicación y subsistema con los que está vinculado el mensaje. En el caso de BizAgi toman los valores 12 y 25 como se observa en la Figura B.3.32.

orig: Es el identificador del push del mensaje al que responde. us: Es el identificador de usuario de Movilidad. PIN: PIN de la BlackBerry que manda el mensaje. idso: Atributo propio de los mensajes de BizAgi, compuesto por el idActividad y

el idProceso. En cuanto al cuerpo del mensaje, el nodo ‘info’ tiene un nodo hijo ‘c’ que contiene un fragmento XML guardado como String. Ese fragmento XML consta del nodo raíz ‘BizAgiWSParam’, que tiene los siguientes nodos hijo:

domain: El dominio es siempre ABG. userName: UsuarioLDAP del usuario. ActivityData: Contiene información sobre la actividad a tramitar. Entities: Contiene las respuestas que ha dado el usuario al formulario.

Este fragmento XML es lo que espera recibir la aplicación de BizAgi como parámetro de entrada al método performActivityAsString, es el parámetro activityInfo.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

87 PROPUESTA DE SOLUCIÓN

Figura B.3.31 - Esquema Ruta Tramitación Actividad

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

88 PROPUESTA DE SOLUCIÓN

Figura B.3.32 - Mensaje BlackBerry: Petición Tramitación Actividad

<xml>

<c fecbbtz="2011-03-10T12:08:44+0100"

fecbbrtz="2011-03-10T11:08:44+0000"

PIN="21369c5e" fec="10/03/2011" fecbb="10/03/2011 12:08:44"

par="-1" td="a" iu="" ac="16" idso="785322~77834" men=""

tas="Actividad" sub="25" app="12" us="6801" sc="NO"

orig="SistemaCentralSOA:e1985052-ebbd-1b7138abb2d3" tp="1">

</c>

<info>

<c e="comentarios">

<![CDATA[

<BizAgiWSParam>

<domain>ABG</domain>

<userName>INJBO</userName>

<ActivityData>

<radNumber>C10-PRL03-24089</radNumber>

<taskId>960</taskId>

<idCase>77834</idCase>

<idWorkItem>785322</idWorkItem>

</ActivityData>

<Entities>

<XPath xpath="idPRL.idPRL_POC.sObservaciones">

Observación

</XPath>

<XPath xpath="idPRL.idPRL_POC.idEncargadoObra">

5

</XPath>

<XPath xpath="idPRL.idPRL_POC.bSubcontrata">

False

</XPath>

<XPath xpath="idPRL.idPRL_POC.idObra">51</XPath>

<XPath xpath="idDatosGenerales.sDescripcionCaso">

Actividad

</XPath>

<XPath xpath="idPRL.idPRL_POC.sUbicacion">

Ubicación

</XPath>

<XPath xpath="idPRL.idPRL_POC.idInterlocutorPRL">

5

</XPath>

<XPath xpath="idPRL.idPRL_POC.idCuestionario01.

idPregunta01">

1

</XPath>

</Entities>

</BizAgiWSParam>

]]>

</c>

</info>

</xml>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

89 PROPUESTA DE SOLUCIÓN

Obtención información de usuario Una vez que llegue un mensaje de petición de tramitación de actividad a la ruta se obtendrá del mismo toda la información que sea de utilidad. Esta información será la siguiente:

Fragmento XML almacenado como String dentro del nodo ‘info’, el cual se guardará como propiedad, activityInfo. Se utilizará cuando se invoque al método performActivityAsString del servicio REST expuesto por BizAgi, WorkflowEngineSOA.asmx.

PIN, us, idso. En el caso del idso habrá que realizar algunas operaciones para separar el idActividad del idProceso.

A continuación se expone un ejemplo de cómo obtener con XPath un atributo de un nodo. Hay que usar una @ para indicar que es un atributo.

Se ha dicho que hay que sacar el idActividad y el idProceso del parámetro idso. El parámetro idso contiene el idActividad seguido del idProceso, separados ambos por un ‘~’. No se dispone de ningún componente que pueda servir para realizar esta operación, por ello hay que recurrir nuevamente a crear una clase Java. Se generará un bean que instancie a la clase ObtencionIds fuera del contexto Camel como ya se hizo con las clases HoraLocal y Push, y en la ruta que nos ocupa llamaremos al método obtenIds de dicho bean. Para definir el bean:

El método obtenIds espera recibir el idso como cuerpo del mensaje, por tanto para invocar al método hay que usar las siguientes líneas:

Ahora se muestra el código Java del método que lleva a cabo la obtención de ambos identificadores.

<setProperty propertyName="idso">

<xpath resultType="java.lang.String">/xml/c/@idso</xpath>

</setProperty>

<bean id="obtencionIds"

class="com.abengoa.sim.soa.utils.ObtencionIds"/>

<setBody><property>idso</property></setBody>

<to uri="bean:obtencionIds?method=obtenIds"/>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

90 PROPUESTA DE SOLUCIÓN

Como se puede observar, hemos usado la clase StringTokenizer. Esta clase permite separar el String en ‘Tokens’, pudiendo indicar qué carácter se quiere como delimitador de Tokens. Por ello se ha pasado al constructor de esta clase el String que contiene el idso, y se ha indicado que el delimitador de Tokens es ‘~’. Luego únicamente se tuvo que usar el método nextToken de la clase StringTokenizer para ir leyendo uno a uno los Tokens. Además de estos datos se generarán los datos fechaDeRecepcion y pushId como ya se hizo en la ruta de movilización de actividades. Sigue haciendo falta más información cómo por ejemplo el BES al que está asignada la BlackBerry del usuario. Por ello se hará una invocación al método getUsuarioDePIN del servicio web ServicioDeUsuarios. Se usa este método porque ahora con lo que se cuenta es el PIN de la BlackBerry y no el usuarioLDAP. Para llamar al método se tiene que generar el mensaje SOAP de la Figura B.3.5. Se volverá a usar una platilla velocity para tal propósito. Si se observa la plantilla (Figura B.3.33), se puede ver que para rellenar el campo usuarioPin se usa la cabecera movilidadPinBB. Por ello antes de llamar al componente velocity hay que crear la cabecera movilidadPinBB a la que se asignará la propiedad PIN previamente obtenida del mensaje.

Figura B.3.33 - getUsuarioDePIN.vm

public void obtenIds(Exchange exchange) {

String idso = (String) exchange.getIn().getBody();

StringTokenizer idsoToken = new StringTokenizer(idso, "~");

exchange.setProperty("idWorkItem", idsoToken.nextToken());

exchange.setProperty("idCase", idsoToken.nextToken());

}

<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/

soap/envelope/ xmlns:ws="http://ws.usuarios.servicios.sim.

telvent.abengoa.com/">

<soapenv:Header/>

<soapenv:Body>

<ws:getUsuarioDePIN>

<usuarioPin>${headers.movilidadPinBB}</usuarioPin>

</ws:getUsuarioDePIN>

</soapenv:Body>

</soapenv:Envelope>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

91 PROPUESTA DE SOLUCIÓN

Una vez obtenida la respuesta se guardan los parámetros que harán falta a lo largo de la ejecución de la ruta. Estos parámetros son: movilidad.urlBes, BES al que está asociada la BlackBerry, y el usuarioLDAP. Ya se tiene todo lo necesario para invocar al método performActivityAsString, por lo que ahora hay que preparar la petición y enviársela al servicio REST WorkflowEngineSOA.asmx de BizAgi.

Petición de tramitación a BizAgi Se vuelve a hacer uso de peticiones GET para llamar a los servicios de BizAgi. Para hacer la petición se vuelve a emplear un endpoint HTTP, y se vuelve a dar valores a las cabeceras CamelHttpMethod y CamelHttpQuery antes de hacer la llamada al componente HTTP. A diferencia del anterior caso de uso, ahora está listo el parámetro que hay que pasar al método de BizAgi. En un principio solo habría que añadir al comienzo el nombre del parámetro “activityInfo=”. Sin embargo, no puede hacerse sin más. Hay que codificar el parámetro con la codificación URL. La codificación URL se hizo en el anterior caso de uso ‘a mano’, directamente en la plantilla velocity sustituyendo ‘<’ y ‘>’ por %3C y %3E. Esto se pudo hacer porque eran los únicos caracteres conflictivos. Ahora se ha pasado a un formulario y pueden aparecer espacios, acentos… por lo que se debe de realizar la codificación de otra manera. Para hacer la codificación se ha creado un nuevo método en la clase ProcesaXML. Este método se llama preparaQueryParam y su código se muestra en la Figura B.3.34. El mensaje que se manda al método debe contener como cuerpo la propiedad activityInfo obtenida del mensaje BlackBerry. En el método guardará este mensaje como un String y se procesará. En primer lugar se busca el primer ‘<’ y se guarda todo lo que venga tras ese índice. De esta forma se elimina cualquier espacio en blanco al comienzo que pueda dar problemas. Una vez hecho esto se realiza la codificación. Para la codificación se usa el método encode de la clase URLEncoder. Este método tiene un pequeño problema, y es que sustituye los espacios por ‘+’ en lugar de por %20. Por ello, tras la codificación se empleará el método replaceAll de la clase String para sustituir todos los ‘+’ por la cadena “%20”. Finalmente antes de devolver el String, se le añade al comienzo el nombre del parámetro “activityInfo=”.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

92 PROPUESTA DE SOLUCIÓN

Figura B.3.34 - Clase: ProcesXML, Método: preparaQueryParam

La petición se hace pues con las siguientes líneas:

Una vez pedido a BizAgi que realice la tramitación se estará a la espera de su respuesta. Tras recibirla se avisa al usuario del resultado a través de su dispositivo BlackBerry.

Procesado de la respuesta de la aplicación BizAgi La respuesta que da BizAgi a una petición de tramitación es como la que se muestra en la Figura B.3.35. En esta respuesta hay una gran cantidad de información. Sin embargo, de toda ella solo interesa el nodo ‘processError’ y sus nodos hijo. En el caso del mensaje de la Figura B.3.35 los nodos ‘errorCode’ y ‘errorMessage’ están vacíos. Esto quiere decir que la tramitación se realizó correctamente. Si hubiese habido algún tipo de error estos nodos contendrían texto en el que darían información sobre lo ocurrido.

public String preparaQueryParam(Exchange exchange)

throws UnsupportedEncodingException{

String xmlOriginal = (String) exchange.getIn().getBody();

int ind = xmlOriginal.indexOf('<');

xmlOriginal = xmlOriginal.substring(ind);

String xmlProcesado = URLEncoder.encode(xmlOriginal,"UTF-8");

xmlProcesado = xmlProcesado.replaceAll("\\+", "%20");

xmlProcesado = "activityInfo=" + xmlProcesado;

return xmlProcesado;

}

<setBody><property>activityInfo</property></setBody>

<to uri="bean:procesaXml?method=preparaQueryParam"/>

<setHeader headerName="CamelHttpQuery">

<simple>${in.body}</simple>

</setHeader>

<setHeader headerName="CamelHttpMethod">

<constant>GET</constant>

</setHeader>

<to uri="http://srv-desbizagi.abg.corp/bizagi_des/WebServices/

WorkflowEngineSOA.asmx/performActivityAsString"/>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

93 PROPUESTA DE SOLUCIÓN

Por tanto, es lógico pensar en basarse en la existencia o no de texto en esos nodos para discernir si ha habido o no error en la tramitación. Sin embargo, no se puede pasar directamente a comprobar esto. El mensaje devuelto por BizAgi requiere de cierto preprocesado. Realmente el mensaje recibido por BizAgi no es como el que se muestra en la Figura B.3.35, sino que va envuelto en un nodo ‘string’. Y no solo eso, además en lugar de ‘<’ y ‘>’ se usa &lt; y &gt; para que se interprete todo como texto dentro del nodo ‘string’. Por tanto el verdadero mensaje es como el mostrado a continuación.

El primer impulso a la hora de procesar el mensaje es usar XPath para quedarse con el contenido del nodo ‘string’. Sin embargo esto no funcionaría, pues daría problemas al estar definido el espacio de nombres en la etiqueta. Por tanto, lo que se hará en primer lugar es eliminar el espacio de nombres de la etiqueta y dejarlo como ‘string’. Para ello se creó un nuevo método en la clase ProcesaXML. El método en cuestión se llama eliminaTempuriOrg y su código se muestra a continuación.

El código es bien sencillo. Se guarda el cuerpo del mensaje en un String, y luego se usa el método replaceAll para sustituir por una cadena vacía la cadena que contiene el espacio de nombres: " xmlns=\"http://tempuri.org/\"".

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

<string xmlns="http://tempuri.org/">&lt;? … process&gt;</string>

public String eliminaTempuriOrg(Exchange exchange){

String xmlOriginal = (String) exchange.getIn().getBody();

return xmlOriginal.replaceAll(" xmlns=\"http://tempuri.org/\"",

"");

}

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

94 PROPUESTA DE SOLUCIÓN

Figura B.3.35 - Ejemplo respuesta a petición de tramitación

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

<process>

<processId>77824</processId>

<processRadNumber>C09-PRL18-24079</processRadNumber>

<savedMessage>

<Entities></Entities>

</savedMessage>

<processWorkflowClass>

<workflowClassId>80</workflowClassId>

<workflowClassName>

pPRL18_CondSeg_ObraCivil

</workflowClassName>

<workflowClassDisplayName>

PRL18 Obra Civil

</workflowClassDisplayName>

<workflowClassProcessForumType>

None

</workflowClassProcessForumType>

<workflowClassDisplay>True</workflowClassDisplay>

<workflowClassUseRadicationNumber>

False

</workflowClassUseRadicationNumber>

</processWorkflowClass>

<processError>

<errorCode></errorCode>

<errorMessage></errorMessage>

</processError>

<CurrentWorkItems>

<workItem>

<workItemId>785242</workItemId>

<workItemState>Inactive</workItemState>

<workItemDuration>1440</workItemDuration>

<workItemEstimatedSolutionDate>

3/14/2011

</workItemEstimatedSolutionDate>

<task>

<taskId>1382</taskId>

<taskName>PRL18_Subproceso</taskName>

<taskDisplayName>

Gestión Proceso PRL 02

</taskDisplayName>

<taskDescription></taskDescription>

<taskHelpText></taskHelpText>

<taskEstimatedDuration>1440</taskEstimatedDuration>

<taskType>Module</taskType>

<taskCost>0</taskCost>

<taskPriority>Normal</taskPriority>

</task>

</workItem>

</CurrentWorkItems>

</process>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

95 PROPUESTA DE SOLUCIÓN

Una vez hecho esto ya se puede usar XPath para obtener el contenido del nodo ‘string’. Tras esto, solo queda sustituir los &lt; y &gt; por ‘<’ y ‘>’. Para hacerlo se crea otro método en la clase ProcesaXML, el método adaptaXml. El código se muestra a continuación.

Este código tampoco es nada complicado, simplemente se limita a sustituir unas cadenas por otras. Ya se tiene la respuesta que nos da BizAgi tal y como se muestra en la Figura B.3.35. Ahora ya se está en disposición de estudiar si ha habido error en la tramitación o no. Como ya se vio, únicamente se tiene que comprobar si existe texto o no en los nodos ‘errorCode’ y ‘errorMessage’. Realmente solo se comprobará uno de ellos. Esto es así porque si uno tiene texto el otro también lo tendrá, ya que uno es un código que se le da al error y el otro es el mensaje de error asociado a dicho código. Se hará la comprobación con el ‘errorCode’, por ejemplo. Se vuelve a hacer uso de XPath y de las etiquetas ‘choice’, ‘when’ y ‘otherwise’ como se muestra en el código que sigue.

public String adaptaXml(Exchange exchange) throws IOException{

String xmlOriginal = (String) exchange.getIn().getBody();

String xmlProcesado = xmlOriginal.replaceAll("&lt;", "<");

xmlProcesado = xmlProcesado.replaceAll("&gt;", ">");

return xmlProcesado;

}

<choice>

<when>

<xpath>not(string(/process/processError/errorCode))</xpath>

<!-- Operaciones a realizar si tramitación OK -->

</when>

<otherwise>

<!-- Operaciones a realizar si error en tramitación -->

</otherwise>

</choice>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

96 PROPUESTA DE SOLUCIÓN

Esta vez se ha usado una nueva función de XPath. La nueva función XPath que se usará es string(), que dice si el nodo al que encierra entre los paréntesis tiene texto. Por tanto se entrará en el nodo ‘when’ si el nodo ‘errorCode’ no contiene texto. En otro caso, si contiene texto, se entrará en el nodo ‘otherwise’. Procesada la respuesta que da BizAgi a la petición de tramitación, se sabe si se ha llevado a cabo con éxito o no. Ahora habrá que generar el mensaje que se hará llegar a la BlackBerry para indicarle este resultado.

Preparación cuerpo mensaje BlackBerry Hay que recordar que el cuerpo del mensaje que se manda a la BlackBerry sigue la estructura mostrada en la Figura B.3.28. En este caso lo que se debe introducir en el nodo ‘formulario’ es un nodo llamado ‘respuesta’ que contenga un mensaje que se mostrará en la BlackBerry. El resto será igual que cuando le se mandó el mensaje a la BlackBerry cuando se movilizó la actividad, con una salvedad, el campo tipoActualización. En este caso hay que asignarle un valor distinto según haya habido error o no. Irá una ‘C’ si la tramitación se realizó correctamente o un a ‘X’ si hubo algún error. Visto esto, ya se puede rellenar con código lo que anteriormente se dejó marcado con ‘Operaciones a realizar si tramitación OK’ y ‘Operaciones a realizar si error en tramitación’.

<!-- Operaciones a realizar si tramitación OK -->

<setBody>

<constant>

&lt;respuesta&gt;La acción se ha ejecutado correctamente /

The action has been made correctly&lt;/respuesta&gt;

</constant>

</setBody>

<setHeader headerName="tipoActualizacion">

<constant>C</constant>

</setHeader>

<!-- Operaciones a realizar si error en tramitación -->

<setBody>

<constant>

&lt;respuesta&gt;La acción no se ha ejecutado correctamente

/ The action has not been made correctly&lt;/respuesta&gt;

</constant>

</setBody>

<setHeader headerName="tipoActualizacion">

<constant>X</constant>

</setHeader>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

97 PROPUESTA DE SOLUCIÓN

Hay que usar las cadenas “&lt;” y “&gt;” en lugar de ‘<’ y ‘>’. Esto se debe a que si no lo hiciésemos se interpretaría la etiqueta ‘respuesta’ como parte del archivo camel-context.xml. Esto provocaría que se produjesen errores cuando ServiceMix intentase ejecutar el bundle, serían errores del tipo: “No existe ningún elemento ‘respuesta’ definido en el archivo xsd”. Una vez hecho esto, ya se sigue procesando el mensaje de igual manera, independientemente de que se haya producido un error al tramitar la actividad o no. El siguiente paso es establecer las cabeceras necesarias y llamar al componente velocity para que ejecute el template actividadBizAgi.vm (mostrado en la Figura B.3.29). Las cabeceras que hay que establecer antes de llamar al componente velocity son: dominio, idActividad, idProceso, usuarioLDAP y el identificador de usuario LDAP. La cabecera tipoActualización ya se estableció cuando se preparó el nodo ‘respuesta’, pues es la única cabecera que dependía del resultado de la tramitación. Una vez que el componente velocity genera el cuerpo del mensaje BizAgi, hay que preparar más cabeceras antes de mandar el mensaje a la ruta encargada de mandar el push.

Preparación para mandar push Cómo ya se vio en el anterior caso de uso, la ruta encargada de mandar el push también tenía la misión de generar tanto el push como el mensaje que se mandará. El mensaje que se mande a esta ruta tenía que tener como cuerpo el cuerpo que tendrá el mensaje de la BlackBerry. Esto se consiguió gracias a la plantilla velocity actividadBizAgi.vm. Además se tenían que añadir todas las cabeceras necesarias para crear la cabecera del mensaje que mandaremos a la BlackBerry y para generar el push. Las cabeceras que hay que crear son: movilidadUrlBes, fechaDeRecepcion, idAplicacion, idTipoDeSubsistema, nombreAbreviadoTipoSubsistema, idSubsistema, nombreTipoSubsitema, portBB y pushId. Hay otras cabeceras que son necesarias, pero que ya fueron definidas, como pueden ser: el pin, el tipo de actualización, el identificador de usuario de movilidad. Una vez creadas todas las cabeceras ya se puede mandar el mensaje Camel a la ruta encargada del push al BES. Ya el BES se encargará de hacer llegar el mensaje a la BlackBerry. La aplicación SIM actuará en consecuencia:

Si detecta que el campo tipoActualizacion de la cabecera es ‘C’ sabe que la tramitación se realizó correctamente. Por tanto marcará con una el mensaje para que el usuario del dispositivo conozca el resultado de la tramitación

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

98 PROPUESTA DE SOLUCIÓN

Si ve que el campo tipoActualizacion es ‘X’ entonces sabe que algo ha ido mal. Por ello, lo que hace es marcar con una el mensaje para que el usuario sepa que no se pudo realizar la tramitación. Además muestra en el display con letras rojas el mensaje que le mandamos en el nodo ‘respuesta’.

Ruta Inicio Proceso

El usuario debe poder iniciar procesos desde su dispositivo móvil. Para ello, la aplicación SIM dispone de una opción para crearlos en la que el usuario indica el proceso que quiere crear y la sociedad a la que pertenece el proceso. Una vez indicado el proceso, la aplicación SIM se encargará de hacer llegar a nuestra ruta de recepción de mensajes una petición en la que indicará el proceso que se quiere crear, la sociedad a la que pertenece y el usuario LDAP del empleado que solicitó el inicio del proceso. La ruta de discriminación de mensajes hará su trabajo y mandará la petición a la ruta de inicio de proceso, que es la que nos ocupa en este momento. Una vez que llega el mensaje con la petición a la ruta de inicio de proceso se guarda la información que contiene la petición (proceso a crear, sociedad, usuario). El siguiente paso, como en todas las rutas relacionadas con los casos de uso, es invocar al Servicio de Usuarios para obtener información sobre el usuario que será de utilidad a lo largo del recorrido de la ruta. Cuando se tenga la información del usuario se hará la llamada al método createCasesAsString del servicio web WorkflowEngineSOA.asmx expuesto por BizAgi. Este método creará el proceso. Responderá con un mensaje en el que dará información sobre lo ocurrido: si ha habido algún error o si todo ha ido correctamente. En el caso de que haya ido bien, el mensaje de respuesta contendrá información sobre el proceso, como puede ser el identificador del proceso y de la siguiente actividad a movilizar. Se procesará la respuesta de BizAgi. Si ha habido error, se mostrará un mensaje en el LOG indicando la imposibilidad de crear el proceso. Si se pudo crear el proceso el siguiente paso en la ruta será movilizar la primera actividad del proceso. Esto se hará de la misma manera que en la ruta de movilización. La ruta acabará con el envío del formulario de la primera actividad a la ruta encargada del envío de los push. En la Figura B.3.36 se ve un esquema que resume el funcionamiento y pasos a seguir en la ejecución de la ruta.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

99 PROPUESTA DE SOLUCIÓN

Figura B.3.36 - Esquema Ruta Inicio Proceso

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

100 PROPUESTA DE SOLUCIÓN

Formato petición de Inicio de Proceso En la Figura B.3.37 se puede ver un ejemplo de una petición de inicio de un proceso mandada por una BlackBerry. En concreto pide iniciar el proceso “PRL 110 Entrada a un espacio confinado” de la sociedad C10.

Figura B.3.37 - Mensaje BlackBerry: Petición Inicio Proceso

En cuanto al cuerpo, contiene un nodo ‘c’ con el código de la sociedad a la que pertenece el proceso y que se indicará cuando pidamos a BizAgi que lo genere.

Obtención información de usuario Cuando llega un mensaje a la ruta lo primero a hacer será obtener la información que interesa de la petición. Lo que interesa es el Pin del usuario, y el proceso que quiere crear así como la sociedad a la que pertenece. El Pin de usuario se usará para llamar al Servicio de Usuarios y obtener toda la información que se necesita del usuario. Los otros dos parámetros se pasarán al método createCasesAsString para que cree el proceso. Además de sacar esta información de la petición, se generará el identificador del push y la fecha en la que se recibió el mensaje como ya se hizo en las dos rutas anteriores. Para invocar al Servicio de Usuarios se operará de la misma manera que en la ruta de tramitación, pues al igual que en ésta se dispone del Pin del usuario. Por lo tanto se deberá pasar el mensaje al componente velocity indicándole que use la plantilla getUsuarioDePIN.vm, previo a lo cual habrá que guardar el Pin como cabecera ‘movilidadPinBB’. De la información devuelta por el Servicio de Usuarios los datos que interesan son:

usuarioLDAP: Necesario para invocar al método createCasesAsString.

<xml>

<c fecbbtz="2011-03-16T12:37:22+0100"

fecbbrtz="2011-03-16T11:37:22+0000" PIN="21369c5e"

fec="16/03/2011 12:37:22" fecbb="16/03/2011 12:37:22"

par="-1" td="a" iu="pPRL110_EntEspConf" ac="161"

idso="1300275442337" men="" tas="Actividad" sub="25"

app="12" us="-1" sc="SI" orig="" tp="0"></c>

<info>

<c e="sociedad">C10</c>

</info>

</xml>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

101 PROPUESTA DE SOLUCIÓN

movilidadUrlBes, movilidadUsuarioMovilidadId, movilidadLocale: Estos datos harán falta si el proceso se crea correctamente y tenemos que movilizar la primera actividad.

Ya se dispone de todo lo necesario para invocar al método createCasesAsString, por lo que ahora hay que preparar la petición y enviársela al servicio REST WorkflowEngineSOA.asmx de BizAgi.

Petición de creación de un proceso a BizAgi De nuevo se usará un endpoint HTTP para enviar mediante GET la petición al servicio web WorkflowEngineSOA.asmx. Por tanto habrá que volver a establecer las cabeceras CamelHttpQuery y CamelHttpMethod. El método createCasesAsString espera recibir el parámetro casesInfo mostrado en la Figura B.3.9. En el caso de la tramitación se proporcionaba directamente el parámetro que esperaba el servicio web, sin embargo en este caso se ha ido obteniendo los datos necesarios y se han ido guardando en propiedades. Por tanto se usará una plantilla de velocity para generar el parámetro casesInfo. La plantilla velocity usada se puede ver en la Figura B.3.38.

Figura B.3.38 - createCasesAsString.vm

Antes de pasar el mensaje al componente velocity hay que guardar como cabeceras el usuario LDAP, el nombre del proceso y la sociedad. Una vez que el componente velocity termine su procesado devolverá un mensaje cuyo cuerpo contendrá el parámetro casesInfo preparado. El siguiente paso será hacer la petición a BizAgi, para lo que se crearán las cabeceras CamelHttpQuery (a partir del cuerpo del mensaje devuelto por el componente velocity) y CamelHttpMethod. Cuando estén creadas las cabeceras se pasará el mensaje al componente HTTP para que haga la petición al método createCasesAsString. Mandada la petición, se estará a la espera de la respuesta que dé BizAgi a la petición. Habrá que procesar esta respuesta para ver que ocurrió con la creación del proceso.

casesInfo=%3CBizAgiWSParam%3E%3Cdomain%3EABG%3C/domain%3E%3Cuser

Name%3E${headers.usuarioLDAP}%3C/userName%3E%3CCases%3E%3CCase%3

E%3CProcess%3E${headers.nombreProceso}%3C/Process%3E%3CEntities%

3E%3CidSociedad%20businessKey=%22sCodigo='${headers.sociedad}'%2

2%3E%3C/idSociedad%3E%3C/Entities%3E%3C/Case%3E%3C/Cases%3E%3C/B

izAgiWSParam%3E

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

102 PROPUESTA DE SOLUCIÓN

Procesado de la respuesta a la petición de inicio de proceso La respuesta que nos da BizAgi cuando se pide que inicie un proceso es como la que se muestra en la Figura B.3.39. Esta respuesta contiene información sobre el proceso creado y de las actividades que están activas en el proceso. Si no se pudo crear el proceso, los nodos hijos del nodo ‘processError’ contendrán información sobre el error. Los nodos dentro del nodo ‘processError’ son ‘errorCode’ y ‘errorMessage’ que como es de esperar contienen el código asignado al error y una breve descripción del mismo. Por tanto, al igual que se hizo en la ruta de la tramitación, nos basaremos en la existencia o no de texto en estos nodos para saber si ha habido algún error o si la creación del proceso se completó correctamente. Antes de poder discernir si ha habido error o no hay que hacer un preprocesado al mensaje de respuesta de BizAgi, pues viene de la misma manera que en la respuesta a la tramitación y no como se muestra en la Figura B.3.39. El preprocesado constará de los siguientes pasos (los mismos que en tramitación):

Eliminación del namespace del nodo ‘string’ mediante el método eliminaTempuriorg del bean procesaXml.

Extracción del contenido del nodo ‘string’. Del contenido del nodo ‘string’ sustituir las cadenas &lt; y &gt; por ‘<’ y ‘>’.

De esta forma se tendrá la respuesta en forma de documento XML como el mostrado en la Figura B.3.39 Una vez que se tenga el mensaje en el formato de la Figura B.3.39, hay que usar el código de la Figura B.3.40 para comprobar si ha habido error o no. Si ha habido error simplemente se imprimirá en el LOG que no se ha podido iniciar el proceso. Si se ha creado correctamente el proceso habrá que movilizar la actividad para hacerle llegar al usuario el formulario.

<to uri="velocity:createCasesAsString.vm"/>

<setHeader headerName="CamelHttpQuery">

<simple>${in.body}</simple>

</setHeader>

<setHeader headerName="CamelHttpMethod">

<constant>GET</constant>

</setHeader>

<to uri="http://srv-desbizagi.abg.corp/bizagi_des/WebServices/

WorkflowEngineSOA.asmx/createCasesAsString"/>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

103 PROPUESTA DE SOLUCIÓN

Figura B.3.39 - Ejemplo respuesta a petición de inicio de proceso

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

<process>

<processId>6463</processId>

<processRadNumber>C10-PRL110-2786</processRadNumber>

<savedMessage>

<Entities></Entities>

</savedMessage>

<processWorkflowClass>

<workflowClassId>208</workflowClassId>

<workflowClassName>pPRL110_EntEspConf</workflowClassName>

</processWorkflowClass>

<processError>

<errorCode></errorCode> <errorMessage></errorMessage>

</processError>

<CurrentWorkItems>

<workItem>

<workItemId>37443</workItemId>

<workItemState>Inactive</workItemState>

<task>

<taskId>3877</taskId>

<taskName>PRL_Subproceso</taskName>

<taskDisplayName>Gestión Proceso PRL</taskDisplayName>

<taskDescription></taskDescription>

<taskHelpText></taskHelpText>

<taskEstimatedDuration>1440</taskEstimatedDuration>

<taskType>Module</taskType>

<taskCost>0</taskCost>

<taskPriority>Normal</taskPriority>

</task>

</workItem>

<workItem>

<workItemId>37445</workItemId>

<workItemState>Inactive</workItemState>

<task>

<taskId>960</taskId>

<taskName>PRLWF01_Cuestionario</taskName>

<taskDisplayName>

Cumplimentar Formulario

</taskDisplayName>

<taskDescription></taskDescription>

<taskHelpText></taskHelpText>

<taskEstimatedDuration>1440</taskEstimatedDuration>

<taskType>UserInteraction</taskType>

<taskCost>0</taskCost>

<taskPriority>Normal</taskPriority>

</task>

</workItem>

</CurrentWorkItems>

</process>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

104 PROPUESTA DE SOLUCIÓN

Figura B.3.40 - Código comprobación error al iniciar proceso

Preparación para la movilización En este apartado se verá cómo obtener los parámetros necesarios para la movilización de una actividad, pues a partir de que se tengan estos parámetros se operará de igual manera que en la ruta de la movilización de la actividad. Recordemos cuales eran estos parámetros:

Usuario LDAP: Era necesario para invocar el método getActivityFormXML del servicio web RenderSOA.asmx. Este parámetro ya lo tenemos, pues también hizo falta para invocar al método createCasesAsString.

Identificadores de actividad y proceso: Hay que indicar a BizAgi la actividad de qué proceso se quiere movilizar.

Tipo de actualización: Se quiere insertar el formulario en la BlackBerry, por lo que el tipo de actualización se pondrá a valor ‘I’.

Al tipo de actualización se le va a asignar un valor constante y el usuario LDAP ya estaba almacenado. Habrá por tanto que ver cómo obtener los identificadores de actividad y proceso de la respuesta que dio BizAgi cuando creó el proceso. Se comenzará con el identificador del proceso. Este es bastante sencillo de ver, pues dentro del nodo ‘process’ se encuentra el nodo ‘processId’ que contiene el identificador del proceso. Simplemente se usará XPath guardar el identificador como una propiedad. Ahora se pasará a ver el identificador de actividad (workItem). En el mensaje devuelto vendrán varias actividades, pero sólo una de ellas interesa. Interesa la actividad que requiere de interacción humana, pues es la que está relacionada con un formulario que habrá que movilizar para que sea cumplimentado por el usuario. El resto son actividades que realiza la propia aplicación de BizAgi sin necesidad de la intervención del usuario.

<choice>

<when>

<xpath>

not(string(/processes/process/processError/errorCode))

</xpath>

<!-- Inicio de Proceso OK =>

Movilizar la primera actividad del proceso -->

</when>

<otherwise>

<!-- Error en Inicio de Proceso =>

Imprimir en el LOG -->

</otherwise>

</choice>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

105 PROPUESTA DE SOLUCIÓN

La actividad que requiere de interacción con un usuario se distingue por el nodo ‘taskType’ con valor ‘UserInteracition’. Por tanto se tiene que indicar en la sentencia XPath que acceda al ‘workItem’ cuyo nodo ‘taskType’ dentro del nodo ‘task’ tenga el valor ‘UserInteraction’ y que una vez seleccionado ese nodo ‘workItem’ acceda al contenido de su nodo hijo ‘workItemId’. En las siguientes líneas se puede ver el código para obtener los dos identificadores:

Una vez que se tengan los identificadores de proceso y de actividad ya se puede realizar la movilización de la actividad tal como se hizo en la ruta de movilización. Como se opera de la misma manera no se comentará esta parte de código, aunque el lector puede consultar el código en los archivos anexos a la memoria del proyecto. Cabe hacerse una pregunta: ¿por qué realizar la movilización en esta ruta en lugar de llamar a la ruta de movilización? Se ha hecho de esta manera para cargar lo menos posible la ruta de movilización. Además así también se carga menos el Servicio de Usuarios, pues ya se llama en la ruta de inicio de proceso al servicio y se obtuvo toda la información necesaria del usuario. Si se llamase a la ruta de movilización, en ésta se volvería a invocar al Servicio de Usuarios, lo cual se podría evitar porque ya se dispone de la información que pueda proporcionar el servicio. Por tanto cuando el usuario desde su BlackBerry pida iniciar un proceso se hace la petición a BizAgi para crearlo. Y además de crearlo se moviliza inmediatamente la primera actividad para que el usuario tenga el formulario al instante en su BlackBerry.

Ruta Delegación Actividad

El usuario puede querer delegar una actividad a otro usuario desde su BlackBerry. Para ello, la aplicación SIM dispone de una opción para ello en la que el usuario indica a que persona quiere delegar la actividad.

<setProperty propertyName="idProceso">

<xpath resultType="java.lang.String">

/processes/process/processId/text()

</xpath>

</setProperty> <setProperty propertyName="idActividad">

<xpath resultType="java.lang.String">

/processes/process/CurrentWorkItems/workItem[task/

taskType=’UserInteraction’]/workItemId/text()

</xpath>

</setProperty>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

106 PROPUESTA DE SOLUCIÓN

Cuando se ha seleccionado el usuario al que delegar la actividad, la aplicación SIM envía a la ruta de recepción de mensajes una petición de delegación. En esta petición mandará el nombre completo del usuario al que se delegará la actividad, y el identificador de la actividad que hay que delegar. También se incluye en la petición el identificador del proceso al que pertenece la actividad. La ruta de discriminación de mensajes hará su trabajo y mandará la petición a la ruta de delegación de actividad, que es la que nos ocupa en este momento. Una vez que llega el mensaje con la petición a la ruta encargada de la delegación de actividades, se guarda la información que contiene la petición: nombre completo del usuario al que delegar la actividad, pin del dispositivo que manda la petición y los identificadores de actividad y proceso. El siguiente paso será la invocación del método getEntitiesAsString del servicio Web EntityMan.asmx expuesto por BizAgi. Este método proporcionará el identificador de usuario LDAP asociado al nombre completo del usuario al que se quiere delegar la actividad. Si no se encuentra el usuario se avisará por el LOG y se dará por perdido el intento de delegación. Si se ha obtenido correctamente el identificador LDAP se pasará a llamar al método assignActivityAsString del servicio Web WorkflowEngineSOA.asmx para que BizAgi realice la tarea de delegación. Una vez realizada la petición se estará a la espera del resultado, y se informará del mismo al usuario que realizó la petición de delegación. Para ello se consultará al servicio de usuarios para obtener información como el BES al que está vinculado el usuario, y posteriormente se enviará el push necesario para la transmisión del mensaje de confirmación o error. Ya BizAgi se encargará de pedir al sistema la movilización de la actividad al nuevo usuario cuando estime oportuno. En la Figura B.3.41 se ve un esquema que resume el funcionamiento y pasos a seguir en la ejecución de la ruta.

Formato petición de Delegación de Actividad En la Figura B.3.42 se puede ver un ejemplo de una petición de delegación de una actividad mandada por una BlackBerry. En concreto pide delegar la actividad 43027 del proceso 7289 al usuario Jesus Burger Onate. De la cabecera lo que interesa del mensaje es el PIN del usuario que manda la petición para con posterioridad mandarle un mensaje de error o de confirmación de la delegación. En cuanto al cuerpo, el nodo ‘info’, está compuesto por un nodo ‘c’ que contiene el nombre completo del usuario al que delegar la actividad y los identificadores que determinan la actividad que hay que delegar.

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

107 PROPUESTA DE SOLUCIÓN

Figura B.3.41 - Esquema Ruta Delegación de Actividad

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

108 PROPUESTA DE SOLUCIÓN

Figura B.3.42 - Mensaje BlackBerry: Petición Delegación Actividad

Obtención de información de la petición El primer paso en la ruta será obtener la información que proporciona la petición. Se guardará como propiedades el atributo PIN de la cabecera de la petición y el contenido del cuerpo. A continuación se extraerán de la propiedad en la que se guardó el cuerpo de la petición el nombre completo del usuario al que delegar la actividad, y los identificadores de proceso y actividad. Estos tres parámetros también serán guardados como propiedades. Además de esta información, se generará el identificador del push y se obtendrá la fecha en la que se recibió la petición como ya se hizo en el resto de las rutas que implementan los casos de uso.

Obtención del usuario LDAP Se proporciona el nombre completo del usuario, a partir del cual hay que obtener el usuario LDAP. Para ello se emplea el método getEntitiesAsString como ya se comentó con anterioridad. Este método espera recibir el parámetro de la Figura B.3.11. Para generar el parámetro no se usará una plantilla de velocity, sino que se hará uso de código Java. Hay que recordar que a los métodos expuestos por BizAgi se les llama mediante GET, por tanto el parámetro tiene que ir con codificación URL. Pero como el nombre

<xml>

<c fecbbtz="2011-04-25T12:47:28+0200"

fecbbrtz="2011-04-25T10:47:28+0000"

PIN="22b41b81" fec="25/04/2011" fecbb="25/04/2011 12:47:28"

par="-1" td="a" iu="" ac="18" idso="43027~7289" men=""

tas="Actividad" sub="1225" app="12" us="6801" sc="NO"

orig="SistemaCentralSOA:e1985052bb8f-1b7138abb2d3" tp="1"/>

<info>

<c e="comentarios">

<![CDATA[

<BizAgiWSParam>

<CaseInfo>

<FullName>Jesus Burgers Onate</FullName>

<idCase>7289</idCase>

<IdWorkItem>43027</IdWorkItem>

</CaseInfo>

</BizAgiWSParam>

]]>

</c>

</info>

</xml>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

109 PROPUESTA DE SOLUCIÓN

completo puede tener espacios y acentos, se necesita realizar la codificación mediante una función de Java. Para generar el parámetro se ha ampliado la clase ProcesXML con un nuevo método: createEntitiesInfo. El código se puede ver en el siguiente cuadro de texto.

El método no requiere demasiada explicación. Se obtiene el nombre completo de la cabecera ‘fullName’ y se genera el parámetro mediante la concatenación de cadenas. Finalmente se codifica a URL como ya se hizo en el método preparaQueryParam. Por tanto para realizar la consulta al método getEntitiesAsString bastará con la ejecución de las siguientes líneas de código.

public String createEntitiesInfo(Exchange exchange)

throws UnsupportedEncodingException{

String xmlOriginal =

(String) exchange.getIn().getHeader("fullName");

xmlOriginal = "<BizAgiWSParam><EntityData><EntityID>1</EntityID>

<Filters> fullName like '" + xmlOriginal +

"' </Filters></EntityData></BizAgiWSParam>";

String xmlProcesado = URLEncoder.encode(xmlOriginal,"UTF-8");

xmlProcesado = xmlProcesado.replaceAll("\\+", "%20");

xmlProcesado = "entitiesInfo=" + xmlProcesado;

return xmlProcesado;

}

<to uri="bean:procesaXml?method=createEntitiesInfo"/>

<setHeader headerName="CamelHttpQuery">

<simple>${in.body}</simple>

</setHeader>

<setHeader headerName="CamelHttpMethod">

<constant>GET</constant>

</setHeader>

<to uri="http://srv-desbizagi.abg.corp/bizagi_des/WebServices/

EntityMan.asmx/getEntitiesAsString" />

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

110 PROPUESTA DE SOLUCIÓN

Una vez realizada la consulta hay que procesar la respuesta para ver si existe el usuario.

Procesado de respuesta de petición de usuario LDAP Si el usuario fue encontrado se obtendrá un mensaje de respuesta como el de la Figura B.3.43. En esta respuesta se puede encontrar el nodo ‘userName’ que contiene el identificador de usuario LDAP que se buscaba. Si el usuario no fuese encontrado se devolvería el mismo mensaje pero con el nodo ‘Entities’ vacío. Por ello, para comprobar si se encontró el usuario se comprobará que el nodo ‘Entities’ tenga algún nodo hijo. Sin embargo, antes de poder hacer la comprobación hay que hacer el mismo preprocesado del mensaje recibido por BizAgi que se hizo en los casos de tramitar una actividad e iniciar un proceso:

Eliminación del namespace del nodo ‘string’ mediante el método eliminaTempuriorg del bean procesaXml.

Extracción del contenido del nodo ‘string’. Del contenido del nodo ‘string’ sustituir las cadenas &lt; y &gt; por ‘<’ y ‘>’.

Una vez hecho el preprocesado sí se tendría el mensaje tal como se muestra en la Figura B.3.43 y podríamos hacer la comprobación. Para realizar ésta, se usarán las siguientes líneas de código.

La función node() devolverá ‘true’ si el nodo al que acompaña tiene algún nodo hijo. Si se da la condición querrá decir que se encontró el usuario y se podrá continuar con la ruta. Si no se da la condición será que no existe el usuario, por lo que se imprimirá un mensaje de error en LOG y se finalizará con la ruta. Supongamos a partir de este punto que se encontró el usuario, el siguiente paso será ahora llevar a cabo la delegación propiamente dicha.

<choice>

<when>

<xpath>/BizAgiWSResponse/Entities[node()]</xpath>

<!-- Existe el usuario -->

</when>

<otherwise>

<!-- No existe el usuario -->

</otherwise>

</choice>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

111 PROPUESTA DE SOLUCIÓN

Figura B.3.43 - Ejemplo respuesta de getEntitiesAsString

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

<BizAgiWSResponse>

<Entities>

<WFUSER key="276">

<enabled>True</enabled>

<ididDatacenter entityName="p_Datacenter" key="5">

<sURLLgvConsultarValor>N/A</sURLLgvConsultarValor>

<sURLVinculoGed>N/A</sURLVinculoGed>

<sNombre>DesaSevilla</sNombre>

<sURLGedResp>N/A</sURLGedResp>

<sURLLgvEjecutarAccion>N/A</sURLLgvEjecutarAccion>

</ididDatacenter>

<idSociedadParaNuevoCaso entityName="p_Sociedad" key="51">

<sNombreSociedad>Telvent Outsourcing S.A.</sNombreSociedad>

<idGrupoNegocio>1</idGrupoNegocio>

<idRolResponsable>10021</idRolResponsable>

<sCodigo>C10</sCodigo>

</idSociedadParaNuevoCaso>

<email>[email protected]</email>

<language entityName="LANGUAGE" key="171">

</language>

<idLocation entityName="LOCATION" key="2">

</idLocation>

<enabledForAssignation>True</enabledForAssignation>

<contactEmail>[email protected]</contactEmail>

<notifByEmail>False</notifByEmail>

<domain>ABG</domain>

<fullName>Jesus Burgers Onate</fullName>

<idUser>276</idUser>

<IDProcesoBusqueda>203</IDProcesoBusqueda>

<idArea entityName="AREA" key="1">

</idArea>

<idWorkListProcType entityName="WORKLISTPROCTYPE" key="1">

</idWorkListProcType>

<EnabledBB>True</EnabledBB>

<userName>INJBO</userName>

<idWorkingTimeSchema entityName="WORKINGTIMESCHEMA" key="1">

</idWorkingTimeSchema>

<DelegateEnabled>False</DelegateEnabled>

<Roles>

</Roles>

<Organizations>

</Organizations>

</WFUSER>

</Entities>

</BizAgiWSResponse>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

112 PROPUESTA DE SOLUCIÓN

Petición de la delegación de una actividad a BizAgi Para realizar la delegación hay que invocar al método assignActivityAsString al que hay que pasarle el parámetro que se muestra en la Figura B.3.10. Los datos que componen este parámetro ya han sido obtenidos: los identificadores de proceso y actividad se obtuvieron de la petición que se recibió de la BlackBerry, y el usuario LDAP se obtuvo mediante la llamada a getEntities as String. Para generar el parámetro se hará uso de la plantilla velocity de la Figura B.3.44. Tras generar el parámetro se realizará la petición GET como ya se ha hecho en varias ocasiones.

Figura B.3.44 - assignActivityAsString.vm

Habrá que comprobar la respuesta de BizAgi para comprobar si se pudo delegar la actividad o no.

Comprobación de la respuesta de petición de delegación Veamos en primer lugar el formato de la respuesta de BizAgi. Si todo fue correctamente se recibe el mensaje de la Figura B.3.45, y si hubo algún tipo de error el de la Figura B.3.46.

Figura B.3.45 - Mensaje devuelto por BizAgi si delegación OK

Figura B.3.46 - Mensaje devuelto por BizAgi si error en delegación

info=%3CBizAgiWSParam%3E%3CCaseInfo%3E%3CUserName%3EABG%5

C${in.headers.usuarioLDAP}%3C/UserName%3E%3CIdCase%3E${in

.headers.idProceso}%3C/IdCase%3E%3CIdWorkItem%3E${in.head

ers.idActividad}%3C/IdWorkItem%3E%3C/CaseInfo%3E%3C/BizAg

iWSParam%3E

<BizAgiWSResponse>Reassign sucessfull</BizAgiWSResponse>

<BizAgiWSError xmlns="http://www.w3.org/2001/XMLSchema-instance">

<ErrorCode xmlns="">?</ErrorCode>

<ErrorMessage xmlns="">?</ErrorMessage>

</BizAgiWSError>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

113 PROPUESTA DE SOLUCIÓN

Hay que tener en cuenta que lo devuelto por BizAgi no es exactamente lo mostrado en las Figuras B.3.45 y B.3.46, sino que están envueltas en un nodo ‘string’ como ya pasó en anteriores respuestas de BizAgi. Por tanto habrá que hacer el mismo preprocesado que ya se hizo en otras ocasiones. Una vez hecho el preprocesado, solo hay que fijarse en el nodo raíz del mensaje para comprobar si hubo error. Si es ‘BizAgiWSResponse’ es que no hubo problemas, y si es ‘BizAgiWSError’ es que hubo algún tipo de error. El error en concreto es indicado en los nodos ‘ErrorCode’ y ‘ErrorMessage’. En el código que se muestra a continuación se muestra la comprobación del mensaje, y cómo se genera el cuerpo del mensaje que enviaremos a la BlackBerry para confirmar la delegación o para informar del error.

Envío de la confirmación de delegación a la BlackBerry Una vez acabada la delegación, haya acabado bien o con error, se debe informar del resultado a la BlackBerry.

<choice>

<when>

<xpath>/BizAgiWSResponse</xpath>

<setHeader headerName="respuesta">

<constant>

&lt;respuesta&gt;La acción se ha ejecutado correctamente

/ The action has been made correctly&lt;/respuesta&gt;

</constant>

</setHeader>

<setHeader headerName="tipoActualizacion">

<constant>C</constant>

</setHeader>

</when>

<otherwise>

<setHeader headerName="respuesta">

<constant>

&lt;respuesta&gt;La acción no se ha ejecutado

correctamente / The action has not been made

correctly&lt;/respuesta&gt;

</constant>

</setHeader>

<setHeader headerName="tipoActualizacion">

<constant>X</constant>

</setHeader>

</otherwise>

</choice>

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA

114 PROPUESTA DE SOLUCIÓN

En el apartado anterior se indicó como se crean los avisos que se darán a la BlackBerry según el caso. El siguiente paso será llamar al método getUsuarioDePIN para obtener información del usuario que mandó la petición de delegación y así poder mandar a continuación el push. Esto se ha hecho ya varias veces a lo largo de la implementación, por lo que no se volverá a repetir en esta memoria. Sin embargo, siempre se puede consultar el código en los archivos anexos a la memoria. Con esto queda explicada la implementación de la solución. En el siguiente capítulo se verán todos los pasos a seguir para ejecutar nuestro bundle, además de algunos ejemplos de ejecución.