1

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

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

当对象具有不同的serialVersionUID时,如何反序列化保存在数据库中的对象

但是,我的问题是弄清楚 JBPM 在 MySQL 中存储流程实例变量的位置,因此我可以编写一个程序,该程序可以对所有实例的所有变量进行交互,重新序列化变量,以便有问题的类将具有新的 SUID,因此 JBPM 可以对流程进行操作。

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

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

4

2 回答 2

1

对 JBPM 的一些分析表明,二进制数据可能会被拆分到多个记录中。mysql 本身可能不是这样,但是 JPBM 代码是为了支持多个 RDBM 而编写的,并且有些对二进制记录的大小有限制。

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

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

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

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

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

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

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

于 2011-06-01T04:57:56.237 回答
0

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

于 2011-05-31T18:36:19.620 回答