cancel
Showing results for 
Search instead for 
Did you mean: 

Spring JpaTransactionManager not saving Activiti entities to DB

neville_sequeir
Confirmed Champ
Confirmed Champ
Nothing about Activiti is being saved to database. Application entities ARE being saved to database.  Below, in order are, the spring file, persitence.xml file and the test case.

Sprint file:

   <context:annotation-config/>
   <aop:aspectj-autoproxy proxy-target-class="true" expose-proxy="true"/>
   <tx:annotation-driven transaction-manager="transactionManager"/>

   
   <bean id="ActivitiTrialDataSource" class="org.apache.commons.dbcp.BasicDataSource" >
      <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver" />
      <property name="url" value="jdbc:jtds:sqlserver://localhost:1433/ActivitiTrial" />
      <property name="username" value="ActivitiTrial" />
      <property name="password" value="ActivitiTrial" />
      <property name="defaultAutoCommit" value="false" />
      <property name="initialSize" value="5" />
   </bean>


   <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="dataSource" ref="ActivitiTrialDataSource" />
       <property name="persistenceUnitName" value="ActivitiTrial"/>
   </bean>

   <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
       <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>



   <!– Activiti –>
   <bean id="activitiDataSource" class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
      <property name="targetDataSource" ref="ActivitiTrialDataSource" />
   </bean>
   
   <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
      <property name="databaseType" value="mssql" />
       <property name="dataSource" ref="activitiDataSource" />
      <property name="transactionsExternallyManaged" value="true" />
       <property name="transactionManager" ref="transactionManager" />
       <property name="databaseSchemaUpdate" value="false" />
      <property name="history" value="audit" />
       <property name="jobExecutorActivate" value="false" />
   </bean>
 
     <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
      <property name="processEngineConfiguration" ref="processEngineConfiguration" />
   </bean>

   <bean id="activitiRepositoryService" factory-bean="processEngine" factory-method="getRepositoryService" />
   <bean id="activitiRuntimeService" factory-bean="processEngine" factory-method="getRuntimeService" />
   <bean id="activitiTaskService" factory-bean="processEngine" factory-method="getTaskService" />
   <bean id="activitiHistoryService" factory-bean="processEngine" factory-method="getHistoryService" />
   <bean id="activitiManagementService" factory-bean="processEngine" factory-method="getManagementService" />



Persistence.xml file:

<persistence-unit name="ActivitiTrial">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
       
        <properties>
            <property name="hibernate.archive.autodetection" value="hbm,class"/>
         <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/>
            <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
            <property name="hibernate.hbm2ddl.auto" value="none"/>
         <property name="hibernate.show_sql" value="false"/>
         <property name="hibernate.ejb.metamodel.generation" value="disabled"/>
        </properties>
</persistence-unit>



TestClass :

@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback=false)
@ContextConfiguration({"classpath:/springApplicationContext.xml"})
public class TrialTest {
   @Autowired
   RepositoryService activitiRepositoryService;

   @Autowired
   TaskService activitiTaskService;


   /**
    * Used for persistence of entities not related to Activiti process engine. i.e, application entities
    * Activiti process engine related persistence is as per a configuration bean named "processEngineConfiguration" found in the Activiti
         * configuration file activiti.cfg.xml.
    */
   @PersistenceContext(unitName="ActivitiTrial")
   EntityManager entityManager;

   
   @Autowired
   ProcessService<String> processServiceActiviti;

   
   @Test
   @Transactional
   public void trialTest() throws Exception {
      activitiRepositoryService.createDeployment().addClasspathResource("process-definitions/neville.bpmn20.xml").deploy();

      
      // 1. Do application work. VERIFIED - THIS ENTITY IS BEING SAVED TO DB.
      ApplicationEntity applicationEntity1 = new ApplicationEntity();
      applicationEntity1.name = "App entity 1";
      entityManager.persist(applicationEntity1);

      
      // 2. Do Actviti work. VERIFIED - None of the ACTIVITI objects are saved to the db.
      ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("aProcessWithOneTaskBetweenStartAndEnd");
      String processInstanceId = processInstance.getId();
      Task userTask = activitiTaskService.createTaskQuery().processInstanceId(processInstanceId).list().get(0);
                // VERIFIED that userTask is not null.

      
      // 1. Do some more application work. VERIFIED - THIS ENTITY IS BEING SAVED TO DB.
      ApplicationEntity applicationEntity2 = new ApplicationEntity();
      applicationEntity2.name = "App entity 2";
      entityManager.persist(applicationEntity2);
   }
}
15 REPLIES 15

neville_sequeir
Confirmed Champ
Confirmed Champ
Using SQL Server profiler, I see a separate database transaction being started for the database interaction caused by Activiti and further I see that separate transaction being rolled back instead of being committed. Other application db interaction is happening on another transaction and this particular transaction is being committed.

