Package com.starflow.wf.engine.handle

Source Code of com.starflow.wf.engine.handle.BaseHandle

/*
* Copyright 2010-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.starflow.wf.engine.handle;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.concurrent.Callable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import com.starflow.wf.core.util.ApplicationContextHolder;
import com.starflow.wf.engine.ExecutorService;
import com.starflow.wf.engine.ProcessEngineException;
import com.starflow.wf.engine.StarFlowState;
import com.starflow.wf.engine.core.Constants;
import com.starflow.wf.engine.event.AbstractFlowEvent;
import com.starflow.wf.engine.event.ActivityStartEvent;
import com.starflow.wf.engine.model.ActivityInst;
import com.starflow.wf.engine.model.ProcessInstance;
import com.starflow.wf.engine.model.elements.ActivityElement;
import com.starflow.wf.engine.transaction.TransactionCallback;
import com.starflow.wf.engine.transaction.TransactionTemplate;
import com.starflow.wf.service.spi.IApplicationExecptionAction;

/**
*
* @author libinsong1204@gmail.com
* @version 1.0
*/
public abstract class BaseHandle implements IHandle {
  protected final Logger logger = LoggerFactory.getLogger(getClass());
 
  /**
   * 执行环节逻辑
   *
   * 异步调用业务逻辑,使用suspend事务策略,忽略异常。
   * 同步调用
   *        join事务策略。只能回滚和忽略异常两种处理方式
   *        suspend事务策略。适合所有处理策略
   *
   * @param event
   * @param actEl
   * @param activityXml
   * @param action
   * @param activityInst
   */
  public void action(final ActivityStartEvent event, final ActivityInst activityInst, ActivityElement activityXml, final IAction action) {
    String invokePattern = activityXml.getInvokePattern();
    final String transactionType = activityXml.getTransactionType();
   
    ExecutorService executor = event.getProcessEngine().getExecutorService();
   
    if(Constants.ACT_AUTO_CALL_SYN.equalsIgnoreCase(invokePattern)) {
      Object result = null;
      //同步调用可以返回运行结果,前提是要设置返回运行结果。
      try {
        result = executor.execute(new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            if(Constants.ACT_TRANSACTION_JOIN.equalsIgnoreCase(transactionType)) {
              return action.execute(event, activityInst);
            } else {
              return executeLogicInNewTransaction(event, activityInst, action);
            }
          }
        }, invokePattern);
       
      } catch (Exception e) {
        handleException(e, event, activityXml);
      }
     
      //执行结果放入相关数据区。
      saveResultRelaData(event, result, activityXml);
    } else {
      //异步执行使用suspend事务。忽略异常
     
      try {
        executor.execute(new Callable<Object>() {
          public Object call() throws Exception {
            return executeLogicInNewTransaction(event, activityInst, action);
          }
        }, invokePattern);
      } catch (Exception e) {
        logger.error("自动环节Action执行失败", e);
      }
    }
  }
 
  /**
   * 执行结果存放到相关数据区。
   * @param result
   * @param activityXml
   */
  protected abstract void saveResultRelaData(ActivityStartEvent event, Object result, ActivityElement activityXml);
 
  /**
   * 异常处理
   *
   * @param e
   * @param event
   * @param activityXml
   */
  protected void handleException(Exception e, ActivityStartEvent event, ActivityElement activityXml) {
    String exceptionStrategy = activityXml.getExceptionStrategy();
   
    if(Constants.ACT_EXCEPTIONSTRATEGY_ROLLBACK.equals(exceptionStrategy))
      throw new ToolAppRollBackException("自动环节Action执行失败", e);
    else if(Constants.ACT_EXCEPTIONSTRATEGY_INTERRUPT.equals(exceptionStrategy)) {
      long activityInstId = event.getActivityInst().getActivityInstId();
      event.getActInstRep().updateActivityStateAndFinalTime(activityInstId, StarFlowState.ACT_APP_EXCEPTION, new Date());
      throw new InterruptStrategyException();
    } else if(Constants.ACT_EXCEPTIONSTRATEGY_APPLICATION.equals(exceptionStrategy)) {
      String beanName = activityXml.getExceptionAction();
      ProcessInstance cloneProcessInstance = new ProcessInstance();
      BeanUtils.copyProperties(event.getProcessInstance(), cloneProcessInstance);
      ActivityInst cloneActivityInst = new ActivityInst();
      BeanUtils.copyProperties(event.getActivityInst(), cloneActivityInst);
      executeExceptionAction(beanName, e, cloneProcessInstance, cloneActivityInst)
    } else if(Constants.ACT_EXCEPTIONSTRATEGY_STEPROLLBACK.equals(exceptionStrategy)) {
      throw new UnsupportedOperationException("单步回退功能没有实现");
      } else {
      logger.error("自动环节Action执行失败", e);
    }
  }
 
  /**
   * 自动环节异常处理逻辑
   * @param beanName
   * @param exception
   * @param cloneProcessInstance
   * @param cloneActivityInst
   * @return
   */
  private void executeExceptionAction(String beanName, Exception exception, ProcessInstance cloneProcessInstance, ActivityInst cloneActivityInst) {
    try {
      //beanName 名称后面没有指定调用方法时。直接调用IToolAppAction.execute
      int index = beanName.indexOf("#");
      IApplicationExecptionAction action = ApplicationContextHolder.getBean(beanName, IApplicationExecptionAction.class);
      if(index == -1) {
        action.execute(exception, cloneProcessInstance, cloneActivityInst);
      } else {
        //反射调用bean指定的方法。
        String methodName = beanName.substring(index + 1);
        if("".equals(beanName))
          throw new ProcessEngineException("IApplicationExecptionAction 实现类Bean:"+beanName+",没有指定方法名称");
       
        beanName = beanName.substring(0, index);
        try {
          Method method = action.getClass().getMethod(methodName, long.class, long.class);
          method.invoke(action, exception, cloneProcessInstance, cloneActivityInst);
        } catch (Exception e) {
          throw new ProcessEngineException("IApplicationExecptionAction 实现类Bean:"+beanName+",没有此方法", e);
        }
      }
    } catch (Exception e) {
      throw new ProcessEngineException("自动环节异常处理逻辑执行失败", e);
    }
  }
 
  /**
   * 挂起当前事务,在一个新事物中执行业务逻辑
   *
   * @param event
   * @param activityInst
   * @param action
   * @return
   */
  protected Object executeLogicInNewTransaction(final AbstractFlowEvent event, final ActivityInst activityInst, final IAction action) {
    TransactionTemplate template = event.getProcessEngine().getTransactionTemplate();
   
    return template.execute(TransactionDefinition.PROPAGATION_REQUIRES_NEW,
        new TransactionCallback<Object>() {

      @Override
      public Object doInTransaction(TransactionStatus status) {
        return action.execute(event, activityInst);
      }
    });
  }
 
  protected static interface IAction {
    public Object execute(AbstractFlowEvent event, ActivityInst activityInst);
  }
}
TOP

Related Classes of com.starflow.wf.engine.handle.BaseHandle

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.