<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Database Exceptions in Unittest in Alfresco Archive</title>
    <link>https://connect.hyland.com/t5/alfresco-archive/database-exceptions-in-unittest/m-p/184812#M137942</link>
    <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;SPAN&gt;Update:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;it could be related to this: &lt;/SPAN&gt;&lt;A href="http://forums.activiti.org/content/parallel-gateway-and-asynchronous-continuations" rel="nofollow noopener noreferrer"&gt;http://forums.activiti.org/content/parallel-gateway-and-asynchronous-continuations&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Update:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;I played a litte with async and sync behaivior:&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;Important: in every setup it worked at least occaisonally, randomly distributed 1/20 something sometimes two in a row, sometimes 30 times not.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;1)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results: most of the time "optimistic locking exception", deadlock-detected. updated in concurrent transaction, calculateTask not started&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;2)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results: 8/10 succeed, 2/10 deadlock,&amp;nbsp; updated in concurrent transaction&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;3, 4)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask (3) Thread.sleep() for 5 seconds)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask (4) Thread.sleep() for 5 seconds&amp;nbsp; on Unittest before submitting form data)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results 2)&amp;amp;3) = see 1), no change&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;5)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask (Thread.sleep() for 5 seconds)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results = NullPointer on calculateTask: execution.getvariable("setBySyncFlow") returns null. HOW?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;6)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask&amp;nbsp; (Thread.sleep() for 5 seconds&amp;nbsp; on Unittest before submitting form data)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results = 15/15 succeed.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;2,5 and 6 are key to the problem i think.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;2 and 6 show that, if the task after the Join is synchrone and the synchrone flow reaches the gateway LAST, everything is fine.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;This explains why 6 is all successes, the async task will never take 5 seconds. in case of 2 the input is almost all the time slower than the async flow, but in 2/10 cases the scheduling favors the main thread and the concurrency issue occurs.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;I don't see an explanation for 5). How can the sync task after the gateway not access the variables set by the sync flow before the gateway? In addition, how does this relate in any way to the asnyc task taking longer to execute?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;If the flow after the gateway is async however, it does not matter who comes first. the only thing i could think of could be, that the main thread considers the process done because there is nothing synchrone left and tries to update the processState to "done" while the async flow wants to start the next task?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;With the gateway as Fork suggestion:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;7)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask (Thread.sleep() for 5 seconds after setVariable("values") does not matter because of transactions)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results = NullPointer on calculateTask: execution.getvariable("setBySyncTask") returns null. (like 5))&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"&gt;😎&lt;/span&gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results = mainly like 1) but seems to work significantly more often BUT: in calculateTask execution.getVariable("setByasyncFlow") returns null occaisonally. This never happend before in any setup.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;I hope the data helps anyone figuring out what is going on. I think 5) might actually be a bug?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;P.S.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;My Unittest, the engine.close() is, well, i just left it there, it does not affect the problem at all.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;public class ProcessTest_randomCalculator {&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt; @Rule&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; public ActivitiRule engine = new ActivitiRule();&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt; @Test&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; @Deployment (resources={"bpmn/randomCalculator.bpmn20.xml"})&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; public void startProcess() throws Exception {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; RuntimeService runtimeService = engine.getRuntimeService();&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("randomCalculator");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; assertNotNull(processInstance.getId());&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; List&amp;lt;Task&amp;gt; taskList = engine.getTaskService().createTaskQuery().taskAssignee("kermit").list();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; assertTrue(taskList.size()==1);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; Map&amp;lt;String, String&amp;gt; params = new HashMap&amp;lt;String, String&amp;gt;();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; params.put("min", "-1000");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; params.put("max", "1000");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; engine.getFormService().submitTaskFormData(taskList.get(0).getId(), params);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; engine.close();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;randomTask-code:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;public class ServiceTaskImpl implements JavaDelegate&amp;nbsp; {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; public void execute(DelegateExecution execution) throws Exception {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; Random rnd&amp;nbsp; = new Random();&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; long baseline = System.currentTimeMillis();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; execution.setVariable("started", baseline);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("SERVICETASK START");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; rnd.setSeed(System.currentTimeMillis());&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; int i = rnd.nextInt() % 100;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; int j = rnd.nextInt() % 100;&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; SerializableValuePair values = new SerializableValuePair(i,j);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; execution.setVariable("values", values);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; Thread.sleep(5000);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("SERVICETASK ENDED: " + (System.currentTimeMillis()-baseline) + " millis");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;calculateTask-code&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;public class CalculateTaskImpl implements JavaDelegate&amp;nbsp; {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; final static Logger logger = LoggerFactory.getLogger("TEST");&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt; public void execute(DelegateExecution execution) throws Exception {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; long baseline = (Long) execution.getVariable("started");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("CALCULATION STARTED: " + (System.currentTimeMillis()-baseline) + " millis");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; SerializableValuePair values = (SerializableValuePair) execution.getVariable("values");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("VALUES: " + values.getA() + " + " + values.getB());&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("MAX: " + execution.getVariable("max"));&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; long max = (Long) execution.getVariable("max");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; long min = (Long) execution.getVariable("min");&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; int result = values.getA() + values.getB();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("VARIABLES RETRIEVED: " + min + ", " + max);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; if(values.getA()&amp;gt;max || values.getB() &amp;gt; max || values.getA()&amp;lt;min || values.getB() &amp;lt; min) {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp; throw new Exception("Values out of bounds.");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; File f = new File("C:\\Users\\A538237\\output.txt");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; PrintWriter w = new PrintWriter(f);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.println(new Date());&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.println(min);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.println(max);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.println("RESULT " + result);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.flush();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.close();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("CALCULATION ENDED: " + (System.currentTimeMillis()-baseline) + " millis");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;the type SerializableValuePair is just two wrapped longs with getter, setters and implements serializable, it is not the porblem&lt;/SPAN&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
    <pubDate>Fri, 08 Aug 2014 09:54:01 GMT</pubDate>
    <dc:creator>billdoor</dc:creator>
    <dc:date>2014-08-08T09:54:01Z</dc:date>
    <item>
      <title>Database Exceptions in Unittest</title>
      <link>https://connect.hyland.com/t5/alfresco-archive/database-exceptions-in-unittest/m-p/184810#M137940</link>
      <description>Hello,I am currently evaluating Activiti for a new project and keep running into seemingly random, database related exceptions likeProcessInstance was updated by another transaction concurrently, Deadlock detected, Variable was concurrently updated in another Procesinstance in Unittests.My Process i</description>
      <pubDate>Thu, 07 Aug 2014 11:56:00 GMT</pubDate>
      <guid>https://connect.hyland.com/t5/alfresco-archive/database-exceptions-in-unittest/m-p/184810#M137940</guid>
      <dc:creator>billdoor</dc:creator>
      <dc:date>2014-08-07T11:56:00Z</dc:date>
    </item>
    <item>
      <title>Re: Database Exceptions in Unittest</title>
      <link>https://connect.hyland.com/t5/alfresco-archive/database-exceptions-in-unittest/m-p/184811#M137941</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;SPAN&gt;Hi,&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;I would use 2 parallel gateways. One to fork execution and the second one (already in the process definition) to join the execution.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;(could you attach your jUnit test project too &lt;/SPAN&gt;&lt;A href="http://forums.activiti.org/content/sticky-how-write-unit-test" rel="nofollow noopener noreferrer"&gt;http://forums.activiti.org/content/sticky-how-write-unit-test&lt;/A&gt;&lt;SPAN&gt;)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;Regards&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;Martin&lt;/SPAN&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Fri, 08 Aug 2014 05:19:20 GMT</pubDate>
      <guid>https://connect.hyland.com/t5/alfresco-archive/database-exceptions-in-unittest/m-p/184811#M137941</guid>
      <dc:creator>martin_grofcik</dc:creator>
      <dc:date>2014-08-08T05:19:20Z</dc:date>
    </item>
    <item>
      <title>Re: Database Exceptions in Unittest</title>
      <link>https://connect.hyland.com/t5/alfresco-archive/database-exceptions-in-unittest/m-p/184812#M137942</link>
      <description>&lt;HTML&gt;&lt;HEAD&gt;&lt;/HEAD&gt;&lt;BODY&gt;&lt;SPAN&gt;Update:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;it could be related to this: &lt;/SPAN&gt;&lt;A href="http://forums.activiti.org/content/parallel-gateway-and-asynchronous-continuations" rel="nofollow noopener noreferrer"&gt;http://forums.activiti.org/content/parallel-gateway-and-asynchronous-continuations&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;Update:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;I played a litte with async and sync behaivior:&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;Important: in every setup it worked at least occaisonally, randomly distributed 1/20 something sometimes two in a row, sometimes 30 times not.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;1)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results: most of the time "optimistic locking exception", deadlock-detected. updated in concurrent transaction, calculateTask not started&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;2)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results: 8/10 succeed, 2/10 deadlock,&amp;nbsp; updated in concurrent transaction&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;3, 4)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask (3) Thread.sleep() for 5 seconds)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask (4) Thread.sleep() for 5 seconds&amp;nbsp; on Unittest before submitting form data)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results 2)&amp;amp;3) = see 1), no change&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;5)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask (Thread.sleep() for 5 seconds)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results = NullPointer on calculateTask: execution.getvariable("setBySyncFlow") returns null. HOW?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;6)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask&amp;nbsp; (Thread.sleep() for 5 seconds&amp;nbsp; on Unittest before submitting form data)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results = 15/15 succeed.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;2,5 and 6 are key to the problem i think.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;2 and 6 show that, if the task after the Join is synchrone and the synchrone flow reaches the gateway LAST, everything is fine.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;This explains why 6 is all successes, the async task will never take 5 seconds. in case of 2 the input is almost all the time slower than the async flow, but in 2/10 cases the scheduling favors the main thread and the concurrency issue occurs.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;I don't see an explanation for 5). How can the sync task after the gateway not access the variables set by the sync flow before the gateway? In addition, how does this relate in any way to the asnyc task taking longer to execute?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;If the flow after the gateway is async however, it does not matter who comes first. the only thing i could think of could be, that the main thread considers the process done because there is nothing synchrone left and tries to update the processState to "done" while the async flow wants to start the next task?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;With the gateway as Fork suggestion:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;7)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask (Thread.sleep() for 5 seconds after setVariable("values") does not matter because of transactions)&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results = NullPointer on calculateTask: execution.getvariable("setBySyncTask") returns null. (like 5))&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&lt;span class="lia-unicode-emoji" title=":smiling_face_with_sunglasses:"&gt;😎&lt;/span&gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;start&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;async-randomTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-userTask &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;gateway&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;sync-calculateTask&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;end&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;results = mainly like 1) but seems to work significantly more often BUT: in calculateTask execution.getVariable("setByasyncFlow") returns null occaisonally. This never happend before in any setup.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;I hope the data helps anyone figuring out what is going on. I think 5) might actually be a bug?&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;P.S.&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;My Unittest, the engine.close() is, well, i just left it there, it does not affect the problem at all.&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;public class ProcessTest_randomCalculator {&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt; @Rule&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; public ActivitiRule engine = new ActivitiRule();&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt; @Test&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; @Deployment (resources={"bpmn/randomCalculator.bpmn20.xml"})&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; public void startProcess() throws Exception {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; RuntimeService runtimeService = engine.getRuntimeService();&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("randomCalculator");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; assertNotNull(processInstance.getId());&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; List&amp;lt;Task&amp;gt; taskList = engine.getTaskService().createTaskQuery().taskAssignee("kermit").list();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; assertTrue(taskList.size()==1);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; Map&amp;lt;String, String&amp;gt; params = new HashMap&amp;lt;String, String&amp;gt;();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; params.put("min", "-1000");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; params.put("max", "1000");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; engine.getFormService().submitTaskFormData(taskList.get(0).getId(), params);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; engine.close();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;randomTask-code:&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;public class ServiceTaskImpl implements JavaDelegate&amp;nbsp; {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; public void execute(DelegateExecution execution) throws Exception {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; Random rnd&amp;nbsp; = new Random();&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; long baseline = System.currentTimeMillis();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; execution.setVariable("started", baseline);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("SERVICETASK START");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; rnd.setSeed(System.currentTimeMillis());&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; int i = rnd.nextInt() % 100;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; int j = rnd.nextInt() % 100;&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; SerializableValuePair values = new SerializableValuePair(i,j);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; execution.setVariable("values", values);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; Thread.sleep(5000);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("SERVICETASK ENDED: " + (System.currentTimeMillis()-baseline) + " millis");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;calculateTask-code&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;public class CalculateTaskImpl implements JavaDelegate&amp;nbsp; {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; final static Logger logger = LoggerFactory.getLogger("TEST");&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt; public void execute(DelegateExecution execution) throws Exception {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; long baseline = (Long) execution.getVariable("started");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("CALCULATION STARTED: " + (System.currentTimeMillis()-baseline) + " millis");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; SerializableValuePair values = (SerializableValuePair) execution.getVariable("values");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("VALUES: " + values.getA() + " + " + values.getB());&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("MAX: " + execution.getVariable("max"));&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; long max = (Long) execution.getVariable("max");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; long min = (Long) execution.getVariable("min");&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; int result = values.getA() + values.getB();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("VARIABLES RETRIEVED: " + min + ", " + max);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; if(values.getA()&amp;gt;max || values.getB() &amp;gt; max || values.getA()&amp;lt;min || values.getB() &amp;lt; min) {&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp;&amp;nbsp; throw new Exception("Values out of bounds.");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; File f = new File("C:\\Users\\A538237\\output.txt");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; PrintWriter w = new PrintWriter(f);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.println(new Date());&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.println(min);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.println(max);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.println("RESULT " + result);&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.flush();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; w.close();&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; System.err.println("CALCULATION ENDED: " + (System.currentTimeMillis()-baseline) + " millis");&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt; }&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;}&lt;/SPAN&gt;&lt;BR /&gt;&lt;SPAN&gt;&amp;lt;/code&amp;gt;&lt;/SPAN&gt;&lt;BR /&gt;&lt;BR /&gt;&lt;SPAN&gt;the type SerializableValuePair is just two wrapped longs with getter, setters and implements serializable, it is not the porblem&lt;/SPAN&gt;&lt;/BODY&gt;&lt;/HTML&gt;</description>
      <pubDate>Fri, 08 Aug 2014 09:54:01 GMT</pubDate>
      <guid>https://connect.hyland.com/t5/alfresco-archive/database-exceptions-in-unittest/m-p/184812#M137942</guid>
      <dc:creator>billdoor</dc:creator>
      <dc:date>2014-08-08T09:54:01Z</dc:date>
    </item>
  </channel>
</rss>

