<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[grow with the flow]]></title><description><![CDATA[thoughts, patterns, suggestions on workflow automation]]></description><link>https://blog.frena.de/</link><image><url>https://blog.frena.de/favicon.png</url><title>grow with the flow</title><link>https://blog.frena.de/</link></image><generator>Ghost 3.40</generator><lastBuildDate>Fri, 07 Nov 2025 03:38:40 GMT</lastBuildDate><atom:link href="https://blog.frena.de/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Where did the execution-listeners go?]]></title><description><![CDATA[Camunda 8 Migration]]></description><link>https://blog.frena.de/camunda-8-migration-execution-listeners/</link><guid isPermaLink="false">651abedd279a8500012062a7</guid><category><![CDATA[camunda 8 migration]]></category><dc:creator><![CDATA[Johannes Deschl]]></dc:creator><pubDate>Tue, 26 Sep 2023 08:16:25 GMT</pubDate><media:content url="https://blog.frena.de/content/images/2023/09/image-from-rawpixel-id-5923949-jpeg.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://blog.frena.de/content/images/2023/09/image-from-rawpixel-id-5923949-jpeg.jpg" alt="Where did the execution-listeners go?"><p>A very common requirement that I saw in all my projects over the last years, is the update of business data related to a process instance.</p><p><strong>Example</strong>: A process for handling offer requests of customers. A DB-table for related business data holds information of the current 'state' that should be updated after an offer is sent to a customer by a sales representative.</p><h3 id="how-to-solve-with-camunda-platform-7-embedded">How to solve with Camunda Platform 7 embedded</h3><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.frena.de/content/images/2023/09/c7_solution_process-1.jpg" class="kg-image" alt="Where did the execution-listeners go?" srcset="https://blog.frena.de/content/images/size/w600/2023/09/c7_solution_process-1.jpg 600w, https://blog.frena.de/content/images/size/w1000/2023/09/c7_solution_process-1.jpg 1000w, https://blog.frena.de/content/images/size/w1600/2023/09/c7_solution_process-1.jpg 1600w, https://blog.frena.de/content/images/size/w2400/2023/09/c7_solution_process-1.jpg 2400w" sizes="(min-width: 1200px) 1200px"></figure><p>In this simple process the state change is modeled as a <em>none intermediate throw event</em>. The Element has a execution listener attached to it. The listener is defined with an expression, that calls a method of a StateService bean from the context and passes a reference and the target state. The reference is the primary key of the business entity that was set as a process-variable upon instance start.</p><p>When running Camunda 7 as an embedded engine we have access to the classpath of the embedding application. Implementing the application with spring boot even allows calls to the bean context from within expressions defined in the BPMN model. The expression from this example</p><blockquote> ${stateService.changeState(execution.getVariable('reference'), 'OFFERED')} </blockquote><p>calls the method 'changeState' of a bean named stateService. The value of the instance-variable 'reference' is used as the first method argument, the value 'OFFERED' as the second.</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2023/09/C7-solution_code.png" class="kg-image" alt="Where did the execution-listeners go?" srcset="https://blog.frena.de/content/images/size/w600/2023/09/C7-solution_code.png 600w, https://blog.frena.de/content/images/size/w1000/2023/09/C7-solution_code.png 1000w, https://blog.frena.de/content/images/2023/09/C7-solution_code.png 1110w" sizes="(min-width: 720px) 720px"></figure><p>But execution listeners are no more with Camunda Platform 8!<br>Due to the new <a href="https://docs.camunda.io/docs/components/zeebe/technical-concepts/architecture/">architecture</a> of Camunda Platform 8, the engine (Zebee) is decoupled from the business code. Business-logic has to be implemented via JobWorkers that get their work from the engine via gRPC-API and report back on success (or failure). <br>You might already know that pattern as "External task pattern" that was already support by Camunda 7.</p><h3 id="how-to-solve-with-camunda-platform-8">How to solve with Camunda Platform 8</h3><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.frena.de/content/images/2023/09/c8_solution_process_serviceTask.png" class="kg-image" alt="Where did the execution-listeners go?" srcset="https://blog.frena.de/content/images/size/w600/2023/09/c8_solution_process_serviceTask.png 600w, https://blog.frena.de/content/images/size/w1000/2023/09/c8_solution_process_serviceTask.png 1000w, https://blog.frena.de/content/images/size/w1600/2023/09/c8_solution_process_serviceTask.png 1600w, https://blog.frena.de/content/images/size/w2400/2023/09/c8_solution_process_serviceTask.png 2400w" sizes="(min-width: 1200px) 1200px"></figure><p>The process looks almost similar. Instead of <em>none intermediate throw event</em>, a service task is used. So that a job worker can pick up the job, the <em>jobType</em> has to be defined - in this case the type is defined as <em>changeState</em>. The target state is provided via a custom header.</p><p>In this example the worker is implemented as part of a spring boot application using <em>spring-boot-starter-camunda</em>. The worker is defined with help of the @JobWorker annotation, that links the implementation to the <em>jobType</em> specified in the BPMN model. By using the @JobWorker annotation, the communication to Zeebe for retrieving and completing the job is taken care of for us. Using the annotation the job will be auto-completed after the execution the method. Instance variables and job headers can be accessed via the ActivatedJob wrapper object.</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2023/09/c8_solution_code.png" class="kg-image" alt="Where did the execution-listeners go?" srcset="https://blog.frena.de/content/images/size/w600/2023/09/c8_solution_code.png 600w, https://blog.frena.de/content/images/size/w1000/2023/09/c8_solution_code.png 1000w, https://blog.frena.de/content/images/2023/09/c8_solution_code.png 1456w" sizes="(min-width: 720px) 720px"></figure><p>An alternative to model the state change as a service task, we could also use an <em>message intermediate throw event</em>. By using the same <em>jobType</em> as in the first model variant, we can use the exact same worker implementation to do the work.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://blog.frena.de/content/images/2023/09/c8_solution_process_messageThrowEvent.png" class="kg-image" alt="Where did the execution-listeners go?" srcset="https://blog.frena.de/content/images/size/w600/2023/09/c8_solution_process_messageThrowEvent.png 600w, https://blog.frena.de/content/images/size/w1000/2023/09/c8_solution_process_messageThrowEvent.png 1000w, https://blog.frena.de/content/images/size/w1600/2023/09/c8_solution_process_messageThrowEvent.png 1600w, https://blog.frena.de/content/images/size/w2400/2023/09/c8_solution_process_messageThrowEvent.png 2400w" sizes="(min-width: 1200px) 1200px"></figure><p>Of course we are not bound to the use of Java. Due to the architecture of Camunda Platform 8, the worker can be implemented in any desired language. In addition to the <a href="https://docs.camunda.io/docs/apis-tools/working-with-apis-tools/#official-zeebe-clients">official Zeebe clients</a>, the Camunda community already came up with a whole bunch of useful client <a href="https://docs.camunda.io/docs/apis-tools/working-with-apis-tools/#community-clients">implementations for different languages and frameworks</a>.</p>]]></content:encoded></item><item><title><![CDATA[Fun with element-templates for Camunda Modeler]]></title><description><![CDATA[<p>The Camunda <a href="https://camunda.com/download/modeler/">Modeler</a> mostly does a good job when it comes to modeling processes intuitively. Starting from an Eclipse based solution to the latest stand-alone version, the experience of quickly designing a business process improved a lot. </p><p>For all of us who need some extra customization, for example to accelerate</p>]]></description><link>https://blog.frena.de/camunda-modeler-template-extension/</link><guid isPermaLink="false">651abedd279a8500012062a2</guid><category><![CDATA[nice-and-handy]]></category><dc:creator><![CDATA[Stefan Frena]]></dc:creator><pubDate>Fri, 27 Sep 2019 11:30:24 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1580654234509-b60db23aa5c7?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDV8fG11c3RlcnxlbnwwfHx8fDE2Mjc2NDc2NTM&amp;ixlib=rb-1.2.1&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1580654234509-b60db23aa5c7?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxMTc3M3wwfDF8c2VhcmNofDV8fG11c3RlcnxlbnwwfHx8fDE2Mjc2NDc2NTM&ixlib=rb-1.2.1&q=80&w=2000" alt="Fun with element-templates for Camunda Modeler"><p>The Camunda <a href="https://camunda.com/download/modeler/">Modeler</a> mostly does a good job when it comes to modeling processes intuitively. Starting from an Eclipse based solution to the latest stand-alone version, the experience of quickly designing a business process improved a lot. </p><p>For all of us who need some extra customization, for example to accelerate input of values in reoccurring tasks, there is a simple way to create and integrate element-templates. </p><p>In a recent project we had a process that was called multiple times from call activities, always with different sets of variable values. I call this <em>flavoring</em>. The example in the following process illustrates what I mean. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://blog.frena.de/content/images/2019/09/image.png" class="kg-image" alt="Fun with element-templates for Camunda Modeler"><figcaption>Call the lower process three times to send congrats</figcaption></figure><p><br>We used to flavor the sub process using variables defined in the In Mapping, like in the picture:</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2019/09/image-3.png" class="kg-image" alt="Fun with element-templates for Camunda Modeler"></figure><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2019/09/image-4.png" class="kg-image" alt="Fun with element-templates for Camunda Modeler"></figure><p>I must say this is not the strongest feature of the modeler in terms of usability. </p><p>Luckily, it offers the possibility of templating it for these purposes. I added the following json to <strong><em>path/of/modeler/resources/element-templates</em></strong>:</p><pre><code>{ 
   "name":"Congrats CallActivity",
   "id":"de.frena.callactivity",
   "appliesTo":[ 
      "bpmn:CallActivity"
   ],
   "properties":[ 
      { 
         "label":"channel",
         "type":"Dropdown",
         "binding":{ 
            "type":"camunda:in",
            "target":"channel",
            "expression":true
         },
         "constraints":{ 
            "notEmpty":true
         },
         "choices":[ 
            { 
               "name":"",
               "value":""
            },
            { 
               "name":"whatsapp",
               "value":"whatsapp"
            },
            { 
               "name":"email",
               "value":"email"
            }
         ]
      },
      { 
         "label":"person to congrat",
         "type":"String",
         "binding":{ 
            "type":"camunda:in",
            "target":"person",
            "expression":true
         },
         "constraints":{ 
            "notEmpty":true
         }
      },
      { 
         "label":"Called Process",
         "description":"the Process Id of the sub process to call",
         "type":"String",
         "value":"Subprocess_ID",
         "editable":false,
         "binding":{ 
            "type":"property",
            "name":"calledElement"
         },
         "constraints":{ 
            "notEmpty":true
         }
      },
      { 
         "label":"business key",
         "editable":false,
         "type":"String",
         "value":"${execution.processBusinessKey}",
         "binding":{ 
            "type":"camunda:in:businessKey"
         }
      },
      {
        "label": "Asynchronous Before",
		"editable":false,
        "type": "Boolean",
        "value": true,
        "binding": {
          "type": "property",
          "name": "camunda:asyncBefore"
        }
      },
      {
        "label": "Asynchronous After",
		"editable":false,
        "type": "Boolean",
        "value": true,
        "binding": {
          "type": "property",
          "name": "camunda:asyncAfter"
        }
      }
   ],
   "entriesVisible":{ 
      "id":true,
      "name":true
   }
}</code></pre><p>After reloading the modeler you can choose the Element-Template for any Call activity and fill in the values in a more efficient way.</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2019/09/image-5.png" class="kg-image" alt="Fun with element-templates for Camunda Modeler"></figure><h3 id="benefits-">Benefits:</h3><!--kg-card-begin: markdown--><ol>
<li>helps in an environment of reoccurring modelling of the same task.</li>
<li>helps to easily review entered values with one click on the task.</li>
</ol>
<!--kg-card-end: markdown--><h3 id="tips-and-tricks-">Tips and Tricks:</h3><!--kg-card-begin: markdown--><ol>
<li>While 'implementing' the json file, the modeler must be restarted after every save of json. To do so, hit F12 Key in modeler. This opens chrome developer tools. Leave them open. Now simply hit Ctrl-R to reload the modeler in a faster more elegant way. Don't forget to save. This Tip I got from <a href="https://github.com/nikku">Nico Rehwaldt</a> at <a href="https://camunda.com/events/camundacon2019-pictures-video/">CamundaCon 2019</a>. Thanks alot!</li>
<li>Checkout the <a href="https://github.com/camunda/camunda-modeler">camunda modeler project</a>  and have a look at <a href="https://github.com/camunda/camunda-modeler/blob/master/resources/element-templates/samples.json">sample.json</a> for all the possibilites you have.</li>
</ol>
<!--kg-card-end: markdown--><p>Let me know what you think and if I can help you to understand this better. This was just a rough nutshell.</p>]]></content:encoded></item><item><title><![CDATA[Camunda 7.10 Spring Boot using Gradle]]></title><description><![CDATA[<p>Sometimes in projects I am faced with questions about process implementation or modeling options I cannot solve right away.</p><p>For this purpose I use a simple easy-to-use spring boot project to explore the possibilites right away. It runs on my localhost, starts fast and only contains a minimum amount of</p>]]></description><link>https://blog.frena.de/camunda-7-10-spring-boot-gradle/</link><guid isPermaLink="false">651abedd279a8500012062a1</guid><category><![CDATA[nice-and-handy]]></category><dc:creator><![CDATA[Stefan Frena]]></dc:creator><pubDate>Fri, 07 Dec 2018 14:17:12 GMT</pubDate><content:encoded><![CDATA[<p>Sometimes in projects I am faced with questions about process implementation or modeling options I cannot solve right away.</p><p>For this purpose I use a simple easy-to-use spring boot project to explore the possibilites right away. It runs on my localhost, starts fast and only contains a minimum amount of necessary classes.</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/process.svg" class="kg-image" alt="process"></figure><p>Heres the new <em>build.gradle</em>, making camunda 7.10 work.</p><pre><code>apply plugin: 'java'

