diff --git a/source/java/org/alfresco/repo/workflow/activiti/AlfrescoProcessEngineConfiguration.java b/source/java/org/alfresco/repo/workflow/activiti/AlfrescoProcessEngineConfiguration.java index f492456f28..36691fca68 100644 --- a/source/java/org/alfresco/repo/workflow/activiti/AlfrescoProcessEngineConfiguration.java +++ b/source/java/org/alfresco/repo/workflow/activiti/AlfrescoProcessEngineConfiguration.java @@ -29,6 +29,7 @@ import org.activiti.engine.impl.variable.SerializableType; import org.activiti.engine.impl.variable.VariableType; import org.activiti.spring.SpringProcessEngineConfiguration; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; +import org.alfresco.repo.workflow.activiti.variable.CustomStringVariableType; import org.alfresco.service.cmr.repository.NodeService; /** @@ -61,6 +62,11 @@ public class AlfrescoProcessEngineConfiguration extends SpringProcessEngineConfi variableTypes.addType(type, serializableIndex); } } + + // WOR-171: Replace string type by custom one to handle large text-values + int stringIndex = variableTypes.getTypeIndex("string"); + variableTypes.removeType(variableTypes.getVariableType("string")); + variableTypes.addType(new CustomStringVariableType(), stringIndex); } @Override diff --git a/source/java/org/alfresco/repo/workflow/activiti/variable/CustomStringVariableType.java b/source/java/org/alfresco/repo/workflow/activiti/variable/CustomStringVariableType.java new file mode 100644 index 0000000000..4b25155992 --- /dev/null +++ b/source/java/org/alfresco/repo/workflow/activiti/variable/CustomStringVariableType.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2005-2011 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.workflow.activiti.variable; + +import org.activiti.engine.impl.persistence.entity.ByteArrayEntity; +import org.activiti.engine.impl.variable.StringType; +import org.activiti.engine.impl.variable.ValueFields; + +/** + * Custom implementation of the Activiti {@link StringType}, which allows string-values + * to be larger than the database-restriction of the TEXT_ column, by using binary storage in case + * the string value exceeds the size. + * + * @author Frederik Heremans + * @since 4.2 + */ +public class CustomStringVariableType extends StringType { + protected static final int MAX_TEXT_LENGTH = 4000; + + @Override + public void setValue(Object value, ValueFields valueFields) + { + if(value != null && ((String) value).length() > MAX_TEXT_LENGTH) + { + ByteArrayEntity byteArray = valueFields.getByteArrayValue(); + byte[] bytes = ((String) value).getBytes(); + if (byteArray==null) + { + valueFields.setByteArrayValue(bytes); + } + else + { + // Reuse the existing byte-array entity on an update instead of creating a new one each time + byteArray.setBytes(bytes); + } + } + else { + // Make sure NO byte-array is present anymore in case this variable exceeded the + // length before this update, but is shorter now + valueFields.setByteArrayValue(null); + + // Revert to storing regular string + super.setValue(value, valueFields); + } + } + + @Override + public Object getValue(ValueFields valueFields) + { + // In case the string is stored as a byte-array, create a string from the stored bytes + // using platform encoding and return this instead of the text-value + if(valueFields.getByteArrayValueId() != null && valueFields.getByteArrayValue() != null) { + return new String(valueFields.getByteArrayValue().getBytes()); + } + return super.getValue(valueFields); + } +} diff --git a/source/test-java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java b/source/test-java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java index 23d8ae0bcf..582ac8bd25 100644 --- a/source/test-java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java +++ b/source/test-java/org/alfresco/repo/workflow/activiti/ActivitiWorkflowServiceIntegrationTest.java @@ -250,6 +250,46 @@ public class ActivitiWorkflowServiceIntegrationTest extends AbstractWorkflowServ assertEquals("This is the description", tasks.get(0).getDescription()); } + /** + * Test to validate fix for WOR-107 + */ + public void testLongTextValues() throws Exception + { + String veryLongTextValue = getLongString(10000); + // start pooled review and approve workflow + WorkflowDefinition workflowDef = deployDefinition(getAdhocDefinitionPath()); + assertNotNull(workflowDef); + + // Create workflow parameters + Map params = new HashMap(); + Serializable wfPackage = workflowService.createPackage(null); + params.put(WorkflowModel.ASSOC_PACKAGE, wfPackage); + Date dueDate = new Date(); + params.put(WorkflowModel.PROP_WORKFLOW_DUE_DATE, dueDate); + params.put(WorkflowModel.PROP_WORKFLOW_PRIORITY, 1); + params.put(WorkflowModel.PROP_COMMENT, veryLongTextValue); + + NodeRef assignee = personManager.get(USER2); + params.put(WorkflowModel.ASSOC_ASSIGNEE, assignee); + + // No exception should be thrown when using *very* long String variables (in this case, 10000) + WorkflowPath path = workflowService.startWorkflow(workflowDef.getId(), params); + assertNotNull(path); + + WorkflowTask startTask = workflowService.getStartTask(path.getInstance().getId()); + assertNotNull(startTask); + + assertEquals(veryLongTextValue, startTask.getProperties().get(WorkflowModel.PROP_COMMENT)); + } + + protected String getLongString(int numberOfCharacters) { + StringBuffer stringBuffer = new StringBuffer(); + for(int i=0; i