Uploaded image for project: 'camunda BPM'
  1. camunda BPM
  2. CAM-5097

Cannot remove async activity from process and redeploy due to possible cache inconsistency

    XMLWordPrintable

    Details

    • Type: Bug Report
    • Status: Closed
    • Priority: L3 - Default
    • Resolution: Fixed
    • Affects Version/s: 7.4.0
    • Fix Version/s: 7.5.0, 7.4.1, 7.5.0-alpha1
    • Component/s: engine
    • Labels:

      Description

      Steps to reproduce:

      1. There are two engines, both configured against the same database
      2. Engine 1 deploys a process with an async task called X
      3. Engine 2 deploys a new version of that process where X is removed
      4. Loading the new process definition into engine 1's cache fails with a NullPointerException (stacktrace below)

      Alternative reproduction steps for a single engine:

      1. Deploy process with an async task called X
      2. Deploy new version of that process where X is removed
      3. Clear deployment cache
      4. Loading the new process definition into the cache fails with a NullPointerException

      Alternative reproduction steps with one engine and multiple threads:

      1. Two process definitions - A and B - with the same key X
      2. Thread 1 begins loading A into the cache, parses A and puts its job declarations into the shared map (org.camunda.bpm.engine.impl.bpmn.deployer.BpmnDeployer#transformDefinitions)
      3. Thread 2 begins loading B into the cache, parses B and puts its job declarations into the shared map(org.camunda.bpm.engine.impl.bpmn.deployer.BpmnDeployer#transformDefinitions)
      4. Thread 1 attempts to create job definitions that don't exist yet for definition A. In the shared map, it finds the job declarations for B. Accordingly, it creates job definitions for activities contained in B (but not in A) (org.camunda.bpm.engine.impl.bpmn.deployer.BpmnDeployer#definitionAddedToDeploymentCache)

      The error may also occur on server restart, if the first version is loaded into the cache before the second version of the process.

      Reason:

      • BpmnDeployer keeps a map of all job declarations it ever saw, index by process definition key
      • when loading an existing process into the cache, it looks up these declarations by key in order to create job definitions for them (migration logic)
      • Legacy migration logic (for multi-instance) assumes that the declarations reference a valid activity in the current process definition

      Side note:

      Test Case:

      Workaround:

      Stacktrace

      java.lang.NullPointerException
      	at org.camunda.bpm.engine.impl.pvm.runtime.LegacyBehavior.isAsync(LegacyBehavior.java:536)
      	at org.camunda.bpm.engine.impl.pvm.runtime.LegacyBehavior.migrateMultiInstanceJobDefinitions(LegacyBehavior.java:528)
      	at org.camunda.bpm.engine.impl.bpmn.deployer.BpmnDeployer.updateJobDeclarations(BpmnDeployer.java:187)
      	at org.camunda.bpm.engine.impl.bpmn.deployer.BpmnDeployer.definitionAddedToDeploymentCache(BpmnDeployer.java:152)
      	at org.camunda.bpm.engine.impl.bpmn.deployer.BpmnDeployer.definitionAddedToDeploymentCache(BpmnDeployer.java:1)
      	at org.camunda.bpm.engine.impl.AbstractDefinitionDeployer.registerDefinition(AbstractDefinitionDeployer.java:294)
      	at org.camunda.bpm.engine.impl.AbstractDefinitionDeployer.loadDefinitions(AbstractDefinitionDeployer.java:246)
      	at org.camunda.bpm.engine.impl.AbstractDefinitionDeployer.postProcessDefinitions(AbstractDefinitionDeployer.java:212)
      	at org.camunda.bpm.engine.impl.AbstractDefinitionDeployer.deploy(AbstractDefinitionDeployer.java:58)
      	at org.camunda.bpm.engine.impl.persistence.deploy.DeploymentCache$1.call(DeploymentCache.java:69)
      	at org.camunda.bpm.engine.impl.persistence.deploy.DeploymentCache$1.call(DeploymentCache.java:1)
      	at org.camunda.bpm.engine.impl.interceptor.CommandContext.runWithoutAuthorization(CommandContext.java:553)
      	at org.camunda.bpm.engine.impl.persistence.deploy.DeploymentCache.deploy(DeploymentCache.java:66)
      	at org.camunda.bpm.engine.impl.persistence.deploy.DeploymentCache.resolveProcessDefinition(DeploymentCache.java:140)
      	at org.camunda.bpm.engine.impl.persistence.deploy.DeploymentCache.findDeployedLatestProcessDefinitionByKey(DeploymentCache.java:102)
      	at org.camunda.bpm.engine.impl.cmd.StartProcessInstanceCmd.execute(StartProcessInstanceCmd.java:63)
      	at org.camunda.bpm.engine.impl.cmd.StartProcessInstanceCmd.execute(StartProcessInstanceCmd.java:1)
      	at org.camunda.bpm.engine.impl.interceptor.CommandExecutorImpl.execute(CommandExecutorImpl.java:24)
      	at org.camunda.bpm.engine.impl.interceptor.CommandContextInterceptor.execute(CommandContextInterceptor.java:95)
      	at org.camunda.bpm.engine.impl.interceptor.LogInterceptor.execute(LogInterceptor.java:30)
      	at org.camunda.bpm.engine.impl.RuntimeServiceImpl.startProcessInstanceByKey(RuntimeServiceImpl.java:66)
      	at org.camunda.bpm.engine.test.bpmn.async.AsyncTaskTest.testDeployAndRemoveAsyncActivity(AsyncTaskTest.java:746)
      	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 junit.framework.TestCase.runTest(TestCase.java:176)
      	at junit.framework.TestCase.runBare(TestCase.java:141)
      	at org.camunda.bpm.engine.impl.test.AbstractProcessEngineTestCase.runBare(AbstractProcessEngineTestCase.java:99)
      	at junit.framework.TestResult$1.protect(TestResult.java:122)
      	at junit.framework.TestResult.runProtected(TestResult.java:142)
      	at junit.framework.TestResult.run(TestResult.java:125)
      	at junit.framework.TestCase.run(TestCase.java:129)
      	at junit.framework.TestSuite.runTest(TestSuite.java:255)
      	at junit.framework.TestSuite.run(TestSuite.java:250)
      	at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84)
      	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
      	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
      	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
      
      
      

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              thorben.lindhauer Thorben Lindhauer
              Reporter:
              thorben.lindhauer Thorben Lindhauer
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: