JBPM流程部署之部署环境初始化

JBPM流程部署之部署环境初始化

 

      流程的部署是流程引擎需要完成的几个重要的任务之一,流程定义是现实中复杂业务需求在流程流转实现的体现;流程部署需要完成xml格式流程定义的校验、流程定义的持久化、流程定义到流程定义实体的转化、流程版本升级和流程实例的迁移等众多的功能;
      今天我们来简单的学习一下流程部署的环境初始化;流程部署环境初始化需要完成部署服务、流程部署缓存、流程部署持久化相关对象、流程引擎支持的节点类型等相关binding对象及相关的部署解析器的实例化;

      流程引擎支持的节点类型初始化

                 流程引擎支持众多的节点类型,比如任务节点、状态节点、子流程等等;此过程初始化JBPM默认支持的系统节点类型;JBPM将xml格式的流程定义解析成运行

            时流程引擎流转所使用的流程定义(ProcessDefinitionImpl)、Activity等对象;而流程引擎对xml的解析也是依赖自己实现的IOC来实现的,所以归根结底流程引

            擎支持的节点类型的初始化,就是将流程引擎支持的节点类型相应的binding进行实例化!此过程中相关的对象和UML类图如下   

                流程引擎支持的节点类型初始化相关对象  
                                   

                流程引擎支持的节点类型初始化相关对象UML图

               

                下面我们通过图中的对象的实现代码,看一下他们的作用

                 jbpm.jpdl.bindings.xml 定义JBPM支持的节点类型和节点事件监听器,我们可以根据业务的需要注释到不使用的节点类型对应的元素,那么运行时就不会解

            析流程定义xml中相应的元素,从而不会生成对应节点的对象;同时我们也可以在这里配置加载我们自定义或者扩展现有的节点类型。

                

< bindings >
  
// 流程引擎支持的各种节点的binding
   < activity binding = " org.jbpm.jpdl.internal.activity.StartBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.StateBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.DecisionBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.EndBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.EndCancelBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.EndErrorBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.ForEachBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.ForkBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.JoinBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.HqlBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.SqlBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.JavaBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.ScriptBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.TaskBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.SubProcessBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.MailBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.GroupBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.CustomBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.AssignBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.PassthroughBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.RulesBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.RulesDecisionBinding "   />
  
< activity binding = " org.jbpm.jpdl.internal.activity.JmsBinding "   />

  
// 流程引擎节点的事件监听器
   < eventlistener binding = " org.jbpm.jpdl.internal.activity.EventListenerBinding "   />
  
< eventlistener binding = " org.jbpm.jpdl.internal.activity.JavaBinding "   />
  
< eventlistener binding = " org.jbpm.jpdl.internal.activity.HqlBinding "   />
  
< eventlistener binding = " org.jbpm.jpdl.internal.activity.SqlBinding "   />
  
< eventlistener binding = " org.jbpm.jpdl.internal.activity.ScriptBinding "   />
  
< eventlistener binding = " org.jbpm.jpdl.internal.activity.MailBinding "   />
  
< eventlistener binding = " org.jbpm.jpdl.internal.activity.AssignBinding "   />
  
< eventlistener binding = " org.jbpm.jpdl.internal.activity.JmsBinding "   />

</ bindings >

             JpdlDeployer 主要负责根据既有的规则生成流程定义的Id,key和版本,同时在首次解析时,通过静态字段JpdlParser来完成相关节点的binding类的实例化

            

public   class  JpdlDeployer  extends  ProcessDeployer {
  
  
private   static  Log log  =  Log.getLog(JpdlDeployer. class .getName());
  
private   static  Parser parser  =   new  Parser();
  
  
// 静态字段自动初始化
   static  JpdlParser jpdlParser  =   new  JpdlParser();
  
static   final  String jpdlExtension  =   " .jpdl.xml " ;

             JpdlDeployer的父类ProcessDeployer中的部分代码,完成对流程定义Id、version、key等的设置并持久化等

 

