All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.webflow.config.FlowExecutorFactoryBean Maven / Gradle / Ivy

There is a newer version: 1.0.6
Show newest version
/*
 * Copyright 2002-2006 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.config;

import java.util.Map;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.springframework.webflow.conversation.ConversationManager;
import org.springframework.webflow.conversation.impl.SessionBindingConversationManager;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
import org.springframework.webflow.engine.impl.FlowExecutionImplStateRestorer;
import org.springframework.webflow.execution.FlowExecutionFactory;
import org.springframework.webflow.execution.FlowExecutionListener;
import org.springframework.webflow.execution.factory.FlowExecutionListenerLoader;
import org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader;
import org.springframework.webflow.execution.repository.FlowExecutionRepository;
import org.springframework.webflow.execution.repository.continuation.ClientContinuationFlowExecutionRepository;
import org.springframework.webflow.execution.repository.continuation.ContinuationFlowExecutionRepository;
import org.springframework.webflow.execution.repository.support.FlowExecutionStateRestorer;
import org.springframework.webflow.execution.repository.support.SimpleFlowExecutionRepository;
import org.springframework.webflow.executor.FlowExecutor;
import org.springframework.webflow.executor.FlowExecutorImpl;

/**
 * The default flow executor factory implementation. As a FactoryBean,
 * this class has been designed for use as a Spring managed bean.
 * 

* This factory encapsulates the construction and assembly of a * {@link FlowExecutor}, including the provision of its * {@link FlowExecutionRepository} strategy. *

* The {@link #setDefinitionLocator(FlowDefinitionLocator) definition locator} * property is required, all other properties are optional. *

* This class has been designed with subclassing in mind. If you want to do advanced * Spring Web Flow customization, e.g. using a custom * {@link org.springframework.webflow.executor.FlowExecutor} implementation, * consider subclassing this class and overriding one or more of the provided * hook methods. * * @author Keith Donald * @author Erwin Vervaet */ public class FlowExecutorFactoryBean implements FactoryBean, InitializingBean { /** * The locator the executor will use to access flow definitions registered * in a central registry. Required. */ private FlowDefinitionLocator definitionLocator; /** * Execution attributes to apply. */ private MutableAttributeMap executionAttributes; /** * The loader that will determine which listeners to attach to flow definition executions. */ private FlowExecutionListenerLoader executionListenerLoader; /** * The conversation manager to be used by the flow execution repository to * store state associated with conversations driven by Spring Web Flow. */ private ConversationManager conversationManager = new SessionBindingConversationManager(); /** * The type of execution repository to configure with executors created by * this factory. Optional. Will fallback to default value if not set. */ private RepositoryType repositoryType; /** * The flow executor this factory bean creates. */ private FlowExecutor flowExecutor; /** * Spring Web Flow executor system defaults. */ private FlowSystemDefaults defaults = new FlowSystemDefaults(); /** * Sets the flow definition locator that will locate flow definitions needed * for execution. Typically also a {@link FlowDefinitionRegistry}. Required. * @param definitionLocator the flow definition locator (registry) */ public void setDefinitionLocator(FlowDefinitionLocator definitionLocator) { this.definitionLocator = definitionLocator; } /** * Sets the system attributes that apply to flow executions launched by the * executor created by this factory. Execution attributes may affect flow * execution behavior. *

* Note: this method simply accepts a generic java.util.Map * to allow for easy configuration by Spring. The map entries should consist * of non-null String keys with object values. * @param executionAttributes the flow execution system attributes */ public void setExecutionAttributes(Map executionAttributes) { this.executionAttributes = new LocalAttributeMap(executionAttributes); } /** * Convenience setter that sets a single listener that always applies to flow * executions launched by the executor created by this factory. * @param executionListener the flow execution listener */ public void setExecutionListener(FlowExecutionListener executionListener) { setExecutionListeners(new FlowExecutionListener[] { executionListener }); } /** * Convenience setter that sets a list of listeners that always apply to * flow executions launched by the executor created by this factory. * @param executionListeners the flow execution listeners */ public void setExecutionListeners(FlowExecutionListener[] executionListeners) { setExecutionListenerLoader(new StaticFlowExecutionListenerLoader(executionListeners)); } /** * Sets the strategy for loading the listeners that will observe executions * of a flow definition. Allows full control over what listeners should * apply to executions of a flow definition launched by the executor created * by this factory. */ public void setExecutionListenerLoader(FlowExecutionListenerLoader executionListenerLoader) { this.executionListenerLoader = executionListenerLoader; } /** * Sets the type of flow execution repository that should be configured for * the flow executors created by this factory. This factory encapsulates the * construction of the repository implementation corresponding to the * provided type. * @param repositoryType the flow execution repository type */ public void setRepositoryType(RepositoryType repositoryType) { this.repositoryType = repositoryType; } /** * Sets the strategy for managing conversations that should be configured * for flow executors created by this factory. *

* The conversation manager is used by the flow execution repository * subsystem to begin and end new conversations that store execution state. */ public void setConversationManager(ConversationManager conversationManager) { this.conversationManager = conversationManager; } /** * Set system defaults that should be used. * @param defaults the defaults to use. */ public void setDefaults(FlowSystemDefaults defaults) { this.defaults = defaults; } // implementing InitializingBean public void afterPropertiesSet() throws Exception { Assert.notNull(definitionLocator, "The flow definition locator is required"); // apply defaults executionAttributes = defaults.applyExecutionAttributes(executionAttributes); repositoryType = defaults.applyIfNecessary(repositoryType); // pass all available parameters to the hook methods so that they // can participate in the construction process // a factory for flow executions FlowExecutionFactory executionFactory = createFlowExecutionFactory(executionAttributes, executionListenerLoader); // a strategy to restore deserialized flow executions FlowExecutionStateRestorer executionStateRestorer = createFlowExecutionStateRestorer(definitionLocator, executionAttributes, executionListenerLoader); // a repository to store flow executions FlowExecutionRepository executionRepository = createExecutionRepository(repositoryType, executionStateRestorer, conversationManager); // combine all pieces of the puzzle to get an operational flow executor flowExecutor = createFlowExecutor(definitionLocator, executionFactory, executionRepository); } // subclassing hook methods /** * Create the flow execution factory to be used by the executor produced by this * factory bean. Configure the execution factory appropriately. Subclasses may * override if they which to use a custom execution factory, e.g. to use a custom * FlowExecution implementation. * @param executionAttributes execution attributes to apply to created executions * @param executionListenerLoader decides which listeners to apply to created executions * @return a new flow execution factory instance */ protected FlowExecutionFactory createFlowExecutionFactory( AttributeMap executionAttributes, FlowExecutionListenerLoader executionListenerLoader) { FlowExecutionImplFactory executionFactory = new FlowExecutionImplFactory(); executionFactory.setExecutionAttributes(executionAttributes); if (executionListenerLoader != null) { executionFactory.setExecutionListenerLoader(executionListenerLoader); } return executionFactory; } /** * Create the flow execution state restorer to be used by the executor produced by * this factory bean. Configure the state restorer appropriately. Subclasses may * override if they which to use a custom state restorer implementation. * @param definitionLocator the definition locator to use * @param executionAttributes execution attributes to apply to restored executions * @param executionListenerLoader decides which listeners should apply to restored * flow executions * @return a new state restorer instance */ protected FlowExecutionStateRestorer createFlowExecutionStateRestorer( FlowDefinitionLocator definitionLocator, AttributeMap executionAttributes, FlowExecutionListenerLoader executionListenerLoader) { FlowExecutionImplStateRestorer executionStateRestorer = new FlowExecutionImplStateRestorer(definitionLocator); executionStateRestorer.setExecutionAttributes(executionAttributes); if (executionListenerLoader != null) { executionStateRestorer.setExecutionListenerLoader(executionListenerLoader); } return executionStateRestorer; } /** * Factory method for creating the flow execution repository for saving and * loading executing flows. Subclasses may override to customize the * repository implementation used. * @param repositoryType a hint indicating what type of repository to create * @param executionStateRestorer the execution state restorer strategy to be used by * the repository * @param conversationManager the conversation manager to use * @return a new flow execution repository instance */ protected FlowExecutionRepository createExecutionRepository( RepositoryType repositoryType, FlowExecutionStateRestorer executionStateRestorer, ConversationManager conversationManager) { if (repositoryType == RepositoryType.SIMPLE) { return new SimpleFlowExecutionRepository(executionStateRestorer, conversationManager); } else if (repositoryType == RepositoryType.CONTINUATION) { return new ContinuationFlowExecutionRepository(executionStateRestorer, conversationManager); } else if (repositoryType == RepositoryType.CLIENT) { return new ClientContinuationFlowExecutionRepository(executionStateRestorer, conversationManager); } else if (repositoryType == RepositoryType.SINGLEKEY) { SimpleFlowExecutionRepository repository = new SimpleFlowExecutionRepository(executionStateRestorer, conversationManager); repository.setAlwaysGenerateNewNextKey(false); return repository; } else { throw new IllegalStateException("Cannot create execution repository - unsupported repository type " + repositoryType); } } /** * Create the flow executor instance created by this factory bean and configure * it appropriately. Subclasses may override if they which to use a custom executor * implementation. * @param definitionLocator the definition locator to use * @param executionFactory the execution factory to use * @param executionRepository the execution repository to use * @return a new flow executor instance */ protected FlowExecutor createFlowExecutor( FlowDefinitionLocator definitionLocator, FlowExecutionFactory executionFactory, FlowExecutionRepository executionRepository) { return new FlowExecutorImpl(definitionLocator, executionFactory, executionRepository); } // implementing FactoryBean public Class getObjectType() { return FlowExecutor.class; } public boolean isSingleton() { return true; } public Object getObject() throws Exception { return flowExecutor; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy