Skip to main content

Java Methods for priint:bpm (Camunda)

1. Introduction

Java methods can be used to facilitate the workflow created inside Camunda. This article tries to deliver a comprehensive guide to writing and using.

There are two possible kinds of methods, both being a Pubserver plugin class with full access to Planner API and using specific Pubserver methods:

1. User Input Form Method - used when the user interacts with the process via form. They can be used for Start Events and User Tasks and are analogic to priint:ui kit classes for dynamic UI. 2. Automation Method - executed via workers by the Camunda server. They can be used for Service Tasks to execute specific methods on Documents, Folders and Publications. Automation Methods are analogic to previous workflow methods. This kind of method does not have any access to renderer.

2. User Input Form

Camunda processes can communicate with users through user tasks.

To define the look of the user task one can use standard BPMN form or use special java method to generate more complex and dynamic UI. There is another use case for it, starting point of the process. Before process starts the window can be raised to enter starting values. This also can be handled by the java method. This point describes how to implement such methods.

a) getMethodName - used to provide the name of the method. It can then be chosen in the modeler inside Neowise. To choose the right method it is necessary to go to the Dynamic Form tab of the User Task and choose Plugin mapped name from the Dynamic Form Type combo-box.

The declaration of the method is as follows:

@PubServerMethod(label = "name", type = PluginMethod.MethodType.GENERIC, description = "plugin method called to obtain a translation of plugin label")
public String getMethodName(
@PubServerMethodParameter(name = "lang", defaultValue =EN, listOfValues = {}) final String lang)

Example code:

@PubServerMethod(label="name", type=PluginMethod.MethodType.GENERIC,	
description="plugin method called to obtain a translation of plugin name")
public String getMethodName(@PubServerMethodParameter(name="lang", defaultValue=EN, listOfValues={}) final String lang) {
if (nameTranslations.containsKey(lang)) {
return nameTranslations.get(lang);
} else {
return nameTranslations.get(EN);
}
}

b) getParameters - it called when the user input form is opened in start process dialog or in the user task detail panel. It is most commonly used to pass input parameters to server tasks e.g. when the user needs to choose which method should be executed next.


@PubServerMethod(label = "parameters", type = PluginMethod.MethodType.BPM_INPUT_FORM_METHOD, description = "plugin method called to obtain a list of parameters needed in gui")
public List<GuiParameter> getParameters(
@PubServerMethodParameter(name = "params") final Map<String, Object> params)

Please note the method type should be set PluginMethod.MethodType.BPM_INPUT_FORM_METHOD

The method returns list of_GuiParameter_objects. Each element of the list represents one GUI component shown in dialog. The components are rendered from the top to the bottom, in order as they are in the list. The_GuiParameter_object can represent the following GUI components:

  • TextField
  • ComboBox
  • CheckBox
  • TextArea
  • UplodButton - This type allows to upload a file to the predefined path which can be set in the Camunda Server Property "uploadRootPath". Then it is possible to process the uploaded file in the exec method of the plugin. Important recommendation! The exec method should remove the file after processing it.

Example code:

@PubServerMethod(label = "Choose action and template (Form)", type = PluginMethod.MethodType.BPM_INPUT_FORM_METHOD,
description = "plugin method called to obtain a list of parameters needed in gui")
public List getParameters(@PubServerMethodParameter(name = "input") final Map<String, Object> input) {
List output = new ArrayList<>();
List errorValues = new ArrayList<>();
errorValues.add(new GuiParameterComboBoxItem("Business error 1", "1"));
errorValues.add(new GuiParameterComboBoxItem("Business error 2", "2"));
errorValues.add(new GuiParameterComboBoxItem("Success", "3"));

String action = (String) input.get("businessErrorValue"); // if there is a value for this variable we need to set it as value in the GuiParameter

output.add(GuiParameter.getComboBox("businessErrorValue", "businessErrorValue", action, errorValues, true));

return output;
}

For more details on creating UI elements please consult this article.

c) updateParameters - this method is called if a GuiParameter has canChangeUI set to true and the user changed the value of that parameter. It is used to recalculate the values and adjust the dialog UI to the new parameter value.

Sometimes, it is necessary to show additional UI elements or change existing elements based on the values inside the plugin e.g. different text fields should be displayed based on the value chosen inside a combo-box. To use such a functionality in your plugin, a special updateParameters method should be implemented:

@PubServerMethod(label="parameters",
type=PluginMethod.MethodType.GENERIC,
description="plugin method called to update a list of parameters needed in gui")
List<GuiParameter> updateParameters(Map<String, Object> params)

The first step to create a dynamic UI in your plugin is to pass canChangeGUI parameter to your created element inside the getParameters method. In the below example checkbox element will be able to change the UI of the plugin:

@PubServerMethod(label = "parameters",
type = PluginMethod.MethodType.GENERIC,
description = "plugin method called to obtain a list of parameters needed in the UI")
public List<GuiParameter> getParameters(@PubServerMethodParameter(name = "params") final Map<String, Object> params) {
List<GuiParameter> parameters = new ArrayList<>();
boolean valueType = true;
if(params.get("exampleCheckbox") != null){
valueType = Boolean.parseBoolean(params.get("exampleCheckbox").toString());
}
// please note the last parameter (canChangeGUI) in the getCheckBox method is set to true.
// It lets the plugin know that this UI element will make changes to the existing UI.
GuiParameter checkBox = GuiParameter.getCheckBox("Example checkbox", "exampleCheckbox", valueType,true);
parameters.add(checkBox);
return parameters;
}

The parameter params contains the values returned in the getParameters method. The returned List<GuiParameter>contains all the elements you want to display after the UI is changed i.e. you will need to copy the existing elements if you want them to be visible after the UI is changed. The below example displays a text field only if the checkbox unchecked :

@PubServerMethod(label="parameters",
type=PluginMethod.MethodType.GENERIC,description="plugin method called to obtain a list of parameters needed in the UI")
public List<GuiParameter> updateParameters(@PubServerMethodParameter(name="params") final Map<String,Object> params) {
boolean valueType = true;
if(params.get("exampleCheckbox") != null){
valueType = Boolean.parseBoolean(params.get("exampleCheckbox").toString());
}
if (!valueType) {
parameters.add(GuiParameter.getTextField("Example additional UI element", "exampleAdditionalUIElement", ""));
return parameters;
}
return parameters;
}

For more details please consult this article.

!IMPORTANT! updateParameters method is obligatory for all plugins to be used inside Neowise.

If your panel does not change you should still implement the updateParameters method, e.g.:

@PubServerMethod(label="parameters",
type=PluginMethod.MethodType.GENERIC,
description="plugin method called to obtain a list of parameters needed in gui")
public List<GuiParameter> updateParameters(@PubServerMethodParameter(name="params") final Map<String,Object> params) {
return getParameters(params);
}

3. Automation Methods

This type of methods is called by the Service Tasks in order to automate the process of publishing. The needed method can be chosen inside the modeler inside Neowise. It is available in the Definition tab of the Service Task. []

The plugin class has to implement the following methods: a) getMethodName - used to provide the name of the Plugin to Camunda. The implementation is the same as for the User Input Form.

b) getParameters - used to provide parameters to the Service Task in the process modeler inside Neowise. Hence it is important for the plugin class to implement the following methods: The implementation is similar as for the User Input Form, but the type should be set to PluginMethod.MethodType. GENERIC. Example code:

@PubServerMethod(label = "getParameters", type = PluginMethod.MethodType.GENERIC,
description = "plugin method called to obtain the list of parameters")
public List getParameters(@PubServerMethodParameter(name = "input") final Map<String, Object> input) {

LOGGER.trace("DemoReportService.getParameters started.");

String reportPath = (String) input.get(REPORT_PATH_KEY); // if there is a value for this variable we need to set it as value in the GuiParameter
if (reportPath==null) reportPath ="C:\\Pubserver\\userdata\\temp\\report.txt"; // we use a default value, if no value is yet set.

List output = new ArrayList<>();
output.add(GuiParameter.getTextField("Report path", REPORT_PATH_KEY, reportPath));

return output;
}

c) updateParameters - as in the User Input Form, this method is called if a GuiParameter has canChangeUI set to true and the user changed the value of that parameter. It is used to recalculate the values and adjust the dialog UI to the new parameter value. The implementation is the same as for the User Input Form.

d) exec - this method is called when the service task is executed in a process instance. It gets all current process instance variables and can add new or modify existing process instance variables via its return object. Please note this method should have one of the following types depending on the needs:

  • BPMN_DOCUMENT_PROCESS_METHOD
  • BPMN_FOLDER_PROCESS_METHOD
  • BPMN_PUBLICATION_PROCESS_METHOD
  • BPMN_DOCUMENT_DOWNLOAD_METHOD
  • BPMN_PUBLICATION_DOWNLOAD_METHOD

Example code:

@PubServerMethod(label = "DemoReportServiceTask", type = PluginMethod.MethodType.BPM_DOCUMENT_PROCESS_METHOD,
description = "Service task creating a report file in path given in parameter key=reportPath")
public Map<String,Object> exec(@PubServerMethodParameter(name = "parameters") final Map<String, Object> parameters) {

LOGGER.trace("DemoReportService.exec started.");

parameters.forEach((s, o) -> LOGGER.info("DemoReportService.exec: parameters key "+s+" value:"+o));

String reportPath = (String) parameters.get(REPORT_PATH_KEY);

try {
FileWriter writer = new FileWriter(reportPath, true);
writer.write("Demo Report of all Parameters");
writer.write("\r\n"); // write new line

parameters.forEach((s, o) -> {
try {
writer.write("key:"+s+"\tvalue:"+o);
writer.write("\r\n"); // write new line
} catch (IOException e) {
e.printStackTrace();
}
});

writer.close();
} catch (IOException e) {
e.printStackTrace();
}

return new HashMap<String,Object>();
}

3.1 Error Handling

There are two possible ways of handling errors inside the process. It can be done either by variable value or by runtime exception. a) Variable value By using this error handling, it is possible to set the expression inside the modeler. [] Example code:

Map<String,Object> outParameters = new HashMap<>();
outParameters.put("methodMessage", methodMessage);
outParameters.put("methodResultCode", methodResultCode);

return outParameters;

b) Runtime exception - it can be thrown inside the code of the plugin. Example code:

throw new RuntimeException("Service task running into a runtime exception for demonstration");