+ com.interface21.SellItemFlow ++]]> +
+ com.interface21.Account ++]]> +
+ /WEB-INF/flows/orderitem-flow.xml ++... are supported as well as wildcard paths such as: +
+ /WEB-INF/flows/**/*-flow.xml ++]]> +
+ com.interface21.SellItemFlow ++]]> +
- * A child registry will delegate to its parent if it cannot fulfill a request to locate a flow definition itself. - * @param parent the parent flow definition registry - */ - public void setParent(FlowDefinitionRegistry parent) { - registry.setParent(parent); - } - - // implementing InitializingBean - - public final void afterPropertiesSet() throws Exception { - init(); - doPopulate(registry); - } - - // implementing FactoryBean - - public Class getObjectType() { - return FlowDefinitionRegistry.class; - } - - public boolean isSingleton() { - return true; - } - - public Object getObject() throws Exception { - // the registry is populated by the time this is called - return getRegistry(); - } - - /** - * Returns the flow definition registry constructed by the factory bean. - */ - public FlowDefinitionRegistry getRegistry() { - return registry; - } - - // subclassing hooks - - /** - * Create the flow definition registry to be populated in {@link #doPopulate(FlowDefinitionRegistry)}. Subclasses - * can override this method if they want to use a custom flow definition registry implementation. - */ - protected FlowDefinitionRegistry createFlowDefinitionRegistry() { - return new FlowDefinitionRegistryImpl(); - } - - /** - * Template method subclasses may override to perform factory bean initialization logic before registry population. - * Will be called before {@link #doPopulate(FlowDefinitionRegistry)}. The default implementation is empty. - */ - protected void init() { - } - - /** - * Template method subclasses must override to perform registry population. - * @param registry the flow definition registry to populate - */ - protected abstract void doPopulate(FlowDefinitionRegistry registry); - -} \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java index 8397d189..4ae093b5 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/ExternalizedFlowDefinitionRegistrar.java @@ -15,13 +15,15 @@ */ package org.springframework.webflow.definition.registry; -import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.Map; import java.util.Set; import org.springframework.core.io.Resource; import org.springframework.core.style.ToStringCreator; +import org.springframework.webflow.engine.builder.FlowServiceLocator; /** * A flow definition registrar that populates a flow definition registry from flow definitions defined within @@ -30,167 +32,139 @@ import org.springframework.core.style.ToStringCreator; *
* Concrete subclasses are expected to derive from this class to provide knowledge about a particular kind of definition * format by implementing the abstract template methods in this class. - *
- * By default, when configuring the {@link #setLocations(Resource[]) locations} property, flow definitions at those - * locations will be assigned a registry identifier equal to the filename of the underlying definition resource, minus - * the filename extension. For example, a XML-based flow definition defined in the file "flow1.xml" will be identified - * as "flow1" when registered in a registry. - *
- * For full control over the assignment of flow identifiers and flow properties, configure formal - * {@link org.springframework.webflow.definition.registry.FlowDefinitionResource} instances using the - * {@link #setResources(FlowDefinitionResource[] resources)} property. * * @see org.springframework.webflow.definition.registry.FlowDefinitionResource * @see org.springframework.webflow.definition.registry.FlowDefinitionRegistry * * @author Keith Donald + * @author Ben Hale */ public abstract class ExternalizedFlowDefinitionRegistrar implements FlowDefinitionRegistrar { /** - * File locations of externalized flow definition resources to load. A set of {@link Resource}} objects. + * The locator of services needed by flow definitions. */ - private Set locations = new HashSet(); + private FlowServiceLocator flowServiceLocator; /** - * A set of formal externalized flow definitions to load. A set of {@link FlowDefinitionResource} objects. + * A set of mappings between a namespace and a set of externalized flow definitions. A map of Strings to Sets + * containing {@link FlowDefinitionResource}s */ - private Set resources = new HashSet(); + private Map namespaceFlowMappings; /** - * Sets the locations (file paths) pointing to externalized flow definitions. - *
- * Flows registered from this set will be automatically assigned an id based on the filename of the flow resource. - * @param locations the resource locations + * The default namespace for flows registered without an explicit namespace. */ - public void setLocations(Resource[] locations) { - this.locations = new HashSet(Arrays.asList(locations)); + private String defaultNamespace = ""; + + /** + * Creates a new registrar with an empty initial set of namespace to flow mappings. + */ + public ExternalizedFlowDefinitionRegistrar() { + this(new HashMap()); } /** - * Sets the formal set of externalized flow definitions this registrar will register. - *
- * Use this method when you want full control over the assigned flow id and the set of properties applied to the - * externalized flow resources. - * @param resources the externalized flow definition specifications + * Creates a new registrar with an initial set of namespace to flow mappings. + * @param namespaceFlowMappings the initial set of namespace to flow mappings */ - public void setResources(FlowDefinitionResource[] resources) { - this.resources = new HashSet(Arrays.asList(resources)); + public ExternalizedFlowDefinitionRegistrar(Map namespaceFlowMappings) { + this.namespaceFlowMappings = namespaceFlowMappings; } /** - * Adds a flow location pointing to an externalized flow resource. - *
- * The flow registered from this location will automatically assigned an id based on the filename of the flow - * resource. - * @param location the definition location + * Sets the default namespace to register flows in. If not set the default namespace is "" (an empty string). + * @param defaultNamespace the default namespace + */ + public void setDefaultNamespace(String defaultNamespace) { + this.defaultNamespace = defaultNamespace; + } + + public void setFlowServiceLocator(FlowServiceLocator flowServiceLocator) { + this.flowServiceLocator = flowServiceLocator; + } + + /** + * Returns the flow service locator for use by subclasses. + */ + protected FlowServiceLocator getFlowServiceLocator() { + return flowServiceLocator; + } + + /** + * Adds an externalized XML flow definition to be registered in the default namespace. + * @param location the resource to register + * @see #addLocation(Resource, String) + * @see #setDefaultNamespace(String) */ public boolean addLocation(Resource location) { - return locations.add(location); + return addLocation(location, defaultNamespace); } /** - * Adds the flow locations pointing to externalized flow resources. - *
- * The flow registered from this location will automatically assigned an id based on the filename of the flow
- * resource.
- * @param locations the definition locations
+ * Adds an externalized XML flow definition to be registered. The resource will be assigned a registry identifier
+ * equal to the filename of the resource, minus the filename extension. For example, an XML-based flow definition
+ * defined in the file flow1.xml will be identified as flow1 in the registry created
+ * by this factory bean.
+ * @param location the resource to register
+ * @param namespace the namespace to register the flow definition in
*/
- public boolean addLocations(Resource[] locations) {
- if (locations == null) {
- return false;
- }
- return this.locations.addAll(Arrays.asList(locations));
+ public boolean addLocation(Resource location, String namespace) {
+ return getFlows(namespace).add(new FlowDefinitionResource(location));
}
/**
- * Adds an externalized flow definition specification pointing to an externalized flow resource.
- *
- * Use this method when you want full control over the assigned flow id and the set of properties applied to the - * externalized flow resource. - * @param resource the definition the definition resource + * Adds an externalized XML flow definition resource to be registered in the default namespace. + * @param resource the flow definition resource to be registered + * @see #addResource(FlowDefinitionResource, String) + * @see #setDefaultNamespace(String) */ public boolean addResource(FlowDefinitionResource resource) { - return resources.add(resource); + return addResource(resource, defaultNamespace); } /** - * Adds the externalized flow definitions pointing to externalized flow resources. - *
- * Use this method when you want full control over the assigned flow id and the set of properties applied to the - * externalized flow resources. - * @param resources the definitions + * Adds an externalized XML flow definition resource to be registered. + * @param resource the flow definition resource to be registered + * @param namespace the namespace to register the flow definition in */ - public boolean addResources(FlowDefinitionResource[] resources) { - if (resources == null) { - return false; - } - return this.resources.addAll(Arrays.asList(resources)); + public boolean addResource(FlowDefinitionResource resource, String namespace) { + return getFlows(namespace).add(resource); } public void registerFlowDefinitions(FlowDefinitionRegistry registry) { - processLocations(registry); - processResources(registry); - } - - // internal helpers - - /** - * Register the flow definitions at the configured file locations. - * @param registry the registry - */ - private void processLocations(FlowDefinitionRegistry registry) { - Iterator it = locations.iterator(); - while (it.hasNext()) { - Resource location = (Resource) it.next(); - if (isFlowDefinitionResource(location)) { - FlowDefinitionResource resource = createFlowDefinitionResource(location); - register(resource, registry); + for (Iterator mappings = namespaceFlowMappings.entrySet().iterator(); mappings.hasNext();) { + Map.Entry mapping = (Map.Entry) mappings.next(); + String namespace = (String) mapping.getKey(); + for (Iterator resources = ((Set) mapping.getValue()).iterator(); resources.hasNext();) { + FlowDefinitionResource resource = (FlowDefinitionResource) resources.next(); + register(resource, namespace, registry); } } } /** - * Register the flow definitions at the configured file locations. + * Registers a flow definition resource in a given namespace. + * @param resource the resource to register + * @param namespace the namespace to register in * @param registry the registry */ - private void processResources(FlowDefinitionRegistry registry) { - Iterator it = resources.iterator(); - while (it.hasNext()) { - FlowDefinitionResource resource = (FlowDefinitionResource) it.next(); - register(resource, registry); + private void register(FlowDefinitionResource resource, String namespace, FlowDefinitionRegistry registry) { + registry.registerFlowDefinition(createFlowDefinitionHolder(resource), namespace); + } + + /** + * Returns the set of flows to be registered in a namespace. + * @param namespace The namespace for the collection to be returned + */ + private Set getFlows(String namespace) { + if (!namespaceFlowMappings.containsKey(namespace)) { + namespaceFlowMappings.put(namespace, new HashSet()); } + return (Set) namespaceFlowMappings.get(namespace); } - /** - * Helper method to register the flow built from an externalized resource in the registry. - * @param resource representation of the externalized flow definition resource - * @param registry the flow registry to register the flow in - */ - protected final void register(FlowDefinitionResource resource, FlowDefinitionRegistry registry) { - registry.registerFlowDefinition(createFlowDefinitionHolder(resource)); - } - - // subclassing hooks - - /** - * Template method that calculates if the given file resource is actually a flow definition resource. Resources that - * aren't flow definitions will be ignored. Subclasses may override; this implementation simply returns true. - * @param resource the underlying resource - * @return true if yes, false otherwise - */ - protected boolean isFlowDefinitionResource(Resource resource) { - return true; - } - - /** - * Factory method that creates a flow definition from an externalized resource location. - * @param location the location of the resource - * @return the externalized flow definition pointer - */ - protected FlowDefinitionResource createFlowDefinitionResource(Resource location) { - return new FlowDefinitionResource(location); - } + // sub-classing hooks /** * Template factory method subclasses must override to return the holder for the flow definition to be registered @@ -201,6 +175,6 @@ public abstract class ExternalizedFlowDefinitionRegistrar implements FlowDefinit protected abstract FlowDefinitionHolder createFlowDefinitionHolder(FlowDefinitionResource resource); public String toString() { - return new ToStringCreator(this).append("locations", locations).append("resources", resources).toString(); + return new ToStringCreator(this).append("namespaceFlowMappings", namespaceFlowMappings).toString(); } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistrar.java b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistrar.java index ac0841e4..e359005b 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistrar.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistrar.java @@ -15,6 +15,7 @@ */ package org.springframework.webflow.definition.registry; + /** * A strategy to use to populate a flow definition registry with one or more flow definitions. *
@@ -42,4 +43,5 @@ public interface FlowDefinitionRegistrar { * @param registry the registry to register flow definitions in */ public void registerFlowDefinitions(FlowDefinitionRegistry registry); + } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuilderFlowRegistryFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuilderFlowRegistryFactoryBean.java deleted file mode 100644 index 2bf26def..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuilderFlowRegistryFactoryBean.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2004-2007 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.engine.builder; - -import org.springframework.webflow.core.collection.AttributeMap; -import org.springframework.webflow.definition.registry.FlowDefinitionHolder; -import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; -import org.springframework.webflow.definition.registry.StaticFlowDefinitionHolder; -import org.springframework.webflow.engine.Flow; -import org.springframework.webflow.engine.builder.AbstractFlowBuilder; -import org.springframework.webflow.engine.builder.AbstractFlowBuildingFlowRegistryFactoryBean; -import org.springframework.webflow.engine.builder.FlowAssembler; - -/** - * Base class for factory beans that create flow definition registries containing flows built using Java based - * {@link AbstractFlowBuilder flow builders}. - *
- * Subclasses only need to define the {@link #doPopulate(FlowDefinitionRegistry)} method and use the - * {@link #registerFlowDefinition(FlowDefinitionRegistry, String, AbstractFlowBuilder)} convenience methods provided by - * this class to register all relevant flows: - * - *
- * public class MyFlowRegistryFactoryBean extends AbstractFlowBuilderFlowRegistryFactoryBean {
- * protected void doPopulate(FlowDefinitionRegistry registry) {
- * registerFlowDefinition(registry, "my-flow", new MyFlowBuilder());
- * registerFlowDefinition(registry, "my-other-flow", new MyOtherFlowBuilder());
- * }
- * }
- *
- *
- * @see AbstractFlowBuilder
- *
- * @since 1.0.2
- *
- * @author Erwin Vervaet
- */
-public abstract class AbstractFlowBuilderFlowRegistryFactoryBean extends AbstractFlowBuildingFlowRegistryFactoryBean {
-
- /**
- * Register the flow built by given flow builder in specified flow definition registry.
- * - * Note that this method will set the {@link #getFlowServiceLocator() flow service locator} of this class on given - * flow builder. - * @param registry the registry to register the flow in - * @param flowId the flow id to assign - * @param flowBuilder the builder used to build the flow - */ - protected void registerFlowDefinition(FlowDefinitionRegistry registry, String flowId, - AbstractFlowBuilder flowBuilder) { - registerFlowDefinition(registry, flowId, null, flowBuilder); - } - - /** - * Register the flow built by given flow builder in specified flow definition registry. - *
- * Note that this method will set the {@link #getFlowServiceLocator() flow service locator} of this class on given - * flow builder. - * @param registry the registry to register the flow in - * @param flowId the flow id to assign - * @param flowAttributes externally assigned flow attributes that can affect flow construction - * @param flowBuilder the builder used to build the flow - */ - protected void registerFlowDefinition(FlowDefinitionRegistry registry, String flowId, AttributeMap flowAttributes, - AbstractFlowBuilder flowBuilder) { - flowBuilder.setFlowServiceLocator(getFlowServiceLocator()); - Flow flow = new FlowAssembler(flowId, flowAttributes, flowBuilder).assembleFlow(); - FlowDefinitionHolder flowHolder = new StaticFlowDefinitionHolder(flow); - registry.registerFlowDefinition(flowHolder); - } -} diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuildingFlowRegistryFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuildingFlowRegistryFactoryBean.java deleted file mode 100644 index eff88afa..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/AbstractFlowBuildingFlowRegistryFactoryBean.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright 2004-2007 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.engine.builder; - -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.binding.convert.ConversionService; -import org.springframework.binding.expression.ExpressionParser; -import org.springframework.context.ResourceLoaderAware; -import org.springframework.core.io.ResourceLoader; -import org.springframework.webflow.action.BeanInvokingActionFactory; -import org.springframework.webflow.definition.registry.AbstractFlowDefinitionRegistryFactoryBean; -import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; -import org.springframework.webflow.engine.Flow; -import org.springframework.webflow.engine.State; -import org.springframework.webflow.execution.Action; - -/** - * A base class for factory beans that create populated registries of flow definitions built using a {@link FlowBuilder}, - * typically a {@link BaseFlowBuilder} subclass. This base class will setup a {@link FlowServiceLocator} for use by the - * flow builder. - *
- * Subclasses should override the {@link #doPopulate(FlowDefinitionRegistry)} template method to perform the registry - * population logic, typically delegating to a - * {@link org.springframework.webflow.definition.registry.FlowDefinitionRegistrar} strategy. - * - * @see org.springframework.webflow.definition.registry.FlowDefinitionRegistry - * @see org.springframework.webflow.definition.registry.FlowDefinitionRegistrar - * - * @author Keith Donald - */ -public abstract class AbstractFlowBuildingFlowRegistryFactoryBean extends AbstractFlowDefinitionRegistryFactoryBean - implements BeanFactoryAware, ResourceLoaderAware { - - /** - * The locator of services needed by the flows built for inclusion in the registry. - */ - private FlowServiceLocator flowServiceLocator; - - /** - * The factory encapsulating the creation of central Flow artifacts such as {@link Flow flows} and - * {@link State states}. - */ - private FlowArtifactFactory flowArtifactFactory; - - /** - * The factory encapsulating the creation of bean invoking actions, actions that adapt methods on objects to the - * {@link Action} interface. - */ - private BeanInvokingActionFactory beanInvokingActionFactory; - - /** - * The parser for parsing expression strings into evaluatable expression objects. - */ - private ExpressionParser expressionParser; - - /** - * A conversion service that can convert between types. - */ - private ConversionService conversionService; - - /** - * A resource loader that can load resources. - */ - private ResourceLoader resourceLoader; - - /** - * The Spring bean factory that manages configured flow artifacts. - */ - private BeanFactory beanFactory; - - /** - * Returns the factory encapsulating the creation of central Flow artifacts such as {@link Flow flows} and - * {@link State states}. - */ - protected FlowArtifactFactory getFlowArtifactFactory() { - return flowArtifactFactory; - } - - /** - * Sets the factory encapsulating the creation of central Flow artifacts such as {@link Flow flows} and - * {@link State states}. - */ - public void setFlowArtifactFactory(FlowArtifactFactory flowArtifactFactory) { - this.flowArtifactFactory = flowArtifactFactory; - } - - /** - * Returns the factory for creating bean invoking actions, actions that adapt methods on objects to the - * {@link Action} interface. - */ - protected BeanInvokingActionFactory getBeanInvokingActionFactory() { - return beanInvokingActionFactory; - } - - /** - * Sets the factory for creating bean invoking actions, actions that adapt methods on objects to the {@link Action} - * interface. - */ - public void setBeanInvokingActionFactory(BeanInvokingActionFactory beanInvokingActionFactory) { - this.beanInvokingActionFactory = beanInvokingActionFactory; - } - - /** - * Returns the expression parser responsible for parsing expression strings into evaluatable expression objects. - */ - protected ExpressionParser getExpressionParser() { - return expressionParser; - } - - /** - * Set the expression parser responsible for parsing expression strings into evaluatable expression objects. - */ - public void setExpressionParser(ExpressionParser expressionParser) { - this.expressionParser = expressionParser; - } - - /** - * Returns the conversion service to use to convert between types; typically from string to a rich object type. - */ - protected ConversionService getConversionService() { - return conversionService; - } - - /** - * Set the conversion service to use to convert between types; typically from string to a rich object type. - */ - public void setConversionService(ConversionService conversionService) { - this.conversionService = conversionService; - } - - // implementing ResourceLoaderAware - - /** - * Returns the injected resource loader. - */ - protected ResourceLoader getResourceLoader() { - return resourceLoader; - } - - public void setResourceLoader(ResourceLoader resourceLoader) { - this.resourceLoader = resourceLoader; - } - - // implementing BeanFactoryAware - - /** - * Returns the bean factory managing this bean. - */ - protected BeanFactory getBeanFactory() { - return beanFactory; - } - - public void setBeanFactory(BeanFactory beanFactory) { - this.beanFactory = beanFactory; - } - - protected final void init() { - flowServiceLocator = createFlowServiceLocator(); - init(flowServiceLocator); - } - - // subclassing hooks - - /** - * Factory method for creating the service locator used to locate webflow services during flow assembly. Subclasses - * may override to customize the instantiation and configuration of the locator returned. - * @return the service locator - */ - protected FlowServiceLocator createFlowServiceLocator() { - DefaultFlowServiceLocator serviceLocator = new DefaultFlowServiceLocator(getRegistry(), beanFactory); - if (flowArtifactFactory != null) { - serviceLocator.setFlowArtifactFactory(flowArtifactFactory); - } - if (beanInvokingActionFactory != null) { - serviceLocator.setBeanInvokingActionFactory(beanInvokingActionFactory); - } - if (expressionParser != null) { - serviceLocator.setExpressionParser(expressionParser); - } - if (conversionService != null) { - serviceLocator.setConversionService(conversionService); - } - if (resourceLoader != null) { - serviceLocator.setResourceLoader(resourceLoader); - } - return serviceLocator; - } - - /** - * Called after properties have been set on the service locator, but before registry population. Subclasses may - * override to perform custom initialization of the flow service locator. - * @param flowServiceLocator the flow service locator to use to locate externally managed services needed during - * flow building and assembly, typically used by a - * {@link org.springframework.webflow.definition.registry.FlowDefinitionRegistrar} - */ - protected void init(FlowServiceLocator flowServiceLocator) { - } - - /** - * Returns the strategy for locating dependent artifacts when a flow is being built. May be called by subclasses - * during {@link #doPopulate(FlowDefinitionRegistry) registry population} to wire in the service locator needed for - * flow assembly. - */ - protected FlowServiceLocator getFlowServiceLocator() { - return flowServiceLocator; - } - - protected abstract void doPopulate(FlowDefinitionRegistry registry); -} \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBean.java new file mode 100644 index 00000000..91c36d44 --- /dev/null +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBean.java @@ -0,0 +1,112 @@ +/* + * Copyright 2004-2007 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.engine.builder; + +import java.util.Iterator; +import java.util.Map; +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.webflow.definition.registry.FlowDefinitionRegistrar; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistryImpl; +import org.springframework.webflow.definition.registry.FlowDefinitionResource; +import org.springframework.webflow.engine.builder.xml.XmlFlowRegistrar; + +/** + * A factory bean that accepts an arbitrary list of {@link FlowDefinitionRegistrar}s and uses them to register flows. + * This implementation should not be used programmatically but rather from the spring-webflow-config XML namespace. + *
+ * Example Usage: + * + *
+ * <flow:registry id="flowRegistry"> + * <flow:location path="flow1.xml"/> + * <flow:location id="foo" path="flow2.xml"/> + * <flow:class name="BarClass"/> + * <flow:crud entity="Account"/> + * <flow:namespace name="baz"> + * <flow:location path="flow3.xml"/> + * <flow:class name="XyzClass"/> + * </flow:namespace> + * </flow:registry> + *+ * + * @author Ben Hale + */ +public class FlowRegistryFactoryBean implements FactoryBean, InitializingBean, BeanFactoryAware { + + private FlowDefinitionRegistry registry; + + private BeanFactory beanFactory; + + private FlowServiceLocator flowServiceLocator; + + private Map xmlNamespaceFlowMappings; + + public void setFlowServiceLocator(FlowServiceLocator flowServiceLocator) { + this.flowServiceLocator = flowServiceLocator; + } + + public void setXmlNamespaceFlowMappings(Map xmlNamespaceFlowMappings) { + this.xmlNamespaceFlowMappings = xmlNamespaceFlowMappings; + } + + public void afterPropertiesSet() throws Exception { + this.registry = new FlowDefinitionRegistryImpl(); + initXml(registry); + } + + public Object getObject() throws Exception { + return registry; + } + + public Class getObjectType() { + return FlowDefinitionRegistry.class; + } + + public boolean isSingleton() { + return true; + } + + public void setBeanFactory(BeanFactory beanFactory) throws BeansException { + this.beanFactory = beanFactory; + } + + private void initXml(FlowDefinitionRegistry registry) { + XmlFlowRegistrar registrar = new XmlFlowRegistrar(getFlowServiceLocator(registry)); + for (Iterator mappings = xmlNamespaceFlowMappings.entrySet().iterator(); mappings.hasNext();) { + Map.Entry mapping = (Map.Entry) mappings.next(); + String namespace = (String) mapping.getKey(); + for (Iterator resources = ((Set) mapping.getValue()).iterator(); resources.hasNext();) { + FlowDefinitionResource resource = (FlowDefinitionResource) resources.next(); + registrar.addResource(resource, namespace); + } + } + registrar.registerFlowDefinitions(registry); + } + + private FlowServiceLocator getFlowServiceLocator(FlowDefinitionRegistry registry) { + if (flowServiceLocator == null) { + this.flowServiceLocator = new DefaultFlowServiceLocator(registry, beanFactory); + } + return flowServiceLocator; + } +} diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBeanTests.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBeanTests.java new file mode 100644 index 00000000..c973e95a --- /dev/null +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowRegistryFactoryBeanTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2004-2007 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.engine.builder; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import junit.framework.TestCase; + +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; +import org.springframework.webflow.definition.registry.FlowDefinitionResource; +import org.springframework.webflow.test.MockFlowServiceLocator; + +/** + * Tests that the factory bean properly creates a {@link FlowDefinitionRegistry} with the proper definitions in it. + */ +public class FlowRegistryFactoryBeanTests extends TestCase { + + public void testXmlRegistrar() throws Exception { + Set emptyNamespace = new HashSet(); + emptyNamespace.add(new FlowDefinitionResource(fromClassPath("flow1.xml"))); + Set bookingNamespace = new HashSet(); + bookingNamespace.add(new FlowDefinitionResource(fromClassPath("flow2.xml"))); + Map xmlNamespaceFlowMappings = new HashMap(); + xmlNamespaceFlowMappings.put("", emptyNamespace); + xmlNamespaceFlowMappings.put("booking", bookingNamespace); + FlowRegistryFactoryBean factoryBean = new FlowRegistryFactoryBean(); + factoryBean.setFlowServiceLocator(new MockFlowServiceLocator()); + factoryBean.setXmlNamespaceFlowMappings(xmlNamespaceFlowMappings); + factoryBean.afterPropertiesSet(); + FlowDefinitionRegistry registry = (FlowDefinitionRegistry) factoryBean.getObject(); + assertEquals("Incorrect number of flows", 2, registry.getFlowDefinitionCount()); + assertTrue("Missing flow", registry.containsFlowDefinition("flow1")); + assertTrue("Missing flow", registry.containsFlowDefinition("booking/flow2")); + } + + private Resource fromClassPath(String resourceName) { + return new ClassPathResource(resourceName, getClass()); + } + +} diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java index ae2994f5..abb385cc 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistrar.java @@ -22,17 +22,19 @@ import org.springframework.webflow.definition.registry.FlowDefinitionHolder; import org.springframework.webflow.definition.registry.FlowDefinitionResource; import org.springframework.webflow.engine.builder.FlowAssembler; import org.springframework.webflow.engine.builder.FlowBuilder; +import org.springframework.webflow.engine.builder.FlowRegistryFactoryBean; import org.springframework.webflow.engine.builder.FlowServiceLocator; import org.springframework.webflow.engine.builder.RefreshableFlowDefinitionHolder; /** * A flow definition registrar that populates a flow definition registry with flow definitions defined in externalized - * XML resources. Typically used in conjunction with a {@link XmlFlowRegistryFactoryBean} but may also be used - * standalone in programmatic fashion. + * XML resources. Typically used in conjunction with a {@link FlowRegistryFactoryBean} but may also be used stand-alone + * in programmatic fashion. *
- * By default, a flow definition registered by this registrar will be assigned a registry identifier equal to the - * filename of the underlying definition resource, minus the filename extension. For example, a XML-based flow - * definition defined in the file "flow1.xml" will be identified as "flow1" when registered in a registry. + * By default, a flow definition added to this registrar with the {@link #addLocation(Resource, String)} method will be + * will be assigned a registry identifier equal to the filename of the underlying definition resource, minus the + * filename extension. For example, a XML-based flow definition defined in the file "flow1.xml" will be identified as + * "flow1" when registered in a registry. *
* Programmatic usage example: * @@ -43,59 +45,28 @@ import org.springframework.webflow.engine.builder.RefreshableFlowDefinitionHolde * new DefaultFlowServiceLocator(registry, beanFactory); * XmlFlowRegistrar registrar = new XmlFlowRegistrar(flowServiceLocator); * File parent = new File("src/webapp/WEB-INF"); - * registrar.addLocation(new FileSystemResource(new File(parent, "flow1.xml")); - * registrar.addLocation(new FileSystemResource(new File(parent, "flow2.xml")); + * registrar.add(new FileSystemResource(new File(parent, "flow1.xml")); + * registrar.add(new FileSystemResource(new File(parent, "flow2.xml")); * registrar.registerFlowDefinitions(registry); * * * @author Keith Donald + * @author Ben Hale */ public class XmlFlowRegistrar extends ExternalizedFlowDefinitionRegistrar { - /** - * The xml file suffix constant. - */ - private static final String XML_SUFFIX = ".xml"; - - /** - * The locator of services needed by flow definitions. - */ - private FlowServiceLocator flowServiceLocator; - /** * The loader of XML-based flow definition documents. */ private DocumentLoader documentLoader; - /** - * Creates a new XML flow registrar. Protected constructor - if used, make sure the required - * {@link #flowServiceLocator} reference is set. - */ - protected XmlFlowRegistrar() { - } - /** * Creates a new XML flow registrar. * @param flowServiceLocator the locator needed to support flow definition assembly */ public XmlFlowRegistrar(FlowServiceLocator flowServiceLocator) { - setFlowServiceLocator(flowServiceLocator); - } - - /** - * Sets the flow service locator. - * @param flowServiceLocator the flow service locator (may not be null) - */ - protected void setFlowServiceLocator(FlowServiceLocator flowServiceLocator) { Assert.notNull(flowServiceLocator, "The flow service locator is required"); - this.flowServiceLocator = flowServiceLocator; - } - - /** - * Returns the flow service locator. - */ - protected FlowServiceLocator getFlowServiceLocator() { - return flowServiceLocator; + setFlowServiceLocator(flowServiceLocator); } /** @@ -107,16 +78,7 @@ public class XmlFlowRegistrar extends ExternalizedFlowDefinitionRegistrar { this.documentLoader = documentLoader; } - /** - * Returns the loader of XML-based flow definition documents. - */ - public DocumentLoader getDocumentLoader() { - return documentLoader; - } - - protected boolean isFlowDefinitionResource(Resource resource) { - return resource.getFilename().endsWith(XML_SUFFIX); - } + // hook methods protected FlowDefinitionHolder createFlowDefinitionHolder(FlowDefinitionResource resource) { FlowBuilder builder = createFlowBuilder(resource.getLocation()); @@ -124,8 +86,6 @@ public class XmlFlowRegistrar extends ExternalizedFlowDefinitionRegistrar { return new RefreshableFlowDefinitionHolder(assembler); } - // hook methods - /** * Factory method that creates and fully initializes the XML-based flow definition builder. * @param location the xml-based resource diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBean.java deleted file mode 100644 index 2ea21fa7..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowRegistryFactoryBean.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2004-2007 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.engine.builder.xml; - -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; - -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; -import org.springframework.webflow.core.collection.AttributeMap; -import org.springframework.webflow.core.collection.LocalAttributeMap; -import org.springframework.webflow.definition.registry.FlowDefinitionRegistry; -import org.springframework.webflow.definition.registry.FlowDefinitionResource; -import org.springframework.webflow.engine.builder.AbstractFlowBuildingFlowRegistryFactoryBean; -import org.springframework.webflow.engine.builder.DefaultFlowServiceLocator; -import org.springframework.webflow.engine.builder.FlowServiceLocator; - -/** - * A factory bean that produces a populated flow registry using an {@link XmlFlowRegistrar}. This is the simplest - * implementation to use when using a Spring BeanFactory to deploy an explicit registry of XML-based Flow definitions - * for execution. - *
- * By default, a configured flow definition will be assigned a registry identifier equal to the filename of the
- * underlying definition resource, minus the filename extension. For example, an XML-based flow definition defined in
- * the file flow1.xml will be identified as flow1 in the registry created by this factory
- * bean.
- *
- * This class is also BeanFactoryAware and when used with Spring will automatically create a configured
- * {@link DefaultFlowServiceLocator} for loading Flow artifacts like Actions from the Spring bean factory during the
- * Flow registration process.
- *
- * This class is also ResourceLoaderAware; when an instance is created by a Spring BeanFactory the
- * factory will automatically configure the XmlFlowRegistrar with a context-relative resource loader for accessing other
- * resources during Flow assembly.
- *
- * Usage example:
- *
- *
- * <bean id="flowRegistry" class="org.springframework.webflow.engine.builder.registry.XmlFlowRegistryFactoryBean"> - * <property name="flowLocations" value="/WEB-INF/flows/*-flow.xml"/> - * </bean> - *- * - * @author Keith Donald - */ -public class XmlFlowRegistryFactoryBean extends AbstractFlowBuildingFlowRegistryFactoryBean { - - /** - * The flow registrar that will perform the definition registrations. - */ - private XmlFlowRegistrar flowRegistrar = new XmlFlowRegistrar(); - - /** - * Temporary holder for flow definition locations. - */ - private Resource[] locations; - - /** - * Temporary holder for flow definitions configured using a property map. - */ - private Properties flowDefinitions; - - /** - * A map that contains a map (java.util.Map) of flow attributes keyed by flow id (String). - */ - private Map flowAttributes; - - /** - * Returns the configured externalized XML flow registrar. - */ - public XmlFlowRegistrar getXmlFlowRegistrar() { - return flowRegistrar; - } - - /** - * Set the configured externalized XML flow registrar. - * @since 1.0.1 - */ - public void setXmlFlowRegistrar(XmlFlowRegistrar flowRegistrar) { - Assert.notNull(flowRegistrar, "The flowRegistrar is required"); - this.flowRegistrar = flowRegistrar; - } - - /** - * Sets the locations (resource file paths) pointing to XML-based flow definitions. - *
- * When configuring as a Spring bean definition, ANT-style resource patterns/wildcards are also supported, taking - * advantage of Spring's built in ResourceArrayPropertyEditor machinery. - *
- * For example: - * - *
- * <bean id="flowRegistry" class="org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean"> - * <property name="flowLocations" value="/WEB-INF/flows/*-flow.xml"/> - * </bean> - *- * - * Another example: - * - *
- * <bean id="flowRegistry" class="org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean"> - * <property name="flowLocations" value="classpath*:/example/flows/*-flow.xml"/> - * </bean> - *- * - * Flows registered from this set will be automatically assigned an id based on the filename of the matched XML - * resource. - * @param locations the resource locations - */ - public void setFlowLocations(Resource[] locations) { - this.locations = locations; - } - - /** - * Convenience method for setting externalized flow definitions from a
java.util.Properties map.
- * Allows for more control over the definition, including which flowId is assigned.
- *
- * Each property key is the flowId and each property value is the string encoded location of the
- * externalized flow definition resource.
- *
- * Here is the exact format: - * - *
- * flowId = resource - *- * - * For example: - * - *
- * <bean id="flowRegistry" class="org.springframework.webflow.engine.builder.xml.XmlFlowRegistryFactoryBean"> - * <property name="flowDefinitions"> - * <value> - * searchFlow=/WEB-INF/flows/search-flow.xml - * detailFlow=/WEB-INF/flows/detail-flow.xml - * </value> - * </property> - * </bean> - *- * - * @param flowDefinitions the flow definitions, defined within a properties map - */ - public void setFlowDefinitions(Properties flowDefinitions) { - this.flowDefinitions = flowDefinitions; - } - - /** - * Sets flow attributes from an externalized
java.util.Map. The keys in the map are String flow ids.
- * The corresponding values should be java.util.Map maps containing flow attributes to be assigned to
- * the flow. A flow with an id not contained in the provided map will get not externally defined flow attributes
- * assigned.
- *
- * Can be used in conjunction with both {@link #setFlowLocations(Resource[])} and
- * {@link #setFlowDefinitions(Properties)}.
- * @param flowAttributes the flow attributes, keyed by flow id
- * @since 1.0.1
- */
- public void setFlowAttributes(Map flowAttributes) {
- this.flowAttributes = flowAttributes;
- }
-
- /**
- * Sets the loader to load XML-based flow definition documents during flow definition assembly. Allows for
- * customization over how flow definition documents are loaded. Optional.
- * @param documentLoader the document loader
- */
- public void setDocumentLoader(DocumentLoader documentLoader) {
- getXmlFlowRegistrar().setDocumentLoader(documentLoader);
- }
-
- protected void init(FlowServiceLocator flowServiceLocator) {
- // simply wire in the locator to the registrar
- getXmlFlowRegistrar().setFlowServiceLocator(flowServiceLocator);
- }
-
- protected void doPopulate(FlowDefinitionRegistry registry) {
- addFlowDefinitionLocations();
- addFlowDefinitionsFromProperties();
- getXmlFlowRegistrar().registerFlowDefinitions(registry);
- }
-
- /**
- * Add configured flow definition locations to the flow definition registrar.
- */
- private void addFlowDefinitionLocations() {
- if (locations != null) {
- for (int i = 0; i < locations.length; i++) {
- String flowId = FlowDefinitionResource.conventionalFlowId(locations[i]);
- getXmlFlowRegistrar().addResource(
- new FlowDefinitionResource(flowId, locations[i], getFlowAttributes(flowId)));
- }
- }
- }
-
- /**
- * Add flow definitions configured using a property map to the flow definition registrar.
- */
- private void addFlowDefinitionsFromProperties() {
- if (flowDefinitions != null) {
- Iterator it = flowDefinitions.entrySet().iterator();
- while (it.hasNext()) {
- Map.Entry entry = (Map.Entry) it.next();
- String flowId = (String) entry.getKey();
- String location = (String) entry.getValue();
- Resource resource = getFlowServiceLocator().getResourceLoader().getResource(location);
- getXmlFlowRegistrar().addResource(
- new FlowDefinitionResource(flowId, resource, getFlowAttributes(flowId)));
- }
- }
- }
-
- /**
- * Returns the flow attributes to be assigned to the flow with given id. Returns null if no attributes should be
- * assigned.
- */
- private AttributeMap getFlowAttributes(String flowId) {
- if (flowAttributes != null) {
- Map attributes = (Map) flowAttributes.get(flowId);
- if (attributes != null) {
- return new LocalAttributeMap(attributes);
- }
- }
- return null;
- }
-}
\ No newline at end of file
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/BeanConfigTests.java b/spring-webflow/src/test/java/org/springframework/webflow/config/BeanConfigTests.java
index 9dc918fc..f98d3fbf 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/config/BeanConfigTests.java
+++ b/spring-webflow/src/test/java/org/springframework/webflow/config/BeanConfigTests.java
@@ -22,7 +22,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.webflow.executor.mvc.FlowController;
/**
- * Test case that illustrates configuration of a FlowController and its associated artefacts using classic spring bean
+ * Test case that illustrates configuration of a FlowController and its associated artifacts using classic spring bean
* configuration information. This test case does not really test much but serves more as an example.
*
* @author Erwin Vervaet
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java b/spring-webflow/src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java
index 92ebfbad..0bc2c99e 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java
+++ b/spring-webflow/src/test/java/org/springframework/webflow/config/WebFlowConfigNamespaceHandlerTests.java
@@ -17,6 +17,7 @@ package org.springframework.webflow.config;
import junit.framework.TestCase;
+import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.beans.factory.parsing.Problem;
import org.springframework.beans.factory.parsing.ProblemReporter;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
@@ -38,17 +39,12 @@ import org.springframework.webflow.executor.FlowExecutorImpl;
/**
* Unit tests for the WebFlowConfigNamespaceHandler and its BeanDefinitionParsers.
- *
- * @author Ben Hale
- * @author Erwin Vervaet
- * @author Christian Dupuis
*/
public class WebFlowConfigNamespaceHandlerTests extends TestCase {
private DefaultListableBeanFactory beanFactory;
protected void setUp() throws Exception {
- super.setUp();
this.beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
reader.loadBeanDefinitions(new ClassPathResource(
@@ -58,16 +54,36 @@ public class WebFlowConfigNamespaceHandlerTests extends TestCase {
public void testRegistryWithPath() {
FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withPath");
assertEquals("Incorrect number of flows loaded", 1, registry.getFlowDefinitionCount());
- }
-
- public void testRegistryWithoutPath() {
- FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withoutPath");
- assertEquals("Incorrect number of flows loaded", 0, registry.getFlowDefinitionCount());
+ assertTrue("Incorrect flow name", registry.containsFlowDefinition("/flow1"));
}
public void testRegistryWithPathWithWildcards() {
FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withPathWithWildcards");
- assertEquals("Incorrect number of flows loaded", 0, registry.getFlowDefinitionCount());
+ assertEquals("Incorrect number of flows loaded", 3, registry.getFlowDefinitionCount());
+ assertTrue("Incorrect flow name", registry.containsFlowDefinition("/flow1"));
+ assertTrue("Incorrect flow name", registry.containsFlowDefinition("/flow2"));
+ }
+
+ public void testRegistryWithId() {
+ FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withId");
+ assertEquals("Incorrect number of flows loaded", 1, registry.getFlowDefinitionCount());
+ assertTrue("Incorrect flow name", registry.containsFlowDefinition("/foo"));
+ }
+
+ public void testWithIdWithWildCards() {
+ XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this.beanFactory);
+ try {
+ reader.loadBeanDefinitions(new ClassPathResource(
+ "org/springframework/webflow/config/webflow-config-namespace-bad.xml"));
+ fail("Should not have allowed id with wildcards");
+ } catch (BeanDefinitionParsingException e) {
+ }
+ }
+
+ public void testRegistryWithNamespace() {
+ FlowDefinitionRegistry registry = (FlowDefinitionRegistry) this.beanFactory.getBean("withNamespace");
+ assertEquals("Incorrect number of flows loaded", 1, registry.getFlowDefinitionCount());
+ assertTrue("Incorrect flow name", registry.containsFlowDefinition("namespace/flow1"));
}
public void testDefaultExecutor() {
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor-factory-bean.xml b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor-factory-bean.xml
index 2d6cca7c..0dbf25d1 100644
--- a/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor-factory-bean.xml
+++ b/spring-webflow/src/test/java/org/springframework/webflow/config/flow-executor-factory-bean.xml
@@ -1,14 +1,27 @@
-
-