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

org.springframework.webflow.execution.repository.continuation.ContinuationFlowExecutionRepository 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.execution.repository.continuation;

import java.io.Serializable;

import org.springframework.util.Assert;
import org.springframework.webflow.conversation.Conversation;
import org.springframework.webflow.conversation.ConversationManager;
import org.springframework.webflow.execution.FlowExecution;
import org.springframework.webflow.execution.repository.FlowExecutionKey;
import org.springframework.webflow.execution.repository.FlowExecutionRestorationFailureException;
import org.springframework.webflow.execution.repository.support.AbstractConversationFlowExecutionRepository;
import org.springframework.webflow.execution.repository.support.FlowExecutionStateRestorer;
import org.springframework.webflow.util.RandomGuidUidGenerator;
import org.springframework.webflow.util.UidGenerator;

/**
 * Stores one to many flow execution continuations (snapshots) per
 * conversation, where each continuation represents a paused, restorable
 * view-state of a flow execution snapshotted at a point in time.
 * 

* The set of active user conversations are managed by a * {@link ConversationManager} implementation, which this repository delegates * to. *

* This repository is responsible for: *

    *
  • Beginning a new conversation when a new flow execution is made * persistent. Each conversation is assigned a unique conversartion id which * forms one part of the flow execution key. *
  • Associating a flow execution with that conversation by adding a * {@link FlowExecutionContinuation} to a continuation group.
    * When a flow execution is placed in this repository a new continuation * snapshot is created, assigned an id, and added to the group. Each * continuation logically represents a state of the conversation at a point in * time that can be restored and continued. These continuations can be * restored to support users going back in their browser to continue a * conversation from a previous point. *
  • Ending existing conversations when persistent flow executions end, as * part of a repository removal operation. *
*

* This repository implementation also provides support for conversation * invalidation after completion, where once a logical conversation * completes (by one of its FlowExecution's reaching an end state), the entire * conversation (including all continuations) is invalidated. This prevents the * possibility of duplicate submission after completion. *

* This repository implementation should be considered when you do have to * support browser navigational button use, e.g. you cannot lock down the * browser and require that all navigational events to be routed explicitly * through Spring Web Flow. * * @author Keith Donald */ public class ContinuationFlowExecutionRepository extends AbstractConversationFlowExecutionRepository { /** * The conversation attribute that stores the "continuation group". */ private static final String CONTINUATION_GROUP_ATTRIBUTE = "continuationGroup"; /** * The continuation factory that will be used to create new continuations to * be added to active conversations. */ private FlowExecutionContinuationFactory continuationFactory = new SerializedFlowExecutionContinuationFactory(); /** * The uid generation strategy to use. */ private UidGenerator continuationIdGenerator = new RandomGuidUidGenerator(); /** * The maximum number of continuations that can be active per conversation. */ private int maxContinuations; /** * Create a new continuation based flow execution repository using given state * restorer and conversation manager. * @param executionStateRestorer the state restoration strategy to use * @param conversationManager the conversation manager to use */ public ContinuationFlowExecutionRepository(FlowExecutionStateRestorer executionStateRestorer, ConversationManager conversationManager) { super(executionStateRestorer, conversationManager); } /** * Returns the continuation factory that encapsulates the construction of * continuations stored in this repository. Defaults to * {@link SerializedFlowExecutionContinuationFactory}. */ public FlowExecutionContinuationFactory getContinuationFactory() { return continuationFactory; } /** * Sets the continuation factory that encapsulates the construction of * continuations stored in this repository. */ public void setContinuationFactory(FlowExecutionContinuationFactory continuationFactory) { Assert.notNull(continuationFactory, "The continuation factory is required"); this.continuationFactory = continuationFactory; } /** * Returns the uid generation strategy used to generate continuation * identifiers. Defaults to {@link RandomGuidUidGenerator}. */ public UidGenerator getContinuationIdGenerator() { return continuationIdGenerator; } /** * Sets the uid generation strategy used to generate unique continuation * identifiers for {@link FlowExecutionKey flow execution keys}. */ public void setContinuationIdGenerator(UidGenerator continuationIdGenerator) { Assert.notNull(continuationIdGenerator, "The continuation id generator is required"); this.continuationIdGenerator = continuationIdGenerator; } /** * Returns the maximum number of continuations allowed per conversation in * this repository. */ public int getMaxContinuations() { return maxContinuations; } /** * Sets the maximum number of continuations allowed per conversation in this * repository. Use -1 for unlimited. */ public void setMaxContinuations(int maxContinuations) { this.maxContinuations = maxContinuations; } public FlowExecution getFlowExecution(FlowExecutionKey key) { FlowExecutionContinuation continuation = getContinuation(key); try { FlowExecution execution = continuation.unmarshal(); // flow execution was deserialized, so restore transient state return getExecutionStateRestorer().restoreState(execution, getConversationScope(key)); } catch (ContinuationUnmarshalException e) { throw new FlowExecutionRestorationFailureException(key, e); } } public void putFlowExecution(FlowExecutionKey key, FlowExecution flowExecution) { FlowExecutionContinuationGroup continuationGroup = getContinuationGroup(key); FlowExecutionContinuation continuation = continuationFactory.createContinuation(flowExecution); continuationGroup.add(getContinuationId(key), continuation); putConversationScope(key, flowExecution.getConversationScope()); } protected void onBegin(Conversation conversation) { // setup a new continuation group for the conversation FlowExecutionContinuationGroup continuationGroup = new FlowExecutionContinuationGroup(maxContinuations); conversation.putAttribute(CONTINUATION_GROUP_ATTRIBUTE, continuationGroup); } protected Serializable generateContinuationId(FlowExecution flowExecution) { return continuationIdGenerator.generateUid(); } protected Serializable parseContinuationId(String encodedId) { return continuationIdGenerator.parseUid(encodedId); } /** * Returns the continuation group associated with the governing * conversation. * @param key the flow execution key * @return the continuation group */ FlowExecutionContinuationGroup getContinuationGroup(FlowExecutionKey key) { FlowExecutionContinuationGroup group = (FlowExecutionContinuationGroup)getConversation(key).getAttribute(CONTINUATION_GROUP_ATTRIBUTE); return group; } /** * Returns the continuation in the group with the specified key. * @param key the flow execution key * @return the continuation. */ protected FlowExecutionContinuation getContinuation(FlowExecutionKey key) throws FlowExecutionRestorationFailureException { try { return getContinuationGroup(key).get(getContinuationId(key)); } catch (ContinuationNotFoundException e) { throw new FlowExecutionRestorationFailureException(key, e); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy