Jugando con jBPM #10 – Variables Instances

Este post tiene como objetivo profundizar sobre la customizacion de almacenamiento de variables de procesos.

(Documentación oficial: http://docs.jboss.com/jbpm/v3.2/userguide/html/context.html#customizingvariablepersistence)

La primer pregunta que nos surge es, cuando necesitamos customizar como se almancenan las variables en jBPM?

A decir verdad, es una buena pregunta. Vamos a empezar haciendo referencia a la documentación oficial en cuanto a las variables que dicen estar soportadas por jBPM para su almacenamiento automático:

  • java.lang.String
  • java.lang.Boolean
  • java.lang.Character
  • java.lang.Float
  • java.lang.Double
  • java.lang.Long
  • java.lang.Byte
  • java.lang.Short
  • java.lang.Integer
  • java.util.Date
  • byte[]
  • java.io.Serializable
  • classes that are persistable with hibernate

Supuestamente estos tipos de variable son fácilmente persistibles por jBPM y no debemos cambiar ninguna configuración para que las variables simplemente se persistan.

De los tipos basicos de datos (String, Boolean, Float, Double, Long, Byte, Short, Integer, Date y byte[]) podemos pensar que hibernate los resuelve directamente fijandose en los mapeos de los tipos de datos especificos para cada base de datos en particular. Y de los dos ultimos tipos (java.io.Serializable y hibernate classes) podemos pensar que vamos a necesitar alguna configuracion especial.
Pero no, ya que el motor de jBPM  para todos los tipos de variable va a revisar el archivo jbpm.varmappings.xml y transformara los objetos de usuario (todos los de la lista anterior) a objetos de tipo VariableInstance, que son objetos que actualmente se encuentran mapeados con Hibernate (mediante un hbm).
Para esta transformación se necesitan dos cosas importantes, los matchers y los converters. (JbpmTypeMatcher, Converter dos interfaces importantes en el paquete: org.jbpm.context.exe)
Estas dos interfaces (JbpmTypeMatcher, Converter) deben ser implementadas en el caso que necesitemos algun tipo nuevo de VariableInstance para nuestro caso particular. Como vemos en la documentacion oficial, los tipos de VariableInstance que tenemos por defecto son los siguientes:
  • DateInstance (with one java.lang.Date field that is mapped to a Types.TIMESTAMP in the database)
  • DoubleInstance (with one java.lang.Double field that is mapped to a Types.DOUBLE in the database)
  • StringInstance (with one java.lang.String field that is mapped to a Types.VARCHAR in the database)
  • LongInstance (with one java.lang.Long field that is mapped to a Types.BIGINT in the database)
  • HibernateLongInstance (this is used for hibernatable types with a long id field. One java.lang.Object field is mapped as a reference to a hibernate entity in the database)
  • HibernateStringInstance (this is used for hibernatable types with a string id field. One java.lang.Object field is mapped as a reference to a hibernate entity in the database)
  • ByteArrayInstance que misteriosamente no aparece en la documentacion
Por lo tanto si empezamos a ver como es la secuencia de funcionamiento, llegamos a la conclusion de que cuando llamamos al metodo setVariable, el objeto de usuario va a ser opcionalmente convertido con el converter apropiado segun el matcher que coincida en el archivo jbpm.varmappings.xml. Cuando nostros estemos customizando este archivo, tenemos que tener cuidado porque el mismo se revisa en orden secuencial, por lo tanto, hay que ver que nuestro tipo custom no matchee con ningun otro matcher antes que el nuestro.
Toda esta interaccion de matchers y converters ocurre dentro de la clase VariableInstance y el metodo createVariableInstance que es invocado cada vez que se llama el metodo setVariable mensionado anteriormente.
public static VariableInstance createVariableInstance(Object value) {
VariableInstance variableInstance = null;

Iterator iter = JbpmType.getJbpmTypes().iterator();
while ( (iter.hasNext())
&& (variableInstance==null) ){
JbpmType jbpmType = (JbpmType) iter.next();

if (jbpmType.matches(value)) {
variableInstance = jbpmType.newVariableInstance();
}
}

if (variableInstance==null) {
variableInstance = new UnpersistableInstance();
}

return variableInstance;
}

Otro clase que juega un papel importante aca es JbpmType:
public JbpmType(JbpmTypeMatcher jbpmTypeMatcher, Converter converter, Class variableInstanceClass) {
this.jbpmTypeMatcher = jbpmTypeMatcher;
this.converter = converter;
this.variableInstanceClass = variableInstanceClass;
}
Ya que podemos observar como se crea engloba al matcher, al converter y al tipo de la clase que estamos por crear el VariableInstance.
Para no extender mucho mas el post, termino dando tres aclaraciones que considero importantes:
  • Vamos a tener que crear un nuevo VariableInstance cuando necesitemos persistir algun objeto de dominio (negocio) con algun mapeo poco comun. Espero tener tiempo y poder postear un ejemplo de eso, asi queda claro que seria un mapeo poco comun.
  • Para nuestros objetos de dominio que tengamos o decidamos mapear con hibernate de la forma mas comun (hbms), siempre y cuando agreguemos los hbms al archivo hibernate.cfg.xml, los objetos seran automaticamente persistidos por hibernate.
  • Para nuestros objetos que no esten mapeados con hibernate pero esten marcados como serializables, estos seran transformados como indica el matcher en jbpm.varmappings.xml a ByteArrayInstance y se guardaran en forma binaria en la base de datos.
Advertisements

2 thoughts on “Jugando con jBPM #10 – Variables Instances”

  1. Muy bien dia.

    Necesito un Gran favor sobre deserealizacion de archivos, llevo bastante tiempo investigando y no encuentro solucion a mi problema. Espero que alguien de buena fe me ayude.

    Necesito deserealizar archivos almacenados en mysql server de un tipo de dato longblob, que fueron almacenados por medio de Runa WFE es un entorno de JBoss jBPM motor de flujo de trabajo.

    Yo Serializo Archivos .DOC y Deserealizo solo los Archivos que yo Serializo (Micodigo), pero no puedo deserealizar los archivos almacenados y Serializados por medio de Runa WFE

    Me da el siguiente Error:

    java.lang.ClassNotFoundException: ru.runa.wf.FileVariable

    Si alguien me puede ayudar, con resolver este problema, o darme un link donde puedo descargar la clase que necesito, o alguna solucion.

    gomezcos@gmail.com

    Mil Gracias.

    Espero su ayuda que tanto la necesito Gracias.

    Like

  2. Gracias por tu pregunta, primero que nada te aclaro que no tengo conocimiento sobre Runa WFE, pero si utiliza por debajo jBPM, la solución debería ser sencilla.
    Contame exactamente como serializas los archivos?
    o los serializa directamente Runa? de ser asi probablemente internamente jBPM se este encargando de esto. Y por lo tanto lo vas a tener que deserializar como un binario de una clase especial que utiliza jBPM. Seguramente te tengas que fijar como que tipo de VariableInstance lo esta serializando.
    Podrias ver en tu base de datos MySQL el contenido de la tabla VariableInstance. Esto seria importante, ya que ahi se encuentran las referencias a las variables que serializa jBPM.
    Saludos. Espero que sirva, sino espero tu nuevo comentario

    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