jBPM5 Console Server and Human Task Server: instalación y configuración

0
7917

jBPM5 Console Server and Human Task Server: instalación y configuración

0. Índice de contenidos.


1. Introducción

Es este tutorial vamos a revisar cómo llevar a cabo una instalación personalizada de los componentes que
dan soporte al core de jBPM5:

  • jBPM Console Server: es la pieza principal que da soporte a la gestión de procesos, proporciona un api REST
    que nos permite además realizar todas las operaciones relacionadas con la gestión de tareas, de usuarios y la
    renderización de formularios. Podríamos decir que es el API de gestión de procesos.
  • jBPM Human Task Server: es una pieza nueva que hace de repositorio de tareas y que permite además realizar todas
    las operaciones necesarias para la gestión de usuarios y formularios. En realidad el API REST que nos
    proporciona el jBPM Console Server no es más que una fachada de estos servicios a los que accede mediante
    JMS.
  • JBPM Console: es una aplicación web que nos permite acceder a la lista de tareas pendientes por usuario o grupo, arrancar
    un proceso y monitorizarlo. Sería la pieza que podríamos incrustar en nuestras aplicaciones o tomar de referencia
    para hacer el mismo uso del API REST del Console Server para desarrollar un bandeja de tareas propia, con la
    tecnología que estimemos oportuna, puesto que no sería más que comunicarnos vía REST.

En este tutorial vamos a realizar una instalación de estos 3 componentes de forma controlada, fuera de la
demo de instalación de jBPM5,
con el soporte de Maven, sobre un Jboss AS 7. Se podría realizar también la instalación sobre un Apache Tomcat
pero ya tenemos sobre Apache Tomcat desplegados Guvnor, el Designer y
aún nos queda desplegar el generador de formularios con lo que vamos a diversificar la carga.
Vamos a dejar el núcleo de los servicios, aquellos que necesitan persistencia a base de datos y comunicación por colas, en Jboss Server.


2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 15′ (2.4 GHz Intel Core i7, 8GB DDR3 SDRAM).
  • Sistema Operativo: Mac OS X Lion 10.7.4
  • jBPM 5.4.2.Final
  • JBoss AS 7.1.1


3. Instalación.

Con el soporte de Maven vamos a añadir vamos a añadir 3 proyectos más a nuestro proyecto tnt-jbpm, que ya vimos en el tutorial de Guvnor:

<modules>
	<module>tnt-designer</module>
	<module>tnt-guvnor</module>
	<module>tnt-jbpm-gwt-console-server</module>
	<module>tnt-jbpm-human-task</module>
	<module>tnt-jbpm-gwt-console</module>
</modules>


3.1. tnt-jbpm-gwt-console-server.

El proyecto tnt-jbpm-gwt-console-server tendría el siguiente pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<parent>
		<groupId>com.autentia.bpm.repository</groupId>
		<artifactId>tnt-jbpm</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<groupId>com.autentia.bpm.repository</groupId>
	<artifactId>tnt-jbpm-gwt-console-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<inceptionYear>2013</inceptionYear>

	<build>
		<finalName>gwt-console-server</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.5.1</version>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.4.2</version>
				<configuration>
					<skipTests>true</skipTests>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<configuration>
					<dependentWarExcludes>WEB-INF/lib/netty-*.jar,WEB-INF/lib/hibernate*.jar,WEB-INF/lib/dom4j-*.jar,WEB-INF/lib/jaxen-*.jar,WEB-INF/lib/jaxme-api-*.jar,WEB-INF/lib/pull-parser-*.jar,WEB-INF/lib/relaxngDatatype-*.jar,WEB-INF/lib/stax-api-1.0.jar,WEB-INF/lib/xml-apis-*.jar,WEB-INF/lib/xpp3-*.jar,WEB-INF/lib/xsdlib-*.jar,WEB-INF/lib/xercesImpl-*.jar,WEB-INF/lib/xmlParserAPIs-*.jar,WEB-INF/lib/xom-*.jar,WEB-INF/lib/icu4j-*.jar,WEB-INF/lib/tagsoup-*.jar,WEB-INF/lib/xalan-*.jar,WEB-INF/lib/serializer-*.jar</dependentWarExcludes>
					<archive>
						<manifestEntries>
							<dependencies>org.jboss.netty</dependencies>
						</manifestEntries>
					</archive>
				</configuration>
				<version>2.3</version>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>org.jbpm</groupId>
			<artifactId>jbpm-gwt-console-server</artifactId>
			<version>5.4.0.Final</version>
			<type>war</type>
		</dependency>
	</dependencies>

</project>