1. I thought, given my configurations, Activiti database interaction would happen on the same transaction as the rest of the application. I have gone through my configuration files and code numerous times and do not see anything wrong therein. Any ideas why a separate transaction is being started for the Activiti db interactions?
2. Of course the previous item is the critical question. However, it would also be interesting to know why is that separate transaction being rolled back?

trademak
Star Contributor
Star Contributor
Hi,

And what's the process definition you are executing?
In which tables are you looking for data in the Activiti schema?

Best regards,

neville_sequeir
Confirmed Champ
Confirmed Champ
Really appreciate the quick responses.
The process definition being executed is a simple three node process having just one User Task between a Start Node and an End Node.
The database tables I am looking for data in are ACT_RE_DEPLOYMENT, ACT_RU_TASK, ACT_HI_TASKINST and ACT_HI_PROCINST
All these tables, and all other Activiti tables, are empty.

Using Activiti version 5.13,  iBatis version 2.1.5.582,  Hibernate version 3.3.0.SP1,  Spring version 3.1.4.RELEASE

Below is the entire content from the process definition XML file:
<code>
<?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" xmlnsSmiley Surprisedmgdc="http://www.omg.org/spec/DD/20100524/DC" xmlnsSmiley Surprisedmgdi="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="neville" name="neville" isExecutable="true">
    <startEvent id="startevent1" name="Start"></startEvent>
    <endEvent id="endevent1" name="End"></endEvent>
    <userTask id="usertask1" name="User Task"></userTask>
    <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
    <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_neville">
    <bpmndi:BPMNPlane bpmnElement="neville" id="BPMNPlane_neville">
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="390.0" y="130.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="130.0" y="130.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="230.0" y="120.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="335.0" y="147.0"></omgdi:waypoint>
        <omgdi:waypoint x="390.0" y="147.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="165.0" y="147.0"></omgdi:waypoint>
        <omgdi:waypoint x="230.0" y="147.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>
</code>

neville_sequeir
Confirmed Champ
Confirmed Champ
Another piece of information that might help someone help me.
If I use  org.springframework.jdbc.datasource.DataSourceTransactionManager  instead of  org.springframework.orm.jpa.JpaTransactionManager  the problem is the reverse  - application entities are NOT saved to db but Activiti entities are.

Even in this scenario, I see separate transactions for Activiti db interaction and other application db interaction.

Has anyone had success in achieving integration of Activiti into an application that uses JPA(Hibernate) for all other persistence and managed to get all db interactions on the same transaction?

trademak
Star Contributor
Star Contributor
Don't see a possible error right now. Could you package this in a small project so that I could use it to do a similar test (with some minor environment changes)? You can attach it to this post as a txt file, or you could create a JIRA issue and attach the project there.

Best regards,

neville_sequeir
Confirmed Champ
Confirmed Champ
Hi Tijs,

Attaching zip file of the maven project - ActivitiTrial.zip
The process definition XML file is src\main\resources\process-definitions\neville.bpmn20.xml
To get application DB schema, use the schema.ddl file (in target\sql\hibernate3) generated by executing <code>mvn clean install -DskipTests</code>
This will create two tables named 'ApplicationEntity' and ID_GENERATOR_TABLE

To execute the test, run the test java class named TrialTest

Please let me know if you need any additional information.
Thanks in advance.

trademak
Star Contributor
Star Contributor
Hi Neville,

Thanks for posting the project, that makes testing this a lot easier.
After struggling a bit, the solution seems to be a Spring JPA configuration issue.
It's described here on StackOverflow:

http://stackoverflow.com/questions/6777419/how-to-configure-spring-to-make-jpa-hibernate-and-jdbc-jd...

So the following entity manager factory configuration is needed to get it working:

<blockcode>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="ActivitiTrialDataSource"/>
    <property name="persistenceUnitName" value="ActivitiTrial"/>
    <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
      </bean>
    </property>
  </bean>
</blockcode>

As you can see I used PostgreSQL to test it in my environment.
Hope this helps to get it working in your environment as well.

Best regards,

neville_sequeir
Confirmed Champ
Confirmed Champ
Hi Tijs,

I tired the changes you pointed out. Now Activiti data is being saved to the database.
However, even now, my application entity that is persisted to the database in code before doing Activiti work, is being committed to the database even before the code for Activiti related work is hit. Which implies that there are multiple transactions - which I confirmed by using SQL Server profiler.

For further verification I changed my test case to intentionally throw an unconditional exception right after entityManager.persist() is called on the first application entity before the activiti work is hit. And I see that that first application entity is committed to the database. So, there are definitely multiple transactions going on.

Any further ideas?

neville_sequeir
Confirmed Champ
Confirmed Champ
Also tried the following (as mentioned in the last comment at http://stackoverflow.com/questions/6777419/how-to-configure-spring-to-make-jpa-hibernate-and-jdbc-jd...) instead of the change you suggested. Still no luck.
<code>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
     <property name="entityManagerFactory" ref="entityManagerFactory"/>
  <property name="jpaDialect">
         <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        </property>
    </bean>
</code>