Activiti custom process parameters and node parameters (generated by JAVA code)

Project address: activiti-workflow
sometimes needs to save some business data in the process. Activiti itself already supports user-defined parameters, and the entire process and user nodes are supported.

Set custom process parameters

The parameters of the entire process are in the Process object. By looking at the Process method, you can see that there is a setAttributes method

 public void setAttributes(Map<String, List<ExtensionAttribute>> attributes) {
    
    
        this.attributes = attributes;
    }

Look at the ExtensionAttribute object, there are these attributes

public class ExtensionAttribute {
    
    
    protected String name;
    protected String value;
    protected String namespacePrefix;
    protected String namespace;

    public ExtensionAttribute() {
    
    
    }
}

Talk about some pits that have been stepped on in use.

It was set up like this

Map<String, List<ExtensionAttribute>> attributes = new HashMap<>(2);
List<ExtensionAttribute> extensionAttributes = new ArrayList<>();
ExtensionAttribute extensionAttribute = new ExtensionAttribute();
extensionAttribute.setName("name");
extensionAttribute.setValue("lisi");
extensionAttribute.setNamespace("user");
extensionAttribute.setNamespacePrefix("activiti");
extensionAttributes.add(extensionAttribute);
attributes.put("user",extensionAttributes);
process.setAttributes(attributes);

This setting can be processed later, but some attributes on the node are not available. For example, the formKey attribute.

This is because Activii sets a namespace for the attributes when parsing the model data into XML.

You can see the UserTaskXMLConverter class

@Override
  @SuppressWarnings("unchecked")
  protected void writeAdditionalAttributes(BaseElement element, BpmnModel model, XMLStreamWriter xtw) throws Exception {
    
    
    UserTask userTask = (UserTask) element;
    writeQualifiedAttribute(ATTRIBUTE_TASK_USER_ASSIGNEE, userTask.getAssignee(), xtw);
    writeQualifiedAttribute(ATTRIBUTE_TASK_USER_OWNER, userTask.getOwner(), xtw);
    writeQualifiedAttribute(ATTRIBUTE_TASK_USER_CANDIDATEUSERS, convertToDelimitedString(userTask.getCandidateUsers()), xtw);
    writeQualifiedAttribute(ATTRIBUTE_TASK_USER_CANDIDATEGROUPS, convertToDelimitedString(userTask.getCandidateGroups()), xtw);
    writeQualifiedAttribute(ATTRIBUTE_TASK_USER_DUEDATE, userTask.getDueDate(), xtw);
    writeQualifiedAttribute(ATTRIBUTE_TASK_USER_BUSINESS_CALENDAR_NAME, userTask.getBusinessCalendarName(), xtw);
    writeQualifiedAttribute(ATTRIBUTE_TASK_USER_CATEGORY, userTask.getCategory(), xtw);
    //这里将formKey写进xml文件
    writeQualifiedAttribute(ATTRIBUTE_FORM_FORMKEY, userTask.getFormKey(), xtw);
    if (userTask.getPriority() != null) {
    
    
      writeQualifiedAttribute(ATTRIBUTE_TASK_USER_PRIORITY, userTask.getPriority().toString(), xtw);
    }
    if (StringUtils.isNotEmpty(userTask.getExtensionId())) {
    
    
      writeQualifiedAttribute(ATTRIBUTE_TASK_SERVICE_EXTENSIONID, userTask.getExtensionId(), xtw);
    }
    if (userTask.getSkipExpression() != null) {
    
    
      writeQualifiedAttribute(ATTRIBUTE_TASK_USER_SKIP_EXPRESSION, userTask.getSkipExpression(), xtw);
    }
    // write custom attributes
    BpmnXMLUtil.writeCustomAttributes(userTask.getAttributes().values(), xtw, defaultElementAttributes, 
        defaultActivityAttributes, defaultUserTaskAttributes);
  }

Follow up the writeQualifiedAttribute method, will call the org.activiti.bpmn.converter.util.BpmnXMLUtil#writeQualifiedAttribute method, you can see here