La única dependencia es con el proyecto maven que distribuye el API y dentro del plugin de generación del war tenemos
que:

  • emular el contenido del assembly que está preparado para la generación del war en un entorno JEE excluyendo aquellas librerías que
    ya existen en Jboss AS
  • añadir al MANISFEST.MF la dependencia de la librería org.jbos.netty necesaria para la comunicación vía JMS.

En nuestro proyecto, vamos a añadir la configuración de la unidad de persistencia para que cree y almacene la información sobre los procesos en una base de datos MySQL.
Así, dentro del directorio src/main/resources/META-INF, vamos a incluir un fichero persistence.xml con el siguiente contenido:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
  xmlns="http://java.sun.com/xml/ns/persistence" 
  xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd">

<persistence-unit name="org.jbpm.persistence.jpa" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:jboss/datasources/jbpm5DS</jta-data-source>
    <mapping-file>META-INF/JBPMorm.xml</mapping-file>
    <mapping-file>META-INF/ProcessInstanceInfo.hbm.xml</mapping-file>
    <mapping-file>META-INF/ExtraIndexes.hbm.xml</mapping-file>

    <class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>
    <class>org.drools.persistence.info.SessionInfo</class>
    <class>org.drools.persistence.info.WorkItemInfo</class>
    <class>org.jbpm.process.audit.ProcessInstanceLog</class>
    <class>org.jbpm.process.audit.NodeInstanceLog</class>
    <class>org.jbpm.process.audit.VariableInstanceLog</class>
    <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>          
      <property name="hibernate.max_fetch_depth" value="3"/>
      <property name="hibernate.hbm2ddl.auto" value="update" />
      <property name="hibernate.show_sql" value="true" />  
      <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
      
      <!-- BZ 841786: AS7/EAP 6/Hib 4 uses new (sequence) generators which seem to cause problems -->      
      <property name="hibernate.id.new_generator_mappings" value="false" />
      
    </properties>        
  </persistence-unit>
    
</persistence>

Y, lo último, será crear un fichero default.jbpm.console.properties en el directorio src/main/resources con el siguiente contenido:

jbpm.console.server.host=localhost
jbpm.console.server.port=8081
jbpm.console.task.service.strategy=HornetQ
jbpm.console.task.service.host=127.0.0.1
jbpm.console.task.service.port=5153
jbpm.console.directory=
guvnor.protocol=http
guvnor.host=localhost:8080
guvnor.subdomain=drools-guvnor
guvnor.usr=admin
guvnor.pwd=admin
guvnor.packages=
guvnor.connect.timeout=10000
guvnor.read.timeout=10000
guvnor.snapshot.name=LATEST

En este fichero se configuran las comunicaciones del API hacia:

  • la consola jBPM: la idea es desplegar Jboss por el puerto 8081, para no colisionar con el puerto de Apache Tomcat,
  • el servidor de tareas, que va vía JMS,
  • el repositorio de Guvnor

Salvo la modificación del puerto jbpm.console.server.port, el resto de propiedades son las de por defecto.


3.2. tnt-jbpm-human-task.

Igualmente, veamos el pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<parent>
		<groupId>com.autentia.bpm.repository</groupId>
		<artifactId>tnt-jbpm</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<groupId>com.autentia.bpm.repository</groupId>
	<artifactId>tnt-jbpm-human-task</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<inceptionYear>2013</inceptionYear>

	<build>
		<finalName>jbpm-human-task</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.5.1</version>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.4.2</version>
				<configuration>
					<skipTests>true</skipTests>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
		        <configuration>
		          <dependentWarExcludes>WEB-INF/lib/netty-*.jar,WEB-INF/lib/hibernate*.jar,WEB-INF/lib/dom4j-*.jar,WEB-INF/lib/jaxen-*.jar,WEB-INF/lib/jaxme-api-*.jar,WEB-INF/lib/pull-parser-*.jar,WEB-INF/lib/relaxngDatatype-*.jar,WEB-INF/lib/stax-api-1.0.jar,WEB-INF/lib/xml-apis-*.jar,WEB-INF/lib/xpp3-*.jar,WEB-INF/lib/xsdlib-*.jar,WEB-INF/lib/xercesImpl-*.jar,WEB-INF/lib/xmlParserAPIs-*.jar,WEB-INF/lib/xom-*.jar,WEB-INF/lib/icu4j-*.jar,WEB-INF/lib/tagsoup-*.jar,WEB-INF/lib/xalan-*.jar,WEB-INF/lib/serializer-*.jar</dependentWarExcludes>
					<archive>
						<manifestEntries>
							<dependencies>org.jboss.netty</dependencies>
						</manifestEntries>
					</archive>
		        </configuration>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>org.jbpm</groupId>
			<artifactId>jbpm-human-task-war</artifactId>	
			<version>5.4.0.Final</version>
			<type>war</type>
		</dependency>
	</dependencies>