   public   void  deploy(DeploymentImpl deployment) {
    
    
for  (String resourceName: deployment.getResourceNames()) {
      
      
if  (resourceName.endsWith(extension)) {
        
// 加载xml格式的流程定义资源
         byte [] bytes  =  deployment.getBytes(resourceName);
        InputStream inputStream 
=   new  ByteArrayInputStream(bytes);
        Parse parse 
=  parser.createParse();
        parse.contextMapPut(Parse.CONTEXT_KEY_DEPLOYMENT, deployment);
        parse.setProblems(deployment.getProblems());
        parse.setInputStream(inputStream);
        
// 解析xml格式的流程定义生成ProcessDefinitionImpl
        parse.execute();
        List
< ProcessDefinitionImpl >  processDefinitions  =  (List < ProcessDefinitionImpl > ) parse.getDocumentObject();
        
if  (processDefinitions != null ) {
          
for  (ProcessDefinitionImpl processDefinition : processDefinitions) {
            
if  ((processDefinition  !=   null &&  (processDefinition.getName()  !=   null )) {
              processDefinition.setSuspended(deployment.isSuspended());

              String imageResourceName 
=  resourceName.substring( 0 , resourceName.lastIndexOf(extension))  +   " .png " ;
              
if  (deployment.getResourceNames().contains(imageResourceName)) {
                processDefinition.setImageResourceName(imageResourceName);
              }

              processDefinition.setDeploymentDbid(deployment.getDbid());

              String processDefinitionName 
=  processDefinition.getName();
              
// 获取已经发布完得流程执行(比如启动流程时获取流程定义对象)
               if  (deployment.hasObjectProperties(processDefinitionName)) {
                String key 
=  deployment.getProcessDefinitionKey(processDefinitionName);
                String id 
=  deployment.getProcessDefinitionId(processDefinitionName);
                Long version 
=  deployment.getProcessDefinitionVersion(processDefinitionName);
                processDefinition.setId(id);
                processDefinition.setKey(key);
                processDefinition.setVersion(version.intValue());
            
              } 
else  {
                
// 流程部署校验并设置流程定义的id、key、version
                checkKey(processDefinition, deployment);
                checkVersion(processDefinition, deployment);
                checkId(processDefinition, deployment);
                
// 持久化对流程定义id、key、version的设置
                deployment.setProcessDefinitionId(processDefinitionName, processDefinition.getId());
                deployment.setProcessDefinitionKey(processDefinitionName, processDefinition.getKey());
                deployment.setProcessDefinitionVersion(processDefinitionName, 
new  Long(processDefinition.getVersion()));
                
                
// execute migration
                
// 流程实例迁移
                Map < ProcessDefinition, MigrationDescriptor >  migrations  =  (Map < ProcessDefinition, MigrationDescriptor > )parse.contextMapGet(Parse.CONTEXT_KEY_MIGRATIONS);
                
if  (migrations  !=   null ) {
                  MigrationDescriptor migrationDescriptor 
=  migrations.get(processDefinition);
                  
if  (migrationDescriptor  !=   null ) {
                    InstanceMigrator.migrateAll(processDefinition, migrationDescriptor);
                  }
                }
                
              }

              deployment.addObject(processDefinitionName, processDefinition);
            }
          }
        }
      }
    }
  }

 

             ProcessDefinitionImpl,流程定义的运行时对象,作为流程实例运行的流转依据,其定义了流程的启动节点,同时父类CompositeElementImpl定义了流程中

       的所有的节点

            

public   class  ProcessDefinitionImpl  extends  CompositeElementImpl  implements  OpenProcessDefinition, ClientProcessDefinition {

  
private   static   final   long  serialVersionUID  =   1L ;
  
private   static   final  Log log  =  Log.getLog(ProcessDefinitionImpl. class .getName());
  
  
public   static   final   int  UNASSIGNED_VERSION  =   - 1 ;

  
/**  user provided short reference for the process definition that 
   * has the same scope as the name.  Multiple versions of the same 
   * process can have the same key. The key is used to build the 
   * globally unique execution ids. 
*/
  
protected  String key;
  
  
/**  the unique id (e.g. combination of name and versionnumber) for this 
   * process definition. 
*/
  
protected  String id;

  
/**  the version number of the process definitions with the same name. */
  
protected   int  version  =  UNASSIGNED_VERSION;
  
  
/**  optional package name similar to the Java package name.  */
  
protected  String packageName;
  
  
/**  time this process was deployed  */
  
protected  Date deploymentTime;
  
  
/**  ref to the deployment  */
  
protected   long  deploymentDbid;
  
  
/**  propagated from deployment to process definition during deploy  */
  
protected   boolean  isSuspended  =   false ;
  
  
/**  the activity which is executed when the process starts  */
  //流程的起始节点
  
protected  ActivityImpl initial;
  

 

              ProcessDefinitionImpl的父类CompositeElementImpl中定义了其所有的直接子节点

public   abstract   class  CompositeElementImpl  extends  ScopeElementImpl  implements  CompositeElement {

  
private   static   final   long  serialVersionUID  =   1L ;
  //流程定义的所有直接子节点,节点本身是可以嵌套的
  
protected  List < ActivityImpl >  activities;
 

 

               JpdlParser定义了部署中需要使用的一些关键信息,并完成xml格式流程定义的解析,并在初次解析xml前完成节点类型binding类的解析初始化

 

public   class  JpdlParser  extends  Parser {

  
private   static   final  Log log  =  Log.getLog(JpdlParser. class .getName());

  
// xml格式流程定义使用的命名空间
   public   static   final  String NAMESPACE_JPDL_40  =   " http://jbpm.org/4.0/jpdl " ;
  
public   static   final  String NAMESPACE_JPDL_42  =   " http://jbpm.org/4.2/jpdl " ;
  
public   static   final  String NAMESPACE_JPDL_43  =   " http://jbpm.org/4.3/jpdl " ;
  
public   static   final  String NAMESPACE_JPDL_44  =   " http://jbpm.org/4.4/jpdl " ;

  
// 当前JBPM的版本、流程定义的命名空间、jbpl的版本
   public   static   final  String CURRENT_VERSION_JBPM  =   " 4.4 " ;
  
public   static   final  String CURRENT_VERSION_NAMESPACE  =
    
" http://jbpm.org/ "   +  CURRENT_VERSION_JBPM  +   " /jpdl " ;
  
public   static   final  String CURRENT_VERSION_PROCESS_LANGUAGE_ID  =
    
" jpdl- "   +  CURRENT_VERSION_JBPM;

  
// 流程定义xml校验使用的xsd
   private   static   final  String[] SCHEMA_RESOURCES  =
    { 
" jpdl-4.0.xsd " " jpdl-4.2.xsd " " jpdl-4.3.xsd " " jpdl-4.4.xsd "  };

  
// 节点类型binding的配置文件
   private   static   final  String[] DEFAULT_BINDING_RESOURCES  =
    { 
" jbpm.jpdl.bindings.xml " " jbpm.user.bindings.xml "  };

  
// 解析配置文件中的binding类
   private   static  JpdlBindingsParser jpdlBindingsParser  =   new  JpdlBindingsParser();

  
// 节点的binding类的分类
   public   static   final  String CATEGORY_ACTIVITY  =   " activity " ;
  
public   static   final  String CATEGORY_EVENT_LISTENER  =   " eventlistener " ;

  
// 初始化时,加载并解析节点的binding类
   public  JpdlParser() {
    parseBindings();
    setSchemaResources(SCHEMA_RESOURCES);
  }

  
// 加载并解析节点的binding类
   protected   void  parseBindings() {
    
this .bindings  =   new  Bindings();

    
for  (String activityResource : DEFAULT_BINDING_RESOURCES) {
      Enumeration
< URL >  resourceUrls  =  getResources(activityResource);
      
if  (resourceUrls.hasMoreElements()) {
        
while  (resourceUrls.hasMoreElements()) {
          URL resourceUrl 
=  resourceUrls.nextElement();
          log.trace(
" loading jpdl bindings from resource:  "   +  resourceUrl);
          jpdlBindingsParser.createParse()
            .setUrl(resourceUrl)
            .contextMapPut(Parse.CONTEXT_KEY_BINDINGS, bindings)
            .execute()
            .checkErrors(
" jpdl bindings from  "   +  resourceUrl.toString());
        }
      }
      
else  {
        log.trace(
" skipping unavailable jpdl activities resource:  "   +  activityResource);
      }
    }
  }

  
protected  Enumeration < URL >  getResources(String resourceName) {
    ClassLoader classLoader 
=  Thread.currentThread().getContextClassLoader();
    Enumeration
< URL >  resourceUrls;
    
try  {
      resourceUrls 
=  classLoader.getResources(resourceName);

      
if  ( ! resourceUrls.hasMoreElements()) {
        resourceUrls 
=  JpdlParser. class .getClassLoader().getResources(resourceName);
      }
    }
    
catch  (Exception e) {
      
throw   new  JbpmException( " couldn't get resource urls for  "   +  resourceName, e);
    }
    
return  resourceUrls;
  }

  
// 解析xml格式的流程定义,并生成processDefinitionImpl
   public  Object parseDocumentElement(Element documentElement, Parse parse) {
        JpdlProcessDefinition processDefinition 
=  instantiateNewJpdlProcessDefinition();
        parse.contextStackPush(processDefinition);

             Bindings负责承载解析生成的节点的binding对象,并负责根据流程定义中的节点元素的tagName找到对相应的bingding对象(用于解析该节点元素)

            

public   class  Bindings {

  
/**  maps categories to a list of bindings  */
  
protected  Map < String, List < Binding >>  bindings  =   null ;
  
public  Set < String >  getTagNames(String category) {
    Set
< String >  tagNames  =   new  HashSet < String > ();

    List
< Binding >  categoryBindings  =  (bindings != null   ?  bindings.get(category) :  null  );
    
if  (categoryBindings != null ) {
      
for  (Binding binding: categoryBindings) {
        tagNames.add(binding.toString());
      }
    }
    
    
return  tagNames;
  }
}

             JpdlBindingsParser 负责解析jbpm.jpdl.bindings.xml,并生成其中配置的binding实例

 

public   class  JpdlBindingsParser  extends  Parser {

  
private   static   final  Log log  =  Log.getLog(JpdlBindingsParser. class .getName());

  
// 解析jbpm.jpdl.bindings.xml中的xml
   public  Object parseDocumentElement(Element documentElement, Parse parse) {
    Bindings bindings 
=  (Bindings) parse.contextMapGet(Parse.CONTEXT_KEY_BINDINGS);
    parse.setDocumentObject(bindings);

    
for  (Element bindingElement : XmlUtil.elements(documentElement)) {
      Binding binding 
=  instantiateBinding(bindingElement, parse);
      bindings.addBinding(binding);
    }

    
return  bindings;
  }

  
// 实例化jbpm.jpdl.bindings.xml中的元素中定义的binding类
   protected  Binding instantiateBinding(Element bindingElement, Parse parse) {
    String bindingClassName 
=  XmlUtil.attribute(bindingElement,  " binding " , parse);

    log.trace(
" adding jpdl binding  " + bindingClassName);

    
if  (bindingClassName != null ) {
      
try  {
        Class
<?>  bindingClass  =  ReflectUtil.classForName(bindingClassName);
        TagBinding binding 
=  (TagBinding) bindingClass.newInstance();

        String tagLocalName 
=  bindingElement.getLocalName();
        
if  ( " activity " .equals(tagLocalName)) {
          binding.setCategory(JpdlParser.CATEGORY_ACTIVITY);
        } 
else   if  ( " eventlistener " .equals(tagLocalName)) {
          binding.setCategory(JpdlParser.CATEGORY_EVENT_LISTENER);
        } 
else  {
          parse.addProblem(
" unrecognized binding tag:  " + tagLocalName);
        }

        
return  binding;
      } 
catch  (Exception e) {
        parse.addProblem(
" couldn't instantiate activity binding  " + bindingClassName, e);
      }
    }
    
return   null ;
  }
}

         初始化发布服务相关和初始化流程部署解析器相关

               流程的发布服务对外提供发布服务,我们可以通过调用该服务来完成流程的发布;流程部署解析器则主要负责xml格式流程定义的解析! 

                流程部署解析器相关对象

              

               流程部署服务相关对象

              

               流程部署解析器和流程部署服务相关对象的UML图,由于两部分的管理比较紧密,所以UML图可能比较复杂

                

                下面我们同样结合UML中的类的代码来探究JBPM的实现

                 jbpm.cfg.xml定义了并导入JBPM中的各种配置文件,方便对配置文件的集中管理

               

< jbpm-configuration >

  
< import  resource ="jbpm.default.cfg.xml"   />
  
< import  resource ="jbpm.businesscalendar.cfg.xml"   />
  
< import  resource ="jbpm.tx.hibernate.cfg.xml"   />
  //流程定义JPDL的配置文件
  
< import  resource ="jbpm.jpdl.cfg.xml"   />
  
< import  resource ="jbpm.bpmn.cfg.xml"   />
  
< import  resource ="jbpm.identity.cfg.xml"   />

  
<!--  Job executor is excluded for running the example test cases.  -->
  
<!--  To enable timers and messages in production use, this should be included.  -->
  
<!--
  <import resource="jbpm.jobexecutor.cfg.xml" />
  
-->

</ jbpm-configuration >

            jbpm.wire.bindings.xml定义了流程引擎需要使用的一些相关对象的binding,是JBPM 自身实现的IOC框架的重要组成部分

           

< wire-bindings >  
  
  
<!--  hibernate bindings  -->   
  
< binding  class ="org.jbpm.pvm.internal.wire.binding.RepositorySessionBinding"   />   
 
  
<!--  services   -->   
  
< binding  class ="org.jbpm.pvm.internal.wire.binding.RepositoryServiceBinding"   />
  
< binding  class ="org.jbpm.pvm.internal.wire.binding.RepositoryCacheBinding"   />
  
  
<!--  deployers  -->
  
< binding  class ="org.jbpm.pvm.internal.wire.binding.DeployerManagerBinding"   />

  
<!--  jpdl bindings  -->
  
< binding  class ="org.jbpm.jpdl.internal.xml.JpdlDeployerBinding"   />  
  

</ wire-bindings >

        jbpm.default.cfg.xml 配置流程引擎的相关对象,配置需要立即实例化的对象会在解析配置文件的同时生成对象实例,否则仅根据相应的binding生成对象的descriptor实例,到实际使用时再延迟实例化

       

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

< jbpm-configuration >

  
< import  resource ="jbpm.default.scriptmanager.xml"   />
  
< import  resource ="jbpm.mail.templates.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 >

  
< transaction-context >
    //部署持久化使用的对象
    
< repository-session  />
    
< db-session  />
    
    
< message-session  />
    
< timer-session  />
    
    
< history-sessions >
      
< object  class ="org.jbpm.pvm.internal.history.HistorySessionImpl"   />
    
</ history-sessions >
    
    
< mail-session >
      
< mail-server >
        
< session-properties  resource ="jbpm.mail.properties"   />
      
</ mail-server >
    
</ mail-session >

  
</ transaction-context >

</ jbpm-configuration >

         ConfigrationImpl作为流程引擎初始化的入口,几乎完成流程引擎所有所有的配置文件的解析,同时负责根据配置生成流程引擎对象

         

ublic  class  ConfigurationImpl  extends  Configuration {
  
// 流程引擎的默认配置文件
   public   static   final  String DEFAULT_CONFIG_RESOURCENAME  =   " jbpm.cfg.xml " ;

  
private   static  Log log  =  Log.getLog(ConfigurationImpl. class .getName());

  
transient   protected   boolean  isConfigured  =   false ;
  
transient  String jndiName;
  
transient   boolean  checkDb  =   true ;
  
transient   boolean  isSpringEnabled  =   false ;
  
//  type is Object because we don't want a dependency on spring in this class
   transient  Object applicationContext  =   null ;
  
// 承载流程相关的descriptor
   transient  WireContext processEngineWireContext  =   new  WireContext( new  WireDefinition(), Context.CONTEXTNAME_PROCESS_ENGINE,  true );
  
// 承载事务相关的descriptor
   transient  WireDefinition transactionWireDefinition  =   new  WireDefinition();
  
transient  ProcessEngine producedProcessEngine;
  
  
public  ConfigurationImpl() {
    
//  to prevent a loop in the constructors, we need to delegate to a non-default constructor in Configuration
     super ( null );
  }
  
  
// 构建流程引擎对象
   public  ProcessEngine buildProcessEngine() {

          ConfigrationParser主要负责解析JBPM的配置文件并根据不同的标签调用不同的Parser

         

public   class  ConfigurationParser  extends  Parser {

  
private   static   final   long  serialVersionUID  =   1L ;
  

  
// 解析配置文件中标签process-engine-context及其子元素
  Parser processEngineContextParser  =   new  WireParser();
  
// 解析配置文件中标签transaction-context及其子元素
  Parser transactionContextParser  =   new  WireParser();

  
protected   static  ConfigurationParser INSTANCE  =   new  ConfigurationParser();
  
  
public   static  ConfigurationParser getInstance() {
    
return  INSTANCE;
  }

  
// 解析配置文件
   public  Object parseDocument(Document document, Parse parse) {

          WireParser主要负责流程定义文件的具体解析,同时负责在首次运行之前解析jbpm.wire.bindings.xml

         

public   class  WireParser  extends  Parser {
  
// 默认的bindings配置文件
   public   static   final  String[] DEFAULT_WIRE_BINDING_RESOURCES  =   new  String[]{
    
" jbpm.wire.bindings.xml " ,
    
" jbpm.user.wire.bindings.xml "
  }; 

  
private   static   final   long  serialVersionUID  =   1L ;
  
  
private   static   final  Log log  =  Log.getLog(WireParser. class .getName());

  
// 生成的descriptor的分类
   public   static   final  String CATEGORY_DESCRIPTOR  =   " descriptor " ;
  
public   static   final  String CATEGORY_OPERATION  =   " operation " ;
  
public   static   final  String CATEGORY_INTERCEPTOR  =   " interceptor " ;


  
private   static  WireParser instance;

  
// 承载jbpm.wire.bindings.xml中的binding实例
   private   static  Bindings defaultBindings;  //  initialized at the bottom of this file



 


  
// 解析配置文件
   public  Object parseDocumentElement(Element documentElement, Parse parse) {
    List
< Element >  elements  =  XmlUtil.elements(documentElement);

    
    WireDefinition wireDefinition 
=  parse.contextStackFind(WireDefinition. class );
    
if  (wireDefinition == null ) {
      wireDefinition 
=   new  WireDefinition();
    }
    
    parse.contextStackPush(wireDefinition);
    
try  {
      
for  (Element descriptorElement: elements) {
        Descriptor descriptor 
=  (Descriptor) parseElement(descriptorElement, parse, CATEGORY_DESCRIPTOR);
        
        
//  add the descriptor
         if  ( (wireDefinition != null )
             
&&  (descriptor != null )
           ) {
          wireDefinition.addDescriptor(descriptor);
        }
      }
    } 
finally  {
      parse.contextStackPop();
    }

    
return  wireDefinition;
  }

  
// 解析jbpm.wire.bindings.xml
   static  {
    
//  default descriptor parsers  // /
    defaultBindings  =   new  Bindings();
    
    BindingParser bindingParser 
=   new  BindingParser();
 
    
for  (String wireResource: DEFAULT_WIRE_BINDING_RESOURCES) {
      ClassLoader classLoader 
=  Thread.currentThread().getContextClassLoader();
      Enumeration
< URL >  resourceUrls;
      
try  {
        resourceUrls 
=  classLoader.getResources(wireResource);

        
if  ( ! resourceUrls.hasMoreElements()) {
          resourceUrls 
=  WireParser. class .getClassLoader().getResources(wireResource);
        }
      } 
catch  (Exception e) {
        
throw   new  JbpmException( " couldn't get resource urls for  " + wireResource, e);
      }
      
if  (resourceUrls.hasMoreElements()) {
        
while  (resourceUrls.hasMoreElements()) {
          URL resourceUrl 
=  resourceUrls.nextElement();
          log.trace(
" loading wire bindings from resource:  " + resourceUrl);
          bindingParser.createParse()
            .setUrl(resourceUrl)
            .contextStackPush(defaultBindings)
            .execute()
            .checkErrors(resourceUrl.toString());
        }
      } 
else  {
        log.trace(
" skipping unavailable wire bindings resource  " + wireResource);
      }
    }
  }

           BindingParser主要负责jbpm.wire.bindings.xml

          

public   class  BindingParser  extends  Parser {

  
private   static   final  Log log  =  Log.getLog(BindingParser. class .getName());

  
public  Object parseDocumentElement(Element documentElement, Parse parse) {
    List
< Element >  elements  =  XmlUtil.elements(documentElement,  " binding " );
    
for  (Element bindingElement : elements) {
      String bindingClassName 
=  XmlUtil.attribute(bindingElement,  " class " );

      log.trace(
" adding wire binding for  " + bindingClassName);

      Binding binding 
=   null ;
      
if  (bindingClassName != null ) {
        
try  {
          Class
<?>  bindingClass  =  ReflectUtil.classForName(bindingClassName);
          binding 
=  (Binding) bindingClass.newInstance();
        } 
catch  (Exception e) {
          log.trace(
" couldn't instantiate binding  " + bindingClassName);
        }
      } 
else  {
        parse.addProblem(
" class is a required attribute in a binding  " + XmlUtil.toString(bindingElement), documentElement);
      }

      
if  (binding != null ) {
        Bindings bindings 
=  parse.contextStackFind(Bindings. class );
        bindings.addBinding(binding);
      }
    }

    
return   null ;
  }
}

         ProcessEnginImpl持有流程解析配置文件形成的相关对象,对外提供相关服务,可以获取相关的对象,为事务提供环境对象实例

        

public   class  ProcessEngineImpl  implements  Context, ProcessEngine, EnvironmentFactory, Serializable {

  
private   static   final   long  serialVersionUID  =   1L ;
  
private   static   final  Log log  =  Log.getLog(ProcessEngineImpl. class .getName());
  
  
public   static   final  String JBPM_LIBRARY_VERSION  =   " 4.4-SNAPSHOT " ;

  
// 持有流程引擎解析配置文件形成的对象
   transient   protected  WireContext processEngineWireContext;
  
transient   protected  WireDefinition transactionWireDefinition;
  
  
transient   protected  ThreadLocal < List < UserProvidedEnvironmentObject >>  userProvidedEnvironmentObjectsThreadLocal  =   new  ThreadLocal < List < UserProvidedEnvironmentObject >> ();
  
transient   protected  ThreadLocal < String >  authenticatedUserIdThreadLocal  =   new  ThreadLocal < String > ();
  
  
transient   protected  CommandService userCommandService  =   null ;
  
  
public  ProcessEngineImpl() {
  }

 


  
// 对外提供各种服务
   public  ExecutionService getExecutionService() {
    
return  get(ExecutionService. class );
  }
  
public  HistoryService getHistoryService() {
    
return  get(HistoryService. class );
  }
  
public  ManagementService getManagementService() {
    
return  get(ManagementService. class );
  }
  
public  TaskService getTaskService() {
    
return  get(TaskService. class );
  }
  
public  IdentityService getIdentityService() {
    
return  get(IdentityService. class );
  }
  
public  RepositoryService getRepositoryService() {
    
return  get(RepositoryService. class );
  }

  
// 提供与事务相关的环境对象
   public  EnvironmentImpl openEnvironment() {
    PvmEnvironment environment 
=   new  PvmEnvironment( this );

    
if  (log.isTraceEnabled()) log.trace( " opening  "   +  environment);

    installAuthenticatedUserId(environment);
    installProcessEngineContext(environment);
    installTransactionContext(environment);

    
return  environment;
  }

  
  

 
  
// 获取流程需要使用的相关对象
   public  Object get(String key) {
    
return  processEngineWireContext.get(key);
  }

  
public   < T >  T get(Class < T >  type) {
    
return  processEngineWireContext.get(type);
  }

  
public  String getName() {
    
return  processEngineWireContext.getName();
  }

  
public   boolean  has(String key) {
    
return  processEngineWireContext.has(key);
  }

  
public  Set < String >  keys() {
    
return  processEngineWireContext.keys();
  }

  
public  Object set(String key, Object value) {
    
return  processEngineWireContext.set(key, value);
  }
  
 

 

  
public   < T >  T execute(Command < T >  command) {
    
return  userCommandService.execute(command);
  }

  
}

        EnvironmentImpl主要为具体的一次事务提供上下文环境,并提供获取相关对象的方法

       

public   abstract   class  EnvironmentImpl  implements  Serializable, Environment {

  
private   static   final   long  serialVersionUID  =   1L ;

 
  
public   abstract  Object get(String name);

 
  
public   abstract  Object get(String name, String[] searchOrder);
  
  
public   abstract  Object get(String name,String[] searchOrder,  boolean  nullAllowed)  throws  JbpmException;
  
  
public   abstract  Object get(String name,  boolean  nullAllowed)  throws  JbpmException;

  
public   abstract   < T >  T get(Class < T >  type); 
 
  
public   abstract   < T >  T get(Class < T >  type, String[] searchOrder);

 
  
static  ThreadLocal < EnvironmentImpl >  currentEnvironment  =   new  ThreadLocal < EnvironmentImpl > ();  
  
static  ThreadLocal < Stack < EnvironmentImpl >>  currentEnvironmentStack  =   new  ThreadLocal < Stack < EnvironmentImpl >> ();

  
public   static  EnvironmentImpl getCurrent() {
    
return  currentEnvironment.get();
  }
  
  
public   static   < T >  T getFromCurrent(Class < T >  type) {
    
return  getFromCurrent(type,  true );
  }

  
public   static   < T >  T getFromCurrent(Class < T >  type,  boolean  required) {
    EnvironmentImpl environment 
=  getCurrent();
    
if  (environment == null ) {
      
if  (required) {
        
throw   new  JbpmException( " no environment to get  " + type.getName());
      }
      
return   null ;
    }
    T object 
=  environment.get(type);
    
if  (object == null ) {
      
if  (required) {
        
throw   new  JbpmException( " no  " + type.getName() + "  in current environment " );
      }
      
return   null ;
    }
    
return  object;
  }


  
public   static  Object getFromCurrent(String name,  boolean  required) {
    EnvironmentImpl environment 
=  getCurrent();
    
if  (environment == null ) {
      
if  (required) {
        
throw   new  JbpmException( " no environment to get ' " + name + " ' " );
      }
      
return   null ;
    }
    Object object 
=  environment.get(name);
    
if  (object == null ) {
      
if  (required) {
        
throw   new  JbpmException( " no ' " + name + " ' in current environment " );
      }
      
return   null ;
    }
    
return  object;
  }

  
static  Stack < EnvironmentImpl >  getStack() {
    
//  lazy initialize the current environment stack
    Stack < EnvironmentImpl >  stack  =  currentEnvironmentStack.get();
    
if  (stack == null ) {
      stack 
=   new  Stack < EnvironmentImpl > ();
      currentEnvironmentStack.set(stack);
    }
    
return  stack;
  }



}

          jbpm.jpdl.cfg.xml配置流程部署管理者和部署解析器

         

< jbpm - configuration >

  
< process - engine - context >
    
// 部署管理者
     < deployer - manager >
      
// 部署解析器
       < jpdl - deployer  />
      
< object  class = " org.jbpm.pvm.internal.repository.RulesDeployer "   />
    
</ deployer - manager >
    
  
</ process - engine - context >

</ jbpm - configuration >

        DeployManager 负责调用部署解析器解析xml流程定义,并管理生成的流程定义进行缓存

        

public   class  DeployerManager {
  
  
private   static  Log LOG  =  Log.getLog(DeployerManager. class .getName());
  
  List
< Deployer >  deployers;
  
  
public   void  deploy(DeploymentImpl deployment) {
    deployment.setProblems(
new  ArrayList < Problem > ());
    
// 调用部署解析器
     for  (Deployer deployer: deployers) {
      deployer.deploy(deployment);
    }
    
    
if  (deployment.hasErrors()) {
      JbpmException jbpmException 
=  deployment.getJbpmException();
      LOG.info(
" errors during deployment of  " + deployment + " " + jbpmException.getMessage());
      
throw   jbpmException;
    }
    
// 缓存流程定义
    RepositoryCache repositoryCache  =  EnvironmentImpl.getFromCurrent(RepositoryCache. class );
    
    
if  (repositoryCache  !=   null ) {
      
      
//  If there are no objects after deploying, then there is something wrong
       if  (deployment.getObjects()  ==   null   ||  deployment.getObjects().isEmpty()) {
        
        
if  (LOG.isWarnEnabled()) {
          LOG.warn(
" WARNING: no objects were deployed! Check if you have configured a correct deployer  "  
                  
+ " in your jbpm.cfg.xml file for the type of deployment you want to do. " );
        }
        
      } 
else  {
        
        repositoryCache.set(deployment.getId(), deployment.getObjects());
        
      }
    }
  }

  
// 更新流程定义
   public   void  updateResource(DeploymentImpl deployment, String resourceName,  byte [] bytes) {
    
for  (Deployer deployer: deployers) {
      deployer.updateResource(deployment, resourceName, bytes);
    }
    
    RepositoryCache repositoryCache 
=  EnvironmentImpl.getFromCurrent(RepositoryCache. class );
    repositoryCache.remove(deployment.getId());
  }
}

          RepositoryService主要对外提供部署服务接口

          

public   class  RepositoryServiceImpl  extends  AbstractServiceImpl  implements  RepositoryService {

  
public  NewDeployment createDeployment() {
    
return   new  DeploymentImpl(commandService);
  }

  
public   void  suspendDeployment(String deploymentId) {
    commandService.execute(
new  SuspendDeploymentCmd(deploymentId));
  }

  
public   void  resumeDeployment(String deploymentId) {
    commandService.execute(
new  ResumeDeploymentCmd(deploymentId));
  }

  
public   void  deleteDeployment(String deploymentId) {
    commandService.execute(
new  DeleteDeploymentCmd(deploymentId));
  }

         RepositorySessionImpl主要负责流程部署的持久化,持有一些部署相关的对象

        

public   class  RepositorySessionImpl  implements  RepositorySession {
  
  
private   static  Log log  =  Log.getLog(RepositorySessionImpl. class .getName());
  
  
protected  Session session;
  
protected  RepositoryCache repositoryCache;
  
protected  DeployerManager deployerManager;

  
public  String deploy(NewDeployment deployment) {
    DeploymentImpl deploymentImpl 
=  (DeploymentImpl) deployment;
    
    
long  dbid  =  DbidGenerator.getDbidGenerator().getNextId();
    deploymentImpl.setDbid(dbid);
    deploymentImpl.initResourceLobDbids();
    
    session.save(deploymentImpl); 
//  will also save the attached resources
    deployerManager.deploy(deploymentImpl);

    
return  deploymentImpl.getId();
  }

        RepositoryCacheImpl 封装集合对流程定义进行缓存

       

public   class  RepositoryCacheImpl  implements  RepositoryCache {
  
  Map
< String, Map < String, Object >>  deployments  =   new  HashMap < String, Map < String,Object >> ();
  Map
< Object, DeploymentClassLoader >  deploymentClassLoaders  =   new  HashMap < Object, DeploymentClassLoader > ();

  
public  Object get(String deploymentId, String objectName) {
    Map
< String, Object >  deploymentObjects  =  deployments.get(deploymentId);
    
if  (deploymentObjects == null ) {
      
return   null ;
    }
    
return  deploymentObjects.get(objectName);
  }

  
public   void  set(String deploymentId, String key, Object cachedObject) {
    Map
< String, Object >  objects  =   new  HashMap < String, Object > ();
    objects.put(key, cachedObject);
    set(deploymentId, objects);
  }

         流程引擎的部署环境的初始化涉及流程引擎的各个方面,相对比较复杂,就简单介绍到这里,接下来我们将结合部署环境的初始化进行扩展自定义!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值