After spending whole days trying to make this work, I gave up, asking for help.
First of all: we're embedding jBPM in our application. Our application already uses a db connection with an ORM strategy on its own. We then have to make jBPM with Hibernate to work together with our code (although using its own database).
With Spring, we configured a JtaTransactionManager with JBoss Transactions implementation. The whole thing is up and almost working. The problem is that we can't inject a HibernateSessionFactory to jBPM in a consistent way. I mean, given the following configuration in Spring:
<bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="jbpmDataSource" /> </property> <property name="configLocation" value="classpath:sysconf/hibernate.cfg.xml" /> <property name="hibernateProperties" ref="hibernateConfigurationProperties" /> <property name="jtaTransactionManager" ref="jbossTransactionManager" /> </bean>
where hibernateProperties is defined as follows:
<bean id="hibernateConfigurationProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="properties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.HSQLDialect </prop> <prop key="hibernate.cache.provider_class"> org.hibernate.cache.HashtableCacheProvider </prop> <prop key="hibernate.transaction.factory_class"> org.hibernate.transaction.JTATransactionFactory </prop> <prop key="hibernate.current_session_context_class">jta</prop> <prop key="hibernate.connection.provider_class"> org.springframework.orm.hibernate3.TransactionAwareDataSourceConnectionProvider </prop> </props> </property> </bean>
(please note that we don't want to set these properties in hibernate.cfg.xml, because we want our configuration to be managed by Spring as a whole)
Then, if we use something like this:
JbpmConfiguration jbpmConfiguration = JbpmConfiguration.parseInputStream(getClass().getResourceAsStream( "/sysconf/jbpm.cfg.xml")); JbpmContext ctx = jbpmConfiguration.createJbpmContext(); ctx.setSessionFactory(mySessionFactory);
(where "mySessionFactory" is retrieved from Spring)
all seems to go ok. The problem is when we try to use the create and drop schema facilities of JbpmConfiguration (org.jbpm.JbpmConfiguration.createSchema() and org.jbpm.JbpmConfiguration.dropSchema()): those methods create a new JbpmContext by their own and we can't set the session factory into it.
We tried to make an extension of DbPersistenceServiceFactory that, upon construction, retrieves BOTH the SessionFactory AND the hibernateConfigurationProperties from Spring (otherwise the properties are not taken from the SessionFactory, but parsed again from the configuration file... !!!) and set it on itself, so that the new DbPersistenceService created should be automatically correctly configured; then, in jbpm.cfg.xml we set:
<jbpm-context> <service name="persistence"> <factory> <bean class="our_own_DbPersistenceServiceFactory_ extension_class_name"> <field name="isTransactionEnabled"> <false /> </field> </bean> </factory> </service> <!-- ... --> </jbpm-context>
(note: we set isTransactionEnabled to false because we don't want jBPM to control the transaction, it has to be controlled from the outside, through the global Spring transaction manager)
But in this way, we still have a problem: the TransactionAwareDataSourceConnectionProvider is not able to retrieve the dataSource when it is asked for a connection (it asks the thread local static variable org.springframework.orm.hibernate3.LocalSessionFactoryBean.configTimeDataSourceHolder for the datasource, but null is returned).
We debugged for hours trying to understand what the cleaner point in which inject our code would be, so that ALL the JbpmContext are created using the SessionFactory and the configuration properties we set up in Spring, but we couldn't success.
Please note that we don't want to use jBPM Spring module.
Thanks in advance to anyone who could help us to find the right approach.