</project>

Tiene las mismas características que el pom.xml del console server, en relación a la exclusión de dependencias en el war y la generación del MANIFEST.MF.

Y, del mismo modo, debemos incluir un persistence.xml en un directorio src/main/resources/META-INF:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence version="2.0"
   xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
        http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="org.jbpm.task" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:jboss/datasources/jbpm5DS</jta-data-source>   
    <mapping-file>META-INF/Taskorm.xml</mapping-file>
    
    
    <class>org.jbpm.task.Attachment</class>
    <class>org.jbpm.task.BooleanExpression</class>
    <class>org.jbpm.task.Comment</class>
    <class>org.jbpm.task.Content</class>
    <class>org.jbpm.task.Deadline</class>
    <class>org.jbpm.task.Delegation</class>
    <class>org.jbpm.task.EmailNotification</class>
    <class>org.jbpm.task.EmailNotificationHeader</class>
    <class>org.jbpm.task.Escalation</class>
    <class>org.jbpm.task.Group</class>
    <class>org.jbpm.task.I18NText</class>
    <class>org.jbpm.task.Notification</class>
    <class>org.jbpm.task.OnAllSubTasksEndParentEndStrategy</class>
    <class>org.jbpm.task.OnParentAbortAllSubTasksEndStrategy</class>
    <class>org.jbpm.task.PeopleAssignments</class>
    <class>org.jbpm.task.Reassignment</class>
    <class>org.jbpm.task.Status</class>
    <class>org.jbpm.task.SubTasksStrategy</class>
    <class>org.jbpm.task.Task</class>
    <class>org.jbpm.task.TaskData</class>
    <class>org.jbpm.task.User</class>
    <properties>
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>          
      <property name="hibernate.max_fetch_depth" value="3"/>
      <property name="hibernate.hbm2ddl.auto" value="update" />
      <property name="hibernate.show_sql" value="true" />  
      <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
      
      <!-- BZ 841786: AS7/EAP 6/Hib 4 uses new (sequence) generators which seem to cause problems -->      
      <property name="hibernate.id.new_generator_mappings" value="false" />
      
    </properties>
  </persistence-unit>
</persistence>


3.3. tnt-jbpm-gwt-console.

Es el más simple de todos puesto que no requiere más configuración que la del pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<parent>
		<groupId>com.autentia.bpm.repository</groupId>
		<artifactId>tnt-jbpm</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>

	<groupId>com.autentia.bpm.repository</groupId>
	<artifactId>tnt-jbpm-gwt-console</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<inceptionYear>2013</inceptionYear>

	<build>
		<finalName>jbpm-console</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.5.1</version>
				<configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<version>2.4.2</version>
				<configuration>
					<skipTests>true</skipTests>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>org.jbpm</groupId>
			<artifactId>jbpm-gwt-console</artifactId>	
			<version>5.4.0.Final</version>
			<type>war</type>
		</dependency>
	</dependencies>
</project>

Lo único que hacemos es un overlay del war, no requiere persistencia porque solo hace uso de los servicios REST y la autenticación la configuramos en el siguiente punto.


3.4. Configuración de Jboss AS.

Ya vimos cómo configurar la persistencia a MySQL en un tutorial anterior y también necesitaríamos añadir la siguiente fuente de datos al fichero de configuración standalone.xml de Jboss

<datasource jta="true" jndi-name="java:jboss/datasources/jbpm5DS" pool-name="jbpmDS" enabled="true" use-java-context="true" use-ccm="true">
    <connection-url>jdbc:mysql://localhost:3306/jbpm5</connection-url>
    <driver>mysql</driver>
    <pool>
    	<min-pool-size>1</min-pool-size>
    	<max-pool-size>4</max-pool-size>
    	<prefill>false</prefill>
    	<use-strict-min>false</use-strict-min>
    	<flush-strategy>FailingConnectionOnly</flush-strategy>
    </pool>
    <security>
        <user-name>jbpm5</user-name>
    	<password>jbpm5</password>
    </security>
    <validation>
        <check-valid-connection-sql>SELECT 1</check-valid-connection-sql>
		<validate-on-match>false</validate-on-match>
		<background-validation>false</background-validation>
	</validation>
</datasource>
<drivers>
    <driver name="mysql" module="com.mysql">
    	<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
	</driver>
</drivers>

Además de lo anterior debemos añadir una gestión de seguridad para autenticarnos en las aplicaciones web, para ello
debemos añadir al mismo standalone.xml la siguiente configuración:

