AnsweredAssumed Answered

formProperty with default value saved to the database even though writable='false'

Question asked by alexg on Oct 23, 2013
Latest reply on Oct 26, 2013 by alexg
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?

Outcomes