From 1cfc17dee8690d135fb916a0c23e14878fc39af7 Mon Sep 17 00:00:00 2001 From: Erwin Vervaet Date: Wed, 13 Jun 2007 14:42:15 +0000 Subject: [PATCH] Reworked fix for SWF-307. --- spring-webflow/changelog.txt | 5 ++-- .../engine/builder/xml/XmlFlowBuilder.java | 24 ++++++++++++------ .../AbstractXmlFlowExecutionTests.java | 20 ++++++++++++++- .../xml/NamedActionXmlFlowBuilderTests.java | 25 ++++--------------- 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/spring-webflow/changelog.txt b/spring-webflow/changelog.txt index f53ffb80..8642359e 100644 --- a/spring-webflow/changelog.txt +++ b/spring-webflow/changelog.txt @@ -35,8 +35,8 @@ Package org.springframework.webflow.engine * Added name(String, Action) method to AbstractFlowBuilder for convenient creation of named actions. * AnnotatedAction now has a convenience putAttribute(String, Object) method. * Added annotate(Action) method to AbstractFlowBuilder. -* Added createLocalBeanFactory(Flow flow, Resource[] resources) hook method to XmlFlowBuilder - to allow for control over the registration of beans needed locally by a flow definition. +* Added createLocalBeanFactory(Flow, Resource[]) and registerLocalBeans(Flow, ConfigurableBeanFactory) hook + methods to XmlFlowBuilder to allow for control over the registration of beans needed locally by a flow definition. Useful for testing (SWF-307). Package org.springframework.webflow.execution @@ -60,6 +60,7 @@ Package org.springframework.webflow.support Package org.springframework.webflow.test * Added the ability to apply multiple listeners to a test case (SWF-334). * Relaxed 'final' qualifier on AbstractXmlFlowExecutionTests#createFlowBuilder(FlowServiceLocator). +* Added registerLocalMockServices(Flow, ConfigurableBeanFactory) hook method to AbstractXmlFlowExecutionTests. Overriding this method is useful for customizing the builder's population of the bean factory local to the flow definition (SWF-307). diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java index 4b50520b..53bb3839 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java @@ -25,6 +25,7 @@ import java.util.List; import javax.xml.parsers.ParserConfigurationException; import org.springframework.beans.factory.BeanFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.binding.convert.ConversionExecutor; import org.springframework.binding.convert.ConversionService; @@ -434,7 +435,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder { return desiredName.equals(node.getNodeName()) || desiredName.equals(node.getLocalName()); } - // internal parsing logic + // internal parsing logic and hook methods private Flow parseFlow(String id, AttributeMap attributes, Element flowElement) { if (!isFlowElement(flowElement)) { @@ -466,11 +467,7 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder { } /** - * Create the local bean factory from the resources provided. This factory typcially houses services needed - * locally by the flow definition. - *

