在Activiti BPMN中使用Non Serializable对象

时间:2016-01-31 10:09:00

标签: serialization activiti

我想将Activiti BPMN流程用于某些数据库更新任务。我的流程如下。

开始活动 - >服务任务1 - >服务任务2 - >服务任务3 - >结束事件

在服务任务1的服务实现类中:我为MySQL数据库创建了一个java.sql.Connection。我需要将相同的Connection对象传递给服务任务2和服务任务3.基本上这两个类将使用相同的Connection对象对数据库进行一些插入。

我尝试如下(dbConn是包含java.sql.Connection类型dbConnection的类)

execution.setVariable("DBConn",dbConn); 

但由于连接对象不可序列化,因此它会出现异常。

"org.activiti.engine.ActivitiException: Couldn't serialize value" 

那么在进程的服务任务之间传递这种非可序列化变量的最佳方法是什么?或者有没有办法在一个地方为多个服务任务定义这样的公共对象,并在服务任务中使用它们(像过程的全局变量那样)

2 个答案:

答案 0 :(得分:2)

首先,您应该知道,根据here创建连接实例后,绝对无法对其进行序列化。

  

原因是连接使用网络资源(例如TCP / IP套接字),该资源使用计算机上的网络堆栈,最终使用计算机的硬件。

只留下这个选择:

  • 设置一个将为你存储连接实例的bean,让它调用它myConnectionRegistry,这个bean的范围应该是单例并注入所有的java委托(服务任务实现)
  • 在第一个任务中,您创建连接,然后使用类似myConnectionRegistry的内容将其注册到connectionRegistry.register(conn, wfId),这会将连接实例添加到私有地图....
  • 在后续任务中,您使用从私有映射中获取连接对象的方法从同一个bean中检索您的任务,如果在映射中未注册任何连接对象,则抛出异常
  • 有一个边界事件被触发该异常并执行必要的操作以确保数据完整性(例如我在评论中描述的用例)
  • 在上一个服务任务中,取消注册您的连接(您也应该关闭它)以防止内存泄漏
  • 确保在设计解决方案时考虑数据库池等...

干杯!

答案 1 :(得分:2)

您可以在Java中使用Thradlocal将连接对象传递给不同的服务任务。

例如,使用如下所示的Base类,并从中扩展每个服务任务。然后,您可以设置dbConnection并在需要时使用get方法。

public class BaseServiceTask
{
    public static final ThreadLocal<Connection> localConnectionContext = new ThreadLocal<Connection>();

    public static void initDBConnector(Connection dbConn)
    {
        localConnectionContext.set(dbConn);
    }

    public static Connection getDBConnector()
    {
        return localConnectionContext.get();
    }
}

注意:
这种方法假设所有服务任务都在同一个线程中执行,这就是这个特定问题的情况,但是一旦你包含了一些用户任务/计时器(或任何异步逻辑),这就不再是一个可行的解决方案了!