<security-domain name="jbpm-console" cache-type="default">
	<authentication>
		<login-module code="UsersRoles" flag="required">
        	<module-option name="usersProperties" value="${jboss.server.config.dir}/users.properties"/>
            <module-option name="rolesProperties" value="${jboss.server.config.dir}/roles.properties"/>
        </login-module>
    </authentication>
</security-domain>

E incluir los ficheros users.properties en el mismo directorio de configuration, con el siguiente contenido:

admin=admin

Y un fichero roles.properties con el siguiente contenido

admin=admin,manager,user

En este mismo standalone.xml podemos modificar el puerto al 8081:

<socket-binding name="http" port="8081"/>

Si todo va bien, accediendo a la siguiente dirección http://localhost:8081/gwt-console-server/rs/process/definitions, veremos una interfaz de autenticación básica

y tras incluir usuario y contraseña admin|admin veremos el resultado de la invocación al API

Accediendo a http://localhost:8081/gwt-console-server/rs/server/resources/jbpm podemos ver un listado de los servicios disponibles:

Y accediendo a la siguiente dirección http://localhost:8081/jbpm-console veremos una interfaz de autenticación:

Y tras incluir usuario y contraseña admin|admin podremos acceder a la consola de procesos y bandeja de tareas:


5. Integración con LDAP.

Si una tarea está asignada a un grupo de usuarios, el jBPM Console Server se pondrá en contacto con el Human Task Server para solicitar un listado de los usuarios
asociados a un grupo y comprobar su existencia.

Del mismo modo, la consola JBPM, para mostrar las pontenciales tareas de un usuario, lleva a cabo una comprobación de los
roles del usuario.

Para añadir usuarios y grupos a la autenticación de la consola jBPM no tenemos más que jugar con los ficheros users.properties:

rcanales=rcanales
jmsanchez=jmsanchez

y roles.properties:

rcanales=admin,manager,user,administrativos
jmsanchez=admin,manager,user,tramitadores

Y para configurar el servidor de tareas humanas para que su repositorio de usuarios sea nuestro servidor LDAP corporativo,
tenemos que añadir un fichero jbpm.usergroup.callback.properties al directorio src/main/resources con un contenido similar al siguiente:

java.naming.provider.url=ldap://localhost:9898
ldap.bind.user=uid=admin,ou=system
ldap.bind.pwd=secret
ldap.user.ctx=ou=users,o=autentia
ldap.role.ctx=ou=groups,o=autentia
ldap.user.roles.ctx=ou=groups,o=autentia
ldap.user.filter=(uid\={0})
ldap.role.filter=(cn\={0})
ldap.user.roles.filter=(uniqueMember\={0})

Apuntando a nuestro servidor ldap con autenticación si es necesario y los parámetros necesarios para que se puedan realizar
las consultas de usuario y grupo.

Los parámetros que he expuesto son los necesarios para autenticarnos contra la estructura organizativa (ldif) que ya vimos en el tutorial anterior sobre
cómo hacer uso de un servidor LDAP embebido con el soporte de Spring Security.

Además de lo anterior deberíamos añadir un fichero web.xml al directorio src/main/webapp/WEB-INF con el contenido del original, pero modificando la entrada relativa a la clase que resuelve los grupos de un usuario

<init-param>
	<param-name>user.group.callback.class</param-name>
	<param-value>org.jbpm.task.identity.LDAPUserGroupCallbackImpl</param-value>
</init-param>

También debemos asegurarnos que haya una estrategía definida para las comunicaciones:

<init-param>
	<param-name>active.config</param-name>
	<param-value>hornetq</param-value>
</init-param>

Con todo ello y, según la configuración definida tanto a nivel de consola como a nivel de ldap, podríamos crear tareas para los grupos de usuarios tramitadores o administrativos.

Un último apunte: para que desde la consola de jBPM se pueda arrancar un nuevo proceso debemos disponer de un usuario Administrator en nuestro directorio activo.

dn: cn=admin,ou=groups,o=autentia
objectClass: groupOfUniqueNames
objectClass: top
objectClass: group
cn: admin
uniqueMember: cn=Administrator,ou=users,o=autentia

dn: cn=Administrator,ou=users,o=autentia
objectClass: organizationalPerson
objectClass: person
objectClass: inetOrgPerson
objectClass: top
cn: Administrator
sn: Administrator
uid: Administrator
mail: info@autentia.com
userPassword:: cGFzcw==


5. Referencias.


6. Conclusiones.

Seguiremos jugando, solo nos queda la integración del generador de formularios dentro del ecosistema.

Si queréis jugar con nosotros aquí os dejo los proyectos mavenizados que se acumulan a los que teníamos para guvnor.

Un saludo.

Jose

jmsanchez@autentia.com

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad