[jbpm-commits] JBoss JBPM SVN: r5361 - in jbpm4/trunk/modules: pvm/src/main/java/org/jbpm/pvm/internal/repository and 4 other directories.

do-not-reply at jboss.org do-not-reply at jboss.org
Tue Jul 28 15:54:59 EDT 2009


Author: jbarrez
Date: 2009-07-28 15:54:58 -0400 (Tue, 28 Jul 2009)
New Revision: 5361

Added:
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/cache/
   jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/cache/RepositoryCacheTest.java
   jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/test/cache/
   jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/test/cache/jbpm_alternative.cfg.xml
   jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/test/cache/jbpm_alternative.hibernate.cfg.xml
Modified:
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/DeleteDeploymentCmd.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositoryCache.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositoryCacheImpl.java
   jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositorySessionImpl.java
Log:
JBPM:2360 check and fix deletion of a deployment in cluster

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/DeleteDeploymentCmd.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/DeleteDeploymentCmd.java	2009-07-28 12:58:30 UTC (rev 5360)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/cmd/DeleteDeploymentCmd.java	2009-07-28 19:54:58 UTC (rev 5361)
@@ -89,7 +89,7 @@
     session.delete(deployment);
     
     RepositoryCache repositoryCache = environment.get(RepositoryCache.class);
-    repositoryCache.set(deploymentId, null);
+    repositoryCache.remove(deploymentId);
 
     return null;
   }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositoryCache.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositoryCache.java	2009-07-28 12:58:30 UTC (rev 5360)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositoryCache.java	2009-07-28 19:54:58 UTC (rev 5361)
@@ -22,6 +22,7 @@
 package org.jbpm.pvm.internal.repository;
 
 import java.util.Map;
+import java.util.Set;
 
 
 /**
@@ -31,6 +32,7 @@
 
   void set(String deploymentId, Map<String, Object> deployedObjects);
   Object get(String deploymentId, String objectName);
+  Set<String> getCachedDeploymentIds();
   void remove(String deploymentId);
   void clear();
 }

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositoryCacheImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositoryCacheImpl.java	2009-07-28 12:58:30 UTC (rev 5360)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositoryCacheImpl.java	2009-07-28 19:54:58 UTC (rev 5361)
@@ -21,8 +21,10 @@
  */
 package org.jbpm.pvm.internal.repository;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 
 /**
@@ -55,6 +57,13 @@
       }
     }
   }
+  
+  public Set<String> getCachedDeploymentIds() {
+    if (deployments != null) {
+      return deployments.keySet();
+    }
+    return Collections.emptySet();
+  }
 
   public void remove(String deploymentDbid) {
     if (deployments!=null) {

Modified: jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositorySessionImpl.java
===================================================================
--- jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositorySessionImpl.java	2009-07-28 12:58:30 UTC (rev 5360)
+++ jbpm4/trunk/modules/pvm/src/main/java/org/jbpm/pvm/internal/repository/RepositorySessionImpl.java	2009-07-28 19:54:58 UTC (rev 5361)
@@ -21,6 +21,7 @@
  */
 package org.jbpm.pvm.internal.repository;
 
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -148,7 +149,12 @@
 
     if (processDefinition!=null) {
       return findProcessDefinitionById(processDefinition.getId());
+    } else {
+      validateRepositoryCache();
     }
+    
+    // if null -> invalidate cache?
+    System.out.println("---------------->" + repositoryCache.get("1", "test_process"));
 
     return null;
   }
@@ -161,7 +167,12 @@
       String objectName = deploymentProperty.getObjectName();
       
       return (ProcessDefinitionImpl) getObject(deploymentId, objectName);
+    } else {
+      validateRepositoryCache();
     }
+    
+    // ? if null -> delete from cache?
+    System.out.println("---------------->" + repositoryCache.get("1", "test_process"));
 
     return null;
   }
@@ -175,4 +186,28 @@
     ).setMaxResults(1).uniqueResult();
     return deploymentProperty;
   }
+  
+  /**
+   * Checks if every entry in the repositoryCache is still valid.
+   * If the entry is not found in the database, it is deleted from the cache.
+   */
+  @SuppressWarnings("unchecked")
+  private void validateRepositoryCache() {
+
+    log.trace("Validating repository cache ... ");
+    Set<Long> dbIds = new HashSet<Long>(session.createQuery("select dbid from " +
+            DeploymentImpl.class.getName() + " as deployment ")
+            .setReadOnly(true)
+            .list());
+    
+    Set<String> cachedIds = repositoryCache.getCachedDeploymentIds();
+    for (String cachedId : cachedIds) {
+      if (!dbIds.contains(Long.valueOf(cachedId))) {
+        log.trace("Invalid entry in repositorycache found, removing now deployment id " + cachedId);
+        repositoryCache.remove(cachedId);
+      }
+    }
+    
+  }
+  
 }

Added: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/cache/RepositoryCacheTest.java
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/cache/RepositoryCacheTest.java	                        (rev 0)
+++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/test/cache/RepositoryCacheTest.java	2009-07-28 19:54:58 UTC (rev 5361)
@@ -0,0 +1,131 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+/**
+ * 
+ */
+package org.jbpm.test.cache;
+
+import org.jbpm.api.Configuration;
+import org.jbpm.api.Execution;
+import org.jbpm.api.ExecutionService;
+import org.jbpm.api.JbpmException;
+import org.jbpm.api.ProcessEngine;
+import org.jbpm.api.ProcessInstance;
+import org.jbpm.test.JbpmTestCase;
+
+
+/**
+ * Test case for the correct working of the repositoryCache.
+ * 
+ * @author Joram Barrez
+ */
+public class RepositoryCacheTest extends JbpmTestCase {
+  
+  private static final String PROCESS_KEY = "test_process";
+  
+  private static final String TEST_PROCESS =
+    "<process name='" + PROCESS_KEY + "'>" +
+      "  <start>" +
+      "    <transition to='a' />" +
+      "  </start>" +
+      "  <state name='a'>" +
+      "    <transition to='theEnd' />" +
+      "  </state>" +
+      "  <end name='theEnd' />" +
+      "</process>";
+
+  /**
+   * Test for JBPM-2360:
+   * 
+   * When a deployment is deleted, the entry is also removed from the
+   * repositoryCache. However, in a clustered environment, the deletion from the
+   * cache is done only on the node on which the deletion operation is invoked.
+   * This means that the other nodes are unaware of the deletion and the 
+   * deployment is not deleted from the cache.
+   * 
+   * This test emulates this scenario using two process engines which use
+   * the same database. One will delete a deployment. The second one must
+   * throw an exception when it tries to use the deployment.
+   *    * When starting a new process
+   *    * When signalling an execution which has a deleted deployment
+   */
+  public void testDeleteDeploymentsUsingTwoProcessEngines() {
+    
+    ProcessEngine processEngine2 = createProcessEngineFromAlternativeConfig();
+    ExecutionService executionService2 = processEngine2.getExecutionService();
+    assertFalse(processEngine.equals(processEngine2));
+    assertFalse(executionService.equals(executionService2));
+    
+    // Deploy the process through the first process engine
+    String deployId = repositoryService.createDeployment()
+                     .addResourceFromString("test_process.jpdl.xml", TEST_PROCESS)
+                     .deploy();
+    
+    // Start process instance on first process engine
+    ProcessInstance pi1 = executionService.startProcessInstanceByKey(PROCESS_KEY);
+    Execution executionAtWaitState1 = pi1.findActiveExecutionIn("a");
+    assertActivityActive(pi1.getId(), "a");
+    
+    // Now start process instance on second process engine
+    ProcessInstance pi2 = executionService2.startProcessInstanceByKey(PROCESS_KEY);
+    Execution executionAtWaitState2 = pi1.findActiveExecutionIn("a");
+    assertActivityActive(pi2.getId(), "a");
+    
+    // Delete the deployment through the first process engine
+    repositoryService.deleteDeploymentCascade(deployId);
+    
+    // Trying to find the two active process instances should fail now
+    assertNull(executionService.findExecutionById(pi1.getId()));
+    assertNull(executionService.findExecutionById(pi2.getId()));
+    
+    // Try to start the process through the first process engine. 
+    // This should fail (since the deployment was deleted).
+    try {
+      executionService.startProcessInstanceByKey(PROCESS_KEY);
+      fail();
+    } catch (JbpmException e) { }
+    
+    // Try to start the process through the second process engine.
+    // This should also fail (ie caches should be updated on both side).
+    try {
+      executionService2.startProcessInstanceByKey(PROCESS_KEY);
+      fail();
+    } catch (JbpmException e) { }
+    
+    // Try to signal a process that was active before the deletion. This should also fail.
+    try {
+      executionService.signalExecutionById(executionAtWaitState1.getId());
+      fail();
+    } catch (JbpmException e) { }
+    try {
+      executionService2.signalExecutionById(executionAtWaitState2.getId());
+      fail();
+    } catch (JbpmException e) { }
+    
+  }
+   
+  private ProcessEngine createProcessEngineFromAlternativeConfig() {
+    Configuration configuration = new Configuration().setResource("org/jbpm/test/cache/jbpm_alternative.cfg.xml");
+    return configuration.buildProcessEngine();
+  }
+
+}

Added: jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/test/cache/jbpm_alternative.cfg.xml
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/test/cache/jbpm_alternative.cfg.xml	                        (rev 0)
+++ jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/test/cache/jbpm_alternative.cfg.xml	2009-07-28 19:54:58 UTC (rev 5361)
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+  <!--
+
+    Alternative configuration: * no create-drop for the database
+  -->
+
+<jbpm-configuration>
+
+  <process-engine-context>
+
+    <repository-service />
+    <repository-cache />
+    <execution-service />
+    <history-service />
+    <management-service />
+    <identity-service />
+    <task-service />
+
+    <hibernate-configuration>
+      <cfg resource="org/jbpm/test/cache/jbpm_alternative.hibernate.cfg.xml" />
+    </hibernate-configuration>
+
+    <hibernate-session-factory />
+
+    <script-manager default-expression-language="juel"
+      default-script-language="juel">
+      <script-language name="juel"
+        factory="org.jbpm.pvm.internal.script.JuelScriptEngineFactory" />
+    </script-manager>
+
+    <id-generator />
+    <types resource="jbpm.variable.types.xml" />
+
+    <address-resolver />
+
+  </process-engine-context>
+
+  <transaction-context>
+    <repository-session />
+    <db-session />
+
+    <message-session />
+    <timer-session />
+    <history-session />
+    <mail-session>
+      <mail-server>
+        <session-properties resource="jbpm.mail.properties" />
+      </mail-server>
+    </mail-session>
+  </transaction-context>
+
+  <import resource="jbpm.businesscalendar.cfg.xml" />
+  <import resource="jbpm.tx.hibernate.cfg.xml" />
+  <import resource="jbpm.jpdl.cfg.xml" />
+  <import resource="jbpm.identity.cfg.xml" />
+
+</jbpm-configuration>

Added: jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/test/cache/jbpm_alternative.hibernate.cfg.xml
===================================================================
--- jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/test/cache/jbpm_alternative.hibernate.cfg.xml	                        (rev 0)
+++ jbpm4/trunk/modules/test-db/src/test/resources/org/jbpm/test/cache/jbpm_alternative.hibernate.cfg.xml	2009-07-28 19:54:58 UTC (rev 5361)
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!DOCTYPE hibernate-configuration PUBLIC
+          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+  <session-factory>
+  
+     <!-- HSQLDB -->
+     <property name="hibernate.dialect">org.hibernate.dialect.HSQLDialect</property>
+     <property name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>
+     <property name="hibernate.connection.url">jdbc:hsqldb:mem:.</property>
+     <property name="hibernate.connection.username">sa</property>
+     <property name="hibernate.connection.password"></property>
+     
+     <!-- Alternative config: no create-drop -->
+     <property name="hibernate.hbm2ddl.auto">update</property>
+     <property name="hibernate.format_sql">true</property>
+     
+     <mapping resource="jbpm.repository.hbm.xml" />
+     <mapping resource="jbpm.execution.hbm.xml" />
+     <mapping resource="jbpm.history.hbm.xml" />
+     <mapping resource="jbpm.task.hbm.xml" />
+     <mapping resource="jbpm.identity.hbm.xml" />
+     
+  </session-factory>
+</hibernate-configuration>



More information about the jbpm-commits mailing list