- * Subclasses may override this metod to customize the population of the context local to the flow definition - * being built, registering mock implementations of services for a test environment. + * Create a bean factory serving as a local flow service registry. * @param flow the current flow definition being built * @param resources the file resources to assemble the bean factory from; typically XML-based * @return the bean factory @@ -511,10 +508,23 @@ public class XmlFlowBuilder extends BaseFlowBuilder implements ResourceHolder { } context.setResourceLoader(getFlowServiceLocator().getResourceLoader()); new XmlBeanDefinitionReader(context).loadBeanDefinitions(resources); + registerLocalBeans(flow, context.getDefaultListableBeanFactory()); context.refresh(); return context; } - + + /** + * Register beans in the bean factory local to the flow definition being built. + *

+ * Subclasses may override this metod to customize the population of the bean factory local to + * the flow definition being built, registering mock implementations of services for a test environment. + * @param flow the current flow definition being built + * @param beanFactory the bean factory + * @since 1.0.4 + */ + protected void registerLocalBeans(Flow flow, ConfigurableBeanFactory beanFactory) { + } + private void destroyLocalServiceRegistry() { localFlowServiceLocator.pop(); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/test/execution/AbstractXmlFlowExecutionTests.java b/spring-webflow/src/main/java/org/springframework/webflow/test/execution/AbstractXmlFlowExecutionTests.java index 91e1e647..39dea2c9 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/test/execution/AbstractXmlFlowExecutionTests.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/test/execution/AbstractXmlFlowExecutionTests.java @@ -15,7 +15,9 @@ */ package org.springframework.webflow.test.execution; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.io.Resource; +import org.springframework.webflow.engine.Flow; import org.springframework.webflow.engine.builder.FlowBuilder; import org.springframework.webflow.engine.builder.FlowServiceLocator; import org.springframework.webflow.engine.builder.xml.XmlFlowBuilder; @@ -51,6 +53,7 @@ import org.springframework.webflow.engine.builder.xml.XmlFlowBuilder; * * * @author Keith Donald + * @author Erwin Vervaet */ public abstract class AbstractXmlFlowExecutionTests extends AbstractExternalizedFlowExecutionTests { @@ -72,6 +75,21 @@ public abstract class AbstractXmlFlowExecutionTests extends AbstractExternalized } protected FlowBuilder createFlowBuilder(Resource resource, FlowServiceLocator flowServiceLocator) { - return new XmlFlowBuilder(resource, flowServiceLocator); + return new XmlFlowBuilder(resource, flowServiceLocator) { + protected void registerLocalBeans(Flow flow, ConfigurableBeanFactory beanFactory) { + registerLocalMockServices(flow, beanFactory); + } + }; + } + + /** + * Template method called to allow registration of mock implementations of + * services local to the flow being tested. + * @param flow the flow to register the services for + * @param beanFactory the local flow service registry, you can register services here + * using {@link ConfigurableBeanFactory#registerSingleton(String, Object)} + * @since 1.0.4 + */ + protected void registerLocalMockServices(Flow flow, ConfigurableBeanFactory beanFactory) { } } \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/NamedActionXmlFlowBuilderTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/NamedActionXmlFlowBuilderTests.java index 8e76aa95..7239fbd6 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/NamedActionXmlFlowBuilderTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/xml/NamedActionXmlFlowBuilderTests.java @@ -15,19 +15,14 @@ */ package org.springframework.webflow.engine.builder.xml; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.support.StaticListableBeanFactory; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; import org.springframework.webflow.action.AbstractAction; import org.springframework.webflow.definition.registry.FlowDefinitionResource; import org.springframework.webflow.engine.Flow; -import org.springframework.webflow.engine.builder.FlowBuilder; -import org.springframework.webflow.engine.builder.FlowServiceLocator; import org.springframework.webflow.execution.Action; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.RequestContext; -import org.springframework.webflow.test.MockFlowServiceLocator; import org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests; /** @@ -71,20 +66,10 @@ public class NamedActionXmlFlowBuilderTests extends AbstractXmlFlowExecutionTest new ClassPathResource("namedActionFlow.xml", NamedActionXmlFlowBuilderTests.class)); } - protected void registerMockServices(MockFlowServiceLocator serviceRegistry) { - serviceRegistry.registerBean("aAction", aAction); - serviceRegistry.registerBean("bBean", bBean); - serviceRegistry.registerBean("cAction", cAction); - } - - protected FlowBuilder createFlowBuilder(Resource resource, FlowServiceLocator flowServiceLocator) { - return new XmlFlowBuilder(resource, flowServiceLocator) { - protected BeanFactory createLocalBeanFactory(Flow flow, Resource[] resources) { - StaticListableBeanFactory beanFactory = new StaticListableBeanFactory(); - beanFactory.addBean("bBean", bBean); - return beanFactory; - } - }; + protected void registerLocalMockServices(Flow flow, ConfigurableBeanFactory beanFactory) { + beanFactory.registerSingleton("aAction", aAction); + beanFactory.registerSingleton("cAction", cAction); + beanFactory.registerSingleton("bBean", bBean); } public void testActionExecutionOrder() {