直接通过MySQL重新序列化JBPM流程变量

时间:2011-05-22 20:21:08

标签: java mysql jbpm

我正在使用一个使用JBPM 3.1和MySQL的应用程序。核心问题是存在包含旧版本外部非JBPM Serializable类的变量的流程实例。升级主应用程序时,这些进程实例会导致JBPM抛出异常,因为主应用程序中特定类实例的SUID已更改。

我相信我有一种使用以下技术修复反序列化过程的方法:

How to deserialize an object persisted in a db now when the object has different serialVersionUID

然而,我的问题是弄清楚MySQL JBPM存储流程实例变量的位置,所以我可以编写一个程序,可以对所有实例的所有变量进行交互,重新整理变量,使得违规类具有新的SUID,所以JBPM可以对这些流程进行操作。

我最初查看JBPM表,看来JBPM_BYTEARRAY和/或JBPM_BYTEBLOCK可能是要操作的表。但是,我不确定如何继续。我猜每个流程变量都存储在一个包装容器类中。那班org.jbpm.context.exe.VariableInstance?还是别的什么?

我想如果我在类路径中有正确的jar文件,并且我知道JBPM用于在MySQL中存储过程变量的主类实例是什么,我可以反序列化类(这将解决SUID问题与嵌入式问题类实例),并将类重新序列化。由于JBPM文档确实提到了有关转换器的内容,我不确定是否必须复制JPBM在反序列化时执行的转换过程,或者标准java反序列化是否足够。

2 个答案:

答案 0 :(得分:1)

对JBPM的一些分析表明二进制数据可以分成多个记录。这可能不是mysql本身的情况,但是JPBM代码是为支持多个RDBM而编写的,有些对二进制记录的大小有限制。

由于这个问题为我赢得了一个风滚草的奖励,我不会在我必须满足的截止日期内得到一个可用的基于mysql的答案,所以我重新考虑了问题发生的核心问题和操作环境,以及提出了一个避免执行直接mysql操作所需的解决方案。

有问题的主要应用程序已经对JBPM进行了一些自定义修改,因此我实现的解决方案改变了JBPM源,它执行流程实例变量的反序列化。这避免了处理从RDBM中提取反序列化二进制数据的JBPM逻辑的需要。

在类org.jbpm.context.exe.converter.SerializableToByteArrayConverter中,我修改了代码以使用返回类的最新SUID的自定义ObjectInputStream类。如果新类包含新字段,则仅使用问题中引用的帖子中描述的最新版本的类替换描述符的技术不起作用。这样做会导致数据结束异常,因为基本反序列化代码会尝试访问类的旧的反序列化版本中的“新”字段。

因此,我只需要替换SUID,但保持描述符的所有其他部分相同。由于JDK没有使ObjectStreamClass可扩展,我创建了一个ObjectInputStream子类,它根据反序列化数据时java库对ObjectInputStream执行的给定调用模式返回新的SUID。

模式:在读取反序列化对象的标题时,调用readUTF()函数(获取类名),然后调用readLong()。因此,如果发生此调用序列,并且readUTF()返回了我想要更改SUID的类名,我将在readLong()调用中返回较新的SUID。

自定义代码读取一个配置文件,该文件指定应该映射到列出的类的最新SUID的类名和关联的SUID。这允许将来映射备用类,而无需修改自定义代码。

注意,这种方法适用于一般的反序列化操作,其中需要将旧的SUID映射到指定类的最新SUID,并且单独保留序列化类描述符的其他部分以避免数据末尾问题(如果较新的类定义包括旧类定义中不存在的附加字段声明。

答案 1 :(得分:0)

您是否知道您是否进行了违反合同的更改,或者只是简单地添加新字段?如果它只是添加新字段,那么只需定义之前的serialversionuid ..否则..您将必须读取具有不同serialversion的所有变量并将它们保存在新类下,因为您是唯一知道如何转换它们的人。