From e4d595b544c0ea9b35611f638ff232283aaad2da Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Sat, 26 Apr 2008 04:56:54 +0000 Subject: [PATCH] made documentation related to webflow-config consistent with implementation --- ...andler.java => FacesNamespaceHandler.java} | 2 +- .../main/resources/META-INF/spring.handlers | 2 +- .../src/spring-webflow-reference.xml | 2 +- spring-webflow-reference/src/system-setup.xml | 12 +- .../config/hotelbooking-portlet-config.xml | 3 - ...owBuilderServicesBeanDefinitionParser.java | 73 +--- ...ionListenerLoaderBeanDefinitionParser.java | 24 +- .../FlowExecutorBeanDefinitionParser.java | 212 +++--------- .../config/FlowExecutorFactoryBean.java | 312 +++++------------- .../config/FlowExecutorSystemDefaults.java | 91 ----- .../FlowRegistryBeanDefinitionParser.java | 100 ++---- .../config/spring-webflow-config-2.0.xsd | 184 ++++------- .../webflow/mvc/builder/MvcEnvironment.java | 20 ++ .../mvc/builder/MvcViewFactoryCreator.java | 11 +- .../webflow/config/EnableScopesService.java | 15 - .../webflow/config/EnableScopesUser.java | 9 - .../config/FlowExecutorFactoryBeanTests.java | 5 +- .../config/enable-flow-scopes-flowdef.xml | 11 - .../webflow/config/enable-flow-scopes.xml | 42 --- .../webflow/config/flow-executor.xml | 2 +- 20 files changed, 284 insertions(+), 848 deletions(-) rename spring-faces/src/main/java/org/springframework/faces/config/{FacesConfigNamespaceHandler.java => FacesNamespaceHandler.java} (92%) delete mode 100644 spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorSystemDefaults.java delete mode 100644 spring-webflow/src/test/java/org/springframework/webflow/config/EnableScopesService.java delete mode 100644 spring-webflow/src/test/java/org/springframework/webflow/config/EnableScopesUser.java delete mode 100644 spring-webflow/src/test/java/org/springframework/webflow/config/enable-flow-scopes-flowdef.xml delete mode 100644 spring-webflow/src/test/java/org/springframework/webflow/config/enable-flow-scopes.xml diff --git a/spring-faces/src/main/java/org/springframework/faces/config/FacesConfigNamespaceHandler.java b/spring-faces/src/main/java/org/springframework/faces/config/FacesNamespaceHandler.java similarity index 92% rename from spring-faces/src/main/java/org/springframework/faces/config/FacesConfigNamespaceHandler.java rename to spring-faces/src/main/java/org/springframework/faces/config/FacesNamespaceHandler.java index b1cfc74b..08d9ae58 100644 --- a/spring-faces/src/main/java/org/springframework/faces/config/FacesConfigNamespaceHandler.java +++ b/spring-faces/src/main/java/org/springframework/faces/config/FacesNamespaceHandler.java @@ -22,7 +22,7 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport; * * @author Jeremy Grelle */ -public class FacesConfigNamespaceHandler extends NamespaceHandlerSupport { +public class FacesNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("flow-builder-services", new FacesFlowBuilderServicesBeanDefinitionParser()); } diff --git a/spring-faces/src/main/resources/META-INF/spring.handlers b/spring-faces/src/main/resources/META-INF/spring.handlers index be6d3eb7..e2b20c70 100644 --- a/spring-faces/src/main/resources/META-INF/spring.handlers +++ b/spring-faces/src/main/resources/META-INF/spring.handlers @@ -1 +1 @@ -http\://www.springframework.org/schema/faces=org.springframework.faces.config.FacesConfigNamespaceHandler \ No newline at end of file +http\://www.springframework.org/schema/faces=org.springframework.faces.config.FacesNamespaceHandler \ No newline at end of file diff --git a/spring-webflow-reference/src/spring-webflow-reference.xml b/spring-webflow-reference/src/spring-webflow-reference.xml index efb97f47..fbee6aad 100644 --- a/spring-webflow-reference/src/spring-webflow-reference.xml +++ b/spring-webflow-reference/src/spring-webflow-reference.xml @@ -1,6 +1,6 @@ diff --git a/spring-webflow-reference/src/system-setup.xml b/spring-webflow-reference/src/system-setup.xml index b171b88d..f877c016 100644 --- a/spring-webflow-reference/src/system-setup.xml +++ b/spring-webflow-reference/src/system-setup.xml @@ -207,24 +207,18 @@ Use the flow-execution-repository element to tune flow execution persistence settings: ]]> +]]> max-conversations - Tune the max-conversations attribute to place a cap on the number of conversations that can be created per user session. + Tune the max-executions attribute to place a cap on the number of flow executions that can be created per user session. max-snapshots - Tune the max-snapshots attribute to place a cap on the number of flow execution snapshots that can be taken per conversation. - - - - conversation-manager - - Set a custom ConversationManager to completely customize where conversational flow state is persisted. + Tune the max-execution-snapshots attribute to place a cap on the number of history snapshots that can be taken per flow execution. diff --git a/spring-webflow-samples/booking-portlet-mvc/src/main/webapp/WEB-INF/config/hotelbooking-portlet-config.xml b/spring-webflow-samples/booking-portlet-mvc/src/main/webapp/WEB-INF/config/hotelbooking-portlet-config.xml index d0ddb05a..51b98426 100644 --- a/spring-webflow-samples/booking-portlet-mvc/src/main/webapp/WEB-INF/config/hotelbooking-portlet-config.xml +++ b/spring-webflow-samples/booking-portlet-mvc/src/main/webapp/WEB-INF/config/hotelbooking-portlet-config.xml @@ -32,9 +32,6 @@ - - - diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParser.java index e65a0440..2a473665 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowBuilderServicesBeanDefinitionParser.java @@ -15,9 +15,7 @@ */ package org.springframework.webflow.config; -import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; @@ -36,22 +34,6 @@ import org.w3c.dom.Element; */ class FlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { - private static final String FORMATTER_REGISTRY_ATTRIBUTE = "formatter-registry"; - - private static final String CONVERSION_SERVICE_ATTRIBUTE = "conversion-service"; - - private static final String EXPRESSION_PARSER_ATTRIBUTE = "expression-parser"; - - private static final String VIEW_FACTORY_CREATOR_ATTRIBUTE = "view-factory-creator"; - - private static final String FORMATTER_REGISTRY_PROPERTY = "formatterRegistry"; - - private static final String CONVERSION_SERVICE_PROPERTY = "conversionService"; - - private static final String EXPRESSION_PARSER_PROPERTY = "expressionParser"; - - private static final String VIEW_FACTORY_CREATOR_PROPERTY = "viewFactoryCreator"; - protected Class getBeanClass(Element element) { return FlowBuilderServices.class; } @@ -64,66 +46,41 @@ class FlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanDefiniti } private void parseFormatterRegistry(Element element, BeanDefinitionBuilder definitionBuilder, ParserContext context) { - String formatterRegistry = element.getAttribute(FORMATTER_REGISTRY_ATTRIBUTE); + String formatterRegistry = element.getAttribute("formatter-registry"); if (StringUtils.hasText(formatterRegistry)) { - definitionBuilder.addPropertyReference(FORMATTER_REGISTRY_PROPERTY, formatterRegistry); + definitionBuilder.addPropertyReference("formatterRegistry", formatterRegistry); } else { - definitionBuilder.addPropertyValue(FORMATTER_REGISTRY_PROPERTY, DefaultFormatterRegistry - .getSharedInstance()); + definitionBuilder.addPropertyValue("formatterRegistry", DefaultFormatterRegistry.getSharedInstance()); } } private void parseConversionService(Element element, BeanDefinitionBuilder definitionBuilder, ParserContext context) { - String conversionService = element.getAttribute(CONVERSION_SERVICE_ATTRIBUTE); + String conversionService = element.getAttribute("conversion-service"); if (StringUtils.hasText(conversionService)) { - definitionBuilder.addPropertyReference(CONVERSION_SERVICE_PROPERTY, conversionService); + definitionBuilder.addPropertyReference("conversionService", conversionService); } else { - definitionBuilder.addPropertyValue(CONVERSION_SERVICE_PROPERTY, DefaultConversionService - .getSharedInstance()); + definitionBuilder.addPropertyValue("conversionService", DefaultConversionService.getSharedInstance()); } } private void parseExpressionParser(Element element, BeanDefinitionBuilder definitionBuilder, ParserContext context) { - String expressionParser = element.getAttribute(EXPRESSION_PARSER_ATTRIBUTE); + String expressionParser = element.getAttribute("expression-parser"); if (StringUtils.hasText(expressionParser)) { - definitionBuilder.addPropertyReference(EXPRESSION_PARSER_PROPERTY, expressionParser); + definitionBuilder.addPropertyReference("expressionParser", expressionParser); } else { - definitionBuilder.addPropertyValue(EXPRESSION_PARSER_PROPERTY, DefaultExpressionParserFactory - .getExpressionParser()); + definitionBuilder + .addPropertyValue("expressionParser", DefaultExpressionParserFactory.getExpressionParser()); } } private void parseViewFactoryCreator(Element element, BeanDefinitionBuilder definitionBuilder, ParserContext context) { - String viewFactoryCreator = element.getAttribute(VIEW_FACTORY_CREATOR_ATTRIBUTE); + String viewFactoryCreator = element.getAttribute("view-factory-creator"); if (StringUtils.hasText(viewFactoryCreator)) { - definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, viewFactoryCreator); + definitionBuilder.addPropertyReference("viewFactoryCreator", viewFactoryCreator); } else { - definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, createBeanDefinitionForClass( - MvcViewFactoryCreator.class, context).getBeanName()); + definitionBuilder.addPropertyValue("viewFactoryCreator", BeanDefinitionBuilder.genericBeanDefinition( + MvcViewFactoryCreator.class).getBeanDefinition()); } } - private BeanDefinitionHolder createBeanDefinitionForClass(Class clazz, ParserContext context) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz); - BeanDefinitionHolder holder = new BeanDefinitionHolder(builder.getBeanDefinition(), BeanDefinitionReaderUtils - .generateBeanName(builder.getBeanDefinition(), context.getRegistry())); - registerBeanDefinition(holder, context.getRegistry()); - return holder; - } - - public static BeanDefinitionHolder registerDefaultFlowBuilderServicesBeanDefinition(ParserContext context) { - FlowBuilderServicesBeanDefinitionParser parser = new FlowBuilderServicesBeanDefinitionParser(); - BeanDefinitionBuilder defaultBuilder = BeanDefinitionBuilder.genericBeanDefinition(FlowBuilderServices.class); - defaultBuilder.addPropertyValue(FORMATTER_REGISTRY_PROPERTY, DefaultFormatterRegistry.getSharedInstance()); - defaultBuilder.addPropertyValue(CONVERSION_SERVICE_PROPERTY, DefaultConversionService.getSharedInstance()); - defaultBuilder.addPropertyValue(EXPRESSION_PARSER_PROPERTY, DefaultExpressionParserFactory - .getExpressionParser()); - defaultBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, parser.createBeanDefinitionForClass( - MvcViewFactoryCreator.class, context).getBeanName()); - BeanDefinitionHolder holder = new BeanDefinitionHolder(defaultBuilder.getBeanDefinition(), - BeanDefinitionReaderUtils.generateBeanName(defaultBuilder.getBeanDefinition(), context.getRegistry())); - parser.registerBeanDefinition(holder, context.getRegistry()); - return holder; - } - -} +} \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutionListenerLoaderBeanDefinitionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutionListenerLoaderBeanDefinitionParser.java index 6a7b6c2b..5b9dbb20 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutionListenerLoaderBeanDefinitionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutionListenerLoaderBeanDefinitionParser.java @@ -28,31 +28,19 @@ import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** - * {@link BeanDefinitionParser} for the <execution-listeners> tag. + * {@link BeanDefinitionParser} for the <flow-execution-listeners> tag. * * @author Ben Hale */ class FlowExecutionListenerLoaderBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { - // elements and attributes - - private static final String LISTENER_ELEMENT = "listener"; - - private static final String CRITERIA_ATTRIBUTE = "criteria"; - - private static final String REF_ATTRIBUTE = "ref"; - - // properties - - private static final String LISTENERS_PROPERTY = "listeners"; - protected Class getBeanClass(Element element) { return FlowExecutionListenerLoaderFactoryBean.class; } protected void doParse(Element element, BeanDefinitionBuilder definitionBuilder) { - List listenerElements = DomUtils.getChildElementsByTagName(element, LISTENER_ELEMENT); - definitionBuilder.addPropertyValue(LISTENERS_PROPERTY, getListenersWithCriteria(listenerElements)); + List listenerElements = DomUtils.getChildElementsByTagName(element, "listener"); + definitionBuilder.addPropertyValue("listeners", parseListenersWithCriteria(listenerElements)); } /** @@ -61,12 +49,12 @@ class FlowExecutionListenerLoaderBeanDefinitionParser extends AbstractSingleBean * @return a map containing keys that are references to given listeners and values of string that represent the * criteria */ - private Map getListenersWithCriteria(List listeners) { + private Map parseListenersWithCriteria(List listeners) { Map listenersWithCriteria = new ManagedMap(listeners.size()); for (Iterator i = listeners.iterator(); i.hasNext();) { Element listenerElement = (Element) i.next(); - RuntimeBeanReference ref = new RuntimeBeanReference(listenerElement.getAttribute(REF_ATTRIBUTE)); - String criteria = listenerElement.getAttribute(CRITERIA_ATTRIBUTE); + RuntimeBeanReference ref = new RuntimeBeanReference(listenerElement.getAttribute("ref")); + String criteria = listenerElement.getAttribute("criteria"); listenersWithCriteria.put(ref, criteria); } return listenersWithCriteria; diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorBeanDefinitionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorBeanDefinitionParser.java index 6edcc3b6..53c5bee0 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorBeanDefinitionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorBeanDefinitionParser.java @@ -35,129 +35,19 @@ import org.w3c.dom.Element; */ class FlowExecutorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { - // elements and attributes - - private static final String CONVERSATION_MANAGER_REF_ATTRIBUTE = "conversation-manager"; - - private static final String EXECUTION_ATTRIBUTES_ELEMENT = "flow-execution-attributes"; - - private static final String ALWAYS_REDIRECT_ON_PAUSE_ELEMENT = "always-redirect-on-pause"; - - private static final String ATTRIBUTE_ELEMENT = "attribute"; - - private static final String NAME_ATTRIBUTE = "name"; - - private static final String VALUE_ATTRIBUTE = "value"; - - private static final String TYPE_ATTRIBUTE = "type"; - - private static final String EXECUTION_LISTENERS_ELEMENT = "flow-execution-listeners"; - - private static final String MAX_CONTINUATIONS_ATTRIBUTE = "max-continuations"; - - private static final String MAX_CONVERSATIONS_ATTRIBUTE = "max-conversations"; - - private static final String REGISTRY_ATTRIBUTE = "flow-registry"; - - private static final String REPOSITORY_ELEMENT = "flow-execution-repository"; - - // properties - - private static final String CONVERSATION_MANAGER_PROPERTY = "conversationManager"; - - private static final String DEFINITION_LOCATOR_PROPERTY = "flowDefinitionLocator"; - - private static final String REPOSITORY_TYPE_PROPERTY = "flowExecutionRepositoryType"; - - private static final String EXECUTION_ATTRIBUTES_PROPERTY = "flowExecutionAttributes"; - - private static final String EXECUTION_LISTENER_LOADER_PROPERTY = "flowExecutionListenerLoader"; - - private static final String MAX_CONTINUATIONS_PROPERTY = "maxContinuations"; - - private static final String MAX_CONVERSATIONS_PROPERTY = "maxConversations"; - protected Class getBeanClass(Element element) { return FlowExecutorFactoryBean.class; } protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder definitionBuilder) { - definitionBuilder.addPropertyReference(DEFINITION_LOCATOR_PROPERTY, getRegistry(element, parserContext)); - definitionBuilder.addPropertyValue(EXECUTION_ATTRIBUTES_PROPERTY, parseAttributes(element)); - addExecutionListenerLoader(element, parserContext, definitionBuilder); - configureRepository(element, definitionBuilder, parserContext); + definitionBuilder.addPropertyReference("flowDefinitionLocator", getFlowRegistry(element, parserContext)); + addFlowExecutionRepositoryProperties(element, definitionBuilder, parserContext); + definitionBuilder.addPropertyValue("flowExecutionAttributes", parseFlowExecutionAttributes(element)); + addFlowExecutionListenerLoader(element, parserContext, definitionBuilder); } - /** - * Configures a repository based on the repository-type attribute or a repository tag. - * @param element the root element to extract repository configuration from - * @param definitionBuilder the builder - * @param parserContext the parserContext - */ - private void configureRepository(Element element, BeanDefinitionBuilder definitionBuilder, - ParserContext parserContext) { - Element repositoryElement = DomUtils.getChildElementByTagName(element, REPOSITORY_ELEMENT); - if (repositoryElement != null) { - String type = getType(element); - if (StringUtils.hasText(type)) { - definitionBuilder.addPropertyValue(REPOSITORY_TYPE_PROPERTY, type); - } - configureContinuations(repositoryElement, definitionBuilder, parserContext); - configureConversationManager(repositoryElement, definitionBuilder, parserContext); - } - } - - /** - * Configure the max continuations setting. - * @param repositoryElement the repository element - * @param definitionBuilder the builder - * @param parserContext the parserContext - */ - private void configureContinuations(Element repositoryElement, BeanDefinitionBuilder definitionBuilder, - ParserContext parserContext) { - String maxContinuations = getMaxContinuations(repositoryElement); - if (StringUtils.hasText(maxContinuations)) { - String type = getType(repositoryElement); - if (StringUtils.hasText(type) && !type.toLowerCase().equals("CONTINUATION")) { - parserContext.getReaderContext().error( - "The 'max-continuations' attribute of the 'flow-execution-repository' element must not " - + "have a value if the 'type' attribute is not 'continuation'", repositoryElement); - } - definitionBuilder.addPropertyValue(MAX_CONTINUATIONS_PROPERTY, maxContinuations); - } - } - - /** - * Configure the conversation manager - * @param repositoryElement the repository element - * @param definitionBuilder the builder - * @param parserContext the parserContext - */ - private void configureConversationManager(Element repositoryElement, BeanDefinitionBuilder definitionBuilder, - ParserContext parserContext) { - String conversationManagerRef = getConversationManagerRef(repositoryElement); - String maxConversations = getMaxConversations(repositoryElement); - if (StringUtils.hasText(conversationManagerRef)) { - if (StringUtils.hasText(maxConversations)) { - parserContext.getReaderContext().error( - "The 'max-conversations' attribute of the 'flow-execution-repository' element must not " - + "have a value if there is a value for the 'conversation-manager' attribute", - repositoryElement); - } - definitionBuilder.addPropertyReference(CONVERSATION_MANAGER_PROPERTY, conversationManagerRef); - } else if (StringUtils.hasText(maxConversations)) { - definitionBuilder.addPropertyValue(MAX_CONVERSATIONS_PROPERTY, maxConversations); - } - } - - /** - * Returns the name of the registry detailed in the bean definition. - * @param element the element to extract the registry name from - * @return the name of the registry - * @param parserContext the parserContext - */ - private String getRegistry(Element element, ParserContext parserContext) { - String registry = element.getAttribute(REGISTRY_ATTRIBUTE); + private String getFlowRegistry(Element element, ParserContext parserContext) { + String registry = element.getAttribute("flow-registry"); if (!StringUtils.hasText(registry)) { return "flowRegistry"; } else { @@ -165,70 +55,45 @@ class FlowExecutorBeanDefinitionParser extends AbstractSingleBeanDefinitionParse } } - /** - * Returns the name of the repository type enum field detailed in the bean definition. - * @param element the element to extract the repository type from - * @return the type of the repository - */ - private String getType(Element element) { - return element.getAttribute(TYPE_ATTRIBUTE); - } - - /** - * Returns the maximum number of continuations detailed in the bean definition. - * @param element the element to extract the max continuations from - * @return the max continuations - */ - private String getMaxContinuations(Element element) { - return element.getAttribute(MAX_CONTINUATIONS_ATTRIBUTE); - } - - /** - * Returns the maximum number of conversations detailed in the bean definition. - * @param element the element to extract the max conversations from - * @return the max conversations - */ - private String getMaxConversations(Element element) { - return element.getAttribute(MAX_CONVERSATIONS_ATTRIBUTE); - } - - /** - * Returns the name of the conversation manager detailed in the bean definition. - * @param element the element to extract the conversation manager name from - * @return the name of the conversation manager - */ - private String getConversationManagerRef(Element element) { - return element.getAttribute(CONVERSATION_MANAGER_REF_ATTRIBUTE); - } - - /** - * Parse execution listener definitions contained in given element. - */ - private void addExecutionListenerLoader(Element element, ParserContext parserContext, - BeanDefinitionBuilder definitionBuilder) { - Element listenersElement = DomUtils.getChildElementByTagName(element, EXECUTION_LISTENERS_ELEMENT); - if (listenersElement != null) { - definitionBuilder.addPropertyValue(EXECUTION_LISTENER_LOADER_PROPERTY, parserContext.getDelegate() - .parseCustomElement(listenersElement, definitionBuilder.getBeanDefinition())); + private void addFlowExecutionRepositoryProperties(Element element, BeanDefinitionBuilder definitionBuilder, + ParserContext parserContext) { + Element repositoryElement = DomUtils.getChildElementByTagName(element, "flow-execution-repository"); + if (repositoryElement != null) { + addMaxExecutions(repositoryElement, definitionBuilder, parserContext); + addMaxSnapshots(repositoryElement, definitionBuilder, parserContext); } } - private Set parseAttributes(Element element) { - Element executionAttributesElement = DomUtils.getChildElementByTagName(element, EXECUTION_ATTRIBUTES_ELEMENT); + private void addMaxExecutions(Element element, BeanDefinitionBuilder definitionBuilder, ParserContext parserContext) { + String maxConversations = element.getAttribute("max-executions"); + if (StringUtils.hasText(maxConversations)) { + definitionBuilder.addPropertyValue("maxFlowExecutions", maxConversations); + } + } + + private void addMaxSnapshots(Element element, BeanDefinitionBuilder definitionBuilder, ParserContext parserContext) { + String maxSnapshots = element.getAttribute("max-execution-snapshots"); + if (StringUtils.hasText(maxSnapshots)) { + definitionBuilder.addPropertyValue("maxFlowExecutionSnapshots", maxSnapshots); + } + } + + private Set parseFlowExecutionAttributes(Element element) { + Element executionAttributesElement = DomUtils.getChildElementByTagName(element, "flow-execution-attributes"); if (executionAttributesElement != null) { HashSet attributes = new HashSet(); Element redirectElement = DomUtils.getChildElementByTagName(executionAttributesElement, - ALWAYS_REDIRECT_ON_PAUSE_ELEMENT); + "always-redirect-on-pause"); if (redirectElement != null) { - String value = redirectElement.getAttribute(VALUE_ATTRIBUTE); + String value = redirectElement.getAttribute("value"); attributes.add(new FlowElementAttribute("alwaysRedirectOnPause", value, "boolean")); } - List attributeElements = DomUtils.getChildElementsByTagName(executionAttributesElement, ATTRIBUTE_ELEMENT); + List attributeElements = DomUtils.getChildElementsByTagName(executionAttributesElement, "attribute"); for (Iterator it = attributeElements.iterator(); it.hasNext();) { Element attributeElement = (Element) it.next(); - String name = attributeElement.getAttribute(NAME_ATTRIBUTE); - String value = attributeElement.getAttribute(VALUE_ATTRIBUTE); - String type = attributeElement.getAttribute(TYPE_ATTRIBUTE); + String name = attributeElement.getAttribute("name"); + String value = attributeElement.getAttribute("value"); + String type = attributeElement.getAttribute("type"); attributes.add(new FlowElementAttribute(name, value, type)); } return attributes; @@ -236,4 +101,13 @@ class FlowExecutorBeanDefinitionParser extends AbstractSingleBeanDefinitionParse return null; } } + + private void addFlowExecutionListenerLoader(Element element, ParserContext parserContext, + BeanDefinitionBuilder definitionBuilder) { + Element listenersElement = DomUtils.getChildElementByTagName(element, "flow-execution-listeners"); + if (listenersElement != null) { + definitionBuilder.addPropertyValue("flowExecutionListenerLoader", parserContext.getDelegate() + .parseCustomElement(listenersElement, definitionBuilder.getBeanDefinition())); + } + } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorFactoryBean.java index 416c2ca3..18ed81c7 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorFactoryBean.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorFactoryBean.java @@ -18,11 +18,14 @@ package org.springframework.webflow.config; import java.util.Iterator; import java.util.Set; +import org.springframework.beans.BeansException; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.binding.convert.ConversionExecutor; import org.springframework.binding.convert.ConversionService; import org.springframework.binding.convert.service.DefaultConversionService; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; import org.springframework.util.Assert; import org.springframework.webflow.conversation.ConversationManager; import org.springframework.webflow.conversation.impl.SessionBindingConversationManager; @@ -41,73 +44,38 @@ import org.springframework.webflow.execution.repository.impl.DefaultFlowExecutio import org.springframework.webflow.execution.repository.support.FlowExecutionStateRestorer; import org.springframework.webflow.executor.FlowExecutor; import org.springframework.webflow.executor.FlowExecutorImpl; +import org.springframework.webflow.mvc.builder.MvcEnvironment; /** - * 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. + * {@link FlowExecutionRepository} strategy. As a FactoryBean, this class has been designed for use as a + * Spring managed bean. *

