config polishing

This commit is contained in:
Keith Donald
2008-03-05 16:45:16 +00:00
parent cae18d7ec0
commit a57b1deb97
15 changed files with 160 additions and 202 deletions

View File

@@ -18,39 +18,24 @@ import org.w3c.dom.Element;
*
* @author Jeremy Grelle
*/
public class FlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
private static final String EXPRESSION_PARSER_ATTRIBUTE = "expression-parser";
private static final String EXPRESSION_PARSER_PROPERTY = "expressionParser";
private static final String VIEW_FACTORY_CREATOR_ATTRIBUTE = "view-factory-creator";
private static final String VIEW_FACTORY_CREATOR_PROPERTY = "viewFactoryCreator";
class FlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
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 CONVERSION_SERVICE_PROPERTY = "conversionService";
public static BeanDefinitionHolder registerDefaultBeanDefinition(ParserContext context) {
FlowBuilderServicesBeanDefinitionParser parser = new FlowBuilderServicesBeanDefinitionParser();
BeanDefinitionBuilder defaultBuilder = BeanDefinitionBuilder.genericBeanDefinition(FlowBuilderServices.class);
defaultBuilder.addPropertyReference(CONVERSION_SERVICE_PROPERTY, parser.createBeanDefinitionForClass(
DefaultConversionService.class, context).getBeanName());
defaultBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, parser.createBeanDefinitionForClass(
MvcViewFactoryCreator.class, context).getBeanName());
defaultBuilder.addPropertyValue(EXPRESSION_PARSER_PROPERTY, DefaultExpressionParserFactory
.getExpressionParser());
BeanDefinitionHolder holder = new BeanDefinitionHolder(defaultBuilder.getBeanDefinition(),
BeanDefinitionReaderUtils.generateBeanName(defaultBuilder.getBeanDefinition(), context.getRegistry()));
parser.registerBeanDefinition(holder, context.getRegistry());
return holder;
}
private static final String EXPRESSION_PARSER_PROPERTY = "expressionParser";
private static final String VIEW_FACTORY_CREATOR_PROPERTY = "viewFactoryCreator";
protected void doParse(Element element, ParserContext context, BeanDefinitionBuilder builder) {
parseConversionService(element, builder, context);
parseExpressionParser(element, builder, context);
parseViewFactoryCreator(element, builder, context);
parseConversionService(element, builder, context);
}
private void parseConversionService(Element element, BeanDefinitionBuilder definitionBuilder, ParserContext context) {
@@ -58,18 +43,7 @@ public class FlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanD
if (StringUtils.hasText(conversionService)) {
definitionBuilder.addPropertyReference(CONVERSION_SERVICE_PROPERTY, conversionService);
} else {
definitionBuilder.addPropertyReference(CONVERSION_SERVICE_PROPERTY, createBeanDefinitionForClass(
DefaultConversionService.class, context).getBeanName());
}
}
private void parseViewFactoryCreator(Element element, BeanDefinitionBuilder definitionBuilder, ParserContext context) {
String viewFactoryCreator = element.getAttribute(VIEW_FACTORY_CREATOR_ATTRIBUTE);
if (StringUtils.hasText(viewFactoryCreator)) {
definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, viewFactoryCreator);
} else {
definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, createBeanDefinitionForClass(
MvcViewFactoryCreator.class, context).getBeanName());
definitionBuilder.addPropertyValue(CONVERSION_SERVICE_PROPERTY, new DefaultConversionService());
}
}
@@ -83,6 +57,16 @@ public class FlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanD
}
}
private void parseViewFactoryCreator(Element element, BeanDefinitionBuilder definitionBuilder, ParserContext context) {
String viewFactoryCreator = element.getAttribute(VIEW_FACTORY_CREATOR_ATTRIBUTE);
if (StringUtils.hasText(viewFactoryCreator)) {
definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, viewFactoryCreator);
} else {
definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, createBeanDefinitionForClass(
MvcViewFactoryCreator.class, context).getBeanName());
}
}
private BeanDefinitionHolder createBeanDefinitionForClass(Class clazz, ParserContext context) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
BeanDefinitionHolder holder = new BeanDefinitionHolder(builder.getBeanDefinition(), BeanDefinitionReaderUtils
@@ -95,4 +79,17 @@ public class FlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanD
return FlowBuilderServices.class;
}
public static BeanDefinitionHolder registerDefaultFlowBuilderServicesBeanDefinition(ParserContext context) {
FlowBuilderServicesBeanDefinitionParser parser = new FlowBuilderServicesBeanDefinitionParser();
BeanDefinitionBuilder defaultBuilder = BeanDefinitionBuilder.genericBeanDefinition(FlowBuilderServices.class);
defaultBuilder.addPropertyValue(CONVERSION_SERVICE_PROPERTY, new DefaultConversionService());
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;
}
}

View File

@@ -20,9 +20,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
@@ -34,7 +33,7 @@ import org.w3c.dom.Element;
*
* @author Keith Donald
*/
class FlowExecutorBeanDefinitionParser extends AbstractBeanDefinitionParser {
class FlowExecutorBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
// elements and attributes
@@ -78,15 +77,15 @@ class FlowExecutorBeanDefinitionParser extends AbstractBeanDefinitionParser {
private static final String MAX_CONVERSATIONS_PROPERTY = "maxConversations";
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
BeanDefinitionBuilder definitionBuilder = BeanDefinitionBuilder
.rootBeanDefinition(FlowExecutorFactoryBean.class);
definitionBuilder.setSource(parserContext.extractSource(element));
protected Class getBeanClass(Element element) {
return FlowExecutorFactoryBean.class;
}
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder definitionBuilder) {
definitionBuilder.addPropertyReference(DEFINITION_LOCATOR_PROPERTY, getRegistryRef(element, parserContext));
definitionBuilder.addPropertyValue(EXECUTION_ATTRIBUTES_PROPERTY, parseAttributes(element));
addExecutionListenerLoader(element, parserContext, definitionBuilder);
configureRepository(element, definitionBuilder, parserContext);
return definitionBuilder.getBeanDefinition();
}
/**

View File

@@ -75,7 +75,8 @@ class FlowRegistryBeanDefinitionParser extends AbstractSingleBeanDefinitionParse
definitionBuilder.addPropertyReference(FLOW_BUILDER_SERVICES_PROPERTY, flowBuilderServices);
} else {
definitionBuilder.addPropertyReference(FLOW_BUILDER_SERVICES_PROPERTY,
FlowBuilderServicesBeanDefinitionParser.registerDefaultBeanDefinition(parserContext).getBeanName());
FlowBuilderServicesBeanDefinitionParser.registerDefaultFlowBuilderServicesBeanDefinition(
parserContext).getBeanName());
}
definitionBuilder.addPropertyValue(FLOW_LOCATIONS_PROPERTY, parseLocations(element));
definitionBuilder.addPropertyValue(FLOW_BUILDERS_PROPERTY, parseFlowBuilders(element));

View File

@@ -3,15 +3,10 @@ package org.springframework.webflow.config;
import java.util.Iterator;
import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.binding.convert.ConversionExecutor;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ClassUtils;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.LocalAttributeMap;
@@ -37,7 +32,7 @@ import org.springframework.webflow.engine.builder.xml.XmlFlowBuilder;
* @author Keith Donald
* @author Jeremy Grelle
*/
class FlowRegistryFactoryBean implements FactoryBean, ResourceLoaderAware, BeanFactoryAware, InitializingBean {
class FlowRegistryFactoryBean implements FactoryBean, InitializingBean {
/**
* The definition registry produced by this factory bean.
@@ -66,16 +61,6 @@ class FlowRegistryFactoryBean implements FactoryBean, ResourceLoaderAware, BeanF
*/
private FlowDefinitionResourceFactory flowResourceFactory;
/**
* The container's resource loader.
*/
private ResourceLoader resourceLoader;
/**
* The containing bean factory this factory bean was deployed in.
*/
private BeanFactory beanFactory;
public void setFlowLocations(FlowLocation[] flowLocations) {
this.flowLocations = flowLocations;
}
@@ -88,16 +73,8 @@ class FlowRegistryFactoryBean implements FactoryBean, ResourceLoaderAware, BeanF
this.flowBuilderServices = flowBuilderServices;
}
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public void afterPropertiesSet() throws Exception {
flowResourceFactory = new FlowDefinitionResourceFactory(resourceLoader);
flowResourceFactory = new FlowDefinitionResourceFactory(flowBuilderServices.getResourceLoader());
flowRegistry = new FlowDefinitionRegistryImpl();
registerFlowLocations();
registerFlowBuilders();

View File

@@ -5,6 +5,7 @@ import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.convert.support.GenericConversionService;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.Assert;
import org.springframework.webflow.action.BeanInvokingActionFactory;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
@@ -26,7 +27,7 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
private FlowBuilderServices flowBuilderServices;
private GenericConversionService flowConversionService;
private ConversionService conversionService;
/**
* Creates a new flow builder context.
@@ -37,14 +38,14 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
*/
public FlowBuilderContextImpl(String flowId, AttributeMap flowAttributes,
FlowDefinitionLocator flowDefinitionLocator, FlowBuilderServices flowBuilderServices) {
Assert.hasText(flowId, "The flow id is required");
Assert.notNull(flowDefinitionLocator, "The flow definition locator is required");
Assert.notNull(flowBuilderServices, "The flow builder services holder is required");
this.flowId = flowId;
this.flowAttributes = flowAttributes;
this.flowDefinitionLocator = flowDefinitionLocator;
this.flowBuilderServices = flowBuilderServices;
flowConversionService = new GenericConversionService();
flowConversionService.addConverter(new TextToTransitionCriteria(this));
flowConversionService.addConverter(new TextToTargetStateResolver(this));
flowConversionService.setParent(this.flowBuilderServices.getConversionService());
this.conversionService = createConversionService();
}
public FlowBuilderServices getFlowBuilderServices() {
@@ -78,7 +79,7 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
}
public ConversionService getConversionService() {
return flowConversionService;
return conversionService;
}
public ResourceLoader getResourceLoader() {
@@ -93,4 +94,18 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
return flowDefinitionLocator;
}
}
/**
* Factory method that creates the conversion service the flow builder will use. Subclasses may override. The
* default implementation registers Web Flow-specific converters thought to be useful for most builder
* implementations, setting the externally-provided builder services conversion service as its parent.
* @return the flow builder conversion service
*/
protected ConversionService createConversionService() {
GenericConversionService service = new GenericConversionService();
service.addConverter(new TextToTransitionCriteria(this));
service.addConverter(new TextToTargetStateResolver(this));
service.setParent(flowBuilderServices.getConversionService());
return service;
}
}

View File

@@ -3,6 +3,7 @@ package org.springframework.webflow.engine.builder.support;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.context.ResourceLoaderAware;
@@ -17,12 +18,18 @@ import org.springframework.webflow.engine.builder.ViewFactoryCreator;
import org.springframework.webflow.execution.Action;
/**
* A simple holder for services needed by a flow builder. These services are typically exposed via a Flow Builder's
* A simple holder for configuring the services used by flow builders. These services are exposed to a builder in a
* {@link FlowBuilderContext}.
*
* Note this class does not attempt to default any service implementations other than the {@link FlowArtifactFactory}
* and {@link BeanInvokingActionFactory}, which are more like builder helper objects than services. It is expected
* clients inject non-null references to concrete service implementations appropriate for their environment.
*
* @see FlowBuilderContextImpl
*
* @author Keith Donald
*/
public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAware {
public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAware, InitializingBean {
/**
* The factory encapsulating the creation of central Flow artifacts such as {@link Flow flows} and
@@ -46,6 +53,7 @@ public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAwar
* The conversion service for converting from one object type to another.
*/
private ConversionService conversionService;
/**
* The parser for parsing expression strings into expression objects. The default is Web Flow's default expression
* parser implementation.
@@ -67,7 +75,6 @@ public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAwar
}
public void setFlowArtifactFactory(FlowArtifactFactory flowArtifactFactory) {
Assert.notNull(flowArtifactFactory, "The flow artifact factory is required");
this.flowArtifactFactory = flowArtifactFactory;
}
@@ -76,7 +83,6 @@ public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAwar
}
public void setBeanInvokingActionFactory(BeanInvokingActionFactory beanInvokingActionFactory) {
Assert.notNull(beanInvokingActionFactory, "The bean invoking action factory is required");
this.beanInvokingActionFactory = beanInvokingActionFactory;
}
@@ -85,7 +91,6 @@ public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAwar
}
public void setViewFactoryCreator(ViewFactoryCreator viewFactoryCreator) {
Assert.notNull("The view factory creator cannot be null");
this.viewFactoryCreator = viewFactoryCreator;
}
@@ -94,7 +99,6 @@ public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAwar
}
public void setConversionService(ConversionService conversionService) {
Assert.notNull(conversionService, "The type conversion service cannot be null");
this.conversionService = conversionService;
}
@@ -103,7 +107,6 @@ public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAwar
}
public void setExpressionParser(ExpressionParser expressionParser) {
Assert.notNull(expressionParser, "The expression parser cannot be null");
this.expressionParser = expressionParser;
}
@@ -112,7 +115,6 @@ public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAwar
}
public void setResourceLoader(ResourceLoader resourceLoader) {
Assert.notNull("The resource loader cannot be null");
this.resourceLoader = resourceLoader;
}
@@ -121,7 +123,19 @@ public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAwar
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
Assert.notNull("The bean factory cannot be null");
this.beanFactory = beanFactory;
}
// implementing InitializingBean
public void afterPropertiesSet() throws Exception {
Assert.notNull(flowArtifactFactory, "The flow artifact factory is required");
Assert.notNull(beanInvokingActionFactory, "The bean invoking action factory is required");
Assert.notNull(viewFactoryCreator, "The view factory creator is required");
Assert.notNull(conversionService, "The type conversion service is required");
Assert.notNull(expressionParser, "The expression parser is required");
Assert.notNull(resourceLoader, "The resource loader is required");
Assert.notNull(beanFactory, "The bean factory is required");
}
}

View File

@@ -1,44 +0,0 @@
package org.springframework.webflow.test;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.binding.convert.support.DefaultConversionService;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.webflow.action.BeanInvokingActionFactory;
import org.springframework.webflow.engine.builder.FlowArtifactFactory;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
import org.springframework.webflow.expression.DefaultExpressionParserFactory;
class FlowBuilderSystemDefaults {
private FlowBuilderServices defaultServices;
public FlowBuilderSystemDefaults() {
defaultServices = new FlowBuilderServices();
defaultServices.setFlowArtifactFactory(new FlowArtifactFactory());
defaultServices.setBeanInvokingActionFactory(new BeanInvokingActionFactory());
defaultServices.setViewFactoryCreator(new MockViewFactoryCreator());
defaultServices.setConversionService(new DefaultConversionService());
defaultServices.setExpressionParser(DefaultExpressionParserFactory.getExpressionParser());
defaultServices.setResourceLoader(new DefaultResourceLoader());
defaultServices.setBeanFactory(new StaticListableBeanFactory());
}
public static FlowBuilderServices get() {
return new FlowBuilderSystemDefaults().createBuilderServices();
}
public FlowBuilderServices createBuilderServices() {
FlowBuilderServices builderServices = new FlowBuilderServices();
applyDefaults(builderServices);
return builderServices;
}
private void applyDefaults(FlowBuilderServices services) {
services.setFlowArtifactFactory(defaultServices.getFlowArtifactFactory());
services.setBeanInvokingActionFactory(defaultServices.getBeanInvokingActionFactory());
services.setViewFactoryCreator(defaultServices.getViewFactoryCreator());
services.setConversionService(defaultServices.getConversionService());
services.setExpressionParser(defaultServices.getExpressionParser());
services.setResourceLoader(defaultServices.getResourceLoader());
services.setBeanFactory(defaultServices.getBeanFactory());
}
}

View File

@@ -49,7 +49,7 @@ public class MockFlowBuilderContext extends FlowBuilderContextImpl {
* Creates a new mock flow service locator.
*/
public MockFlowBuilderContext(String flowId, AttributeMap attributes) {
super(flowId, attributes, new FlowDefinitionRegistryImpl(), FlowBuilderSystemDefaults.get());
super(flowId, attributes, new FlowDefinitionRegistryImpl(), TestFlowBuilderServicesFactory.getServices());
}
/**

View File

@@ -0,0 +1,32 @@
package org.springframework.webflow.test;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.binding.convert.support.DefaultConversionService;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
import org.springframework.webflow.expression.DefaultExpressionParserFactory;
/**
* Factory that encapsulates configuration of default flow builder services for a test environment.
* @author Keith Donald
*/
public class TestFlowBuilderServicesFactory {
private static FlowBuilderServices services;
private TestFlowBuilderServicesFactory() {
}
public static FlowBuilderServices getServices() {
if (services != null) {
return services;
} else {
services = new FlowBuilderServices();
services.setViewFactoryCreator(new MockViewFactoryCreator());
services.setConversionService(new DefaultConversionService());
services.setExpressionParser(DefaultExpressionParserFactory.getExpressionParser());
services.setResourceLoader(new DefaultResourceLoader());
services.setBeanFactory(new StaticListableBeanFactory());
return services;
}
}
}

View File

@@ -23,7 +23,6 @@ import org.springframework.webflow.definition.FlowDefinition;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.builder.FlowAssembler;
import org.springframework.webflow.engine.builder.FlowBuilder;
import org.springframework.webflow.engine.builder.FlowBuilderContext;
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
import org.springframework.webflow.execution.FlowExecutionListener;
import org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader;
@@ -144,34 +143,24 @@ public abstract class AbstractExternalizedFlowExecutionTests extends AbstractFlo
*/
protected final Flow buildFlow() {
FlowDefinitionResource resource = getResource(resourceFactory);
FlowBuilderContext builderContext = createFlowBuilderContext(resource);
MockFlowBuilderContext builderContext = new MockFlowBuilderContext(resource.getId(), resource.getAttributes());
configureFlowBuilderContext(builderContext);
FlowBuilder builder = createFlowBuilder(resource.getPath());
FlowAssembler assembler = new FlowAssembler(builder, builderContext);
return assembler.assembleFlow();
}
/**
* Create the flow builder context to build the flow definition at the resource location provided.
* @param resource the flow definition resource
* @return the flow builder context
*/
protected FlowBuilderContext createFlowBuilderContext(FlowDefinitionResource resource) {
MockFlowBuilderContext builderContext = new MockFlowBuilderContext(resource.getId(), resource.getAttributes());
configure(builderContext);
return builderContext;
}
/**
* Subclasses may override this hook to customize the builder context for the flow being tested. Useful for
* registering mock subflows or other builder services.
* @param builderContext the mock flow builder context.
* registering mock subflows or other builder services. By default, this method does nothing.
* @param builderContext the mock flow builder context to configure
*/
protected void configure(MockFlowBuilderContext builderContext) {
protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) {
}
/**
* Get the flow definition to be tested.
* Get the resource defining the flow to be tested.
* @param resourceFactory a helper for constructing the resource to be tested
* @return the flow definition resource
*/

View File

@@ -28,24 +28,20 @@ import org.springframework.webflow.engine.builder.xml.XmlFlowBuilder;
* <pre>
* public class SearchFlowExecutionTests extends AbstractXmlFlowExecutionTests {
*
* protected FlowDefinitionResource getFlowDefinitionResource() {
* return createFlowDefinitionResource(&quot;src/main/webapp/WEB-INF/flows/search-flow.xml&quot;);
* protected FlowDefinitionResource getResource(FlowDefinitionResourceFactory resourceFactory) {
* return resourceFactory.createClassPathResource(&quot;search-flow.xml&quot;, getClass());
* }
*
* public void testStartFlow() {
* startFlow();
* assertCurrentStateEquals(&quot;displaySearchCriteria&quot;);
* ExternalContext context = new MockExternalContext();
* startFlow(context);
* assertCurrentStateEquals(&quot;enterSearchCriteria&quot;);
* }
*
* public void testDisplayCriteriaSubmitSuccess() {
* startFlow();
* MockParameterMap parameters = new MockParameterMap();
* parameters.put(&quot;firstName&quot;, &quot;Keith&quot;);
* parameters.put(&quot;lastName&quot;, &quot;Donald&quot;);
* ViewSelection view = signalEvent(&quot;search&quot;, parameters);
* assertCurrentStateEquals(&quot;displaySearchResults&quot;);
* assertModelAttributeCollectionSize(1, &quot;results&quot;, view);
* protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) {
* builderContext.registerBean(&quot;searchService&quot;, new TestSearchService());
* }
*
* }
* </pre>
*
@@ -80,8 +76,8 @@ public abstract class AbstractXmlFlowExecutionTests extends AbstractExternalized
/**
* Template method subclasses may override to register mock implementations of services used locally by the flow
* being tested.
* @param flowBeanFactory the local flow service registry; register mock services with it using
* being tested. By default, this method does nothing.
* @param flowBeanFactory the local flow bean factory, you may register mock services with it using
* {@link ConfigurableBeanFactory#registerSingleton(String, Object)}
*/
protected void registerMockFlowBeans(ConfigurableBeanFactory flowBeanFactory) {

View File

@@ -7,19 +7,16 @@ import org.springframework.webflow.definition.FlowDefinition;
import org.springframework.webflow.execution.FlowExecutionListenerAdapter;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.executor.FlowExecutor;
import org.springframework.webflow.test.MockExternalContext;
public class FlowExecutorBeanDefinitionParserTests extends TestCase {
private ClassPathXmlApplicationContext context;
private FlowExecutor executor;
public void setUp() {
context = new ClassPathXmlApplicationContext("org/springframework/webflow/config/flow-executor.xml");
executor = (FlowExecutor) context.getBean("flowExecutor");
}
public void testExecute() {
MockExternalContext context = new MockExternalContext();
public void testConfigOk() {
context.getBean("flowExecutor", FlowExecutor.class);
}
public static class ConfigurationListener extends FlowExecutionListenerAdapter {

View File

@@ -4,12 +4,9 @@ import java.util.HashSet;
import junit.framework.TestCase;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.binding.convert.support.DefaultConversionService;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.webflow.definition.FlowDefinition;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
import org.springframework.webflow.test.TestFlowBuilderServicesFactory;
public class FlowRegistryFactoryBeanTests extends TestCase {
private FlowRegistryFactoryBean factoryBean;
@@ -25,12 +22,8 @@ public class FlowRegistryFactoryBeanTests extends TestCase {
FlowLocation location1 = new FlowLocation("flow1", "org/springframework/webflow/config/flow.xml", attributes);
FlowLocation location2 = new FlowLocation("flow2", "org/springframework/webflow/config/flow.xml", attributes);
FlowLocation[] flowLocations = new FlowLocation[] { location1, location2 };
FlowBuilderServices builderServices = new FlowBuilderServices();
builderServices.setConversionService(new DefaultConversionService());
factoryBean.setFlowBuilderServices(builderServices);
factoryBean.setFlowBuilderServices(TestFlowBuilderServicesFactory.getServices());
factoryBean.setFlowLocations(flowLocations);
factoryBean.setResourceLoader(new DefaultResourceLoader());
factoryBean.setBeanFactory(new StaticListableBeanFactory());
factoryBean.afterPropertiesSet();
FlowDefinitionRegistry registry = (FlowDefinitionRegistry) factoryBean.getObject();
FlowDefinition def = registry.getFlowDefinition("flow1");
@@ -46,11 +39,8 @@ public class FlowRegistryFactoryBeanTests extends TestCase {
public void testGetFlowRegistryGeneratedFlowId() throws Exception {
FlowLocation location1 = new FlowLocation(null, "org/springframework/webflow/config/flow.xml", null);
FlowLocation[] flowLocations = new FlowLocation[] { location1 };
FlowBuilderServices builderServices = new FlowBuilderServices();
factoryBean.setFlowBuilderServices(builderServices);
factoryBean.setFlowBuilderServices(TestFlowBuilderServicesFactory.getServices());
factoryBean.setFlowLocations(flowLocations);
factoryBean.setResourceLoader(new DefaultResourceLoader());
factoryBean.setBeanFactory(new StaticListableBeanFactory());
factoryBean.afterPropertiesSet();
FlowDefinitionRegistry registry = (FlowDefinitionRegistry) factoryBean.getObject();
FlowDefinition def = registry.getFlowDefinition("flow");
@@ -63,10 +53,7 @@ public class FlowRegistryFactoryBeanTests extends TestCase {
FlowLocation location1 = new FlowLocation(null, "org/springframework/webflow/config/flow.xml", null);
FlowLocation[] flowLocations = new FlowLocation[] { location1 };
factoryBean.setFlowLocations(flowLocations);
FlowBuilderServices builderServices = new FlowBuilderServices();
factoryBean.setFlowBuilderServices(builderServices);
factoryBean.setResourceLoader(new DefaultResourceLoader());
factoryBean.setBeanFactory(new StaticListableBeanFactory());
factoryBean.setFlowBuilderServices(TestFlowBuilderServicesFactory.getServices());
factoryBean.afterPropertiesSet();
FlowDefinitionRegistry registry = (FlowDefinitionRegistry) factoryBean.getObject();
FlowDefinition def = registry.getFlowDefinition("flow");

View File

@@ -1,31 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:web="http://www.springframework.org/schema/webflow-config"
xmlns:webflow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">
<web:flow-executor id="flowExecutor" flow-registry="flowRegistry">
<web:flow-execution-repository type="continuation" max-conversations="1" max-continuations="2"/>
<web:flow-execution-attributes>
<web:alwaysRedirectOnPause value="false"/>
<web:attribute name="foo" value="bar"/>
<web:attribute name="bar" value="2" type="integer"/>
</web:flow-execution-attributes>
<web:flow-execution-listeners>
<web:listener ref="listener" criteria="*"/>
</web:flow-execution-listeners>
</web:flow-executor>
<webflow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
<webflow:flow-execution-repository type="continuation" max-conversations="1" max-continuations="2"/>
<webflow:flow-execution-attributes>
<webflow:alwaysRedirectOnPause value="false"/>
<webflow:attribute name="foo" value="bar"/>
<webflow:attribute name="bar" value="2" type="integer"/>
</webflow:flow-execution-attributes>
<webflow:flow-execution-listeners>
<webflow:listener ref="listener" criteria="*"/>
</webflow:flow-execution-listeners>
</webflow:flow-executor>
<bean id="listener" class="org.springframework.webflow.config.FlowExecutorBeanDefinitionParserTests$ConfigurationListener" />
<web:flow-registry id="flowRegistry" flow-builder-services="flowBuilderServices">
<web:flow-location path="org/springframework/webflow/config/flow.xml" />
</web:flow-registry>
<bean id="flowBuilderServices" class="org.springframework.webflow.engine.builder.support.FlowBuilderServices" />
<webflow:flow-registry id="flowRegistry">
<webflow:flow-location path="org/springframework/webflow/config/flow.xml" />
</webflow:flow-registry>
</beans>

View File

@@ -67,7 +67,7 @@ public class SearchFlowExecutionTests extends AbstractXmlFlowExecutionTests {
assertCurrentStateEquals("displayResults");
}
protected void configure(MockFlowBuilderContext builderContext) {
protected void configureFlowBuilderContext(MockFlowBuilderContext builderContext) {
builderContext.getFlowBuilderServices().setExpressionParser(new WebFlowELExpressionParser());
Flow mockDetailFlow = new Flow("detail-flow");
mockDetailFlow.setInputMapper(new AttributeMapper() {