repositories {
	mavenCentral()
}

dependencies {
    compile (group: 'org.camunda.bpm.springboot', name: 'camunda-bpm-spring-boot-starter', version: '3.2.0')
    compile group: 'org.camunda.bpm.springboot', name: 'camunda-bpm-spring-boot-starter-webapp', version: '3.2.0'
    compile group: 'org.camunda.bpm.springboot', name: 'camunda-bpm-spring-boot-starter-rest', version: '3.2.0'

    compile group: 'org.springframework', name: 'spring-tx', version: '5.0.6.RELEASE'
    compile group: 'com.h2database', name: 'h2', version: '1.4.196'
}</code></pre><p>I update this project every time a new major camunda version is released (every 6 months). Since I mostly work with gradle I adapt the given maven pom.</p><p></p><h1 id="check-out-and-run-the-code">check out and run the code</h1><p><a href="https://github.com/stefanfrena/camunda/tree/master/standard-spring-boot">https://github.com/stefanfrena/camunda/tree/master/standard-spring-boot</a><br></p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/process-1.svg" class="kg-image" alt="process"></figure><p>Let me know what you think.</p>]]></content:encoded></item><item><title><![CDATA[Mocking Call Activites on the fly]]></title><description><![CDATA[<p>Remember the times you knew alot about unit testing but would never think of actually seeing your precious models as units? Well, times changed and nowadays I really enjoy the good feeling of knowing that a 100% BPM testcoverage is relatively easy to achieve.</p><p>A very developer friendly way to</p>]]></description><link>https://blog.frena.de/process-unit-testing-mock-call-activity-assert-scenario/</link><guid isPermaLink="false">651abedd279a85000120629f</guid><category><![CDATA[testing]]></category><dc:creator><![CDATA[Stefan Frena]]></dc:creator><pubDate>Fri, 19 Oct 2018 09:00:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1511772232230-4f2c0f036093?ixlib=rb-0.3.5&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=1080&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ&amp;s=cd024f53c1ccf7f392fb3efee79d787a" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1511772232230-4f2c0f036093?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ&s=cd024f53c1ccf7f392fb3efee79d787a" alt="Mocking Call Activites on the fly"><p>Remember the times you knew alot about unit testing but would never think of actually seeing your precious models as units? Well, times changed and nowadays I really enjoy the good feeling of knowing that a 100% BPM testcoverage is relatively easy to achieve.</p><p>A very developer friendly way to create tests for process models is brought to us by <a href="https://github.com/martinschimak">Martin Schimak</a>, with <a href="https://github.com/camunda/camunda-bpm-assert-scenario">camunda bpm assert scenario</a>:</p><p><em>"This community extension to Camunda BPM enables you to write robust test suites for process models. The larger your process models, the more often you change them, the more value you will get out of using it."</em></p><p>Check it out! You wont regret it.</p><p>The idea of a scenario test though is to really create an end-to-end <em>scenario</em> including execution of all sub processes. But sometimes I dont need or want this - so if there is one thing I would add to this project it's the ability to mock call activities. Hence seeing only the main process as <em>unit under test</em>.</p><p>But you can achieve this mocking anyway by simply deploying a mock-process model on the fly, no xml file needed, using  <strong><a href="https://docs.camunda.org/manual/7.9/user-guide/model-api/bpmn-model-api/create-a-model/">Camundas BPMN model (fluent) api</a></strong>. Check this out:</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/callapprovalprocess.svg" class="kg-image" alt="Mocking Call Activites on the fly"></figure><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/callactivitydetails.png" class="kg-image" alt="Mocking Call Activites on the fly"></figure><p><br>Lets pretend this would be our process under test and we are not interested in taking care of the called subprocess. We just want to mock it and its behaviour. All we want is to test, if the main process works.</p><p>We run a testcase like this:</p><pre><code>@Test
public void test_rejection() {
    deployMockedSubProcess("reject");
    Scenario scenario = Scenario.run(process).startByKey("process").execute();
    ProcessEngineAssertions.assertThat(scenario.instance(process)).hasPassed("EndEvent_Rejected");
  }