public static void writeQualifiedAttribute(String attributeName, String value, XMLStreamWriter xtw) throws Exception {
    
    
    if (StringUtils.isNotEmpty(value)) {
    
    
      //ACTIVITI_EXTENSIONS_NAMESPACE = "http://activiti.org/bpmn";
      //ACTIVITI_EXTENSIONS_PREFIX = "activiti";
      xtw.writeAttribute(ACTIVITI_EXTENSIONS_PREFIX, ACTIVITI_EXTENSIONS_NAMESPACE, attributeName, value);
    }
  }

The namespace set here is "http://activiti.org/bpmn", but because when setting custom parameters for the process, the namespace set for the variable is "user", which causes the namespace of the entire process to become itself Set. This will cause the formKey to be stored in but not out.

Solution
1. Don't set NamespacePrefix to "actiiviti" when setting the process namespace, the Namespace should be set by yourself.
2. Or the NamespacePrefix is ​​"actiiviti", but the Namespace must be "http://activiti.org/bpmn".

Set node custom parameters

The node settings custom parameter settings UserTask.setCustomProperties. Part of the code

 if(customs!= null){
    
    
     List<CustomProperty> customProperties = new ArrayList<>();
     Map<String, String> map = MapUtil.objectToMap(customs);
     for (String k : map.keySet()) {
    
    
         CustomProperty customProperty = new CustomProperty();
         customProperty.setName(k);
         customProperty.setSimpleValue(map.get(k));
         customProperty.setId(k);
         customProperties.add(customProperty);
     }
     userTask.setCustomProperties(customProperties);
 }

Here customs is a custom parameter object, and the properties inside are defined by themselves. Then use MapUtil.objectToMap to convert the object to Map. Adding an attribute in this way basically eliminates the need to change the code.

It should be noted that when the node is set, it is the CustomProperties property, but when it is taken out, it is ExtensionElements.

Parsing code

 Map<String, List<ExtensionElement>> extensionElements = userTask.getExtensionElements();
        if(extensionElements != null && extensionElements.size() > 0) {
    
    
            Map<String, Object> attributeMap = new HashMap<>(2);
            for (String k : extensionElements.keySet()) {
    
    
                List<ExtensionElement> extensionElement = extensionElements.get(k);
                if (CollectionUtil.isNotEmpty(extensionElement)) {
    
    
                    for (ExtensionElement extension : extensionElement) {
    
    
                        attributeMap.put(extension.getName(), extension.getElementText());
                    }
                }
                CustomPropertiesDTO customPropertiesDTO = new CustomPropertiesDTO();
                customPropertiesDTO = (CustomPropertiesDTO) MapUtil.mapToObject(attributeMap, customPropertiesDTO);
                processNodeDTO.setCustomProperties(customPropertiesDTO);
            }
        }

The source code of activiti is in org.activiti.bpmn.converter.UserTaskXMLConverter#writeExtensionChildElements

@Override
  protected boolean writeExtensionChildElements(BaseElement element, boolean didWriteExtensionStartElement, XMLStreamWriter xtw) throws Exception {
    
    
    UserTask userTask = (UserTask) element;
    didWriteExtensionStartElement = writeFormProperties(userTask, didWriteExtensionStartElement, xtw);
    didWriteExtensionStartElement = writeCustomIdentities(element, didWriteExtensionStartElement, xtw);
    if (!userTask.getCustomProperties().isEmpty()) {
    
    
       //取出自定义属性
      for (CustomProperty customProperty : userTask.getCustomProperties()) {
    
    
        
        if (StringUtils.isEmpty(customProperty.getSimpleValue())) {
    
    
          continue;
        }
        
        if (didWriteExtensionStartElement == false) {
    
    
          //放进extensionElements属性
          xtw.writeStartElement(ELEMENT_EXTENSIONS);
          didWriteExtensionStartElement = true;
        }
        xtw.writeStartElement(ACTIVITI_EXTENSIONS_PREFIX, customProperty.getName(), ACTIVITI_EXTENSIONS_NAMESPACE);
        xtw.writeCharacters(customProperty.getSimpleValue());
        xtw.writeEndElement();
      }
    }
    return didWriteExtensionStartElement;
  }

Guess you like

Origin blog.csdn.net/qq_34758074/article/details/103359179