如何在 Activiti JavaDelegate 中访问 spring bean?
我正在尝试获取一个简单的 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 没有在正在调用的类中使用 spring bean我的 JavaService 任务,它正在创建一个新实例。
<?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 实体的引用?
任何/所有回复表示赞赏!
2011年6月28日 更新: 在尝试更改 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)
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.
I modified the spring config file so that it performs an include of my custom spring configuration file:
<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.
Here is my Spring Config:
<?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:
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.
<?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?
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.
I change the xml file to look like this:
<?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:
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的一个项目使用 Activiti 和 spring。我认为 JavaDelagate 可能是问题所在。您可以通过这种方式从 activiti 的服务任务中调用每个 spring bean:
bean 定义:
activiti xml:
您还可以将参数传递给函数,例如流程变量:
我总是以这种方式使用服务任务,并且单例 bean 没有出现问题。
希望有帮助。如果我不明白你的问题,请发表评论。
更新:
我的项目使用 activiti 像嵌入式工作流引擎。 Activiti 使用与我的 web 应用相同的 applicationContext。
我的流程引擎配置:
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:
bean definition:
activiti xml:
You can also pass parameters to the functions for example process variables:
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.
UPDATE:
My project uses activiti like an embedded workflow engine. Activiti uses the same applicationContext with my webapp.
My process engine configuration:
我正在使用
@Autowired
引入我的依赖项。由于 JavaDelegate 不是由 Spring 实例化的,因此我调用
Delegate 超类的构造函数,它将所有依赖项注入到 Delegate 中。您可能想知道从哪里获取 applicationContext,http ://sujitpal.blogspot.com/2007/03/accessing-spring-beans-from-legacy-code.html为您提供了答案。
I'm using
@Autowired
to bring in my dependencies. Since the JavaDelegate is not instantiated by Spring, I call
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.html provides you with the answer.
我的猜测是,activiti 确实总是会创建一个新实例,因为 activiti 不知道它应该从 spring 容器中检索实例。
如果您还没有检查过此资源:
http://www.activiti.org/userguide /index.html#springintegration
也许这就是你所需要的(即ProcessEngineFactoryBean)
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.
If you haven't checked this resource yet:
http://www.activiti.org/userguide/index.html#springintegration
maybe it's what you need (i.e. ProcessEngineFactoryBean)