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

发布于 2024-11-09 00:48:50 字数 854 浏览 3 评论 0原文

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

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

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

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

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

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

I'm working with an application that uses JBPM 3.1 and MySQL. The core problem is that there are processes instances with variables that contain an older version of an external, non-JBPM Serializable class. When the main application is upgraded, these processes instances cause an exception to be thrown by JBPM since the SUID of a specific class instance has changed in the main application.

I believe I have a method for fixing the deserialization process using the technique described in the following:

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

However, my problem is figuring out where in MySQL JBPM stores process instance variables, so I can write a program that can interate over all the variables for all instances, an reserialize the variables so the offending class will have the new SUID, so JBPM can operate against the processes.

My initial looking at the JBPM tables, it appears that the JBPM_BYTEARRAY and/or JBPM_BYTEBLOCK may be the tables to operate against. However, I'm unsure how to proceed. I'm guessing each process variable is stored in a wrapping container class. Is that class org.jbpm.context.exe.VariableInstance? Or is it something else?

I figure if I have the proper jar files in the class path, and I know what the main class instance is that JBPM uses to store process variables in MySQL, I can deserialize the class (which will fix the SUID problem with the embedded problem class instance), and reserialize the class back. Since JBPM documentation does mention stuff about converters, I'm unsure if I have to replicate the conversion process JPBM does when deserializing, or if standard java deserialization is enough.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

策马西风 2024-11-16 00:48:50

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

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

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

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

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

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

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

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

Some analysis of JBPM indicates that binary data may be split across multiple records. This may not be the case for mysql itself, but the JPBM code is written to support multiple RDBMs, and some have limits on the size of binary records.

Since the question earned me a tumbleweed reward, I was not going to get a usable mysql-based answer in within the deadline I had to meet, so I re-considered the core problem and the operating context the problem occurs, and came up with a solution that avoided the needed to perform direct mysql operations.

The main application in question already has some customize modifications to JBPM, so the solution I implemented altered JBPM source which performs the deserialization of process instance variables. This avoids the need to deal with JBPM logic that extracts the deserialized binary data from the RDBMs.

In the class org.jbpm.context.exe.converter.SerializableToByteArrayConverter, I modifed the code to use a custom ObjectInputStream class that returns the latest SUID of a class. The technique of just replacing the descriptor with the latest version of the class as described in the post referenced in the question does not work if the new class includes new fields. Doing so causes an end-of-data exception since the base deserialization code tries to access the "new" fields in the old, deserialized version of the class.

Therefore, I just need to replace the SUID, but keep all other parts of the descriptor the same. Since the JDK does not make ObjectStreamClass extensible, I created a sub-class of ObjectInputStream that returns the new SUID based upon a given calling pattern the java library executes against ObjectInputStream when deserialzing data.

The pattern: When reading the header of a deserialized object, the readUTF() function is called (to obtain the class name) followed by a readLong() call. Therefore, if this calling sequence occurs, and if the readUTF() returned the class name I want to change the SUID of, I return the newer SUID in the readLong() call.

The custom code reads a configuration file that specifies class names and associated SUIDs that should be mapped to the latest SUIDs for the classes listed. This allows mapping of alternate classes in the future w/o modifying the custom code.

Note, this approach is applicable to general deserialization operations, where one needs to map old SUIDs to the latest SUIDs of specified classes, and leaving the other parts of the serialized class descriptor alone to avoid end-of-data problems if the newer class definition includes additional field declarations not present in the older class definition.

逐鹿 2024-11-16 00:48:50

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

Do you know if you made changes that break the contract or is it just simple adding new fields ? If it is simply adding new fields, then just define prior serialversionuid.. Otherwise.. you will have to read all the variables that have different serialversionids and save them under the new class because you are the only person who knows how to convert them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文