cancel
Showing results for 
Search instead for 
Did you mean: 

Activiti Explorer + Spring + JPA

fergomez
Champ in-the-making
Champ in-the-making
Hello,

I'm a new user of Activiti and I've been trying to use my Activiti application that uses JPA in the Activiti Explorer.

I've tried a lot of different configurations and I don't manage to make it work in the Explorer, but it works perfectly fine if I run a regular unit-test. My guess is that I'm not able to configure the activity context file properly, but I don't know why. I searched the whole Internet and checked all the related threads on these forums with no success. Here you have my examples:

* Process:
(/src/main/resources/diagrams/InventoryCreation.bpmn20.xml)
<?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="inventoryCreation" name="Inventory Creation" isExecutable="true">
    <startEvent id="theStart" name="Start" activiti:initiator="${initiator}"></startEvent>
    <userTask id="setManagement" name="Set management" activiti:candidateGroups="management">
      <documentation>Choose a management group to administer the inventory.</documentation>
      <extensionElements>
        <activiti:formProperty id="managerGroup" name="Manager Group" type="string" variable="managerGroup" required="true"></activiti:formProperty>
      </extensionElements>
    </userTask>
    <serviceTask id="createInventory" name="Create Inventory" activiti:expression="${inventoryService.createInventory(managerGroup)}" activiti:resultVariableName="inventory"></serviceTask>
    <endEvent id="theEnd" name="End"></endEvent>
    <sequenceFlow id="flow1" sourceRef="theStart" targetRef="setManagement"></sequenceFlow>
    <sequenceFlow id="flow2" sourceRef="setManagement" targetRef="createInventory"></sequenceFlow>
    <sequenceFlow id="flow3" sourceRef="createInventory" targetRef="theEnd"></sequenceFlow>
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_inventoryCreation">
    <bpmndi:BPMNPlane bpmnElement="inventoryCreation" id="BPMNPlane_inventoryCreation">
      <bpmndi:BPMNShape bpmnElement="theStart" id="BPMNShape_theStart">
        <omgdc:Bounds height="35.0" width="35.0" x="250.0" y="255.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
        <omgdc:Bounds height="55.0" width="105.0" x="450.0" y="245.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="servicetask1" id="BPMNShape_servicetask1">
        <omgdc:Bounds height="55.0" width="105.0" x="740.0" y="245.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
        <omgdc:Bounds height="35.0" width="35.0" x="980.0" y="255.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="setManagement" id="BPMNShape_setManagement">
        <omgdc:Bounds height="55.0" width="105.0" x="450.0" y="245.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="createInventory" id="BPMNShape_createInventory">
        <omgdc:Bounds height="55.0" width="105.0" x="740.0" y="245.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="theEnd" id="BPMNShape_theEnd">
        <omgdc:Bounds height="35.0" width="35.0" x="980.0" y="255.0"></omgdc:Bounds>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
        <omgdi:waypoint x="285.0" y="272.0"></omgdi:waypoint>
        <omgdi:waypoint x="450.0" y="272.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
        <omgdi:waypoint x="555.0" y="272.0"></omgdi:waypoint>
        <omgdi:waypoint x="740.0" y="272.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
        <omgdi:waypoint x="845.0" y="272.0"></omgdi:waypoint>
        <omgdi:waypoint x="980.0" y="272.0"></omgdi:waypoint>
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

* Deployment
- Inventory.java
- InventoryService.java
- InventoryCreation.bpmn20.xml

.bar
file with these three files deployed via Explorer, with no problem
.jar
file added to
/var/lib/tomcat7/webapps/activiti-explorer/WEB-INF/lib

Both built with an ant file (I can post it if necessary, but since the process works, I guess it's not needed)

* Inventory.java (Entity file)
package org.inventory;

import java.util.List;
import java.util.ArrayList;

import org.inventory.Asset;

import javax.persistence.Entity;
import javax.persistence.ElementCollection;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Inventory {

   @Id
   @GeneratedValue
   private int id;

   private String managerGroup;

   @ElementCollection(fetch=FetchType.EAGER)
   private List<Asset> assets;

   public int getId() {
      return id;
   }

   public void setId(int id) {
      this.id = id;
   }

   /**
    * @return the managerGroup
    */
   public String getManagerGroup() {
      return managerGroup;
   }

   /**
    * @param managerGroup the managerGroup to set
    */
   public void setManagerGroup(String managerGroup) {
      this.managerGroup = managerGroup;
   }

   /**
    * @return the assets
    */
   public List<Asset> getAssets() {
      if (assets == null)
      {
         this.assets = new ArrayList<Asset>();
      }
      return assets;
   }

   /**
    * @param assets the assets to set
    */
   public void setAssets(List<Asset> assets) {
      this.assets = assets;
   }
   
   

}


* InventoryService.java (Entity Service)
package org.inventory;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

public class InventoryService {

   @PersistenceContext
   private EntityManager entityManager;

   public Inventory createInventory(String managerGroup) {
      Inventory inventory = new Inventory();
      inventory.setManagerGroup(managerGroup);
      
      entityManager.persist(inventory);
      return inventory;
   }
   
}
This test works perfectly fine:
* InventoryTest.java (extends
AbstractTest
from the typical examples)
package org.inventory;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.activiti.engine.FormService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.task.Task;
import org.inventory.Inventory;
import org.myutils.RandomUtils;

import org.common.AbstractTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:inventory/jpa-application-context.xml")
public class InventoryTest extends AbstractTest {
   
   @PersistenceContext
   private EntityManager entityManager;
   
   @Autowired
   private RuntimeService runtimeService;

   @Autowired
   private TaskService taskService;
   
   @Autowired
   private FormService formService;
   
   @Autowired
   private RepositoryService repositoryService;
      
   @Test
   public void createInventory() throws Exception {
            
      runtimeService.startProcessInstanceByKey("inventoryCreation");
      
      Task task = taskService.createTaskQuery().singleResult();
      assertNotNull(task);
      assertNull(task.getAssignee());
      
      taskService.claim(task.getId(), "kermit");   
      
      task = taskService.createTaskQuery().singleResult();
      assertNotNull(task.getAssignee());
      assertEquals("kermit", task.getAssignee());      
      
      task = taskService.createTaskQuery().taskAssignee("kermit").singleResult();
      assertEquals("kermit", task.getAssignee());
      
      Map<String, String> formProperties = new HashMap<String, String>();
      formProperties.put("managerGroup", "management");
      formService.submitTaskFormData(task.getId(), formProperties);
    
      Inventory inventory = (Inventory) entityManager.createQuery("from Inventory i").getSingleResult();
      assertNotNull(inventory);
      assertEquals("management", inventory.getManagerGroup());
      
      task = taskService.createTaskQuery().taskAssignee("kermit").singleResult();
      assertNull(task);
   }

}

I share a persistent local database for all the applications. This is the JPA configuration that makes it work on tests.

* JPA-Application-Context.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
   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
                           http://www.springframework.org/schema/context 
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd
                           http://www.springframework.org/schema/tx      
                           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

   <context:component-scan base-package="org.inventory" />

   <bean id="activitiDataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
      <property name="driverClass" value="org.h2.Driver" />
      <property name="url" value="jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000" />
      <property name="username" value="sa" />
      <property name="password" value="" />
   </bean>

   <bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
      <property name="persistenceXmlLocation">
         <value>classpath:inventory/jpa-persistence.xml</value>
      </property>
   </bean>

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

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

   <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
      <property name="databaseType" value="h2" />
      <property name="dataSource" ref="activitiDataSource" />
      <property name="transactionManager" ref="transactionManager" />
      <property name="databaseSchemaUpdate" value="true" />
      <property name="jpaEntityManagerFactory" ref="entityManagerFactory" />
      <property name="jpaHandleTransaction" value="true" />
      <property name="jpaCloseEntityManager" value="true" />
      <property name="deploymentResources">
         <list>
            <value>classpath*:diagrams/InventoryCreation.bpmn20.xml</value>
         </list>
      </property>
      <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" />
   <bean id="formService" factory-bean="processEngine" factory-method="getFormService" />

   <bean id="assetService" class="org.inventory.AssetService" />
   <bean id="inventoryService" class="org.inventory.InventoryService" />

</beans>


* jpa-persistence.xml (Persistence config)
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
   <persistence-unit name="inventoryPersistence" transaction-type="RESOURCE_LOCAL">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <class>org.inventory.Inventory</class>
      <class>org.inventory.Asset</class>
      <exclude-unlisted-classes>true</exclude-unlisted-classes>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
         <property name="hibernate.hbm2ddl.auto" value="create-drop" />
         <property name="hibernate.connection.driver_class" value="org.h2.Driver" />
         <property name="hibernate.connection.url" value="jdbc:h2:tcp://localhost/~/test2;DB_CLOSE_ON_EXIT=FALSE" />
         <property name="hibernate.connection.username" value="sa" />
         <property name="hibernate.connection.password" value="" />
      </properties>
   </persistence-unit>
</persistence>


This is the default configuration of explorer (
/WEB-INF/activiti-standalone-context.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" xmlns:context="http://www.springframework.org/schema/context"
   xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">
      
  <!– This Spring config file is NOT used in Alfresco, as the Activiti engine is wired in a different way there –>
      
  <!–<bean id="demoDataGenerator" class="org.activiti.explorer.demo.DemoDataGenerator" init-method="init">
    <property name="processEngine" ref="processEngine" />
    –> 
    <!– Set following properties to false if certain demo data is not wanted –>
    <!–<property name="createDemoUsersAndGroups" value="true" />
    <property name="createDemoProcessDefinitions" value="true" />
    <property name="createDemoModels" value="true" />
    <property name="generateReportData" value="true" />
  </bean>
  –>
  <bean id="dbProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:db.properties" />
    <!– Allow other PropertyPlaceholderConfigurer to run as well –>
    <property name="ignoreUnresolvablePlaceholders" value="true" />
  </bean>
   
  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="defaultAutoCommit" value="false" />
  </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="true" />
    <property name="customFormTypes">
      <list>
        <bean class="org.activiti.explorer.form.UserFormType"/>
        <bean class="org.activiti.explorer.form.ProcessDefinitionFormType"/>
        <bean class="org.activiti.explorer.form.MonthFormType"/>  
      </list>
    </property>
  </bean>
 
  <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean" destroy-method="destroy">
     <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" />
  <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />
 
  <bean id="activitiLoginHandler" class="org.activiti.explorer.ui.login.DefaultLoginHandler">
    <property name="identityService" ref="identityService" />
  </bean>
 
</beans>

And this is the code that doesn't make explorer break, trying to merge the default info with my tests' info.


<?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:context="http://www.springframework.org/schema/context"
   xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">

  <!–<context:component-scan base-package="org.inventory" />       –>
  <!– This Spring config file is NOT used in Alfresco, as the Activiti engine is wired in a different way there –>
      
  <!–<bean id="demoDataGenerator" class="org.activiti.explorer.demo.DemoDataGenerator" init-method="init">
    <property name="processEngine" ref="processEngine" />
    –>
    <!– Set following properties to false if certain demo data is not wanted –>
    <!–<property name="createDemoUsersAndGroups" value="true" />
    <property name="createDemoProcessDefinitions" value="true" />
    <property name="createDemoModels" value="true" />
    <property name="generateReportData" value="true" />
    </bean>–>
 
  <bean id="dbProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:db.properties" />
    <!– Allow other PropertyPlaceholderConfigurer to run as well –>
    <property name="ignoreUnresolvablePlaceholders" value="true" />
  </bean>
   
  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <!–<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">–>
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="defaultAutoCommit" value="false" />
  </bean>

  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSource" />
  </bean>

  <!–<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
     <property name="persistenceXmlLocation">
        <value>classpath:jpa-persistence.xml</value>
     </property>
  </bean>

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

  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
       <property name="entityManagerFactory" ref="entityManagerFactory" />
  </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="true" />
<!–   <property name="jpaEntityManagerFactory" ref="entityManagerFactory" />
   <property name="jpaHandleTransaction" value="true" />
   <property name="jpaCloseEntityManager" value="true" />
–>
     <property name="customFormTypes">
        <list>
           <bean class="org.activiti.explorer.form.UserFormType"/>
           <bean class="org.activiti.explorer.form.ProcessDefinitionFormType"/>
           <bean class="org.activiti.explorer.form.MonthFormType"/>  
        </list>
     </property>
  </bean>
 
  <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean" destroy-method="destroy">
     <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" />
  <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />
  <bean id="formService" factory-bean="processEngine" factory-method="getFormService" />

 
  <bean id="activitiLoginHandler" class="org.activiti.explorer.ui.login.DefaultLoginHandler">
    <property name="identityService" ref="identityService" />
  </bean>
 
  <bean id="assetService" class="org.inventory.AssetService" />
  <bean id="inventoryService" class="org.inventory.InventoryService" />


</beans>

But with that configuration, once I run a process it breaks when I submit the user task saying "WARNING! Error while evaluating expression: ${inventoryService.createInventory(managerGroup)}". Since there's no way to persist the new classes (no JPA integration), it makes sense that it doesn't work.

On the other hand, this is the code I'm trying to set in order to work:

<?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:context="http://www.springframework.org/schema/context"
   xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">

  <!–<context:component-scan base-package="org.inventory" />       –>
  <!– This Spring config file is NOT used in Alfresco, as the Activiti engine is wired in a different way there –>
      
  <!–<bean id="demoDataGenerator" class="org.activiti.explorer.demo.DemoDataGenerator" init-method="init">
    <property name="processEngine" ref="processEngine" />
    –>
    <!– Set following properties to false if certain demo data is not wanted –>
    <!–<property name="createDemoUsersAndGroups" value="true" />
    <property name="createDemoProcessDefinitions" value="true" />
    <property name="createDemoModels" value="true" />
    <property name="generateReportData" value="true" />
    </bean>–>
 
  <bean id="dbProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:db.properties" />
    <!– Allow other PropertyPlaceholderConfigurer to run as well –>
    <property name="ignoreUnresolvablePlaceholders" value="true" />
  </bean>
   
  <!–<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">–>
  <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="defaultAutoCommit" value="false" />
  </bean>

<!–  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
     <property name="dataSource" ref="dataSource" />
  </bean>–>

<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
     <property name="persistenceXmlLocation">
        <value>classpath:jpa-persistence.xml</value>
     </property>
  </bean>

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

  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
       <property name="entityManagerFactory" ref="entityManagerFactory" />
  </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="true" />
   <property name="jpaEntityManagerFactory" ref="entityManagerFactory" />
   <property name="jpaHandleTransaction" value="true" />
   <property name="jpaCloseEntityManager" value="true" />

     <property name="customFormTypes">
        <list>
           <bean class="org.activiti.explorer.form.UserFormType"/>
           <bean class="org.activiti.explorer.form.ProcessDefinitionFormType"/>
           <bean class="org.activiti.explorer.form.MonthFormType"/>  
        </list>
     </property>
  </bean>
 
  <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean" destroy-method="destroy">
     <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" />
  <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService" />
  <bean id="formService" factory-bean="processEngine" factory-method="getFormService" />

 
  <bean id="activitiLoginHandler" class="org.activiti.explorer.ui.login.DefaultLoginHandler">
    <property name="identityService" ref="identityService" />
  </bean>
 
  <bean id="assetService" class="org.inventory.AssetService" />
  <bean id="inventoryService" class="org.inventory.InventoryService" />


</beans>

This way what I get once I restart tomcat is a completely blank page (no source code) that disappears once I revert the changes, restart the server again and refresh the webpage. Everytime I try a different configuration I get that blank page on the login screen, so I'm very lost and I don't know what to do, where to check for a solution or how to continue with this.

Furthermore, I wrote
classpath:jpa-persistence.xml
in the
activity-standalone-context.xml
and I don't know exactly if I copied the file in the correct path. Right now the xml is in
/WEB-INF/classes/
and I think it's the right path, but I'm not sure. I also can also attach the
Asset.java
file for solving this problem, but I think that's not part of the problem.

Any help will be very welcome. I hope all this information is enough for you. Thanks for your awesome work here in these forums (I've actually learned a lot) and for your time reading this. Best regards.
9 REPLIES 9

fergomez
Champ in-the-making
Champ in-the-making
One fix to my previous post. When I write:
<property name="hibernate.connection.url" value="jdbc:h2:tcp://localhost/~/test2;DB_CLOSE_ON_EXIT=FALSE" />
On jpa-persistence.xml it actually is "test", not "test2". It's the same configuration than the db.properties of the explorer.

frederikherema1
Star Contributor
Star Contributor
Do you see any stacktraces in the tomcat-console/logs? You get a blank page (not a 500 or 404 response)?

Hello, Frederik,

What I get is a 404 response:

127.0.0.1 - - [06/Dec/2013:14:36:36 +0100] "GET /activiti-explorer/ HTTP/1.1" 404 -

fergomez
Champ in-the-making
Champ in-the-making
I was just guessing… Do I need to change something in the activiti-rest application?

Has anyone tried to recreate this example?


Thanks again.

EDIT: Obviously, I already had my DB configuration changed to the same one working with the explorer.

frederikherema1
Star Contributor
Star Contributor
If you get a 404 on the /activiti-explorer/, this means that the web app wasn't deployed correctly. Can you check the server logs (in case of tomcat, catalona.out and localhost.log) to see if an exception was thrown during deployment of the WAR on server-boot?

Thanks! I'm new with tomcat too so I didn't know about the existence of these useful logs. At least, that's a progress and I can work on it. I already see on catalina.out that there's something wrong, so I'll update this later in case I found the solution (for anyone else wondering) or in case I get another problem.


Kind regards.

mgiebler
Champ in-the-making
Champ in-the-making
There really needs to be a working example of how to integrate Activiti Explorer with JPA using Spring.  Being able to integrate JPA with Activiti in a unit test is great and one of the reasons I’m looking at Activiti as our BPM solution, but the real world use of this will be a centralized location for all workflows in Activiti Explorer as our end users are not going to be executing unit tests to run their workflow process. I’ve been looking for several weeks for a good working example and this post is the closest I could find, but it still looks like it is not complete and not working.  If someone could complete this example – complete with configuration file to integrate both JPA into Activiti Explorer that would be very much appreciated. 
Here is what I have tried so far along with notes of the results.  Hopefully one of these attempts are close and someone can point me in the right direction in getting it right.

First Attempt.
I used the code from fergomez on this post with this modification – I want to get this workflow to run in a more real world environment, that is with other workflows that are running, so I un-commented the demoDataGenerator been so that demo data will be generated. This first attempt was on an empty database on MySQL.  (only thing run on mysql was ‘CREATE SCHEMA `activiti` ;’)  After starting up the server, I got key violation errors.  The pertinent part of the stack trace is here.  I have a copy of the full stack trace if needed.

Caused by: com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`activiti`.`act_id_membership`, CONSTRAINT `ACT_FK_MEMB_USER` FOREIGN KEY (`USER_ID_`) REFERENCES `act_id_user` (`ID_`))
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:931)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2985)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3256)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1313)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:874)
at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)
at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)
at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:41)
at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:66)
at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:45)
at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:100)
at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:75)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:148)
… 49 more
Jan 10, 2014 8:42:40 PM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext


Attempt number 2
Before running my second attempt, I started the server using the original configuration files in order to get the demo database generated.  Once that was in place I re-tried with everything set up as in my first attempt.  Basically using fergomez’s configuration.

After startup, things initially looked promising because I saw the tables for this process (Inventory and Asset) get generated in the database.  I was able to login as Kermit.  I tried one of the demo processes (vacation request) and it appeared to start correctly but it didn’t seem to persist into the database.  There are no errors in the stack trace.  Next I tried to deploy the process definition.  The deployment did not persist into the database and I was not able to start the process as it was not available to me in Activiti Explorer.  There are no errors in the stack trace. 


Attempt 3
Doing some more research, I found the following post:
http://forums.activiti.org/content/spring-transaction-support
This post suggests using the TransactionAwareDataSourceProxy.  It also suggests that if you are going to use this, you will also need to continue to use the DataSourceTransactionManager for the transactionManager bean to work with the underlying Datasource.

To try and make this work, I added the following bean:

<blockcode>
<bean id="activitiDataSource"
class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<property name="targetDataSource" ref="dataSource">
</bean>
</blockcode>

Then in the processEngineConfiguration I used activitiDataSource for the dataSource property:

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

I also changed the transactionManagerBean back to org.springframework.jdbc.datasource.DataSourceTransactionManager.

