Activiti6 + Pf4J 解决serviceTask ClassNotFount 问题

本文档描述了在使用SpringBoot和Activiti6重构审批流程项目时,采用插件模式遇到的ClassNotFoundException问题。作者将项目分为activiti-core、activiti-plugin-api和activiti-plugin-xxx三个模块,旨在实现核心逻辑与特定功能的解耦。然而,由于pf4j的类加载机制,导致流程执行时找不到类。为解决此问题,作者自定义了一个ClassLoader,使其先尝试父ClassLoader加载,若失败则遍历所有插件的ClassLoader,成功解决了问题。


一、背景

最近在使用 Springboot + Activiti6 重构和优化审批流程闭环管理的项目,前期由于该项目会不停的将软件应用到不同的用户与场景,同时可预知的未来可能还会存在各种用户的各种特定需求,所以为了以后的软件升级和代码维护,所以我准备使用插件的模式来做项目的设计。

不同用户的项目核心程序使用一套统一的核心逻辑代码,特定功能通过不同的用户插件实现特定功能,不影响其他用户版本的软件功能,核心代码通过接口的方式为插件提供功能接入,在应对不同用户的不同需求的时候只需要扩展接口开发插件,在插件中实现具体的核心功能逻辑即可。

因此在插件框架的选择上我选择了pf4j,因为使用起来比较简单。pf4j每个插件通过不同的ClassLoader将对应插件内的接口实现类加载到程序中。

二、项目设计

按照上面的思路,我将项目分为了三个模块

  • activiti-core
    负责整合项目的核心逻辑,包括前端接口,流程处理逻辑,与插件交互逻辑等应用的核心逻辑
  • activiti-plugin-api
    用来定义插件应该实现的接口,activiti-core 通过该模块与所有实现了这些插件api的插件进行交互。
  • activiti-plugin-xxx
    所有实现了 activiti-plugin-api 对应扩展接口的插件集合,用于处理不同用户的特定的业务逻辑。(包括不同要求的任务通知、不同要求的审批单生成逻辑等)

三、存在的问题

首先,根据上面的设计,所有的插件是不应该引用任何activiti-core的代码,在插件层面应该是对activiti-core模块没有任何感知的,插件只应该通过实现对应的 activiti-api 接口达到与activiti-core 交互的目的。

其次,具体的流程文件定义是在插件中的,流程中很大概率会存在类似于 serviceTask 这样的任务节点,比如:

<serviceTask id="servicetask1" name="文档上传" activiti:class="com.anke.activiti.plugin.prodef.jisan.UploadFileService">
      <extensionElements>
        <activiti:field name="uploadFile">
          <activiti:expression><![CDATA[${warnNoticeDoc}]]></activiti:expression>
        </activiti:field>
      </extensionElements>
</serviceTask>

这里我定义了一个文件上传的serviceTask节点,指定了使用 com.anke.activiti.plugin.prodef.jisan.UploadFileService 这个类来进行处理。

ClassNotFoundException

但是,由于PF4J每一个插件使用不同的ClassLoader,而Activiti的核心处理逻辑在activiti-core这个模块里面,这就会导致流程处理在执行到该节点的时候报错,由于不在同一个ClassLoader下,所以无法找到该节点的处理类。

Caused by: org.activiti.engine.ActivitiClassLoadingException: Class not found: com.anke.activiti.plugin.prodef.jisan.UploadFileService
	at org.activiti.engine.impl.util.ReflectUtil.loadClass(ReflectUtil.java:87)
	at org.activiti.engine.impl.util.ReflectUtil.instantiate(ReflectUtil.java:134)
	... 122 common frames omitted
Caused by: java.lang.ClassNotFoundException: com.anke.activiti.plugin.prodef.jisan.UploadFileService
	at org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader.loadClass(TomcatEmbeddedWebappClassLoader.java:72)
	at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1188)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at org.activiti.engine.impl.util.ReflectUtil.loadClass(ReflectUtil.java:288)
	at org.activiti.engine.impl.util.ReflectUtil.loadC
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值