zoukankan      html  css  js  c++  java
  • JBPM深入解析之变量设计

    JBPM深入解析之变量设计

          在流程的流转的过程中,很多时候我们需要根据不同的实际情况传入一些初始化数据,以便完成我们个性化的业务需求;同时很多时候我们需要在不同的节点之间共享一些业务数据,特别是一些节点要以前一节点的输出作为输入等;变量对于流程引擎来说很重要,可以说没有变量,那么我们就不能运行时动态的设置和传入一些数据,这将极大的限制流程的灵活性!
          变量类型
           全局变量,所有的节点都可以获取并设置该变量的值
           局部变量,只在该节点及其子节点可以获取并设置该变量的值
          变量的传入
           在流程定义中进行变量的定义

          

    <?xml version="1.0" encoding="UTF-8"?>

    <process name="EndMultiple" xmlns="http://jbpm.org/4.4/jpdl">

      
    <start g="16,96,48,48">
        
    <transition to="get return code" name=""/>
      
    </start>

      
    <state g="96,94,111,52" name="get return code">
        
    <transition g="151,60:-36,11" name="200" to="ok"/>
        
    <transition g=":-16,-27" name="400" to="bad request"/>
        
    <transition g="151,183:-33,-32" name="500" to="internal server error"/>
      
    </state>

      
    <end g="238,37,48,48" name="ok"/>
      
    <end g="238,98,48,48" name="bad request"/>
      
    <end g="240,160,48,48" name="internal server error"/>
      
      
    <variable    name="msg" init-expr="jbpm" type="string">      
      
    </variable>
      
          
    <null></null>
    </variable>

    </process>


           在启动流程流程实例的时候传入全局变量

        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put(
    "category""big");
        variables.put(
    "dollars"100000);
        Execution execution 
    = executionService.startProcessInstanceByKey("TaskVariables", variables);

           在唤醒那些可外部唤醒类型的节点时候传入局部变量

           

        variables = new HashMap<String, Object>();
        variables.put(
    "category""small");
        variables.put(
    "lires"923874893);
        taskService.completeTask(taskId, variables)

           在任务存在的情况下,可以在任务等待外部唤醒时进行局部变量的设置

        variables = new HashMap<String, Object>();
        variables.put(
    "category""small");
        variables.put(
    "lires"923874893);    
        taskService.setVariables(taskId, variables);

           在任何时候都可以通过执行服务传入设置全局变量

          

        variables = new HashMap<String, Object>();
        variables.put(
    "category""small");
        variables.put(
    "lires"923874893);    
        executionService.setVariable(execution.getId(),variables)
        variables = new HashMap<String, Object>();
        variables.put(
    "category""small");
        variables.put(
    "lires"923874893);    
        executionService.signalExecutionById(execution.getId(),variables);

          变量架构设计  

          
          TypeSet、DefaultTypeSet
          TypeSet定义了流程引擎中通过变量类型和matcher两种方式查找变量类型的接口;DefaultTypeSet对TypeSet的接口进行了实现,并定义了一个List<TypeMapping>来装载所有的变量类型的映射变量实例。
          TypeSet

         

    package org.jbpm.pvm.internal.type;


    /**
     * 
    @author Tom Baeyens
     
    */
    public interface TypeSet {

      Type findTypeByMatch(String key, Object value);
      Type findTypeByName(String typeName);

    }


          DefaultTypeSet

         

    package org.jbpm.pvm.internal.type;

    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;


    /**
     * 
    @author Tom Baeyens
     
    */
    public class DefaultTypeSet implements TypeSet, Serializable {

      
    private static final long serialVersionUID = 1L;

      
    protected List<TypeMapping> typeMappings;

      
    public Type findTypeByMatch(String key, Object value) {
        
    if (typeMappings!=null) {
          
    for (TypeMapping typeMapping: typeMappings) {
            
    if (typeMapping.matches(key, value)) {
              
    return typeMapping.getType();
            }
          }
        }
        
        
    return null;
      }

      
    public Type findTypeByName(String typeName) {
        
    if ( (typeMappings!=null)
               
    && (typeName!=null)
           ) {
          
    for (TypeMapping typeMapping: typeMappings) {
            Type type 
    = typeMapping.getType();
            
    if (typeName.equals(type.getName())) {
              
    return type;
            }
          }
        }
        
    return null;
      }

      
    public void addTypeMapping(TypeMapping typeMapping) {
        
    if (typeMappings==null) {
          typeMappings 
    = new ArrayList<TypeMapping>();
        }
        typeMappings.add(typeMapping);
      }
    }


           TypeSet的初始化     在配置文件中配置流程引擎中需要使用的变量的类型

           Jbpm.defaut.cfg.xml引入变量类型配置的文件路径

    <process-engine-context>
     
       
    <repository-service />
       
    <repository-cache />
       
    <execution-service />
       
    <history-service />
       
    <management-service />
       
    <identity-service />
       
    <task-service />

       
    <object class="org.jbpm.pvm.internal.id.DatabaseDbidGenerator">
         
    <field name="commandService"><ref object="newTxRequiredCommandService" /></field>
       
    </object>

       
    <object class="org.jbpm.pvm.internal.id.DatabaseIdComposer" init="eager" />
       
       
    <object class="org.jbpm.pvm.internal.el.JbpmElFactoryImpl" />
       
    <!--定义变量配置文件的路径-->
       
    <types resource="jbpm.variable.types.xml" />

       
    <address-resolver />

     
    </process-engine-context>

           Jbpm.variable.types.xml定义了变量的类型、使用的转换器等信息

          

    <types>

      
    <!-- types stored in a native column -->
      
    <type name="string" class="java.lang.String" variable-class="org.jbpm.pvm.internal.type.variable.StringVariable" />
      
    <type name="long"   class="java.lang.Long" variable-class="org.jbpm.pvm.internal.type.variable.LongVariable" />
      
    <type name="double" class="java.lang.Double" variable-class="org.jbpm.pvm.internal.type.variable.DoubleVariable" />

      
    <!-- types converted to a string -->
      
    <type name="date"    class="java.util.Date" converter="org.jbpm.pvm.internal.type.converter.DateToStringConverter" variable-class="org.jbpm.pvm.internal.type.variable.StringVariable" />
      
    <type name="boolean" class="java.lang.Boolean" converter="org.jbpm.pvm.internal.type.converter.BooleanToStringConverter" variable-class="org.jbpm.pvm.internal.type.variable.StringVariable" />
      
    <type name="char"    class="java.lang.Character" converter="org.jbpm.pvm.internal.type.converter.CharacterToStringConverter" variable-class="org.jbpm.pvm.internal.type.variable.StringVariable" />

      
    <!-- types converted to a long -->
      
    <type name="byte"    class="java.lang.Byte" converter="org.jbpm.pvm.internal.type.converter.ByteToLongConverter" variable-class="org.jbpm.pvm.internal.type.variable.LongVariable" />
      
    <type name="short"   class="java.lang.Short" converter="org.jbpm.pvm.internal.type.converter.ShortToLongConverter" variable-class="org.jbpm.pvm.internal.type.variable.LongVariable" />
      
    <type name="integer" class="java.lang.Integer" converter="org.jbpm.pvm.internal.type.converter.IntegerToLongConverter" variable-class="org.jbpm.pvm.internal.type.variable.LongVariable" />

      
    <!-- types converted to a double -->
      
    <type name="float" class="java.lang.Float" converter="org.jbpm.pvm.internal.type.converter.FloatToDoubleConverter" variable-class="org.jbpm.pvm.internal.type.variable.DoubleVariable" />

      
    <!-- byte[] and char[] -->
      
    <type name="byte[]" class="[B" variable-class="org.jbpm.pvm.internal.type.variable.BlobVariable" />
      
    <type name="char[]" class="[C" variable-class="org.jbpm.pvm.internal.type.variable.TextVariable" />

      
    <type name="hibernate-long-id"   class="hibernatable" id-type="long" variable-class="org.jbpm.pvm.internal.type.variable.HibernateLongVariable" />
      
    <type name="hibernate-string-id" class="hibernatable" id-type="string" variable-class="org.jbpm.pvm.internal.type.variable.HibernateStringVariable" />

      
    <type name="serializable" class="serializable" converter="org.jbpm.pvm.internal.type.converter.SerializableToBytesConverter" variable-class="org.jbpm.pvm.internal.type.variable.BlobVariable" />

      
    <!-- TODO: add ejb3 entity bean support -->
      
    <!-- TODO: add JCR activity support -->
      
    <!-- TODO: add collection support -->
      
    </types>

             TypesBinding解析jbpm.variable.types.xml中的变量类型定义        

           

    public class TypesBinding extends WireDescriptorBinding {

      
    public TypesBinding() {
        
    super("types");
      }

      
    public Object parse(Element element, Parse parse, Parser parser) {
        StreamInput streamSource 
    = null;
        
    //查找type文件    
        if (element.hasAttribute("file")) {
          String fileName 
    = element.getAttribute("file");
          File file 
    = new File(fileName);
          
    if (file.exists() && file.isFile()) {
            streamSource 
    = new FileStreamInput(file);
            parser.importStream(streamSource, element, parse);
          } 
    else {
            parse.addProblem(
    "file "+fileName+" isn't a file", element);
          }
        }

        
    if (element.hasAttribute("resource")) {
          String resource 
    = element.getAttribute("resource");
          ClassLoader classLoader 
    = Thread.currentThread().getContextClassLoader();
          streamSource 
    = new ResourceStreamInput(resource, classLoader);
          parser.importStream(streamSource, element, parse);
        }

        
    if (element.hasAttribute("url")) {
          String urlText 
    = element.getAttribute("url");
          
    try {
            URL url 
    = new URL(urlText);
            streamSource 
    = new UrlStreamInput(url);
            parser.importStream(streamSource, element, parse);
          } 
    catch (Exception e) {
            parse.addProblem(
    "couldn't open url "+urlText, e);
          }
        }

        TypesDescriptor typesDescriptor 
    = new TypesDescriptor();

        List
    <Element> typeElements = XmlUtil.elements(element, "type");
        
    for (Element typeElement: typeElements) {
          TypeMapping typeMapping 
    = parseTypeMapping(typeElement, parse, parser);
          typesDescriptor.addTypeMapping(typeMapping);
        }
        
    return typesDescriptor;
      }

      
    protected TypeMapping parseTypeMapping(Element element, Parse parse, Parser parser) {
        TypeMapping typeMapping 
    = new TypeMapping();
        Type type 
    = new Type();
        typeMapping.setType(type);

        
    // type name
        
    //类型名称
        if (element.hasAttribute("name")) {
          type.setName(element.getAttribute(
    "name"));
        }

        String hibernateSessionFactoryName 
    = XmlUtil.attribute(element, "hibernate-session-factory");

        
    // first we get the matcher
        Matcher matcher = null;
        
    if (element.hasAttribute("class")) {
          String className 
    = element.getAttribute("class");

          
    // if type="serializable"
          if ("serializable".equals(className)) {
            matcher 
    = new SerializableMatcher();

          
    // if type="hibernatable"
          } else if ("hibernatable".equals(className)) {
            
    if (element.hasAttribute("id-type")) {
              String idType 
    = element.getAttribute("id-type");
              
    if ("long".equalsIgnoreCase(idType)) {
                matcher 
    = new HibernateLongIdMatcher(hibernateSessionFactoryName);
              } 
    else if ("string".equalsIgnoreCase(idType)) {
                matcher 
    = new HibernateStringIdMatcher(hibernateSessionFactoryName);
              } 
    else {
                parse.addProblem(
    "id-type was not 'long' or 'string': "+idType, element);
              }
            } 
    else {
              parse.addProblem(
    "id-type is required in a persistable type", element);
            }

          
    // otherwise, we expect type="some.java.ClassName"
          } else {
            matcher 
    = new ClassNameMatcher(className);
          }

        } 
    else {
          
    // look for the matcher element
          Element matcherElement = XmlUtil.element(element, "matcher");
          Element matcherObjectElement 
    = XmlUtil.element(matcherElement);
          
    if (matcherObjectElement!=null) {
            
    try {
              Descriptor descriptor 
    = (Descriptor) parser.parseElement(matcherObjectElement, parse);
              matcher 
    = (Matcher) WireContext.create(descriptor);
            } 
    catch (ClassCastException e) {
              parse.addProblem(
    "matcher is not a "+Matcher.class.getName()+""+(matcher!=null ? matcher.getClass().getName() : "null"), element);
            }
          } 
    else {
            parse.addProblem(
    "no matcher specified in "+XmlUtil.toString(element), element);
          }
        }

        typeMapping.setMatcher(matcher);

        
    // parsing the converter
        Converter converter = null;
        
    if (element.hasAttribute("converter")) {
          String converterClassName 
    = element.getAttribute("converter");
          
    try {
            Class
    <?> converterClass = ReflectUtil.classForName(converterClassName);
            converter 
    = (Converter) converterClass.newInstance();
          } 
    catch (Exception e) {
            parse.addProblem(
    "couldn't instantiate converter "+converterClassName, element);
          }
        } 
    else {
          
    // look for the matcher element
          Element converterElement = XmlUtil.element(element, "converter");
          Element converterObjectElement 
    = XmlUtil.element(converterElement);
          
    if (converterObjectElement!=null) {
            
    try {
              converter 
    = (Converter) parser.parseElement(converterObjectElement, parse);
            } 
    catch (ClassCastException e) {
              parse.addProblem(
    "converter is not a "+Converter.class.getName()+""+(converter!=null ? converter.getClass().getName() : "null"), element);
            }
          }
        }

        type.setConverter(converter);

        
    // parsing the variable class

        Class
    <?> variableClass = null;
        
    if (element.hasAttribute("variable-class")) {
          String variableClassName 
    = element.getAttribute("variable-class");
          
    try {
            variableClass 
    = ReflectUtil.classForName(variableClassName);
          } 
    catch (Exception e) {
            parse.addProblem(
    "couldn't instantiate variable-class "+variableClassName, e);
          }
        } 
    else {
          parse.addProblem(
    "variable-class is required on a type: "+XmlUtil.toString(element), element);
        }

        type.setVariableClass(variableClass);

        
    return typeMapping;
      }
    }

            TypeDescriptor用于运行时生成DefaultTypeSet
            

    public class TypesDescriptor extends AbstractDescriptor {

      private static final long serialVersionUID = 1L;
      
      DefaultTypeSet defaultTypeSet = new DefaultTypeSet();
      
      public Object construct(WireContext wireContext) {
        return defaultTypeSet;
      }
      
      public Class
    < ? > getType(WireDefinition wireDefinition) {
        return DefaultTypeSet.class;
      }

      public void addTypeMapping(TypeMapping typeMapping) {
        defaultTypeSet.addTypeMapping(typeMapping);
      }
      
      public DefaultTypeSet getDefaultTypeSet() {
        return defaultTypeSet;
      }
    }

     
            TypeMapping作为映射器,负责承载变量的类型和matcher
          

    public class TypeMapping implements Serializable {

      Matcher matcher;
      Type type;

      
    private static final long serialVersionUID = 1L;
      
      
    public boolean matches(String name, Object value) {
        
    return matcher.matches(name, value);
      }
      
      
    public String toString() {
        
    return "("+matcher+"-->"+type+")";
      }
      
      
    public void setMatcher(Matcher matcher) {
        
    this.matcher = matcher;
      }
      
    public Type getType() {
        
    return type;
      }
      
    public void setType(Type type) {
        
    this.type = type;
      }
      
    public Matcher getMatcher() {
        
    return matcher;
      }
    }

     

          Matcher,递归查询给定变量的类型以及所有的基类中是否有与该Matcher对应的类的变量类型相同的。
         

    public class ClassNameMatcher implements Matcher {

      
    private static final long serialVersionUID = 1L;
      
      String className 
    = null;
      
      
    public ClassNameMatcher(String className) {
        
    this.className = className;
      }
      
      
    public String toString() {
        
    return className;
      }

      
    public boolean matches(String name, Object value) {
        
    if (value==null) {
          
    return true;
        }
        
        Class
    <?> valueClass = value.getClass();
        
        
    while (valueClass!=null) {
          
    if (className.equals(value.getClass().getName())) {
            
    return true;
          } 
    else {
            Class
    <?>[] interfaces = valueClass.getInterfaces();
            
    for (int i=0; i<interfaces.length; i++) {
              
    if (className.equals(interfaces[i].getName())) {
                
    return true;
              }
            }
            valueClass 
    = valueClass.getSuperclass();
          }
        }
        
    return false;
      }
    }


            Type 定义变量类型的名称、转换器和对应的Variable

            

    public class Type implements Serializable {

      
    private static final long serialVersionUID = 1L;
      
      
    protected String name;
      
    protected Converter converter;
      
    protected Class<?> variableClass;

      
    public String toString() {
        
    if (name!=null) {
          
    return name;
        }
        StringBuilder text 
    = new StringBuilder();
        
    if (converter!=null) {
          text.append(converter.toString());
          text.append(
    "-->");
        }
        
    if (variableClass!=null) {
          text.append(variableClass.getSimpleName());
        } 
    else {
          text.append(
    "undefined");
        }
        
    return text.toString();
      }
      
      
    public Converter getConverter() {
        
    return converter;
      }
      
    public void setConverter(Converter converter) {
        
    this.converter = converter;
      }
      
    public Class< ? > getVariableClass() {
        
    return variableClass;
      }
      
    public void setVariableClass(Class< ? > variableClass) {
        
    this.variableClass = variableClass;
      }
      
    public String getName() {
        
    return name;
      }
      
    public void setName(String name) {
        
    this.name = name;
      }
    }

           Converter,负责变量运行时的表现形式和持久化形式进行转化
          

    public class SerializableToBytesConverter implements Converter {

      
    private static final long serialVersionUID = 1L;
      
      
    public boolean supports(Object value, ScopeInstanceImpl scopeInstance, Variable variable) {
        
    if (value==nullreturn true;
        
    return Serializable.class.isAssignableFrom(value.getClass());
      }

      
    public Object convert(Object o, ScopeInstanceImpl scopeInstance, Variable variable) {
        
    byte[] bytes = null;
        
    try {
          ByteArrayOutputStream baos 
    = new ByteArrayOutputStream(); 
          ObjectOutputStream oos 
    = new ObjectOutputStream(baos);
          oos.writeObject(o);
          oos.flush();
          bytes 
    = baos.toByteArray();

          Transaction transaction 
    = EnvironmentImpl.getFromCurrent(Transaction.classfalse);
          
    if (transaction!=null) {
            transaction.registerDeserializedObject(
    new DeserializedObject(o, scopeInstance, (BlobVariable) variable));
          }
          
        } 
    catch (IOException e) {
          
    throw new JbpmException("couldn't serialize '"+o+"'", e);
        }
        
        
    return bytes;
      }

      
    public Object revert(Object o, ScopeInstanceImpl scopeInstance, Variable variable) {
        
    byte[] bytes = (byte[]) o;
        
    try {
          ByteArrayInputStream bais 
    = new ByteArrayInputStream(bytes);

          ObjectInputStream ois 
    = null;
         
          ois 
    = new DeploymentObjectInputStream(bais, scopeInstance.getExecution().getProcessDefinition().getDeploymentId());
          
          Object object 
    = ois.readObject();
          
          Transaction transaction 
    = EnvironmentImpl.getFromCurrent(Transaction.classfalse);
          
    if (transaction!=null) {
            transaction.registerDeserializedObject(
    new DeserializedObject(object, scopeInstance, (BlobVariable) variable));
          }
          
          
    return object;

        } 
    catch (Exception e) {
          
    throw new JbpmException("couldn't deserialize object", e);
        }
      }
    }

            Variable,定义具体的变量以及一些持久化需要的属性

           

    public class StringVariable extends Variable {
      
      
    private static final long serialVersionUID = 1L;
      
      
    protected String string = null;

      
    public boolean isStorable(Object value) {
        
    if (value==nullreturn true;
        
    return (String.class==value.getClass());
      }

      
    public Object getObject() {
        
    return string;
      }

      
    public void setObject(Object value) {
        
    this.string = (String) value;
        
    if (value!=null) {
          
    this.textValue = string;
        } 
    else {
          
    this.textValue = null;
        }
      }
    }


     

  • 相关阅读:
    (转)MapReduce中的两表join几种方案简介
    Java 网络编程(转)
    RDD的转换操作---RDD转换过程
    mapreduce 实现pagerank
    mapreduce 实现矩阵乘法
    Spark Standalone运行过程
    (转)MapReduce二次排序
    (转)《深入理解java虚拟机》学习笔记10——并发编程(二)
    jetty启动源码分析
    tomcat源码分析 Http11Processor process
  • 原文地址:https://www.cnblogs.com/wufengtinghai/p/2108551.html
Copyright © 2011-2022 走看看