【问题标题】:How can I access a spring bean in Activiti JavaDelegate?如何在 Activiti JavaDelegate 中访问 spring bean?
【发布时间】:2011-06-24 22:15:40
【问题描述】:

我试图让一个简单的 Spring 示例与 Activiti 5.5 一起使用,但遇到了一些麻烦。我正在使用在 %activiti_home%/apps/apache-tomcat-6.0.32/webapps/activiti-rest 下配置了 activiti 的流程引擎。

我修改了 spring 配置文件,使其包含我的自定义 spring 配置文件:

<import resource="classpath*:applicationContext*.xml"/> 

我将 applicationContext.xml 文件部署到 activiti-rest/WEB-INF/classes 文件夹。 Activiti 启动正常,我在我的 bean 构造函数中看到 System.out.println,所以我知道我的 spring 配置正在被读取并且 bean 正在被构造。我为实现 JavaDelegate 的类创建了一个 spring bean,并将我的 bean 注入它,它总是出现 null。

这是我的 Spring 配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx" 
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

    <bean id="myBean" class="org.bpmn.examples.MyBean"/>
    <bean id="taskBean" class="org.bpmn.examples.GetBeanTest">
            <property name="myBean" ref="myBean"/>
    </bean>
</beans>

这是我的 Bean:

package org.bpmn.examples;

import java.io.Serializable;

public class MyBean implements Serializable {

    public MyBean() {
        super();
        System.out.println("<========================== myBean ===========================>");
        System.out.println("<========================== myBean ===========================>");
        System.out.println("<========================== myBean ===========================>");
    }
    /**
     * 
     */
    private static final long serialVersionUID = -2867207654072787909L;
    Long id;
    String description;

    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }

}

这是我实现 JavaDelegate 的类:

package org.bpmn.examples;

import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.JavaDelegate;

public class GetBeanTest implements JavaDelegate {

    private MyBean myBean;

    @Override
    public void execute(DelegateExecution execution) throws Exception {
        if(myBean == null){
            System.out.println("Bean was null!");
        }else{
            System.out.println("Bean is valid!");
        }

    }

    public void setMyBean(MyBean myBean) {
        this.myBean = myBean;
    }
}

这一切对我来说似乎很简单,但是我认为问题在于 Activiti 没有在我的 JavaService 任务上调用的类中使用 spring bean,它正在创建一个新实例。

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
  <process id="TestSpringConfig" name="TestSpringConfig">
    <documentation>Place documentation for the 'TestSpringConfig' process here.</documentation>
    <startEvent id="startevent1" name="Start"></startEvent>
    <serviceTask id="servicetask1" name="BeanTest" activiti:class="org.bpmn.examples.GetBeanTest"></serviceTask>
    <endEvent id="endevent1" name="End"></endEvent>
    <sequenceFlow id="flow1" name="" sourceRef="startevent1" targetRef="servicetask1"></sequenceFlow>
    <sequenceFlow id="flow2" name="" sourceRef="servicetask1" targetRef="endevent1"></sequenceFlow>
  </process>
</definitions>

如何获得对 Spring Bean 的引用,无论是简单的,例如我这里的,还是配置为 JPA 实体的?

感谢任何/所有回复!


6.28.2011 更新: 在尝试将 activiti-rest 应用程序更改为使用 SpringProcessEngineConfiguration 而不是独立的 StandaloneProcessEngineConfiguration 时,我更改了 activiti-cfg.jar 文件中的 activiti-cfg.xml 文件并重新启动了 Tomcat。

我将 xml 文件更改为如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
        <property name="driverClass" value="org.h2.Driver" />
        <property name="url" value="jdbc:h2:tcp://localhost/activiti" />
        <property name="username" value="sa" />
        <property name="password" value="" />
    </bean>

  <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"/>
  <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
    <property name="processEngineConfiguration" ref="processEngineConfiguration" />
  </bean>

  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </bean>

  <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
    <property name="dataSource" ref="dataSource" />
    <property name="transactionManager" ref="transactionManager" />
    <property name="databaseSchemaUpdate" value="true" />
    <property name="jobExecutorActivate" value="false" />
  </bean>

  <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
    <property name="processEngineConfiguration" ref="processEngineConfiguration" />
  </bean>

  <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
  <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
  <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService" />
  <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService" />
  <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService" />

</beans>

当我重新启动 Tomcat 时没有出现异常,但是当我打开资源管理器并尝试登录时,我得到以下异常:

INFO: Server startup in 12011 ms
10:32:02,338  ERROR [extensions.webscripts.AbstractRuntime] Exception from executeScript - redirecting to status template error: 05280000 Wrapped Exception (with status template): null
org.springframework.extensions.webscripts.WebScriptException: 05280000 Wrapped Exception (with status template): null
    at org.springframework.extensions.webscripts.AbstractWebScript.createStatusException(AbstractWebScript.java:742)
    at org.springframework.extensions.webscripts.DeclarativeWebScript.execute(DeclarativeWebScript.java:167)

【问题讨论】:

    标签: spring workflow javabeans activiti


    【解决方案1】:

    我的一个项目使用 Activiti 和 spring。我认为 JavaDelagate 可能是问题所在。您可以通过这种方式从 activiti 的每个 spring bean 的服务任务中调用:

    bean 定义:

    <bean id="exampleBean" class="org.bpmn.examples.ExampleBean"/>
    

    活动 xml:

    <serviceTask id="servicetask" name="Example" activiti:expression="${exampleBean.doSomething()}"></serviceTask>
    

    您还可以将参数传递给函数,例如流程变量:

    <serviceTask id="servicetask" name="Example" activiti:expression="${exampleBean.doSomething(processVariable)}"></serviceTask>
    

    我总是以这种方式使用服务任务,并且没有遇到单例 bean 的问题。 希望能帮助到你。如果我不明白您的问题,请发表评论。

    更新:

    我的项目使用像嵌入式工作流引擎一样的 activiti。 Activiti 使用与我的 webapp 相同的 applicationContext。

    我的流程引擎配置:

    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
            <property name="databaseType" value="mssql" />
            <property name="dataSource" ref="dataSource" />
            <property name="transactionManager" ref="transactionManager" />
            <property name="databaseSchemaUpdate" value="true" />
            <property name="jobExecutorActivate" value="true" />
            <property name="deploymentResources" value="classpath*:/diagrams/*.bpmn20.xml" />           
        </bean> 
    
    
        <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
            <property name="processEngineConfiguration" ref="processEngineConfiguration" />
        </bean>
    

    【讨论】:

    • 那么你上面的exampleBean是JavaDelegate吗?接口方法execute做了什么?
    • 另外,您是在使用 activiti-rest 流程引擎并通过 Jar 文件将您的类部署到应用程序中,还是在创建自己的流程引擎?
    • 我更新了我的答案。请检查我的流程引擎配置。 exampleBean 是一个简单的 Spring bean,没有实现 JavaDelegate。您可以使用我在示例中编写的表达式从 activiti 调用 bean 方法。
    • 您仍然可以使用开箱即用的 Activiti 工具(例如 Explorer 和 Probe)访问您的流程/任务吗?
    • 我没有使用这些工具,因为我认为这些应用程序还不太稳定,我无法将探针与 mssql 数据库集成。我只使用了一个手动实现的 Probe 功能(重新启动失败的 activiti 作业)。我只需要更新其中一个 activiti 表中的重试次数。
    【解决方案2】:

    我正在使用 @Autowired

    引入我的依赖项。由于 JavaDelegate 没有被 Spring 实例化,所以我调用了

    applicationContext.getAutowireCapableBeanFactory().autowireBean(this);
    

    在我的委托超类的构造函数中,它将所有依赖项注入到委托中。您可能想知道从哪里获取 applicationContext,http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html 为您提供了答案。

    【讨论】:

      【解决方案3】:

      我的猜测是 activiti 确实总是会创建一个新实例,因为 activiti 不知道它应该从 spring 容器中检索一个实例。

      如果您还没有查看此资源:

      http://www.activiti.org/userguide/index.html#springintegration

      也许这就是你所需要的(即 ProcessEngineFactoryBean)

      【讨论】:

      • 是的,我读过该部分几次。在我看来,如果您想从头开始构建自己的流程引擎,或者如果您想将其嵌入到现有应用程序中,那么 spring 配置似乎是适用的。我希望能够使用 Activiti 附带的工具,例如 explorer 和 probe。我尝试更改活动休息配置以使用 SpringProcessEngineConfiguration 而不是 StandaloneProcessEngineConfiguration 并且它破坏了工具身份管理配置。随项目分发的 Spring 示例还有很多不足之处。
      • 我认为你真的需要让 activiti 感知 Spring,这意味着:Activiti 不能控制你的进程 Bean 的生命周期,但必须从 Spring 容器中检索实例。我很遗憾听到这些例子并没有详细解释一切。 “破坏工具身份管理配置”是什么意思?你能发布更多细节吗?
      • 我想要做的是使用 activiti-rest 应用程序,并在其中添加我自己的 spring bean,以便我可以重用工具(Explorer 和 Probe)。我将其余应用程序中的 activiti-cfg.xml 文件更改为使用 SpringProcessEngineConfiguration 而不是 StandaloneProcessEngineConfiguration,我无法登录 Explorer 或探测它为身份服务抛出了 NPE。似乎可能需要一些额外的配置来告诉处理引擎如何对用户进行身份验证?
      猜你喜欢
      • 2022-11-10
      • 1970-01-01
      • 2011-07-27
      • 2017-05-13
      • 2018-04-23
      • 2013-04-11
      • 1970-01-01
      • 1970-01-01
      • 2016-08-19
      相关资源
      最近更新 更多