But what if you want to use JSON Variables without mapping to Java objects? With the next alpha release we will introduce a new ValueType “json” (and “xml” but that is an other story).
In this post I demonstrate how you can use the JSON value type to
- implement HTML Forms which work with a JSON Variable,
- implement BPMN Sequence Flow conditions based on the properties of the JSON Variable.
Example Process
Create a JSON variable in a start form
<form role="form" class="form-horizontal">
<script cam-script type="text/form-script">
var customer = $scope.customer = {};
camForm.on('form-loaded', function () {
// declare a 'json' variable 'customer'
camForm.variableManager.createVariable({
name: 'customer',
type: 'json',
value: customer
});
});
</script>
<div class="control-group">
<label class="control-label" for="firstName">First Name</label>
<div class="controls">
<input id="firstName" class="form-control"
type="text" ng-model="customer.firstName" required />
</div>
</div>
<!-- Additional fields omitted -->
</form>
The custom java script creates a new object and binds it to the angular $scope
of the form as a variable named customer
. Then a new process variable named customer
will be created when the form has been loaded successfully. The type of the process variable is set to json
, so that the variable will be persisted simply as JSON without the need to deserialize it to a custom Java object.
The form itself is a plain angular form (see ng-model
binding of input field).
Accessing an existing JSON variable in a task form
<form role="form" class="form-horizontal">
<script cam-script type="text/form-script">
camForm.on('form-loaded', function () {
// tell the form SDK to fetch the json variable name 'customer'
camFom.variableManager.fetchVariable('customer');
});
camForm.on('variable-fetched', function () {
// work with the variable (bind it to current angular $scope)
$scope.customer = camForm.variableManager.variableValue('customer');
});
</script>
<div class="control-group">
<label class="control-label" for="firstName">First Name</label>
<div class="controls">
<input id="firstName" class="form-control"
type="text" ng-model="customer.firstName" required />
</div>
</div>
<!-- Additional fields omitted -->
</form>
Accessing an existing JSON variable in an expressions
In the past you could already store JSON as variable values. However, you needed to store it as a String variable. The problem with that is that in a sequence flow you cannot easily write EL Expressions using the properties of the JSON if it is stored as a String.
In Camunda 7.2 we introduced Spin and it became possible to pare the String within El and use the Spin API for formulating conditions:
${ JSON(customer).prop("age").numberValue() >= 21}
While this was a huge improvement the problem is that if you need to interpret the same variable as JSON multiple times within a command, it needs to be parsed multiple times (among other downsides).
Now that we introduce JSON variables as native ValueTypes, you can directly access the properties of a JSON variable in conditions:
<sequenceFlow id="SequenceFlow_4" name="age above 21"
sourceRef="ExclusiveGateway_1" targetRef="UserTask_2">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[
${ customer.prop("age").numberValue() >= 21 }
]]>
</conditionExpression>
</sequenceFlow>
<sequenceFlow id="SequenceFlow_5" name="age under 21"
sourceRef="ExclusiveGateway_1" targetRef="UserTask_3">
<conditionExpression xsi:type="tFormalExpression">
<![CDATA[
${ customer.prop("age").numberValue() < 21 }
]]>
</conditionExpression>
</sequenceFlow>
The example resources can be found in GitHub.