</code></pre><p>As you can see, before we actually kick off the process, we deploy a lightweight process model <em>on the fly</em> which will produce a mocked outcome. In this case we set the outcome to <em>reject</em>. Note: The id of this mock has to be the same id the main process is loocking for. In our case it is <em>thesubprocess</em>.</p><p>Here is the method:</p><pre><code>private void deployMockedSubProcess(String result) {
    BpmnModelInstance modelInstance = Bpmn.createExecutableProcess() //
        .id("thesubprocess") //
        .startEvent() //
        .serviceTask().camundaResultVariable("result").camundaExpression(result) //
        .endEvent() //
        .done();

    Deployment deployment =
        rule.getProcessEngine().getRepositoryService().createDeployment()
            .addModelInstance("thesubprocess" + ".bpmn", modelInstance).deploy();
   
  }
</code></pre><p>In alot of cases this really suffices and it is a handy way to getting things done if you do not want to go full scenario.</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/rejected.png" class="kg-image" alt="Mocking Call Activites on the fly"></figure><h1 id="check-out-and-run-the-code">check out and run the code</h1><p><a href="https://github.com/stefanfrena/camunda/tree/master/assert-scenario-mock-call-activity">https://github.com/stefanfrena/camunda/tree/master/assert-scenario-mock-call-activity</a></p><p>Let me know what you think and if I can help you to understand this better. This was just a rough nutshell.</p>]]></content:encoded></item><item><title><![CDATA[Camunda 7.9 Spring Boot using Gradle]]></title><description><![CDATA[<p>Sometimes in projects I am faced with questions about process implementation or modeling options I cannot solve right away.</p><p>For this purpose I use a simple easy-to-use spring boot project to explore the possibilites right away. It runs on my localhost, starts fast and only contains a minimum amount of</p>]]></description><link>https://blog.frena.de/camunda-7-9-spring-boot-gradle/</link><guid isPermaLink="false">651abedd279a85000120629e</guid><category><![CDATA[nice-and-handy]]></category><dc:creator><![CDATA[Stefan Frena]]></dc:creator><pubDate>Thu, 07 Jun 2018 09:42:00 GMT</pubDate><content:encoded><![CDATA[<p>Sometimes in projects I am faced with questions about process implementation or modeling options I cannot solve right away.</p><p>For this purpose I use a simple easy-to-use spring boot project to explore the possibilites right away. It runs on my localhost, starts fast and only contains a minimum amount of necessary classes.</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/process.svg" class="kg-image" alt="process"></figure><p>Heres the new <em>build.gradle</em>, making camunda 7.9 work.</p><pre><code>apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'eclipse-wtp'
apply plugin: 'org.springframework.boot'

