如何在 Activiti JavaDelegate 中访问 spring bean?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6474324/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 04:34:02  来源:igfitidea点击:

How can I access a spring bean in Activiti JavaDelegate?

springworkflowjavabeansactiviti

提问by Griff

I'm trying to get a simple Spring example to work with Activiti 5.5, and having some trouble. I'm using the process engine configured with activiti under %activiti_home%/apps/apache-tomcat-6.0.32/webapps/activiti-rest.

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

I modified the spring config file so that it performs an include of my custom spring configuration file:

我修改了 spring 配置文件,以便它执行包含我的自定义 spring 配置文件:

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

I deployed my applicationContext.xml file to the activiti-rest/WEB-INF/classes folder. Activiti starts up fine, and I see the System.out.println in my bean constructor, so I know that my spring config is being read and the bean is being constructed. I created a spring bean for the class that implements JavaDelegate and injected my bean to it and it always comes up null.

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

Here is my Spring Config:

这是我的 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>

Here is my 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;
    }

}

Here is my class that implements the JavaDelegate:

这是我实现 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;
    }
}

This all seems pretty straightforward to me, however I think the problem is that Activiti is not using a spring bean in the class that is being invoked on my JavaService task, it is creating a new instance.

这一切对我来说似乎很简单,但是我认为问题在于 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>

How do I get a reference to a Spring Bean either a simple one such as I have here, or one that has been configured as a JPA Entity?

我如何获得对 Spring Bean 的引用,要么是像我这里那样的简单引用,要么是已配置为 JPA 实体的引用?

Any/All replies appreciated!

任何/所有回复表示赞赏!



6.28.2011 Updated: In trying to change the activiti-rest app to use the SpringProcessEngineConfiguration instead of the standalone StandaloneProcessEngineConfiguration, I changed the activiti-cfg.xml file in the activiti-cfg.jar file and restarted Tomcat.

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

I change the xml file to look like this:

我将 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>

When I restarted Tomcat no exceptions appear, however when I bring up Explorer and try to login, I get the following Exception:

当我重新启动 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)

回答by lepike

One of my project uses Activiti with spring. I think that JavaDelagate can be the problem. You can call from activiti's service task every spring bean this way:

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

bean definition:

豆定义:

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

activiti xml:

活动xml:

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

You can also pass parameters to the functions for example process variables:

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

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

I always use service tasks this way, and haven't got problem with singleton beans. Hope it helps. Please take a comment, if I didn't understand your problem.

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

UPDATE:

更新:

My project uses activiti like an embedded workflow engine. Activiti uses the same applicationContext with my webapp.

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

My process engine configuration:

我的流程引擎配置:

<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>

回答by Urobe

I'm using @Autowired

我正在使用@Autowired

to bring in my dependencies. Since the JavaDelegate is not instantiated by Spring, I call

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

applicationContext.getAutowireCapableBeanFactory().autowireBean(this);

in the constructor of my Delegate's Superclass, which injects all dependencies into the Delegate. You might wonder where to get the applicationContext from, http://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.htmlprovides you with the answer.

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

回答by mkro

My guess ist that activiti will indeed always create a new instance because activiti is not aware of the fact that it should retrieve an instance from the spring container.

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

If you haven't checked this resource yet:

如果您尚未检查此资源:

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

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

maybe it's what you need (i.e. ProcessEngineFactoryBean)

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