* The 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 */ -class FlowExecutorFactoryBean implements FactoryBean, InitializingBean { +class FlowExecutorFactoryBean implements FactoryBean, ApplicationContextAware, InitializingBean { + + private static final String ALWAYS_REDIRECT_ON_PAUSE = "alwaysRedirectOnPause"; - /** - * The locator the executor will use to access flow definitions registered in a central registry. Required. - */ private FlowDefinitionLocator flowDefinitionLocator; - /** - * Execution attributes to apply. - */ + private Integer maxFlowExecutions; + + private Integer maxFlowExecutionSnapshots; + private Set flowExecutionAttributes; - /** - * The loader that will determine which listeners to attach to flow definition executions. - */ private FlowExecutionListenerLoader flowExecutionListenerLoader; - /** - * 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; - - /** - * The maximum number of allowed concurrent conversations in the session. - */ - private Integer maxConversations; - - /** - * The type of execution repository to configure with executors created by this factory. Optional. Will fallback to - * default value if not set. - */ - private FlowExecutionRepositoryType flowExecutionRepositoryType; - - /** - * The maximum number of allowed continuations for a single conversation. Only used when the repository type is - * {@link FlowExecutionRepositoryType#CONTINUATION}. - */ - private Integer maxContinuations; - - /** - * The conversion service to use for type conversion of flow execution attribute values. - */ private ConversionService conversionService = DefaultConversionService.getSharedInstance(); - /** - * The flow executor this factory bean creates. - */ private FlowExecutor flowExecutor; + private MvcEnvironment environment; + /** * Sets the flow definition locator that will locate flow definitions needed for execution. Typically also a * {@link FlowDefinitionRegistry}. Required. @@ -117,6 +85,20 @@ class FlowExecutorFactoryBean implements FactoryBean, InitializingBean { this.flowDefinitionLocator = flowDefinitionLocator; } + /** + * Set the maximum number of allowed flow executions allowed per user. + */ + public void setMaxFlowExecutions(int maxFlowExecutions) { + this.maxFlowExecutions = new Integer(maxFlowExecutions); + } + + /** + * Set the maximum number of history snapshots allowed per flow execution. + */ + public void setMaxFlowExecutionSnapshots(int maxFlowExecutionSnapshots) { + this.maxFlowExecutionSnapshots = new Integer(maxFlowExecutionSnapshots); + } + /** * Sets the system attributes that apply to flow executions launched by the executor created by this factory. * Execution attributes may affect flow execution behavior. @@ -135,84 +117,20 @@ class FlowExecutorFactoryBean implements FactoryBean, InitializingBean { this.flowExecutionListenerLoader = flowExecutionListenerLoader; } - /** - * 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 setFlowExecutionRepositoryType(FlowExecutionRepositoryType repositoryType) { - this.flowExecutionRepositoryType = repositoryType; - } + // implementing ApplicationContextAware - /** - * Set the maximum number of continuation snapshots allowed for a single conversation when using the - */ - public void setMaxContinuations(int maxContinuations) { - this.maxContinuations = new Integer(maxContinuations); - } - - /** - * Set the maximum number of allowed concurrent conversations in the session. This is a convenience setter to allow - * easy configuration of the maxConversations property of the default {@link SessionBindingConversationManager}. Do - * not use this when an explicit conversation manager is configured. - * @see SessionBindingConversationManager#setMaxConversations(int) - */ - public void setMaxConversations(int maxConversations) { - this.maxConversations = new Integer(maxConversations); - } - - /** - * 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. - *

- * By default, a {@link SessionBindingConversationManager} is used. Do not use setMaxConversations when using this - * method. - */ - public void setConversationManager(ConversationManager conversationManager) { - this.conversationManager = conversationManager; - } - - /** - * TODO never called. Sets the conversion service for converting string-encoded flow execution attributes to typed - * values. - * @param conversionService the conversion service - */ - public void setConversionService(ConversionService conversionService) { - this.conversionService = conversionService; + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + environment = MvcEnvironment.environmentFor(applicationContext); } // implementing InitializingBean public void afterPropertiesSet() throws Exception { Assert.notNull(flowDefinitionLocator, "The flow definition locator property is required"); - - // apply defaults - FlowExecutorSystemDefaults defaults = new FlowExecutorSystemDefaults(); - - MutableAttributeMap executionAttributes = defaults.applyExecutionAttributes(createExecutionAttributeMap()); - flowExecutionRepositoryType = defaults.applyIfNecessary(flowExecutionRepositoryType); - - // pass all available parameters to the hook methods so that they - // can participate in the construction process - - // a strategy to restore deserialized flow executions - FlowExecutionStateRestorer executionStateRestorer = createFlowExecutionStateRestorer(flowDefinitionLocator, - executionAttributes, flowExecutionListenerLoader); - - // a repository to store flow executions - FlowExecutionRepository executionRepository = createFlowExecutionRepository(flowExecutionRepositoryType, - executionStateRestorer, conversationManager); - - // a factory for flow executions - FlowExecutionFactory executionFactory = createFlowExecutionFactory(executionAttributes, - flowExecutionListenerLoader, (FlowExecutionKeyFactory) executionRepository); - - // combine all pieces of the puzzle to get an operational flow executor - flowExecutor = createFlowExecutor(flowDefinitionLocator, executionFactory, executionRepository); + MutableAttributeMap executionAttributes = createFlowExecutionAttributes(); + DefaultFlowExecutionRepository executionRepository = createFlowExecutionRepository(executionAttributes); + FlowExecutionFactory executionFactory = createFlowExecutionFactory(executionAttributes, executionRepository); + flowExecutor = new FlowExecutorImpl(flowDefinitionLocator, executionFactory, executionRepository); } // implementing FactoryBean @@ -229,110 +147,7 @@ class FlowExecutorFactoryBean implements FactoryBean, InitializingBean { return flowExecutor; } - // subclassing hook methods - - /** - * 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 specified by the user, could be null in which case the - * default conversation manager should be used - * @return a new flow execution repository instance - */ - protected FlowExecutionRepository createFlowExecutionRepository(FlowExecutionRepositoryType repositoryType, - FlowExecutionStateRestorer executionStateRestorer, ConversationManager conversationManager) { - if (conversationManager == null) { - conversationManager = createDefaultConversationManager(); - } - if (repositoryType == null || repositoryType == FlowExecutionRepositoryType.CONTINUATION) { - DefaultFlowExecutionRepository repository = new DefaultFlowExecutionRepository(conversationManager, - executionStateRestorer); - if (maxContinuations != null) { - repository.setMaxContinuations(maxContinuations.intValue()); - } - return repository; - } else if (repositoryType == FlowExecutionRepositoryType.SIMPLE) { - DefaultFlowExecutionRepository repository = new DefaultFlowExecutionRepository(conversationManager, - executionStateRestorer); - repository.setMaxContinuations(1); - return repository; - } else if (repositoryType == FlowExecutionRepositoryType.SINGLEKEY) { - DefaultFlowExecutionRepository repository = new DefaultFlowExecutionRepository(conversationManager, - executionStateRestorer); - repository.setAlwaysGenerateNewNextKey(false); - return repository; - } else { - throw new IllegalStateException("Cannot create execution repository - unsupported repository type " - + repositoryType); - } - } - - /** - * Create the conversation manager to be used in the default case, e.g. when no explicit conversation manager has - * been configured. This implementation return a {@link SessionBindingConversationManager}. - * @return the default conversation manager - */ - protected ConversationManager createDefaultConversationManager() { - SessionBindingConversationManager conversationManager = new SessionBindingConversationManager(); - if (maxConversations != null) { - conversationManager.setMaxConversations(maxConversations.intValue()); - } - return conversationManager; - } - - /** - * 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, FlowExecutionKeyFactory keyFactory) { - FlowExecutionImplFactory executionFactory = new FlowExecutionImplFactory(); - executionFactory.setExecutionAttributes(executionAttributes); - if (executionListenerLoader != null) { - executionFactory.setExecutionListenerLoader(executionListenerLoader); - } - executionFactory.setExecutionKeyFactory(keyFactory); - return executionFactory; - } - - /** - * 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); - } - - private MutableAttributeMap createExecutionAttributeMap() { + private MutableAttributeMap createFlowExecutionAttributes() { LocalAttributeMap executionAttributes = new LocalAttributeMap(); if (flowExecutionAttributes != null) { for (Iterator it = flowExecutionAttributes.iterator(); it.hasNext();) { @@ -340,9 +155,62 @@ class FlowExecutorFactoryBean implements FactoryBean, InitializingBean { executionAttributes.put(attribute.getName(), getConvertedValue(attribute)); } } + putDefaultFlowExecutionAttributes(executionAttributes); return executionAttributes; } + private void putDefaultFlowExecutionAttributes(LocalAttributeMap executionAttributes) { + if (!executionAttributes.contains(ALWAYS_REDIRECT_ON_PAUSE)) { + if (environment == MvcEnvironment.PORTLET) { + executionAttributes.put(ALWAYS_REDIRECT_ON_PAUSE, Boolean.FALSE); + } else { + executionAttributes.put(ALWAYS_REDIRECT_ON_PAUSE, Boolean.TRUE); + } + } + } + + private DefaultFlowExecutionRepository createFlowExecutionRepository(AttributeMap executionAttributes) { + ConversationManager conversationManager = createConversationManager(); + FlowExecutionStateRestorer executionStateRestorer = createFlowExecutionStateRestorer(executionAttributes); + DefaultFlowExecutionRepository repository = new DefaultFlowExecutionRepository(conversationManager, + executionStateRestorer); + if (maxFlowExecutionSnapshots != null) { + repository.setMaxContinuations(maxFlowExecutionSnapshots.intValue()); + } + return repository; + } + + private ConversationManager createConversationManager() { + SessionBindingConversationManager conversationManager = new SessionBindingConversationManager(); + if (maxFlowExecutions != null) { + conversationManager.setMaxConversations(maxFlowExecutions.intValue()); + } + return conversationManager; + } + + private FlowExecutionStateRestorer createFlowExecutionStateRestorer(AttributeMap executionAttributes) { + FlowExecutionImplStateRestorer executionStateRestorer = new FlowExecutionImplStateRestorer( + flowDefinitionLocator); + executionStateRestorer.setExecutionAttributes(executionAttributes); + if (flowExecutionListenerLoader != null) { + executionStateRestorer.setExecutionListenerLoader(flowExecutionListenerLoader); + } + return executionStateRestorer; + } + + private FlowExecutionFactory createFlowExecutionFactory(AttributeMap executionAttributes, + FlowExecutionKeyFactory keyFactory) { + FlowExecutionImplFactory executionFactory = new FlowExecutionImplFactory(); + executionFactory.setExecutionAttributes(executionAttributes); + if (flowExecutionListenerLoader != null) { + executionFactory.setExecutionListenerLoader(flowExecutionListenerLoader); + } + executionFactory.setExecutionKeyFactory(keyFactory); + return executionFactory; + } + + // utility methods + private Object getConvertedValue(FlowElementAttribute attribute) { if (attribute.needsTypeConversion()) { Class targetType = fromStringToClass(attribute.getType()); diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorSystemDefaults.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorSystemDefaults.java deleted file mode 100644 index 790a9a8c..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowExecutorSystemDefaults.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2004-2008 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.io.Serializable; - -import org.springframework.core.style.ToStringCreator; -import org.springframework.webflow.core.collection.LocalAttributeMap; -import org.springframework.webflow.core.collection.MutableAttributeMap; - -/** - * Encapsulates overall flow system configuration defaults. Allows for centralized application of, and if necessary, - * overridding of system-wide default values. - * - * @author Keith Donald - */ -class FlowExecutorSystemDefaults implements Serializable { - - /** - * The default 'alwaysRedirectOnPause' execution attribute value. - */ - private boolean alwaysRedirectOnPause = true; - - /** - * The default flow execution repository type. - */ - private FlowExecutionRepositoryType repositoryType = FlowExecutionRepositoryType.CONTINUATION; - - /** - * Overrides the alwaysRedirectOnPause execution attribute default. Defaults to "true". - * @param alwaysRedirectOnPause the new default value - */ - public void setAlwaysRedirectOnPause(boolean alwaysRedirectOnPause) { - this.alwaysRedirectOnPause = alwaysRedirectOnPause; - } - - /** - * Overrides the default repository type. - * @param repositoryType the new default value - */ - public void setRepositoryType(FlowExecutionRepositoryType repositoryType) { - this.repositoryType = repositoryType; - } - - /** - * Applies default execution attributes if necessary. Defaults will only apply in the case where the user did not - * configure a value, or explicitly requested the 'default' value. - * @param executionAttributes the user-configured execution attribute map - * @return the map with defaults applied as appropriate - */ - public MutableAttributeMap applyExecutionAttributes(MutableAttributeMap executionAttributes) { - if (executionAttributes == null) { - executionAttributes = new LocalAttributeMap(1, 1); - } - if (!executionAttributes.contains("alwaysRedirectOnPause")) { - executionAttributes.put("alwaysRedirectOnPause", new Boolean(alwaysRedirectOnPause)); - } - return executionAttributes; - } - - /** - * Applies the default repository type if requested by the user. - * @param selectedType the selected repository type (may be null if no selection was made) - * @return the repository type, with the default applied if necessary - */ - public FlowExecutionRepositoryType applyIfNecessary(FlowExecutionRepositoryType selectedType) { - if (selectedType == null) { - return repositoryType; - } else { - return selectedType; - } - } - - public String toString() { - return new ToStringCreator(this).append("alwaysRedirectOnPause", alwaysRedirectOnPause).append( - "repositoryType", repositoryType).toString(); - } -} \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParser.java index 081c1551..c4d64c15 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParser.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParser.java @@ -22,12 +22,18 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.binding.convert.service.DefaultConversionService; +import org.springframework.binding.format.registry.DefaultFormatterRegistry; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; +import org.springframework.webflow.engine.builder.support.FlowBuilderServices; +import org.springframework.webflow.expression.DefaultExpressionParserFactory; +import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator; import org.w3c.dom.Element; /** @@ -37,103 +43,65 @@ import org.w3c.dom.Element; */ class FlowRegistryBeanDefinitionParser extends AbstractSingleBeanDefinitionParser { - private static final String FLOW_BUILDER_SERVICES_ATTRIBUTE = "flow-builder-services"; - - private static final String PARENT_ATTRIBUTE = "parent"; - - private static final String FLOW_LOCATION_ELEMENT = "flow-location"; - - private static final String FLOW_LOCATION_PATTERN_ELEMENT = "flow-location-pattern"; - - private static final String FLOW_BUILDER_ELEMENT = "flow-builder"; - - private static final String ID_ATTRIBUTE = "id"; - - private static final String PATH_ATTRIBUTE = "path"; - - private static final String CLASS_ATTRIBUTE = "class"; - - private static final String DEFINITION_ATTRIBUTES_ELEMENT = "flow-definition-attributes"; - - private static final String ATTRIBUTE_ELEMENT = "attribute"; - - private static final String NAME_ATTRIBUTE = "name"; - - private static final String VALUE_ATTRIBUTE = "value"; - - private static final String TYPE_ATTRIBUTE = "type"; - - private static final String FLOW_LOCATIONS_PROPERTY = "flowLocations"; - - private static final String FLOW_LOCATION_PATTERNS_PROPERTY = "flowLocationPatterns"; - - private static final String FLOW_BUILDERS_PROPERTY = "flowBuilders"; - - private static final String FLOW_BUILDER_SERVICES_PROPERTY = "flowBuilderServices"; - - private static final String PARENT_PROPERTY = "parent"; - protected Class getBeanClass(Element element) { return FlowRegistryFactoryBean.class; } protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder definitionBuilder) { - String flowBuilderServices = getFlowBuilderServicesAttribute(element); + String flowBuilderServices = element.getAttribute("flow-builder-services"); if (StringUtils.hasText(flowBuilderServices)) { - definitionBuilder.addPropertyReference(FLOW_BUILDER_SERVICES_PROPERTY, flowBuilderServices); + definitionBuilder.addPropertyReference("flowBuilderServices", flowBuilderServices); } else { - definitionBuilder.addPropertyReference(FLOW_BUILDER_SERVICES_PROPERTY, - FlowBuilderServicesBeanDefinitionParser.registerDefaultFlowBuilderServicesBeanDefinition( - parserContext).getBeanName()); + definitionBuilder.addPropertyValue("flowBuilderServices", createDefaultFlowBuilderServices(parserContext)); } - String parent = getParentAttribute(element); + String parent = element.getAttribute("parent"); if (StringUtils.hasText(parent)) { - definitionBuilder.addPropertyReference(PARENT_PROPERTY, parent); + definitionBuilder.addPropertyReference("parent", parent); } - definitionBuilder.addPropertyValue(FLOW_LOCATIONS_PROPERTY, parseLocations(element)); - definitionBuilder.addPropertyValue(FLOW_LOCATION_PATTERNS_PROPERTY, parseLocationPatterns(element)); - definitionBuilder.addPropertyValue(FLOW_BUILDERS_PROPERTY, parseFlowBuilders(element)); + definitionBuilder.addPropertyValue("flowLocations", parseLocations(element)); + definitionBuilder.addPropertyValue("flowLocationPatterns", parseLocationPatterns(element)); + definitionBuilder.addPropertyValue("flowBuilders", parseFlowBuilders(element)); } private List parseLocations(Element element) { - List locationElements = DomUtils.getChildElementsByTagName(element, FLOW_LOCATION_ELEMENT); + List locationElements = DomUtils.getChildElementsByTagName(element, "flow-location"); if (locationElements.isEmpty()) { return Collections.EMPTY_LIST; } List locations = new ArrayList(locationElements.size()); for (Iterator it = locationElements.iterator(); it.hasNext();) { Element locationElement = (Element) it.next(); - String id = locationElement.getAttribute(ID_ATTRIBUTE); - String path = locationElement.getAttribute(PATH_ATTRIBUTE); + String id = locationElement.getAttribute("id"); + String path = locationElement.getAttribute("path"); locations.add(new FlowLocation(id, path, parseAttributes(locationElement))); } return locations; } private List parseLocationPatterns(Element element) { - List locationPatternElements = DomUtils.getChildElementsByTagName(element, FLOW_LOCATION_PATTERN_ELEMENT); + List locationPatternElements = DomUtils.getChildElementsByTagName(element, "flow-location-pattern"); if (locationPatternElements.isEmpty()) { return Collections.EMPTY_LIST; } List locationPatterns = new ArrayList(locationPatternElements.size()); for (Iterator it = locationPatternElements.iterator(); it.hasNext();) { Element locationPatternElement = (Element) it.next(); - String value = locationPatternElement.getAttribute(VALUE_ATTRIBUTE); + String value = locationPatternElement.getAttribute("value"); locationPatterns.add(value); } return locationPatterns; } private Set parseAttributes(Element element) { - Element definitionAttributesElement = DomUtils.getChildElementByTagName(element, DEFINITION_ATTRIBUTES_ELEMENT); + Element definitionAttributesElement = DomUtils.getChildElementByTagName(element, "flow-definition-attributes"); if (definitionAttributesElement != null) { - List attributeElements = DomUtils.getChildElementsByTagName(definitionAttributesElement, ATTRIBUTE_ELEMENT); + List attributeElements = DomUtils.getChildElementsByTagName(definitionAttributesElement, "attribute"); HashSet attributes = new HashSet(attributeElements.size()); for (Iterator it = attributeElements.iterator(); it.hasNext();) { Element attributeElement = (Element) it.next(); - String name = attributeElement.getAttribute(NAME_ATTRIBUTE); - String value = attributeElement.getAttribute(VALUE_ATTRIBUTE); - String type = attributeElement.getAttribute(TYPE_ATTRIBUTE); + String name = attributeElement.getAttribute("name"); + String value = attributeElement.getAttribute("value"); + String type = attributeElement.getAttribute("type"); attributes.add(new FlowElementAttribute(name, value, type)); } return attributes; @@ -143,26 +111,28 @@ class FlowRegistryBeanDefinitionParser extends AbstractSingleBeanDefinitionParse } private List parseFlowBuilders(Element element) { - List builderElements = DomUtils.getChildElementsByTagName(element, FLOW_BUILDER_ELEMENT); + List builderElements = DomUtils.getChildElementsByTagName(element, "flow-builder"); if (builderElements.isEmpty()) { return Collections.EMPTY_LIST; } List builders = new ArrayList(builderElements.size()); for (Iterator it = builderElements.iterator(); it.hasNext();) { Element builderElement = (Element) it.next(); - String id = builderElement.getAttribute(ID_ATTRIBUTE); - String className = builderElement.getAttribute(CLASS_ATTRIBUTE); + String id = builderElement.getAttribute("id"); + String className = builderElement.getAttribute("class"); builders.add(new FlowBuilderInfo(id, className, parseAttributes(builderElement))); } return builders; } - private String getFlowBuilderServicesAttribute(Element element) { - return element.getAttribute(FLOW_BUILDER_SERVICES_ATTRIBUTE); - } - - private String getParentAttribute(Element element) { - return element.getAttribute(PARENT_ATTRIBUTE); + private BeanDefinition createDefaultFlowBuilderServices(ParserContext context) { + BeanDefinitionBuilder defaultBuilder = BeanDefinitionBuilder.genericBeanDefinition(FlowBuilderServices.class); + defaultBuilder.addPropertyValue("formatterRegistry", DefaultFormatterRegistry.getSharedInstance()); + defaultBuilder.addPropertyValue("conversionService", DefaultConversionService.getSharedInstance()); + defaultBuilder.addPropertyValue("expressionParser", DefaultExpressionParserFactory.getExpressionParser()); + defaultBuilder.addPropertyValue("viewFactoryCreator", BeanDefinitionBuilder.genericBeanDefinition( + MvcViewFactoryCreator.class).getBeanDefinition()); + return defaultBuilder.getBeanDefinition(); } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd b/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd index b5e3acd2..93b5b8c5 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/spring-webflow-config-2.0.xsd @@ -169,66 +169,7 @@ The fully qualified class name of the FlowBuilder implementation. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -274,6 +215,65 @@ The custom ExpressionParser implementation to use to compile expression strings + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -284,82 +284,26 @@ The custom ViewFactoryCreator implementation to use produce ViewFactories capabl - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcEnvironment.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcEnvironment.java index 81857071..8bbacc07 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcEnvironment.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcEnvironment.java @@ -15,7 +15,11 @@ */ package org.springframework.webflow.mvc.builder; +import org.springframework.context.ApplicationContext; import org.springframework.core.enums.StaticLabeledEnum; +import org.springframework.util.ClassUtils; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.portlet.context.ConfigurablePortletApplicationContext; /** * Supported Spring Web MVC environments. @@ -38,4 +42,20 @@ public class MvcEnvironment extends StaticLabeledEnum { super(code, label); } + /** + * Calculates the web environment from the state of the provided application context. + * @param applicationContext the application context + * @return the web environment the context is running in, or null if not running in a web environment + */ + public static MvcEnvironment environmentFor(ApplicationContext applicationContext) { + if (ClassUtils.isPresent("javax.portlet.PortletContext") + && applicationContext instanceof ConfigurablePortletApplicationContext) { + return MvcEnvironment.PORTLET; + } else if (applicationContext instanceof WebApplicationContext) { + return MvcEnvironment.SERVLET; + } else { + return null; + } + } + } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcViewFactoryCreator.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcViewFactoryCreator.java index 60f57954..5d32e351 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcViewFactoryCreator.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/builder/MvcViewFactoryCreator.java @@ -22,8 +22,6 @@ import org.springframework.binding.expression.ExpressionParser; import org.springframework.binding.format.FormatterRegistry; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; -import org.springframework.util.ClassUtils; -import org.springframework.web.portlet.context.ConfigurablePortletApplicationContext; import org.springframework.web.servlet.View; import org.springframework.web.servlet.ViewResolver; import org.springframework.webflow.engine.builder.ViewFactoryCreator; @@ -113,12 +111,7 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon } public void setApplicationContext(ApplicationContext applicationContext) { - if (ClassUtils.isPresent("javax.portlet.PortletContext") - && applicationContext instanceof ConfigurablePortletApplicationContext) { - environment = MvcEnvironment.PORTLET; - } else { - environment = MvcEnvironment.SERVLET; - } + environment = MvcEnvironment.environmentFor(applicationContext); } public ViewFactory createViewFactory(Expression viewId, ExpressionParser expressionParser, @@ -128,7 +121,7 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon } else if (environment == MvcEnvironment.PORTLET) { return new PortletMvcViewFactory(viewId, flowViewResolver, expressionParser, formatterRegistry); } else { - throw new IllegalStateException("Environment not supported " + environment); + throw new IllegalStateException("Web Environment " + environment + " not supported "); } } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/EnableScopesService.java b/spring-webflow/src/test/java/org/springframework/webflow/config/EnableScopesService.java deleted file mode 100644 index c76bc6b6..00000000 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/EnableScopesService.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.springframework.webflow.config; - -import org.springframework.util.Assert; - -public class EnableScopesService { - private EnableScopesUser user; - - public void setUser(EnableScopesUser user) { - this.user = user; - } - - public void execute() { - Assert.isTrue("foo".equals(user.getName())); - } -} diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/EnableScopesUser.java b/spring-webflow/src/test/java/org/springframework/webflow/config/EnableScopesUser.java deleted file mode 100644 index 7f3104d3..00000000 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/EnableScopesUser.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.springframework.webflow.config; - -public class EnableScopesUser { - private String name = "foo"; - - public String getName() { - return name; - } -} diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/FlowExecutorFactoryBeanTests.java b/spring-webflow/src/test/java/org/springframework/webflow/config/FlowExecutorFactoryBeanTests.java index 3cdda32f..59a5c188 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/FlowExecutorFactoryBeanTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/FlowExecutorFactoryBeanTests.java @@ -66,13 +66,12 @@ public class FlowExecutorFactoryBeanTests extends TestCase { Set attributes = new HashSet(); attributes.add(new FlowElementAttribute("foo", "bar", null)); factoryBean.setFlowExecutionAttributes(attributes); - factoryBean.setFlowExecutionRepositoryType(FlowExecutionRepositoryType.CONTINUATION); FlowExecutionListener listener = new FlowExecutionListenerAdapter() { }; factoryBean.setFlowExecutionListenerLoader(new StaticFlowExecutionListenerLoader(listener)); - factoryBean.setMaxContinuations(2); - factoryBean.setMaxConversations(1); + factoryBean.setMaxFlowExecutionSnapshots(2); + factoryBean.setMaxFlowExecutions(1); factoryBean.afterPropertiesSet(); FlowExecutor executor = (FlowExecutor) factoryBean.getObject(); MockExternalContext context = new MockExternalContext(); diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/enable-flow-scopes-flowdef.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/enable-flow-scopes-flowdef.xml deleted file mode 100644 index 5da4d878..00000000 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/enable-flow-scopes-flowdef.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/enable-flow-scopes.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/enable-flow-scopes.xml deleted file mode 100644 index a3b9d4e4..00000000 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/enable-flow-scopes.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor.xml index 34b2907f..01fbba17 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor.xml +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor.xml @@ -9,7 +9,7 @@ http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd"> - +