buildscript {
	ext {
        springBootVersion = '2.0.2.RELEASE'
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}

repositories {
	mavenCentral()
}

dependencies {
	compile (group: 'org.camunda.bpm.springboot', name: 'camunda-bpm-spring-boot-starter', version: '3.0.0'){
		exclude module: 'spring-tx'
	}
	
	compile group: 'org.springframework', name: 'spring-tx', version: '5.0.6.RELEASE'
	
	compile group: 'org.camunda.bpm.springboot', name: 'camunda-bpm-spring-boot-starter-webapp', version: '3.0.0'
	compile group: 'org.camunda.bpm.springboot', name: 'camunda-bpm-spring-boot-starter-rest', version: '3.0.0'
	
	compile group: 'com.h2database', name: 'h2', version: '1.4.196'
}
</code></pre><p>I update this project every time a new major camunda version is released (every 6 months). Since I mostly work with gradle I adapt the given maven pom.</p><p>The adaption is sometimes a bit tricky. This time, the first approach resulted in an exception using plain:<br></p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/plain.png" class="kg-image" alt="plain"></figure><pre><code>org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'persistenceExceptionTranslationPostProcessor' defined in class path resource
[org/springframework/boot/autoconfigure/dao/PersistenceExceptionTranslationAutoConfiguration.class]: Initialization of bean failed; nested exception is java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
Caused by: java.lang.IllegalStateException: No persistence exception translators found in bean factory. Cannot perform exception translation.
</code></pre><p>I fixed it (see <em>build.gradle</em> above) following this hint on <a href="https://github.com/camunda/camunda-bpm-spring-boot-starter/issues/42">github</a>:</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/tx.png" class="kg-image" alt="tx"></figure><h1 id="check-out-and-run-the-code">check out and run the code</h1><p><a href="https://github.com/stefanfrena/camunda/tree/master/standard-spring-boot">https://github.com/stefanfrena/camunda/tree/master/standard-spring-boot</a><br></p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/process-1.svg" class="kg-image" alt="process"></figure><p>Let me know what you think.</p>]]></content:encoded></item><item><title><![CDATA[Speed up tasklists using redundant user task management]]></title><description><![CDATA[<p>During the implementation of tasklists we should always think about runtime behaviour in a production scenario.<br>But lets be honest - first of all backend devs are more interested in data quality than response time (&lt;2 secs). So in every developers life there comes the day he gets a</p>]]></description><link>https://blog.frena.de/speed-up-optimize-camunda-tasklists-redundant/</link><guid isPermaLink="false">651abedd279a85000120629d</guid><category><![CDATA[nutshell]]></category><dc:creator><![CDATA[Stefan Frena]]></dc:creator><pubDate>Tue, 22 May 2018 15:11:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1477466535227-9f581b3eec21?ixlib=rb-0.3.5&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=1080&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ&amp;s=0a3a6650864b02fd78a97cca2f78ec0e" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1477466535227-9f581b3eec21?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ&s=0a3a6650864b02fd78a97cca2f78ec0e" alt="Speed up tasklists using redundant user task management"><p>During the implementation of tasklists we should always think about runtime behaviour in a production scenario.<br>But lets be honest - first of all backend devs are more interested in data quality than response time (&lt;2 secs). So in every developers life there comes the day he gets a <em><strong>speeding ticket</strong></em>.</p><p>The main problem during the retrieval of tasks and coresponding data often is, that user tasks are created and stored in the camunda schema (<em><a href="https://docs.camunda.org/manual/7.5/user-guide/process-engine/database/#tasks-act-ru-task">ACT_RU_TASK</a></em> table) while business data (that has to be presented to the user) is stored in another business-related schema. So you may first</p><ol><li>retrieve a camunda task list</li><li>followed by iterating over this list to get some IDs (customer, account) from the coresponding process variables to</li><li>collect data from your business-related tables (using those IDs) and</li><li>create a business task list using these entities.</li></ol><p>Might take a while right...?<br></p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/wait.svg" class="kg-image" alt="Speed up tasklists using redundant user task management"></figure><p>To solve this dilemma and make things performant <a href="https://docs.camunda.org/manual/7.7/examples/tutorials/custom-queries/">camunda documentation</a> suggests <em><strong>custom queries</strong></em> which is a fine approach if you can manage to have all your data in <em>one</em> place:</p><blockquote>"Precondition: In order to use your own MyBatis (or all types of SQL) queries, your domain data and the process engine data must be stored in the same database. Otherwise you cannot technically construct a single SQL query, which is our goal in terms of performance optimization", <a href="https://docs.camunda.org/manual/7.7/examples/tutorials/custom-queries/#custom-mybatis-queries">[camunda documentation]</a>.</blockquote><p>Unfortunately this was just not possible in a recent customer scenario so we went with a kind of unusual way:</p><h1 id="redundant-user-task-management">Redundant user task management</h1><p><strong>The basic idea</strong> is to have a representation of each and every user task of your engine stored somewhere else in a spezialized table. And this representation contains exactly the information needed by the user.</p><p>Since we could not change the way on <em>how</em> to retrieve data while creating a task we changed the <em>when</em>! Imagine a task list containing 10 tasks and each task needs 1 second to get fully loaded with additional data. It takes 10 secs <em>every time</em> the task list is requested. Instead we now run this "1-second-running code" only once at task creation (before the user even takes notice of its existence) and store a co-responding record to our specialized table.</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/do.svg" class="kg-image" alt="Speed up tasklists using redundant user task management"></figure><p>Requesting a task list now just means to query that specialized table. This sped up things a lot in our application.</p><p>Further thoughts:</p><ol><li>Yes yes yes I know. Holding "same" data in different places and having to keep it in sync is nothing you want to do on a frequent base. There are lots of developers who do not really like this idea. You should maybe just use it for important tasklists that cannot be sped up in other ways.</li><li>The above shown example uses two service tasks for crating and removing a user task. This is just for the purpose of clarification. In our scenario, we worked with listeners at start and end of task creation.  This also has the important effect that you can use the actual <em>taskId</em> when storing and deleting it!</li></ol><p>Let me know what you think and if I can help you to understand this better. This was just a rough nutshell.</p>]]></content:encoded></item><item><title><![CDATA[The Substitute - a holiday replacement approach using camunda candidate groups]]></title><description><![CDATA[<p>In a recent project I was faced by a real classic in user task management. The age old question about how to handle holiday replacement the right way.</p><p>In this post I am going to explain my approach using as much of camunda ready-to-use functionality to avoid overhead.</p><blockquote>Situation: Jack</blockquote>]]></description><link>https://blog.frena.de/holiday-replacement-camunda-candidate-groups/</link><guid isPermaLink="false">651abedd279a85000120629c</guid><category><![CDATA[nutshell]]></category><dc:creator><![CDATA[Stefan Frena]]></dc:creator><pubDate>Thu, 29 Mar 2018 16:43:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1501426026826-31c667bdf23d?ixlib=rb-1.2.1&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=1080&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1501426026826-31c667bdf23d?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ" alt="The Substitute - a holiday replacement approach using camunda candidate groups"><p>In a recent project I was faced by a real classic in user task management. The age old question about how to handle holiday replacement the right way.</p><p>In this post I am going to explain my approach using as much of camunda ready-to-use functionality to avoid overhead.</p><blockquote>Situation: Jack needs holidays and leaves for a week. John, the substitute, jumps in. He now has to deal with all of Jacks existing and newly created tasks.</blockquote><p>A first approach often presented by developers is to postpone user assignment to the very last second before a user task is created. This can be done by some piece of code e.g. asking ldap for help.</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/diagram_1-1.svg" class="kg-image" alt="The Substitute - a holiday replacement approach using camunda candidate groups"></figure><p>But what about tasks already assigned to Jack? How can John get them to show up in his task list? The above mentioned solution does not work here.<br>The solution I was thinking of had to handle the following requirements:</p><p><strong>1.</strong> assign new user tasks to the substitute collegue(s)<br><strong>2.</strong> assign already existing user tasks to the substitute collegue(s)<br><strong>3.</strong> holiday jack still can access all of his tasks (including new ones)<br><strong>4.</strong> do not iterate over every single task and update the assignee</p><p>This is what I did: Instead of filling the assignee field of a user task during process modelling I made use of <a href="https://docs.camunda.org/manual/7.8/reference/bpmn20/tasks/user-task/#candidate-groups">candidate groups</a>. A candidate group contains all the users that have the right to work on a task.</p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/task-2.png" class="kg-image" alt="The Substitute - a holiday replacement approach using camunda candidate groups"></figure><p><br>For simplicity, lets call the <em>candidate group</em> "jacks_tasks". You can create it in camunda cockpit or using camunda's <a href="https://docs.camunda.org/manual/7.8/user-guide/process-engine/identity-service/">identity service</a> at runtime. Create a user Jack and add him to his own candidate group.<br>Something like this (using IdentityService):</p><pre><code>Group jacksGroup = identityService.newGroup("jacks_tasks");
identityService.saveGroup(jacksGroup);

User jack = identityService.newUser("Jack");
identityService.saveUser(jack);

identityService.createMembership(jack, jacksGroup);
</code></pre><p>I used a listener on task creation which ran the code in order to set up group and user straight before assignment.</p><p>To make sure Jack gets his task list filled (while not on holidays) you don't query for him as <em>assignee</em> but <em>task candidate user</em> (even the effort of refactoring this in an existing project isn't that bad):</p><pre><code>List&lt;Task&gt; list = taskService.createTaskQuery().taskCandidateUser("Jack").list();
</code></pre><p><strong>Note</strong>: the user Jack here is just a simple camunda user even without permission to log into camunda task list. Use any (external) user id you prefer and/or need in order to retrieve usertasks.</p><h1 id="now-comes-the-substitution-part">Now comes the substitution part</h1><p>Create (even on the fly) a user <em>John</em>, add him to the candidate group <em>jacks_tasks</em> and John will have access to all of Jacks tasks immediately with this <strong>single configuration step</strong>.</p><pre><code>User john = identityService.newUser("John");
identityService.saveUser(john);
identityService.createMembership(john, jacksGroup);
</code></pre><p>You don't need to iterate over dozens of tasks and update the assignee! Add more users to the group if John needs backup. Jack (member of the group) still can access his tasks. Nice and shiney.</p><p>Further thoughts:</p><ol><li> Yes I know, it is not very likely that Jack just leaves the office without notice. But think about a scenario where he calls in sick... But still, what about a foreseeable absence coming up? For that purpose we built a self-service for Jack and his collegues to configure substitution for a certain timespan. A util process takes care of the rest:  </li><li> To prevent the camunda workflow engine from containing tons of generated users without any task (and hence purpose), you could clean up users and candidate groups in intervals/at process end. Take a look at this: </li></ol><pre><code>//get all users in jacks_tasks
List&lt;User&gt; userList = identityService.createUserQuery().memberOfGroup("jacks_tasks").list();

