Jugando con jBPM #15 – Identity Component

Primero que nada bienvenidos al post numero #15 de la serie Jugando con jBPM. En este post veremos algunos detalles del componente de identidades.

Como estamos acostumbrados a ver en la típica imagen de arquitectura (o división lógica del proyecto) de jBPM se diferencia el componente de Identity (Identidades) como un bloque separado del core del framework:

Componentes de jBPM
Componentes de jBPM

Esta separacion le da a jBPM la flexibilidad de poder adaptarse a cualquier modulo de identidades que ya se encuentre en la empresa donde se vaya a realizar una implementación.

Pero entonces, en que consiste este modulo Identity que muestra la figura?

La respuesta es bastante simple, consiste en un modulo muy simple, que funciona out-of-the-box, que cuenta con tres conceptos para administrar nuestras identidades: Usuarios, Grupos y Membresias (User, Group y Membership). La idea es que apenas empezamos a usar jBPM ya tengamos una forma fácil y sencilla de user datos de usuarios, grupos y las relaciones N a N entre ellos con las membresias.

Esto no quiere decir que jBPM esta fuertemente acoplado a este esquema de usuarios, ya que en la mayoría de los casos, tenemos que adaptarnos a implementaciones y estructuras ya existentes de identidades.

Llegado al caso en el que tenemos que remover el componente de identidades que viene con jBPM y adaptar nuestro propio componente, debemos tener en cuenta cuales son los pasos a seguir y que bloques o clases debemos reescribir para adaptarnos.

El primer dato que encontramos si buscamos un poco sobre el tema es que debemos comentar en el archivo hibernate.cfg.xml las siguientes lineas:

<!-- identity mappings (begin) ===
<mapping resource="org/jbpm/identity/User.hbm.xml"/>
<mapping resource="org/jbpm/identity/Group.hbm.xml"/>
<mapping resource="org/jbpm/identity/Membership.hbm.xml"/>
==== identity mappings (end) -->

Estos mapeos de hibernate se encargan de administrar las entidades que se manejan en este modulo que viene por defecto, cuyo diagrama de clases es el siguiente:

Modelo de Clases de Identity
Modelo de Clases de Identity

Por lo tanto desactivando estos mapeos desacoplamos totalmente a jBPM de este modulo de identidades que viene por defecto, y estamos listos para insertar nuestro propio (puede ser ya existente) modelo al framework.

jBPM para realizar este desacoplamiento de la forma mas transparente posible, maneja el concepto de actor, que es simplemente un String que representa a nuestros usuarios o grupos de usuarios.

Ahora bien, si en este punto nosotros tenemos un proceso que tiene una tarea y la asignación de esta tarea se realiza mediante una expresion, como por ejemplo:

<task name="Elegir tarea del dia">
 <assignment expression="group(admin)"/>
 ..

Esta expresión lo que hace es resolver el grupo admin y asignarle la tarea a todos los usuarios de este grupo (en este caso admin).

