Package org.springframework.webflow.executor

Source Code of org.springframework.webflow.executor.FlowExecutorImpl

/*
* Copyright 2004-2012 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 org.springframework.webflow.executor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.context.ExternalContextHolder;
import org.springframework.webflow.core.FlowException;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.definition.FlowDefinition;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
import org.springframework.webflow.execution.FlowExecution;
import org.springframework.webflow.execution.FlowExecutionFactory;
import org.springframework.webflow.execution.FlowExecutionKey;
import org.springframework.webflow.execution.repository.FlowExecutionLock;
import org.springframework.webflow.execution.repository.FlowExecutionRepository;

/**
* The default implementation of the central facade for <i>driving</i> the execution of flows within an application.
* <p>
* This object is responsible for creating and launching new flow executions as requested by clients, as well as
* resuming existing, paused executions (that were waiting to be resumed in response to a user event).
* <p>
* This object is a facade or entry point into the Spring Web Flow execution system and makes the overall system easier
* to use. The name <i>executor</i> was chosen as <i>executors drive executions</i>.
* <p>
* <b>Commonly used configurable properties</b><br>
* <table border="1">
* <tr>
* <td><b>name</b></td>
* <td><b>description</b></td>
* <td><b>default</b></td>
* </tr>
* <tr>
* <td>definitionLocator</td>
* <td>The service locator responsible for loading flow definitions to execute.</td>
* <td>None</td>
* </tr>
* <tr>
* <td>executionFactory</td>
* <td>The factory responsible for creating new flow executions.</td>
* <td>None</td>
* </tr>
* <tr>
* <td>executionRepository</td>
* <td>The repository responsible for managing flow execution persistence.</td>
* <td>None</td>
* </tr>
* </table>
* </p>
*
* @see FlowDefinitionLocator
* @see FlowExecutionFactory
* @see FlowExecutionRepository
*
* @author Keith Donald
* @author Erwin Vervaet
* @author Colin Sampaleanu
*/
public class FlowExecutorImpl implements FlowExecutor {

  private static final Log logger = LogFactory.getLog(FlowExecutorImpl.class);

  /**
   * The locator to access flow definitions registered in a central registry.
   */
  private FlowDefinitionLocator definitionLocator;

  /**
   * The abstract factory for creating a new execution of a flow definition.
   */
  private FlowExecutionFactory executionFactory;

  /**
   * The repository used to save, update, and load existing flow executions to/from a persistent store.
   */
  private FlowExecutionRepository executionRepository;

  /**
   * Create a new flow executor.
   * @param definitionLocator the locator for accessing flow definitions to execute
   * @param executionFactory the factory for creating executions of flow definitions
   * @param executionRepository the repository for persisting paused flow executions
   */
  public FlowExecutorImpl(FlowDefinitionLocator definitionLocator, FlowExecutionFactory executionFactory,
      FlowExecutionRepository executionRepository) {
    Assert.notNull(definitionLocator, "The locator for accessing flow definitions is required");
    Assert.notNull(executionFactory, "The execution factory for creating new flow executions is required");
    Assert.notNull(executionRepository, "The repository for persisting flow executions is required");
    this.definitionLocator = definitionLocator;
    this.executionFactory = executionFactory;
    this.executionRepository = executionRepository;
  }

  /**
   * Returns the locator to load flow definitions to execute.
   */
  public FlowDefinitionLocator getDefinitionLocator() {
    return definitionLocator;
  }

  /**
   * Returns the abstract factory used to create new executions of a flow.
   */
  public FlowExecutionFactory getExecutionFactory() {
    return executionFactory;
  }

  /**
   * Returns the repository used to save, update, and load existing flow executions to/from a persistent store.
   */
  public FlowExecutionRepository getExecutionRepository() {
    return executionRepository;
  }

  public FlowExecutionResult launchExecution(String flowId, MutableAttributeMap<?> input, ExternalContext context)
      throws FlowException {
    try {
      if (logger.isDebugEnabled()) {
        logger.debug("Launching new execution of flow '" + flowId + "' with input " + input);
      }
      ExternalContextHolder.setExternalContext(context);
      FlowDefinition flowDefinition = definitionLocator.getFlowDefinition(flowId);
      FlowExecution flowExecution = executionFactory.createFlowExecution(flowDefinition);
      flowExecution.start(input, context);
      if (!flowExecution.hasEnded()) {
        FlowExecutionLock lock = executionRepository.getLock(flowExecution.getKey());
        lock.lock();
        try {
          executionRepository.putFlowExecution(flowExecution);
        } finally {
          lock.unlock();
        }
        return createPausedResult(flowExecution);
      } else {
        return createEndResult(flowExecution);
      }
    } finally {
      ExternalContextHolder.setExternalContext(null);
    }
  }

  public FlowExecutionResult resumeExecution(String flowExecutionKey, ExternalContext context) throws FlowException {
    try {
      if (logger.isDebugEnabled()) {
        logger.debug("Resuming flow execution with key '" + flowExecutionKey);
      }
      ExternalContextHolder.setExternalContext(context);
      FlowExecutionKey key = executionRepository.parseFlowExecutionKey(flowExecutionKey);
      FlowExecutionLock lock = executionRepository.getLock(key);
      lock.lock();
      try {
        FlowExecution flowExecution = executionRepository.getFlowExecution(key);
        flowExecution.resume(context);
        if (!flowExecution.hasEnded()) {
          executionRepository.putFlowExecution(flowExecution);
          return createPausedResult(flowExecution);
        } else {
          executionRepository.removeFlowExecution(flowExecution);
          return createEndResult(flowExecution);
        }
      } finally {
        lock.unlock();
      }
    } finally {
      ExternalContextHolder.setExternalContext(null);
    }
  }

  private FlowExecutionResult createEndResult(FlowExecution flowExecution) {
    return FlowExecutionResult.createEndedResult(flowExecution.getDefinition().getId(), flowExecution.getOutcome());
  }

  private FlowExecutionResult createPausedResult(FlowExecution flowExecution) {
    return FlowExecutionResult.createPausedResult(flowExecution.getDefinition().getId(), flowExecution.getKey()
        .toString());
  }

}
TOP

Related Classes of org.springframework.webflow.executor.FlowExecutorImpl

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.