Re-serializar variables de proceso JBPM directamente a través de MySQL

Estoy trabajando con una aplicación que usa JBPM 3.1 y MySQL. El problema central es que hay instancias de procesos con variables que contienen una versión anterior de una Serializableclase externa que no es JBPM . Cuando se actualiza la aplicación principal, estas instancias de procesos hacen que JBPM genere una excepción ya que el SUID de una instancia de clase específica ha cambiado en la aplicación principal.

Creo que tengo un método para arreglar el proceso de deserialización utilizando la técnica que se describe a continuación:

Cómo deserializar un objeto persistió en una base de datos ahora cuando el objeto tiene diferente serialVersionUID

Sin embargo, mi problema es averiguar en qué parte de MySQL JBPM almacena las variables de instancia de proceso, para poder escribir un programa que pueda interactuar sobre todas las variables para todas las instancias, y volver a serializar las variables para que la clase infractora tenga el nuevo SUID, para que JBPM pueda operar contra los procesos.

Mi primer vistazo a las tablas JBPM, parece que JBPM_BYTEARRAY y / o JBPM_BYTEBLOCK pueden ser las tablas para operar. Sin embargo, no estoy seguro de cómo proceder. Supongo que cada variable de proceso se almacena en una clase de contenedor de envoltura. Es esa clase org.jbpm.context.exe.VariableInstance? ¿O es otra cosa?

Me imagino que si tengo los archivos jar adecuados en la ruta de clase, y sé cuál es la instancia de clase principal que JBPM usa para almacenar variables de proceso en MySQL, puedo deserializar la clase (que solucionará el problema SUID con la clase de problema incrustado instancia) y volver a serializar la clase. Dado que la documentación de JBPM menciona cosas sobre los convertidores, no estoy seguro de si tengo que replicar el proceso de conversión que JPBM hace al deserializar, o si la deserialización estándar de Java es suficiente.

Respuesta 1

Algunos análisis de JBPM indican que los datos binarios pueden dividirse en múltiples registros. Puede que este no sea el caso para mysql, pero el código JPBM está escrito para admitir múltiples RDBM, y algunos tienen límites en el tamaño de los registros binarios.

Dado que la pregunta me valió una recompensa de planta rodadora, no iba a obtener una respuesta utilizable basada en mysql dentro de la fecha límite que tenía que cumplir, así que volví a considerar el problema central y el contexto operativo en el que se produce, y se me ocurrió Una solución que evitaba la necesidad de realizar operaciones mysql directas.

La aplicación principal en cuestión ya tiene algunas modificaciones personalizadas a JBPM, por lo que la solución que implementé modificó la fuente JBPM que realiza la deserialización de las variables de instancia de proceso. Esto evita la necesidad de lidiar con la lógica JBPM que extrae los datos binarios deserializados de los RDBM.

En la clase org.jbpm.context.exe.converter.SerializableToByteArrayConverter, modifiqué el código para usar una ObjectInputStreamclase personalizada que devuelva el último SUID de una clase. La técnica de simplemente reemplazar el descriptor con la última versión de la clase como se describe en la publicación a la que se hace referencia en la pregunta no funciona si la nueva clase incluye nuevos campos. Hacerlo provoca una excepción de fin de datos ya que el código de deserialización base intenta acceder a los campos "nuevos" en la versión antigua y deserializada de la clase.

Por lo tanto, solo necesito reemplazar el SUID, pero mantener todas las otras partes del descriptor iguales. Dado que el JDK no se hace ObjectStreamClassextensible, creé una subclase ObjectInputStreamque devuelve el nuevo SUID basado en un patrón de llamada dado contra el que se ejecuta la biblioteca Java ObjectInputStreamal deserializar los datos.

El patrón: al leer el encabezado de un objeto deserializado, readUTF()se llama a la función (para obtener el nombre de la clase) seguida de una readLong()llamada. Por lo tanto, si se produce esta secuencia de llamada y readUTF()devuelve el nombre de la clase de la que quiero cambiar el SUID, devuelvo el SUID más nuevo en la readLong()llamada.

El código personalizado lee un archivo de configuración que especifica los nombres de clase y los SUID asociados que deberían asignarse a los últimos SUID para las clases enumeradas. Esto permite la asignación de clases alternativas en el futuro sin modificar el código personalizado.

Tenga en cuenta que este enfoque es aplicable a las operaciones de deserialización general, donde uno necesita asignar SUID antiguos a los últimos SUID de clases especificadas, y dejar solo las otras partes del descriptor de clase serializado para evitar problemas de fin de datos si la definición de clase más nueva incluye declaraciones de campo adicionales que no están presentes en la definición de clase anterior.

Respuesta: 2

Tengo un generador de código que genera clases con mucho código privado como: clase A {private void meth1 () {...} private int var1; clase privada SubA {privado voth meth2 () {...}}} ...

Tengo una entidad de Hibernate en mi código. buscaría eso y, según el valor de una de las propiedades, diga "isProcessed", continúe y: cambie el valor de "isProcessed" a "Yes" (la propiedad que ...

Entonces, tengo un detector de mouse que está conectado a varios objetos de la siguiente manera: for (int i = 0; i <Grids.size (); i ++) {Grids.get (i) .addMouseListener (new GameMouseListener ()); } Ahora el problema ...

Soy algo nuevo en Java y el marco de Android, sin embargo, lo que estoy haciendo no lo considero una tarea complicada. Hay un servidor LAMP XML-RPC que devuelve una matriz de estructuras (matriz de asociativos ...