Hi all,In my bpmn file I have a "status" formProperty declared as follows:
<userTask id="handleRequest" name="Handle request">
<extensionElements>
<activiti:formProperty id="requestApproved"
name="Do you approve this request" type="enum" required="true">
<activiti:value id="true" name="Approve" />
<activiti:value id="false" name="Reject" />
</activiti:formProperty>
<activiti:formProperty id="status" name="Status"
type="string" default="ACTIVE" readable="true" writable="false" />
</extensionElements>
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>approver</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
The call to formProperty.getValue() for "status" returns "ACTIVE" as expected:
final FormProperty formProperty = formService.getTaskFormData(task.getId()).getFormProperties().get(1);
final String value = formProperty.getValue();
assertEquals("ACTIVE", value);
But when I submit form data, the "status" variable gets created in the database and can be found in ACT_RU_VARIABLE table despite the writable="false" declaration:
formService.submitTaskFormData(task.getId(), Collections.singletonMap("requestApproved", (Object) "true"));
Documentation states that the property does not get submitted when declared non-writable, which means you would not expect it to be saved to the database. After all, there is an explicit check in the beginning of org.activiti.engine.impl.form.FormPropertyHandler.submitFormProperty() method:
if (!isWritable && properties.containsKey(id)) {
throw new ActivitiException("form property '"+id+"' is not writable");
}
To my mind, the problem is that this method does not check isWritable flag before storing the variable to the database:
if (propertyExits || (modelValue != null)) {
if (variableName != null) {
execution.setVariable(variableName, modelValue);
} else if (variableExpression != null) {
variableExpression.setValue(modelValue, execution);
} else {
execution.setVariable(id, modelValue);
}
}
It seems like isWritable should be checked in the final else, so you would have the following instead of the code above:
if (propertyExits || (modelValue != null)) {
if (variableName != null) {
execution.setVariable(variableName, modelValue);
} else if (variableExpression != null) {
variableExpression.setValue(modelValue, execution);
} else if (isWritable) {
execution.setVariable(id, modelValue);
}
}
So is it a bug, or am I missing something?