600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > JBPM 4.3 + Spring 3 + jBoss + JPA + JTA

JBPM 4.3 + Spring 3 + jBoss + JPA + JTA

时间:2022-09-27 13:59:15

相关推荐

JBPM 4.3 + Spring 3 + jBoss + JPA + JTA

来源:/jbpm-43-spring-3-jboss-jpa-jta-configuration

Many an hour was spent trying to get jBPM 4.3 to run in a Spring application while using a container managed persistence unit defined in persistence.xml. There's both good news and bad news for those of you wanting to accomplish this.

The bad news is you cannot rely solely on the hibernate session factory created by the container when using jBPM 4.3. This is because the SpringProcessEngine meant to integrate jBPM 4.3 with Spring assumes the presence of a LocalSessionFactoryBean in the Spring application context.

The good news is you can get jBPM 4.3 to work simply by providing a LocalSessionFactoryBean. This does not mean your application needs to use this bean. It only means that jBPM needs to use it. Your application can still use the container managed JPA persistence unit defined in persistence.xml. And as long as you are using JTA transactions, everything will be transactional as expected. Meaning if you complete some task in a task node, and then an exception is thrown by your application code later in the chain, both the changes made by your application code and the changes made by jBPM will be rolled back appropriately.

This solution has been tested on jBoss AS 5.1 GA, 6.0.0.M1, and 6.0.0.M2.

Here is how you configure this to work.

1. First, the persistence.xml. Notice that there are no jBPM mapping files specified here:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<persistence xmlns="/xml/ns/persistence" xmlns:xsi="/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="/xml/ns/persistence /xml/ns/persistence/persistence_1_0.xsd">

<!-- Define the container managed persistence unit using JTA. -->

<persistence-unit name="persistenceUnit" transaction-type="JTA">

<provider>org.hibernate.ejb.HibernatePersistence</provider>

<jta-data-source>java:/SquareOneDataSource</jta-data-source>

<!-- Any mapping files for the application go here. -->

<mapping-file>so.filter.hbm.xml</mapping-file>

<!--

These have been put in the hibernate session factory

inside the applicationContext.xml spring configuration.

-->

<!-- <mapping-file>jbpm.repository.hbm.xml</mapping-file>

<mapping-file>jbpm.execution.hbm.xml</mapping-file>

<mapping-file>jbpm.history.hbm.xml</mapping-file>

<mapping-file>jbpm.task.hbm.xml</mapping-file>

<mapping-file>jbpm.identity.hbm.xml</mapping-file> -->

<!--

These hibernate properties will be used by your application

code since we will inject this persistence unit with @PersistenceContext

using Spring. Spring will use JNDI to lookup the persistence

unit and inject it.

-->

<properties>

<property name="jboss.entity.manager.jndi.name"

value="java:SquareOnePersistenceUnit" />

<property name="jboss.entity.manager.factory.jndi.name"

value="java:SquareOnePersistenceUnitFactory" />

<property name="hibernate.session_factory_name"

value="java:SquareOneHibernateSessionFactory" />

<!-- Hibernate Configuration Properties -->

<property name="hibernate.archive.autodetection" value="class, hbm" />

<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />

<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />

<property name="hibernate.hbm2ddl.auto" value="update" />

<property name="hibernate.show_sql" value="true" />

<property name="hibernate.format_sql" value="true" />

<property name="hibernate.use_sql_comments" value="true" />

<property name="hibernate.default_batch_fetch_size" value="25" />

<property name="hibernate.order_updates" value="true" />

<property name="hibernate.generate_statistics" value="true" />

<!-- Hibernate JDBC and Connection Properties -->

<property name="hibernate.jdbc.batch_size" value="25" />

<property name="hibernate.connection.autocommit" value="false" />

<property name="hibernate.connection.release_mode" value="auto" />

<!-- Hibernate Cache Properties -->

<!-- <entry key="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" /> -->

<!-- <entry key="net.sf.ehcache.configurationResourceName" value="ehcache.xml" /> -->

<property name="hibernate.cache.use_query_cache" value="true" />

<property name="hibernate.cache.use_second_level_cache" value="true" />

<!-- Hibernate Transaction Properties -->

<!-- <property name="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" /> -->

<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />

<property name="hibernate.transaction.auto_close_session" value="false" />

<property name="hibernate.transaction.flush_before_completion" value="false" />

<property name="hibernate.current_session_context_class" value="org.hibernate.context.JTASessionContext" />

<!-- Hibernate Search -->

<!-- <entry key="hibernate.search.default.directory_provider" value="false" />

<entry key="hibernate.search.default.indexBase" value="C:/Temp/hibernate_test_indexes" />

<entry key="hibernate.search.default.batch.merge_factor" value="10" />

<entry key="hibernate.search.default.batch.max_buffered_docs" value="10" />

<entry key="hibernate.search.default.optimizer.operation_limit" value="500" />

<entry key="hibernate.search.default.optimizer.transaction_limit.max" value="100" /> -->

</properties>

</persistence-unit>

</persistence>

2. Next, the Spring applicationContext.xml. The LocalSessionFactoryBean will only be used by jBPM:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<beans xmlns="/schema/beans"

xmlns:aop="/schema/aop"

xmlns:context="/schema/context"

xmlns:jee="/schema/jee"

xmlns:tx="/schema/tx"

xmlns:xsi="/2001/XMLSchema-instance"

xmlns:ehcache="/schema/ehcache"

xsi:schemaLocation="/schema/aop /schema/aop/spring-aop-3.0.xsd

/schema/beans /schema/beans/spring-beans-3.0.xsd

/schema/context /schema/context/spring-context-3.0.xsd

/schema/jee /schema/jee/spring-jee-3.0.xsd

/schema/tx /schema/tx/spring-tx-3.0.xsd

/schema/ehcache /schema/cache/springmodules-ehcache.xsd">

<!--

Activates a load-time weaver for the context. Any bean within the context that

implements LoadTimeWeaverAware (such as LocalContainerEntityManagerFactoryBean)

will receive a reference to the auto-detected load-time weaver.

-->

<context:load-time-weaver aspectj-weaving="on" />

<!-- Use this to specify exactly which load-time weaver should be used, but

it should get auto-detected. -->

<!-- <context:load-time-weaver aspectj-weaving="on" weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver" /> -->

<!--

This will automatically locate any and all property files you have

within your classpath, provided they fall under the META-INF/spring

directory. The located property files are parsed and their values can

then be used within application context files in the form of

${propertyKey}.

-->

<context:property-placeholder location="classpath*:META-INF/*.properties" />

<!--

Turn on AspectJ @Configurable support. As a result, any time you

instantiate an object, Spring will attempt to perform dependency

injection on that object. This occurs for instantiation via the "new"

keyword, as well as via reflection. This is possible because AspectJ

is used to "weave" Roo-based applications at compile time. In effect

this feature allows dependency injection of any object at all in your

system, which is a very useful feature (without @Configurable you'd

only be able to dependency inject objects acquired from Spring or

subsequently presented to a specific Spring dependency injection

method). Roo applications use this useful feature in a number of

areas, such as @PersistenceContext injection into entities.

-->

<context:spring-configured />

<!--

This declaration will cause Spring to locate every @Component,

@Repository and @Service in your application. In practical terms this

allows you to write a POJO and then simply annotate the new POJO as an

@Service and Spring will automatically detect, instantiate and

dependency inject your service at startup time. Importantly, you can

then also have your new service injected into any other class that

requires it simply by declaring a field for your service inside the

relying class and Spring will inject it.

Furthermore, this turns on @Autowired, @PostConstruct etc support. These

annotations allow you to use common Spring and Java Enterprise Edition

annotations in your classes without needing to do any special configuration.

The most commonly used annotation is @Autowired, which instructs Spring to

dependency inject an object into your class.

-->

<context:component-scan base-package="com.so" />

<!-- enables interpretation of the @Required annotation to ensure that dependency injection actually occures -->

<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>

<!-- enables interpretation of the @PersistenceUnit/@PersistenceContext annotations providing convenient

access to EntityManagerFactory/EntityManager -->

<!-- <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/> -->

<!--

Activates various annotations to be detected in bean classes: Spring's

@Required and @Autowired, as well as JSR 250's @PostConstruct,

@PreDestroy and @Resource (if available) and JPA's @PersistenceContext

and @PersistenceUnit (if available).

-->

<context:annotation-config transaction-manager="transactionManager" />

<!--

Instruct Spring to perform declarative transaction management

