Reworked fix for SWF-307.

This commit is contained in:
Erwin Vervaet
2007-06-13 14:42:15 +00:00
parent c599ef28a8
commit 1cfc17dee8
4 changed files with 44 additions and 30 deletions

View File

@@ -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).

View File

@@ -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.
* <p>
* 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.
* <p>
* 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();
}

View File

@@ -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;
* </pre>
*
* @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) {
}
}

View File

@@ -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() {