`
betafox
  • 浏览: 147653 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JBPM与SPRING事务整合之深度历险

阅读更多

------------------此文很早就写了,不知何故在博客上找不到了,所以重新录进来...---------------------

 

spring modules中包含了spring集成JBPM的机制,在使用的发现其并没有彻底解决两者的事务处理统一的问题,经过一段事件的摸索终于将jpbm与spring完全整合,主要是事务处理的整合,工作流代码与业务代码在一个事务上下文进行;

 

第一步:首先引入spring-modules-jbpm31.jar,同时将jbpm包含的所有hibernate映射文件解压出来,集成到spring配置文件中,可以使用类路径下的目录形式简化,如下:

 

xml 代码
  1. <property name="mappingDirectoryLocations">
  2. <list>
  3. <value>classpath:/conf/mapping/jbpm/<!---->value>
  4. <!---->list>
  5. <!---->property>

 

 

经测试在这种方式在weblogic上不能正常加载,从jar包加载也有问题必须解压到目录;

第二步:配置JPBM的大字段处理类型,这一步估计大家都知道,没什么说的;

xml 代码
  1. <!---->
  2. <bean id="jbpmTypes" class="org.springframework.orm.hibernate3.TypeDefinitionBean">
  3. <property name="typeName" value="string_max" />
  4. <property name="typeClass" value="org.jbpm.db.hibernate.StringMax" />
  5. <!---->bean>

 

xml 代码
  1. <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  2. <property name="lobHandler" ref="oracleLobHandle" />
  3. <property name="dataSource" ref="dataSource" />
  4. <property name="typeDefinitions"> 注意这里
  5. <ref bean="jbpmTypes" />
  6. <!---->property>
  7. 。。。。。。

 

第三步:配置spring modules,通过 springmodules 初始化jbpmConfiguration;

xml 代码

 

    <!-- jBPM configuration-->
    <bean id="jbpmConfiguration"
          class="org.springmodules.workflow.jbpm31.LocalJbpmConfigurationFactoryBean">
        <property name="sessionFactory" ref="sessionFactory" />

        <property name="configuration" value="classpath:/conf/jbpm.cfg.xml" />注意这里

        <!--<property name="configuration" value="classpath:/org/jbpm/default.jbpm.cfg.xml" />-->
        <!--<property name="processDefinitions">-->
        <!--<list>-->
        <!--<ref local="demoWorkflow" />-->
        <!--</list>-->
        <!--</property>-->

        <!--<property name="createSchema" value="true"/>-->
    </bean>

 

 

xml 代码(/conf/jbpm.cfg.xml

<jbpm-configuration>

    <jbpm-context>
        <!--<service name="persistence" factory="org.jbpm.persistence.db.DbPersistenceServiceFactory" />-->
        <service name="persistence">
            <factory>
                <bean class="org.jbpm.persistence.db.DbPersistenceServiceFactory">
                    <field name="isTransactionEnabled">
                        <false />  注意这里
                    </field>
                    <field name="isCurrentSessionEnabled">
                        <true />  注意这里
                    </field>
                </bean>
            </factory>
        </service>

        <service name="message" factory="org.jbpm.msg.db.DbMessageServiceFactory" />
        <service name="scheduler" factory="org.jbpm.scheduler.db.DbSchedulerServiceFactory" />
        <service name="logging" factory="org.jbpm.logging.db.DbLoggingServiceFactory" />
        <service name="authentication" factory="org.jbpm.security.authentication.DefaultAuthenticationServiceFactory" />
    </jbpm-context>

    <!--<string name="resource.hibernate.cfg.xml" value="hibernate.cfg.xml" />-->注意这里

    <string name="resource.business.calendar" value="org/jbpm/calendar/jbpm.business.calendar.properties" />
    <string name="resource.default.modules" value="org/jbpm/graph/def/jbpm.default.modules.properties" />
    <string name="resource.converter" value="org/jbpm/db/hibernate/jbpm.converter.properties" />
    <string name="resource.action.types" value="org/jbpm/graph/action/action.types.xml" />
    <string name="resource.node.types" value="org/jbpm/graph/node/node.types.xml" />
    <string name="resource.parsers" value="org/jbpm/jpdl/par/jbpm.parsers.xml" />
    <string name="resource.varmapping" value="org/jbpm/context/exe/jbpm.varmapping.xml" />

    <long name="jbpm.msg.wait.timout" value="5000" singleton="true" />
    <int name="jbpm.byte.block.size" value="1024" singleton="true" />
    <string name="mail.smtp.host" value="localhost" />
    <bean name="jbpm.task.instance.factory" class="org.jbpm.taskmgmt.impl.DefaultTaskInstanceFactoryImpl"
          singleton="true" />
    <bean name="jbpm.variable.resolver" class="org.jbpm.jpdl.el.impl.JbpmVariableResolver" singleton="true" />
    <bean name="jbpm.mail.address.resolver" class="org.jbpm.identity.mail.IdentityAddressResolver" singleton="true" />

</jbpm-configuration>

 

第四步:修改JBPM自带的过滤器(web.xml),初始化当前请求线程的JBPM Context时从spring获取我们上面配置的jbpmConfiguration;其自带过滤器是通过JbpmConfiguration.getInstance获取的,不能公用spring事务上下文的hibernate session;

 

xml 代码
  1. <filter>
  2. <filter-name>JbpmContextFilter<!---->filter-name>
  3. <filter-class>com.**.**.workflow.web.JbpmContextHolder<!---->filter-class> 注意这里
  4. <!---->filter>

 

 

java 代码(JbpmContextHolder<!---->filter.java
  1. import com.**.**.core.container.ApplicationContext;
  2. import org.jbpm.JbpmConfiguration;
  3. import org.jbpm.JbpmContext;
  4. import javax.servlet.*;
  5. import javax.servlet.http.HttpServletRequest;
  6. import java.io.IOException;
  7. import java.io.Serializable;
  8. import java.security.Principal;
  9. public class JbpmContextHolder implements Filter, Serializable {
  10. private static final long serialVersionUID = 1L;
  11. String jbpmConfigurationResource = null;
  12. String jbpmContextName = null;
  13. boolean isAuthenticationEnabled = true;
  14. public void init(FilterConfig filterConfig) throws ServletException {
  15. // get the jbpm configuration resource
  16. this.jbpmConfigurationResource = filterConfig.getInitParameter("jbpm.configuration.resource");
  17. // get the jbpm context to be used from the jbpm configuration
  18. this.jbpmContextName = filterConfig.getInitParameter("jbpm.context.name");
  19. if (jbpmContextName == null) {
  20. jbpmContextName = JbpmContext.DEFAULT_JBPM_CONTEXT_NAME;
  21. }
  22. // see if authentication is turned off
  23. String isAuthenticationEnabledText = filterConfig.getInitParameter("authentication");
  24. if ((isAuthenticationEnabledText != null)
  25. && ("disabled".equalsIgnoreCase(isAuthenticationEnabledText))
  26. ) {
  27. isAuthenticationEnabled = false;
  28. }
  29. }
  30. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  31. String actorId = null;
  32. // see if we can get the authenticated swimlaneActorId
  33. if (servletRequest instanceof HttpServletRequest) {
  34. HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
  35. Principal userPrincipal = httpServletRequest.getUserPrincipal();
  36. if (userPrincipal != null) {
  37. actorId = userPrincipal.getName();
  38. }
  39. }
  40. JbpmContext jbpmContext = getJbpmConfiguration().createJbpmContext(jbpmContextName);
  41. try {
  42. if (isAuthenticationEnabled) {
  43. jbpmContext.setActorId(actorId);
  44. }
  45. filterChain.doFilter(servletRequest, servletResponse);
  46. } finally {
  47. jbpmContext.close();
  48. }
  49. }

  50. 注意:下面是修改后的方法,从spring获取JbpmConfiguration;
  51. ApplicationContext是我们对spring的封装,可以改成自己的bean加载方式;

  52. protected JbpmConfiguration getJbpmConfiguration() {
  53. return (JbpmConfiguration) ApplicationContext.getInstance().getBizComponent("jbpmConfiguration");
  54. }
  55. public void destroy() {
  56. }
  57. }


第五步:大功告成

经过上边的修改后,从spring事务过程中调用JBPM方法、或者spring modules的方法时都会直接纳入当前事务,实现一致的提交和回滚;

 

第六步:后话

 

由于JBPM本身的设计问题,采用这样的解决方案后对JBPM API的调用必须在事务环境中运行,例如不能直接在struts action调用JBPM API代码;当然有解决的办法,但是需要对JBPM做进一步的修改,小弟为了保持JBPM的纯洁性,只改了JBPM的外围代码,没有动大手术,o(∩_∩)o...

 

另一个相关的问题就是不能直接在单元测试中获取JBPMContext,需要手工开启事务管理器; 

 

附单元测试代码:

 

public void testNonTrans() throws Exception {
        try {
            assertNull(jbpmConfiguration.getCurrentJbpmContext());

            jbpmConfiguration.createJbpmContext();

            JbpmContext context = jbpmConfiguration.getCurrentJbpmContext();

            assertNotNull(context);


            System.out.println(help.getDecisionHandler());//有事务环境

            try {
                help2.getProcessInstance(new Long(57424));//无事务环境:必然报错
                // org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
                assertTrue(false);
            } catch (Exception e) {

                assertTrue(true);
            }

            assertNotNull(basedao.getCurrentSession());//HibernateBaseDAO关联的hibernatetemplate默认的autocreate为true,所以可以得到session

            assertFalse(basedao.getCurrentSession() == basedao.getCurrentSession());//不在事务中每次创建新的不同的session

            assertTrue(context.getSessionFactory() == basedao.getSessionFactory());//SessionFactory公用

            try {
                context.getSessionFactory().getCurrentSession();//无事务环境时从SessionFactory获取session必然报错,同context.getSession()
                // org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
                assertTrue(false);
            } catch (Exception e) {

                assertTrue(true);
            }

            try {
                basedao.getSessionFactory().getCurrentSession();//无事务环境时从SessionFactory获取session必然报错
                // org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
                assertTrue(false);
            } catch (Exception e) {
                e.printStackTrace();
                assertTrue(true);
            }

            assertNotNull(context.getSessionFactory().openSession());

            assertNotNull(basedao.getSessionFactory().openSession());

            assertFalse(context.getSessionFactory().openSession() == basedao.getSessionFactory().openSession());

            assertTrue(true);

        } catch (Exception e) {
            e.printStackTrace();
            assertFalse(true); //失败
        }
    }

    public void testTransConfig() throws Exception {

        TransactionStatus status = beginTransation();

        assertNull(jbpmConfiguration.getCurrentJbpmContext());

        jbpmConfiguration.createJbpmContext();

        JbpmContext context = jbpmConfiguration.getCurrentJbpmContext();

        assertNotNull(context);

        try {

            System.out.println(help.getDecisionHandler());
            System.out.println(help2.getProcessInstance(new Long(57424)));

            assertNotNull(context.getSession());

            assertTrue(context.getSession() == context.getSession());//相同的session

            assertTrue(basedao.getCurrentSession() == basedao.getCurrentSession());//相同的session

            assertTrue(context.getSessionFactory() == basedao.getSessionFactory());//相同

            assertTrue(context.getSession() == basedao.getCurrentSession());//相同

            assertTrue(context.getSessionFactory().getCurrentSession() == basedao.getSessionFactory().getCurrentSession());//从相同的SessionFactory取getCurrentSession是相同的

        } catch (Exception e) {
            e.printStackTrace();
        }

        transactionManager.commit(status);

        ///////////


    }
分享到:
评论
7 楼 zhenrs 2013-04-07  
可以把ApplicationContext贴出来不
6 楼 zhang1210 2012-05-23  
请问楼主ApplicationContext这个是又重新定义的吗?求指教
5 楼 ssuupv 2008-11-04  
这是因为通过spring的类路径加载hbm方式在weblogic下有问题,无法正常加载;

   <property name="mappingLocations">  
这样就可以了

4 楼 betafox 2008-08-06  
这是因为通过spring的类路径加载hbm方式在weblogic下有问题,无法正常加载;

理论上,在其他应用服务器上你可以直接引用jbpm.jar中的hbm.xml文件....
3 楼 jinguizi 2008-08-04  
你不觉得第一步很愚蠢,用jbpm还要去把jar包解压缩
2 楼 yuyanshan 2008-07-27  
能把你的这几个配置文件件完整的贴出来参考一下吗?
1 楼 isky 2008-06-11  
留下脚印  日后备查

相关推荐

    工作流(JBPM)一些有用资料整合

    "JBPM与SPRING事务整合之深度历险"这一主题着重探讨了如何在Spring环境中配置和使用JBPM,确保工作流操作与Spring的事务管理无缝集成。Spring是一个广泛应用的轻量级Java框架,提供了丰富的企业级功能,包括事务管理...

    jbpm4.3与spring整合

    ### jbpm4.3与Spring框架的整合指南 在企业级应用开发中,流程管理引擎JBPM(JBoss Business Process Management)与Spring框架的结合使用是常见的一种技术方案。JBPM是一个灵活、强大的业务流程管理工具,而Spring...

    JBPM4与Spring整合例子代码

    **JBPM4与Spring整合详解** JBPM4(Java Business Process Management 4)是一个开源的工作流管理系统,它提供了业务流程的建模、部署、执行和监控功能。Spring框架则是Java应用开发中的一个核心组件,主要负责依赖...

    jbpm4和spring整合例子

    近期网上有人介绍jBPM4与Spring整合的2种方式,但没有人贴出代码,闲着无聊写了个例子,源码见附件,在WEBLOGIC下运行正常,事务由spring控制http://ip:7001/Spring/helloWorld.do

    jBPM4与Spring整合的2种方式

    **标题:“jBPM4与Spring整合的2种方式”** **内容概述:** jBPM4是一款开源的工作流管理系统,它提供了业务流程管理(BPM)和工作流服务。而Spring是一个广泛应用的Java企业级应用框架,它简化了开发、配置和管理...

    jbpm5 spring3 整合实例

    在spring3中整合jbpm5的例子,前台用spring mvc3做了简单的页面。 其中用到了jbpm5的persistence,local human service等,简单、完整。 用的mysql数据库,修改下spring datasource的配置,然后用mvn jetty:run编译...

    jbpm4.3-spring2.5整合

    jbpm4.3-spring2.5整合是一个关键的话题,涉及到企业级工作流管理系统Jbpm与Spring框架的集成。Jbpm是一个开源的工作流程管理(BPM)和业务规则管理系统,它允许开发者设计、执行、管理和监控业务流程。而Spring是...

    jbpm与spring集成

    【jbpm与Spring集成】是企业级应用中常见的技术整合,旨在利用jbpm(Java Business Process Management)的流程管理能力,结合Spring框架的灵活服务管理,实现高效、可扩展的业务流程自动化。jbpm是一个开源的工作流...

    jbpm+spring配置

    6. **事务管理**:由于jbpm的操作往往涉及数据库事务,因此需要确保jbpm的事务与Spring的事务管理协调一致。通常,jbpm会参与到Spring的全局事务中,这需要正确配置jbpm的事务策略。 7. **异常处理**:jbpm的异常...

    JBPM4.3 Spring会签 实例

    这些bean是Spring与JBPM交互的基础,通过它们可以启动流程实例、执行任务以及查询流程状态。 其次,创建流程定义(.bpmn文件)来描述会签流程。在这个流程中,可以设置多个并行的任务节点,每个节点代表一个会签的...

    Jbpm4.4 整合Spring Hibernate4

    在这个版本中,Jbpm与Spring框架和Hibernate ORM工具进行了整合,实现了更加灵活和高效的企业级应用开发。 **1. Jbpm简介** Jbpm4.4是Jbpm系列的一个版本,它主要负责处理业务流程的建模、执行、管理和监控。它支持...

    JBPM4.4+spring+ext整合

    【JBPM4.4+Spring+EXT 整合详解】 JBPM(Java Business Process Management)是一个开源的工作流管理系统,主要用于处理业务流程自动化。版本4.4是JBPM的一个重要里程碑,它提供了强大的工作流设计、执行和监控能力...

    jbpm5.4 spring mvc 集成

    以上就是jbpm5.4与Spring MVC集成开发中涉及的核心技术点,包括jbpm的工作流管理、Spring MVC的Web架构、Jetty服务器、Maven构建工具以及JTA事务管理。理解并掌握这些知识点,对于成功实现集成并开发高效、稳定的...

    JBPM与Spring集成开发指南

    当与Spring集成时,可以通过Spring的Bean定义和依赖注入来管理JBPM的工作流实例,同时利用Spring AOP来实现流程监控和事务管理。 集成开发的关键点包括: 1. **配置Spring容器**:将JBPM的相关组件如TaskService、...

    JBPM5 整合Spring3经典案例

    - **事务管理**:Spring的事务管理器可以与JBPM的事务管理相结合,确保流程操作的原子性和一致性。 - **AOP集成**:Spring的AOP可以在流程执行的关键点添加拦截器,实现日志记录、权限检查等功能。 - **Bean管理**:...

    jbpm4.0.0alpha2整合到spring

    【jbpm4.0.0alpha2整合到spring】是一个关于企业级业务流程管理(BPM)系统Jbpm与Spring框架集成的技术实践。Jbpm是一个开源的BPM平台,它提供了工作流引擎、流程设计工具以及相关API,使得开发者能够方便地创建和...

    JBPM与Spring集成开发指南.docx

    【JBPM与Spring集成开发指南】 JBPM(Java Business Process Management)是一款开源的工作流引擎,它允许开发者在Java应用程序中实现复杂的业务流程自动化。而Spring框架则是Java领域中广泛使用的轻量级应用框架,...

    jbpm与ssh框架整合

    jbpm4与SSH框架的整合是将jBPM(java Business Process Managerment)这一轻量级工作流引擎与Struts2、Spring和Hibernate(SSH)这三大主流Java开发框架结合的过程,以实现企业级应用中的业务流程管理和控制。jBPM是...

    jbpm4.4 ibatis-spring 整合

    jbpm4.4 ibatis-spring 整合

Global site tag (gtag.js) - Google Analytics