automatically on annotated classes.

-->

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager" />

<!--

Instruct Spring to retrieve and apply @AspectJ aspects which are defined

as beans in this context (such as the CallMonitoringAspect below).

-->

<aop:aspectj-autoproxy proxy-target-class="true" />

<!--

Post-processor to perform exception translation on @Repository classes (from native

exceptions such as JPA PersistenceExceptions to Spring's DataAccessException hierarchy).

-->

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

<!-- ========================================================================= -->

<!-- Entity Manager -->

<!-- ========================================================================= -->

<!-- Container managed data source. -->

<jee:jndi-lookup id="dataSource" jndi-name="java:/SquareOneDataSource"/>

<!--

Spring will inject this container managed persistence

unit anywhere you use @PersistenceContext.

-->

<jee:jndi-lookup id="entityManagerFactory" jndi-name="java:/SquareOnePersistenceUnitFactory" />

<!-- JTA transaction manager to be used by everyone! -->

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">

<property name="transactionManagerName" value="java:/TransactionManager" />

<property name="userTransactionName" value="UserTransaction" />

</bean>

<!--

The JNDI Hibernate session factory will not work for jBPM 4.3 as jBPM is expecting

a Spring LocalSessionFactoryBean. So we specify our mappings here. This will only

be used by jBPM. Spring will still inject the container managed persistence unit

anywhere you use @PersistenceContext.

-->

<!-- <jee:jndi-lookup id="sessionFactory" jndi-name="java:/SquareOneHibernateSessionFactory" /> -->

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<!-- <property name="configLocation" value="classpath:/jbpm/jbpm.hibernate.cfg.xml" /> -->

<property name="dataSource" ref="dataSource" />

<property name="mappingResources">

<list>

<value>jbpm.repository.hbm.xml</value>

<value>jbpm.execution.hbm.xml</value>

<value>jbpm.history.hbm.xml</value>

<value>jbpm.task.hbm.xml</value>

<value>jbpm.identity.hbm.xml</value>

</list>

</property>

<!--

Hibernate properties needed to configure the session factory to use JTA. This

will ensure that jBPM can participate in the application's JTA transactions.

-->

<property name="hibernateProperties">

<props>

<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>

<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>

<prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>

<prop key="hibernate.connection.datasource">java:/SquareOneDataSource</prop>

<prop key="jta.UserTransaction">UserTransaction</prop>

<prop key="hibernate.hbm2ddl.auto">update</prop>

</props>

</property>

</bean>

<!-- jBPM beans. -->

<bean id="springHelper" class="org.jbpm.pvm.internal.processengine.SpringHelper" />

<bean id="processEngine" factory-bean="springHelper" factory-method="createProcessEngine" />

</beans>

3. The jbpm.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>

<jbpm-configuration>

<import resource="jbpm.default.cfg.xml" />

<import resource="jbpm.tx.spring.cfg.xml" />

<import resource="jbpm.jpdl.cfg.xml" />

<import resource="jbpm.bpmn.cfg.xml" />

<import resource="jbpm.identity.cfg.xml" />

<import resource="jbpm.businesscalendar.cfg.xml" />

<import resource="jbpm.console.cfg.xml" />

<!-- Commented out for dev environment only. -->

<import resource="jbpm.jobexecutor.cfg.xml" />

<!--

This is not needed.

<process-engine-context>

<string name="spring.cfg" value="applicationContext.xml" />

</process-engine-context>

-->

</jbpm-configuration>

Comments (16)

Mar 04,

Captain Caveman liked this post.

Mar 04,

Twitter said...

Could you please share this sample code with us

Mar 05,

Captain Caveman said...

I'm sorry, what code are you referring to? This post is about how to configure jBPM 4.3 with Spring and a container managed persistence unit. Following the configuration above, you should be able to accomplish this.

Apr 13,

Marcel said...

I see you're using <context:component-scan /> in your configuration. How do you get that to work in jboss? We were not able to get it working due to the VFS.

Apr 13,

Captain Caveman said...

Sorry Marcel, I'm not sure what problems you are having getting it to work. What version of jboss? It works for me on 5.1, 6M1 and 6M2. I do remember an issue with Spring 2.5 and JBoss's classloader that was supposed to have been fixed in Spring 3. Could this be related? I'm using Spring 3.

Apr 14,

Marcel said...

You just answered the question. I guess for spring 3 it is not a problem. We were using spring 2.5.6.

Apr 14,

Marcel said...

When I run your configuration example against spring 2.5.6 with jbpm4.3, jbpm is still looking for the jbpm.hibernate.cfg.xml, eventhough it is configured in the application context in spring. Do we still need this file. Meaning we now have 3 places where we configure hibernate:

org.hibernate.HibernateException: jbpm.hibernate.cfg.xml not found

at org.hibernate.util.ConfigHelper.getResourceAsStream(ConfigHelper.java:170)

at org.hibernate.cfg.Configuration.getConfigurationInputStream(Configuration.java:1439)

at org.hibernate.cfg.Configuration.configure(Configuration.java:1461)

at org.jbpm.pvm.internal.wire.descriptor.HibernateConfigurationDescriptor$AddCfgResource.apply(HibernateConfigurationDescriptor.java:151)

at org.jbpm.pvm.internal.wire.descriptor.HibernateConfigurationDescriptor.apply(HibernateConfigurationDescriptor.java:90)

at org.jbpm.pvm.internal.wire.descriptor.HibernateConfigurationDescriptor.initialize(HibernateConfigurationDescriptor.java:76)

at org.jbpm.pvm.internal.wire.WireContext.performInitialization(WireContext.java:533)

Apr 14,

Marcel said...

Sorry, I seem to have following in my jbpm.cfg.xml:

<import />

Of course this should be removed, then it works

Apr 14,

Marcel said...

Sorry, removed by blog:

<import>

Apr 14,

Marcel said...

RRRRR, again removed....

import resource="jbpm.tx.spring.cfg.xml"

Apr 14,

Marcel said...

This is not going very well, it should be:

import resource="jbpm.tx.hibernate.cfg.xml"

Apr 14,

Captain Caveman said...

I'm glad to hear you got it working Marcel.

Jun 22,

Cyril said...

Hello, I would like to know whether you are able to call Spring beans directly from your process using a JUEL value, as in :

<java>

expr="#{serviceRequest}" method="sendRequestForProduction"

continue="async" g="442,84,136,52"

var="previousActionResult">

<arg><object /></arg>

<transition />

</java>

jBPM recognizes "serviceRequest" s a Spring bean name, as long as I work with local transactions.

But when I try to use JTA, then jBPM is no longer able to parse "#{serviceRequest}" as a Spring bean. I get the error :

-06-22 17:09:44,531 ERROR [org.jbpm.pvm.internal.cmd.ExecuteJobCmd] (pool-9-thread-1) exception while executing 'ExecuteActivityMessage[140003]'

org.jbpm.api.JbpmException: script evaluation error: javax.el.PropertyNotFoundException: Cannot find property serviceRequest

at org.jbpm.pvm.internal.script.ScriptManager.evaluate(ScriptManager.java:130)

at org.jbpm.pvm.internal.script.ScriptManager.evaluate(ScriptManager.java:118)

at org.jbpm.pvm.internal.script.ScriptManager.evaluateExpression(ScriptManager.java:90)

at org.jbpm.pvm.internal.wire.descriptor.ObjectDescriptor.construct(ObjectDescriptor.java:180)

at org.jbpm.pvm.internal.wire.WireContext.construct(WireContext.java:469)

...

I tried to inject JTA by two different methods :

1. injected jtaTransactionManager (provided by JBoss) into my LocalSessionFactoryBean :

<bean>

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<property>

value="classpath:jbpm.hibernate.cfg.xml" />

<property />

<property>

ref="jtaTransactionManagerJBPM"/>

</bean>

<jee:jndi-lookup />

2. tried a config closer to yours (especially the LocalSessionFactoryBean.

Both attempts produced the same result : everything works, except "serviceRequest" bean is no longer recognized by jBPM.

Other nodes (not injected that way) work properly, JTA transactions do what they are supposed to do, etc.

Thank you if you can help!

Jun 22,

Cyril said...

Oops, XML came out a bit messed up. Hope the problem remains understandable.

Jan 22,

Michael said...

Hi, I want to integarte jbpm3 with jpa, spring and jboss - do you have any example with this maybe?

Feb 16,

Andrew Swan said...

Thanks, this was useful for learning about the JBoss JPA config options.

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。