for (User user : userList) {
  List&lt;Task&gt; list = taskService.createTaskQuery().taskCandidateUser(user.getId()).list();
  //delete user if he has not tasks atm
  if(list.size() == 0){
    identityService.deleteUser(user.getId());
  }
}

List&lt;Task&gt; list = taskService.createTaskQuery().taskCandidateGroup("jacks_tasks").list();
//delete group if it has no tasks atm
if(list.size() == 0){
  identityService.deleteGroup(groupId);
}
</code></pre><h1 id="check-out-and-run-the-code">check out and run the code</h1><p><a href="https://github.com/stefanfrena/camunda/tree/master/holiday-replacement">https://github.com/stefanfrena/camunda/tree/master/holiday-replacement</a><br></p><figure class="kg-card kg-image-card"><img src="https://blog.frena.de/content/images/2018/10/process-2.svg" class="kg-image" alt="The Substitute - a holiday replacement approach using camunda candidate groups"></figure><p>This approach works fine and I think it is a fine base for further requirements in user task management. Let me know what you think and if I can help you to understand this better. This was just a rough nutshell.</p>]]></content:encoded></item><item><title><![CDATA[hello there]]></title><description><![CDATA[<p>Welcome to this blog about our idea(s) of workflow automation and integration. We want to use it to discuss thoughts, patterns, suggestions, nutshells and bombshells. </p>]]></description><link>https://blog.frena.de/hello-there/</link><guid isPermaLink="false">651abedd279a85000120629b</guid><dc:creator><![CDATA[Stefan Frena]]></dc:creator><pubDate>Wed, 28 Mar 2018 09:10:00 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1452421822248-d4c2b47f0c81?ixlib=rb-1.2.1&amp;q=80&amp;fm=jpg&amp;crop=entropy&amp;cs=tinysrgb&amp;w=1080&amp;fit=max&amp;ixid=eyJhcHBfaWQiOjExNzczfQ" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1452421822248-d4c2b47f0c81?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&w=1080&fit=max&ixid=eyJhcHBfaWQiOjExNzczfQ" alt="hello there"><p>Welcome to this blog about our idea(s) of workflow automation and integration. We want to use it to discuss thoughts, patterns, suggestions, nutshells and bombshells. </p>]]></content:encoded></item></channel></rss>