cancel
Showing results for 
Search instead for 
Did you mean: 

HistoricFormProperty don't store the transformed value by the FormType

mikedias
Champ in-the-making
Champ in-the-making
Hi,

Sometimes we need to store big variables in a process instance. Knowing that
ACT_RU_VARIABLE.TEXT_
is a VARCHAR(4000), we create a BinaryFormType to store the big string as a byte array. But, when history level is AUDIT, the engine tries to insert the unprocessed big value at
ACT_HI_DETAIL.TEXT_
, causing a <b>Value too long for column "TEXT_ VARCHAR(4000)"</b>.

Here is a test case that demonstrate the issue:

BPMN 2.0 file:

<?xml version='1.0' encoding='UTF-8'?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
  <process id="binaryProcess" name="Binary Process" isExecutable="true">
    <startEvent id="sid-F9F0F672-8C03-4E1A-B5C0-C169B016E612">
      <extensionElements>
         <activiti:formProperty id="binaryProperty" name="binaryProperty" type="binary" />
      </extensionElements>
    </startEvent>
    <sequenceFlow id="sid-71C72183-6D1B-420B-96AB-476F10D7E905" sourceRef="sid-F9F0F672-8C03-4E1A-B5C0-C169B016E612" targetRef="sid-7CD47B08-8638-4A81-BC0C-89C2AC065684" />
    <userTask id="sid-7CD47B08-8638-4A81-BC0C-89C2AC065684" name="Binary Task">
      <extensionElements>
        <activiti:formProperty id="binaryProperty" name="binaryProperty" type="binary" />
      </extensionElements>
    </userTask>
    <sequenceFlow id="sid-56169958-5967-437D-8D1B-CFE42CDBDC5C" sourceRef="sid-7CD47B08-8638-4A81-BC0C-89C2AC065684" targetRef="sid-B3FF1567-3EC4-4053-BEF2-AC11883F0497" />
    <endEvent id="sid-B3FF1567-3EC4-4053-BEF2-AC11883F0497" />
  </process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_binaryProcess">
    <bpmndi:BPMNPlane bpmnElement="binaryProcess" id="BPMNPlane_binaryProcess">
      <bpmndi:BPMNShape bpmnElement="sid-F9F0F672-8C03-4E1A-B5C0-C169B016E612" id="BPMNShape_sid-F9F0F672-8C03-4E1A-B5C0-C169B016E612">
        <omgdc:Bounds height="30.0" width="30.0" x="112.0" y="142.0" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-7CD47B08-8638-4A81-BC0C-89C2AC065684" id="BPMNShape_sid-7CD47B08-8638-4A81-BC0C-89C2AC065684">
        <omgdc:Bounds height="80.0" width="100.0" x="187.0" y="117.0" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape bpmnElement="sid-B3FF1567-3EC4-4053-BEF2-AC11883F0497" id="BPMNShape_sid-B3FF1567-3EC4-4053-BEF2-AC11883F0497">
        <omgdc:Bounds height="28.0" width="28.0" x="332.0" y="143.0" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge bpmnElement="sid-56169958-5967-437D-8D1B-CFE42CDBDC5C" id="BPMNEdge_sid-56169958-5967-437D-8D1B-CFE42CDBDC5C">
        <omgdi:waypoint x="287.0" y="157.0" />
        <omgdi:waypoint x="332.0" y="157.0" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge bpmnElement="sid-71C72183-6D1B-420B-96AB-476F10D7E905" id="BPMNEdge_sid-71C72183-6D1B-420B-96AB-476F10D7E905">
        <omgdi:waypoint x="142.0" y="157.0" />
        <omgdi:waypoint x="187.0" y="157.0" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</definitions>

Test case:
[java]
package org.activiti.engine.test.history;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.form.AbstractFormType;
import org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration;
import org.activiti.engine.impl.history.HistoryLevel;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Task;
import org.junit.Test;

public class HistoricFormPropertyTest {
 
  public static final String BPMN_FILE_PATH = "org/activiti/engine/test/history/HistoricFormPropertyTest.binaryProperty.bpmn20.xml";
 
  public class BinaryFormType extends AbstractFormType {

    public String getName() {
      return "binary";
    }

    public Object convertFormValueToModelValue(String propertyValue) {
      return propertyValue.getBytes();
    }

    public String convertModelValueToFormValue(Object modelValue) {
      return new String((byte[])modelValue);
    }
   
  }
 
  public ProcessEngine buildProcessEngine(String historyLevel) {
    List<AbstractFormType> customFormTypes = new ArrayList<AbstractFormType>();
    customFormTypes.add(new BinaryFormType());
   
    StandaloneInMemProcessEngineConfiguration pec = new StandaloneInMemProcessEngineConfiguration();
    pec.setCustomFormTypes(customFormTypes);
    pec.setHistory(historyLevel);
    return pec.buildProcessEngine();
  }
 
  @Test
  public void testBigStringFormData() {
    //ProcessEngine pe = buildProcessEngine(HistoryLevel.NONE.getKey()); // works
    ProcessEngine pe = buildProcessEngine(HistoryLevel.AUDIT.getKey()); // fail
   
    Deployment d = pe.getRepositoryService().createDeployment().addClasspathResource(BPMN_FILE_PATH).deploy();
    ProcessDefinition pd = pe.getRepositoryService().createProcessDefinitionQuery().deploymentId(d.getId()).singleResult();
   
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 10000; i++) {
      sb.append("big String… ");
    }
   
    Map<String, String> properties = new HashMap<String, String>();
    properties.put("binaryProperty", sb.toString());
   
    pe.getFormService().submitStartFormData(pd.getId(), properties);
   
    Task t = pe.getTaskService().createTaskQuery().singleResult();
   
    pe.getFormService().submitTaskFormData(t.getId(), properties);
   
  }
 
}
[/java]

My suggestion to solve this is:
  • Change the
    HistoricFormProperty
    to receive a Object instead of String;
  •  
  • Change the
    FormPropertyHandler.submitFormProperty
    to return the transformed value;
  •  
  • Change the
    SubmitTaskFormCmd
    and
    SubmitStartFormCmd
    to report form properties after form handler transformation.
What do you think? Can I do this fix or there are a better solution?
2 REPLIES 2

pmsevestre
Champ in-the-making
Champ in-the-making
If you use a  recent version of MSSQL or MSDE, you can redefine those columns to a VARCHAR(MAX) type. For small sizes it will behave just like an ordinary varchar(), but large values will be handled as TEXT columns.

More information in the following link:

http://social.msdn.microsoft.com/Forums/sqlserver/en-US/4d9c6504-496e-45ba-a7a3-ed5bed731fcc/varchar...

I've used this approach with activiti 5.12.1 and could not find any side effects. Even search by variable value continues to work (SQL SERVER 2008 R2)

mikedias
Champ in-the-making
Champ in-the-making
Hi pmsevestre, thanks for the answer!

We are using the same approach to save attachments as process instance variable, so we really want to store the value as a byte array. Moreover, we want to use the HistoricFormProperty to keep a record of what was submitted in completed tasks.

But is good to know about this feature. Can be useful in another use case.
Getting started

Tags


Find what you came for

We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.