Workflow scripts
Concept
Een script is een stuk code dat complexer is dan een expressie. Scripts bieden het voordeel dat ze logica kunnen bevatten zoals loops, conditionele statements, validatieregels en functies. Ze worden gebruikt om meer geavanceerde bewerkingen uit te voeren die niet mogelijk zijn met eenvoudige workflow expressies.
Aan workflow scripts kleven ook een aantal nadelen:
De uitvoering van het script gebeurt volledig binnen de scope van het proces en dus ook synchroon met het proces. Er is dus geen mogelijkheid tot ontkoppeling.
Je brengt (gevoelige) dossierdata binnen in je proces, waardoor je dit proces na afloop ook weer moet gaan anonymiseren.
Workflow scripts zitten verwerkt in je BPMN-beschrijving en zijn daardoor erg moeilijk te onderhouden.
Van zodra je het gevoel hebt dat bovenstaande nadelen beginnen op te spelen, kun je maar beter gebruik maken van extensies.
Script opstellen
Scripts kunnen geschreven worden in JavaScript.
Tip: gebruik een AI-assistent om scripts op te bouwen.
Opgelet: vanaf platform versie 24.0.X maken we gebruik van de GraalJS engine. Voorheen was dat de Nashorn engine. Zie deze release note. Wie toch nog gebruik wil maken van de Nashorn engine kan dit instellen binnen de applicatie eigenschappen.
Script integreren in de workflow
Een script integreren in de workflow kan op verschillende manieren. Hieronder enkele voor de hand liggende werkwijzes.
Via een script task.
Bij het definiëren van een inputparameter voor een taak.
Via een listener op eender welk BPMN-element.
Telkens moet je het type script (bijvoorbeeld JavaScript) als verplichte parameter meegeven. Indien niet, wordt het script als string gezien en dus niet uitgevoerd.
Script voorbeelden
Vierkantswortel berekenen
Eenvoudig JavaScript script dat een getal (bv. 81) neemt en de vierkantswortel (bv. 9) teruggeeft.
// Procesvariabele 'getal' ophalen en toewijzen aan script variabele 'number'
var number = execution.getVariable("test");
// Vierkantswortel nemen en resultaat toewijzen aan script variabele 'sqrtValue'
var sqrtValue = Math.sqrt(number);
// Script variabele 'sqrtValue' wegschrijven naar procesvariabele 'vierkantsWortel'
execution.setVariable("vierkantsWortel", sqrtValue);
Omgaan met lijsten, maps en lijst-maps
Via workflow expressies zijn de mogelijkheden hier erg beperkt. Vandaar dat JavaScript scripts de betere manier zijn om deze complexere structuren te manipuleren binnen de context van de workflow.
Extra eigenschap toevoegen aan alle entries in een lijst-map
Een lijst-map die je opbouwt binnen de context van een formulier kan je als variabele vrijgeven in het proces, en daar via een script gaan bewerken. Hier willen we voor elke entry een extra eigenschap toevoegen (extraKey en extraValue).
// Procesvariabele 'mijnFormulierLijst' ophalen en toewijzen aan variabele 'myList'
var myList = execution.getVariable("mijnFormulierLijst");
// Nieuwe lijst aanmaken
var newList = new java.util.ArrayList(); // Initialize a new ArrayList
// Iteraten over de originele lijst
for (var i = 0; i < myList.size(); i++) {
var item = myList.get(i); // Elke map in de oorspronkelijke lijst ophalen
// Kopie maken van de huidig opgehaalde map
var newItem = new java.util.LinkedHashMap(item); // Kopie maken
// Nieuwe entry (key-value) toevoegen aan de gekopieerde map
newItem.put("extraKey", "extraValue");
// Gekopieerde en gemanipuleerde map toevoegen aan de nieuwe lijst
newList.add(newItem);
}
// Nieuwe lijst wegschrijven naar procesvariabele 'mijnNieuweFormulierLijst'
execution.setVariable("mijnNieuweFormulierLijst", newList);
Itereren over entries in een lijst-map
Een lijst-map die je opbouwt binnen de context van een formulier kan je als variabele vrijgeven in het proces, en daar via een script gaan bewerken. Hier willen we itereren over elke entry en bijvoorbeeld het gemiddelde nemen van de getalwaarde binnen het specifieke key-value pair “leeftijd”.
// Haal de inputlijst op
var lijst = execution.getVariable("personenLijst");
var totaalLeeftijd = 0;
var aantal = lijst.size();
// Itereer over elke persoon in de lijst
for (var i = 0; i < aantal; i++) {
var persoon = lijst.get(i);
totaalLeeftijd += persoon.get("leeftijd");
}
// Bereken het gemiddelde
var gemiddelde = aantal > 0 ? totaalLeeftijd / aantal : 0;
// Sla het resultaat op als procesvariabele
execution.setVariable("gemiddeldeLeeftijd", gemiddelde);
Twee lijsten samenvoegen en sorteren
Twee lijsten opgebouwd binnen de context van het proces, kan je via een script gaan manipuleren. Je kan ze bijvoorbeeld gaan samenvoegen tot een nieuwe lijst.
// Originele lijsten ophalen
var lijst1 = execution.getVariable("lijst1");
var lijst2 = execution.getVariable("lijst2");
// Nieuwe lege lijst aanmaken
var samengevoegd = new java.util.ArrayList();
// Inhoud kopiëren (niet verwijzen naar de originele)
samengevoegd.addAll(lijst1);
samengevoegd.addAll(lijst2);
// Lijst sorteren van A naar Z (natuurlijke volgorde)
java.util.Collections.sort(samengevoegd);
// Resultaat opslaan in een nieuwe procesvariabele
execution.setVariable("samengevoegdeLijstGesorteerd", samengevoegd);
Twee lijst-maps samenvoegen, sorteren, totaal berekenen, validatie op totaal
Een lijst-map die je opbouwt binnen de context van een formulier kan je als variabele vrijgeven in het proces, en daar via een script gaan bewerken. Hier voegen we twee lijst-maps samen tot één nieuwe lijst-map, sorteren we alfabetisch op de eigenschap “naam”, berekenen we het totaal van waardes onder de eigenschap “subsidiebedrag” en stellen we een validatieregel in die zegt dat het totaal niet hoger mag zijn dan 5000. Indien hoger dan 5000, creëren we een BPMN-error die je vervolgens kan opvangen via een error event in de workflow.
// Haal de twee lijst-maps op
var lijst1 = execution.getVariable("mijnLijstMap1");
var lijst2 = execution.getVariable("mijnLijstMap2");
// Maak een nieuwe lijst aan (kopie, geen verwijzing)
var gecombineerdeLijst = new java.util.ArrayList();
gecombineerdeLijst.addAll(lijst1);
gecombineerdeLijst.addAll(lijst2);
// Initialiseer totaalbedrag
var totaal = 0;
// Itereer en tel subsidiebedragen op
for (var i = 0; i < gecombineerdeLijst.size(); i++) {
var item = gecombineerdeLijst.get(i);
if (item.containsKey("subsidiebedrag")) {
totaal += item.get("subsidiebedrag");
}
}
// Validatie: totaal mag niet hoger zijn dan 5000
if (totaal > 5000) {
throw new org.camunda.bpm.engine.delegate.BpmnError("TE_HOOG_SUBSIDIEBEDRAG", "Totaal subsidiebedrag overschrijdt de limiet van 5000 euro.");
}
// Sortering op naam (A > Z)
java.util.Collections.sort(gecombineerdeLijst, new java.util.Comparator({
compare: function(a, b) {
return a.get("naam").compareToIgnoreCase(b.get("naam"));
}
}));
// Zet resultaten als procesvariabelen
execution.setVariable("gecombineerdeLijstGesorteerd", gecombineerdeLijst);
execution.setVariable("totaalSubsidiebedrag", totaal);