I’m now able to start a process and it will persist into the database. I can also successfully deploy the InventoryCreation process.
Starting an InventoryCreation process resulted in a nullPointerException when trying to access the entityManager in InventoryService.  Here is the important part of the error:

Caused by: java.lang.NullPointerException
at org.inventory.InventoryService.createInventory(InventoryService.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.activiti.engine.impl.javax.el.BeanELResolver.invoke(BeanELResolver.java:479)

Attempt 4
This time I tried to inject an entityManager into the inventoryService bean.  To do this, I first added setter and getter methods to InventoryService

<blockcode>
public void setEntityManager(EntityManager entityManager) {
   this.entityManager = entityManager;
  }
</blockcode>

I then created a sharedEntityManagerBean.
<blockcode>
<bean id="fssSharedEntityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
  <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
</blockcode>
And finally injected into the inventoryService bean:
<blockcode>
<bean id="inventoryService" class="org.inventory.InventoryService" >
<property  name="entityManager" ref="fssSharedEntityManager" />
  </bean>
</blockcode>


Here are the important parts to the error I get when calling entityManger.persist in the InventoryService:
Caused by: org.activiti.engine.ActivitiException: Cannot flush EntityManager, an active transaction is required
at org.activiti.engine.impl.variable.EntityManagerSessionImpl.flush(EntityManagerSessionImpl.java:58)
at org.activiti.engine.impl.variable.JPAEntityVariableType.setValue(JPAEntityVariableType.java:63)
at org.activiti.engine.impl.persistence.entity.VariableInstanceEntity.setValue(VariableInstanceEntity.java:176)

.
.
.

Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:793)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
at $Proxy410.flush(Unknown Source)
at org.activiti.engine.impl.variable.EntityManagerSessionImpl.flush(EntityManagerSessionImpl.java:54)

Don't know what else to try.

mgiebler
Champ in-the-making
Champ in-the-making
OK, I got this to work in Activiti-explorer thanks to this posting http://forums.activiti.org/content/spring-jpatransactionmanager-not-saving-activiti-entities-db.  Basically I have the same setup as in Attempt 4 in my previous post and the key to making it all work is to use this entityManagerFactory bean
<blockcode>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="persistenceUnitName" value="inventoryPersistence"/>
    <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" />
      </bean>
    </property>
  </bean>
</blockcode>

fergomez
Champ in-the-making
Champ in-the-making
Hello again,

Mgiebler, would you post your whole working configuration? I've changed a lot the project, so I started from scratch again, but I'm still not able to make it work. Thanks in advance.


Kind regards.