Les recomiendo que vean en la documentación oficial como pueden ser estas expresiones ya que es un tema bastante interesante. (link: http://docs.jboss.com/jbpm/v3.2/userguide/html_single/#theidentitycomponent)

Por lo tanto si tratamos de ejecutar nuestro proceso y hemos desactivado los mapeos a las entidades de hibernate, vamos a ver en la consola el siguiente WARN:

11:10:24,812 [main] WARN  QuerySplitter : no persistent classes found for query class: select g from org.jbpm.identity.Group as g where g.name = :groupName

Que nos dice exactamente eso, no tiene ninguna clase para consultar los grupos de usuarios y resolver la expresion que habiamos puesto en el tag assigment dentro de nuestra tarea.

Entonces, la pregunta que se hace obvia es: quien se encarga de hacer estas resoluciones de expresiones?

La respuesta tambien es obvia y es una clase llamada: org.jbpm.identity.assignment.ExpressionAssignmentHandler

La cual mediante una propiedad ExpressionSession expressionSession, se encarga de comunicarse con el esquema de identidades que se encontraba mapeado con hibernate. En este caso del mapeo con hibernate donde nuestro esquema de identidades se encuentra almacenado en la base de datos (es muy comun que el esquema de identidades este en un Arbol LDAP tambien) la clase que implementa la interfaz ExpressionSession para esta implementacion del componente de identidades es: org.jbpm.identity.hibernate.IdentitySession.

SI analizamos los metodos de esta clase veremos que ellos cumplen con todas las funcionalidades necesarias para resolver usuarios y grupos de la manera mas simple (en este caso realizando consultas con la session de hibernate a las entidades mapeadas).

Algunos metodos de org.jbpm.identity.hibernate.IdentitySession:

</pre>
public User getUserByName(String userName) {
    User user = null;
    Query query = session.createQuery(
      "select u " +
      "from org.jbpm.identity.User as u " +
      "where u.name = :userName"
    );
    query.setString("userName", userName);
    List users = query.list();
    if ( (users!=null)
         && (users.size()>0) ) {
      user = (User) users.get(0);
    }
    return user;
  }

  public Group getGroupByName(String groupName) {
    Group group = null;
    Query query = session.createQuery(
      "select g " +
      "from org.jbpm.identity.Group as g " +
      "where g.name = :groupName"
    );
    query.setString("groupName", groupName);
    List groups = query.list();
    if ( (groups!=null)
         && (groups.size()>0) ) {
      group = (Group) groups.get(0);
    }
    return group;
  }

Como ultimo dato agrego que la sugerencia, muy correcta en la documentación, dice que si queremos reutilizar el esquema de acceso a los componentes de identidades que nos propone jBPM debemos extender la clase ExpressionAssignmentHandler y sobre escribir el método getExpressionSession que en este caso nos devolvería en vez de un org.jbpm.identity.hibernate.IdentitySession nuestra propia implementación de acceso a nuestras propias identidades.

Entonces las ideas que me gustaría que quedaran claras en este post son las cosas a tener en cuenta para implementar o acoplar un nuevo esquema de identidades a jBPM.

También espero que les sirva como punta pie inicial para investigar en profundidad estas expresiones de asignación que son muy importantes cuando tenemos tareas y grupos de usuarios complejos.

Cualquier consulta, ya saben que estoy a su disposición.

Advertisements

35 thoughts on “Jugando con jBPM #15 – Identity Component”

  1. Excelente, blog, Salaboy. Me leí todas las entradas referidas a jbpm. Estoy laburando con esta herramienta y me sirvieron muchísimo. También me interesó mucho jboss drools.

    Aprovecho para hacerte una consulta. Estoy buscando una forma elegante para llamar a un workflow dentro de otro (algo así como invocaciones a sub-workflows). Pensé en escribir el código directamente en un ActionHandler; instanciar un ProcessInstance desde el execute y darle el signal() para largarlo a correr. Pero me gustaría saber si conocés alguna forma mejor. Si se puede hacer de forma gráfica con el plug-in de eclipse (GPD) o de alguna otra forma mejor.

    También aprovecho para hacer publicidad de mis dos blogs técnicos, por si te interesan (o a alguien que lea el blog):

    http://elblogdelfrasco.blogspot.com/
    http://tecnologiasjava.blogspot.com/

    Saludos,
    Adrián

    Like

  2. Claro que tienes la posibilidad de llamar sub procesos de una forma muy sencilla que es utilizando nodos de tipo process-state. En GPD lo tienes en la paleta, debes especificar el nombre del proceso y también puedes escoger alguna de las versiones del mismo en el caso de que tengas varias.
    Estuve viendo tus blogs y estan bastante buenos también. Si estas interesado en que agreguemos links cruzados para que la gente interesada en estos temas tenga donde buscar comentame por privado. Saludos. Cualquier duda consulta sin problemas.

    Like

  3. Buenas, tengo una consulta conceptual: Digamos que tengo 2 aplicaciones. La applicacion 1 donde se deploya e instancia el proceso. Y la aplicación 2, donde un usuario “user1” ejecuta determinada Task.
    Mi duda es:
    El user1 desde la aplicacion 2, ejecuta:
    JbpmContext context = JbpmConfiguration.getInstance().createJbpmContext();
    List tasks = context.getTaskMgmtSession().findTaskInstances(“user1”);

    y luego ejecuta una tarea.
    a)Esa tarea que ejecuta, es una llamada remota (onda EJB) a la maquina virtual de la aplicacion 1, donde se deployo el proceso? o la idea, es que todos los llamados se realicen siempre desde la aplicacion 1? (y obviamente los actions se ejecuten ahi)

    b) Cual es la diferencia entre llamar a tasks con JbpmConfiguration.getInstance().createJbpmContext().getTaskMgmtSession().findTaskInstances(“user1”)
    o usar executionService.getTaskList(“cg”); como figura en este tutorial
    http://www.jboss.com/products/jbpm/docs/tutorial

    Muchisimas gracias, me interesa sobre todo la pregunta a) para entender cual es la idea de uso y manejo concurrencia de JBPM

    thanks a lot!

    Like

  4. Gracias por tu comentario. Vamos por le pregunta a) primero asi queda claro el funcionamiento.
    En caso de tener dos aplicaciones que incluyan el jar jbpm-jpdl, ambas aplicaciones se comunican de manera independiente con la base de datos que estes utilizando. Por lo tanto en el caso que tu mencionas no se hace ninguna llamada remota a ningún lado. Para que tus procesos funcionen correctamente en ambas aplicaciones, las configuraciones acerca las base de datos que se utilizan deben ser claramente las mismas.
    Esta bueno mencionar tambien, que lo que has comentado, es solo una de las posibles distribuciones que puedes hacer de jBPM. Por otro lado también puedes usar jbpm-enterprise.ear donde ahi si tus aplicaciones tendrian la opcion de no incluir el jar jbpm-jpdl y comunicarse por SLSB (EJB) contra la API.
    Espero haber sido claro, es todo un tema para discutir, si quieres o tienes mas dudas puedes seguir comentando asi ampliamos el tema.

    Con respecto a la pregunta b), en realidad no la analice mucho, porque desde el vamos el titulo del articulo es: JBoss jBPM 2.0 Tutorial, por lo tanto en la versión 3.2.x no creo que aplique.

    Saludos. Espero mas comentarios tuyos!

    Like

  5. Buenísimo!, me aclaró muchísimo, gracias!

    Pero me genera una nueva duda puntual, tambien conceptual:
    Supongamos que tenemos el escenario de la pregunta anterior con las dos aplicaciones ambas con el jar jbpm-jpdl contra la misma base.
    El usuario “user” desde la aplicacion 2, busca una tarea para aprobar, la encuentra y la arranca. Pero esa tarea que acaba de arrancar utiliza un “Action Handler” cuyo codigo fuente se encuentra en la aplicacion 1!!.
    Como se resuelve esta situacion? esto es lo que no me termina de cerrar
    algunas cosas q se me ocurren:
    a) la aplicacion 1, monitorea constantemente la base, usando un patron observer, y cuando detecta que se tiene que ejecutar una tarea lo hace?
    b)en la aplicacion 2, tiene tambien que estar todas los Action Handlers?
    c) otra opcion

    muchas gracias!
    Fer

    Like

  6. Gracias por tu nuevo comentario,
    Son dudas comunes a la hora de usar jBPM. Y si vas a necesitar tener tu jar con todos tu action handlers por cada proceso que compartan tus aplicaciones en cada una de las mismas. Sino no tendrían acceso a la lógica de estos action handler y te generara una DelegationException.

    Por esto te sugiero analizar los otros tipos de deploy de jBPM, ya que si estas utilizando un servidor de aplicaciones, es por lo general donde se nuclean las clases que van a depender de tu proceso, en este caso los action handlers.

    Saludos

    Like

  7. Hi salaboy,
    I tryed to extend org.jbpm.identity.assignment.ExpressionAssignmentHandler but I don’t know how to tell to JBPM to load this custom class. I tryed with

    ,
    without success.

    Any help appreciated…

    Like

  8. Hi salaboy,
    I tryed to extend org.jbpm.identity.assignment.ExpressionAssignmentHandler but I don’t know how to tell to JBPM to load this custom class. I tryed with ,
    without success.

    Any help appreciated…

    Like

  9. Hola Sala, quería hacerte una consulta.
    En caso de que no use el componente Identity.
    El nombre del usuario al que se le haya asignado la tarea, se persistira igualmente, en algun lado?

    muchas gracias

    Like

  10. Claro.. se persistirá el actorId en la información de la task instance. Tambien asi los pooled actors en el caso de que estes usando.
    Esta información se mantiene en el proceso y tu aplicación debera encargarse de revisar que lo que se asigno en el actorId es correcto buscando en el identity component que estes usando.

    A esta información la puedes corroborar viendo el archivo TaskInstance.hbm.xml que especifica el mapeo de la entidad TaskIntance a la tabla JBPM_TASKINSTANCE.

    Saludos

    Like

  11. Muchas gracias Sala!!!!.
    Una pregunta mas 🙂 .
    Estoy tratando de asignar una tarea a un actor (pedro) al definir el proceso.
    Desde el xml es fácil seria:

    Pero el problema es que necesito hacerlo programaticamente (new Task()), y no encuentro ningun metodo en la clase Task para hacerlo. Solo esta el metodo setActorIdExpression, pero es otra cosa.

    Se te ocurre alguna forma de hacerlo?

    Like

  12. Si el tema es lo que yo necesitaba hacer es modelar el proceso programaticamente, luego instanciar el proceso y listo, Ya tener todos los actores asignados a las tareas. Como se puede hacer usando el xml con pense que se podria hacer tambien a traves de la API. (new Task(), etc)
    Quería evitar usar variables.
    Me suena raro que se pueda hacer desde el xml y no desde la API. Sigo pensando que haciendo alguna vueltita se debe poder hacer.

    Like

  13. 1)
    new ProcessDefinition(); new TaskNode(stepName) y despues agrego el Task al ProcessDefinition.

    Me falta poder agregar los actores a los tasks en el processDefinition y soluciono todo.

    Me suena raro no poder setear esos atributos, si se puede hacer desde el xml

    Estoy haciendo un pequeño framework sobre jbpm para una funcionalidad particular (aprobaciones, etc)

    2) 3.2.3

    Gracias!!

    Like

  14. Tengo que implementar un api que se conecte al servidor y inicie procesos, continue procesos, consulte tareas y suspenda procesos. Este api será cliente. La única manera de implementarlo sería usando EJB? podrías orientarme un poco? conoces algún ejemplo?

    Like

    1. Hola como estas?
      Gracias por tu comentario. Yo te recomendaría que si estas en una aplicación Java EE revises el modulo jbpm-enterprise del proyecto que ya posee una funcionalidad llamada CommnadServiceBean que te sirve exactamente para eso.
      El tema de que sea un EJB depende de tu arquitectura. Primero tienes que saber bien que necesitas para poder tomar una decisión de ese tipo.
      Cualquier otra consulta, aqui estare.

      Like

      1. Muchas gracias por tu rapida respuesta.
        La arquitectura es un servidor donde esta instalado jbpm-jpdl 3.2.3.

        Tengo que hacer un api que se conecte a ese servidor en remoto y haga acciones simples como desplegar un nuevo proceso, continuarlo, suspenderlo y consultar tareas.

        Leyendo la documentación la única solución que he visto es crear un cliente que haga uso de los servicios J2EE. En concreto una stateless session bean que ejecuta comandos.

        ¿Crees que esta es la solución?

        Por otro lado no estoy 100% seguro que el jbpm instalado en el jboss tenga los servicios J2EE bien desplegados (tambien soy nuevo con JBOSS)

        ¿Como podría comprobarlo?

        Como ves ando bastante perdido, te agradezco mucho tu ayuda.

        Like

  15. He conseguido conectarme al jndi del servidor pero no me encuentra el ejb “CommandServiceBean”. ¿Sabes donde estan configurados los ejb’s?

    Like

    1. Puede que ni siquiera esten desplegados, tienes que ver si estas utilizando jbpm-enterprise o no.
      Si te conectaste contra JNDI, que recursos estas utilizando? para que te querias conectar a JNDI principalmente?
      Saludos

      Like

      1. para trarme el CommandServiceBean stateless session bean para poder ejecutar comandos remotamente.

        ¿Como puedo saber si están desplegados?

        Like

  16. Si no mal recuerdo, en tu arbol de JNDI deberian aparecer como:
    ejb/CommandService/local y ejb/CommnadService/remote

    Si no aparecen deberías revisar tu directorio deploy de tu instancia de jboss para revisar si esta el modulo jbpm-enterprise desplegado, sino esta deberías desplegarlo y configurarlo adecuadamente.

    Like

  17. Me da un error que no encuentra el ebj:

    javax.naming.NameNotFoundException: CommandService not bound

    Creo que está bien desplegado, pero para complicar mas la cosa también soy nuevo con jboss. He copiado el jbpm en D:\jbpm-jpdl-suite-3.2.3\server\server\jbpm\deploy

    ¿Como puedo comprobar si esta bien desplegado?

    Muchas gracias

    Like

  18. Como va cesar, es muy difícil diagnosticar un error de ese tipo si no entiendo muy bien que tienes instalado, que tienes desplegado y como tienes configurado tu jboss.
    Si eres nuevo por ahí todavía no conoces algo llamado jmx-console, que te da las descripciones de los componentes desplegados en tu instancia y mucha información mas sobre como esta configurado tu entorno.
    Busca por ese lado y aprende a usar la jmx-console, te sera de gran ayuda en el futuro.

    Like

  19. Muchas Gracias, he logrado avanzar algo. He conseguido traerme el CommandServiceBean y parece que que ejecuta comandos (por ahora vacios) de forma correcta.

    Estaba probando a ejecutar lo siguiente:

    GetProcessDefinitionsCommand command = new GetProcessDefinitionsCommand(true);
    Object result = remoteCMDService.execute(command);

    sin embargo no se muy bien como manejar el resultado. No se si debería castearlo.

    Muchas Gracias Un Saludo

    Like

  20. Buenos dias, estoy tambien empezando con jBPM y me piden que avance una tarea que esta parada añadiendole variables. Lo hago con:

    SignalCommand signalCommand = new SignalCommand(); signalCommand.setTokenId(processInstance.getRootToken().getId());
    signalCommand.setVariables(aWorkItem); remoteCMDService.execute(signalCommand);

    pero aparte de continuar la tarea parece que crea otra, sabeis si lo estoy haciendo bien. Muchas gracias de antemano.

    Like

  21. Por cierto Cesar, al hacer:

    GetProcessDefinitionsCommand command = new GetProcessDefinitionsCommand(true);
    Object result = remoteCMDService.execute(command);

    el result lo puedes castear a ArrayList y de ahí ya puedes obtener lo que te interese.

    Like

  22. Hola como estan
    tengo una consulta , en la empresa estamos analizando de usar una base noSQL y el unico lugar donde estamos con incertidumbre de como manejarnos es con jbpm.
    Sacar el bloque de identity no parece algo complejo.
    Me preocupa todo el resto del modelo , tenemos en el xml de hibernate mapeado entidades como JBPM_SWINMLANE , esto no se donde esta encapsulado ?
    espeor que me entiendan un poco la pregunta.
    Gracias y saludos.

    Like

    1. Hola como estas?
      Gracias por escribir. Primero que nada, estas queriendo usar una base de datos noSQL solo para la parte de identity? o para todo jBPM?
      Si es para todo jBPM, los mapeos de Hibernate se encuentran en un archivo llamado default.hibernate.cfg.xml dentro de la distribucion oficial (version 3.2.x).
      Si mal no recuerdo, ese archivo contiene la referencia a todos los archivos que mapean todas las clases del framework.
      Saludos

      Like

  23. Estimado
    Quisiera saber si hay forma de escribir una clase para registrar auditorias de cuando inicia y cuando termina un proceso, de antemano te agradezco la ayuda que me puedas dar, estoy trabajando con jBPM 3.2.6

    Like

    1. Si totalmente, estoy seguro que había una forma fácil de hacerlo, pero hace tanto que no veo 3.2.6 que es imposible que me acuerde como se hacia. Estoy seguro de que tocaba ese tema en mi libro, no lo tenes por ahí como para consultarlo?
      Saludos

      Like

    1. Ya probaste con este clase:
      ??
      Si esa no es suficiente como dice ahí tenes que crear una implementación similar que guarde la información donde vos quieras y luego configurarla de la misma manera para que jbpm la tome.
      Saludos

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s