diff --git a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryFactoryBean.java b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryFactoryBean.java index 7618003a..de7097ce 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryFactoryBean.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/config/FlowRegistryFactoryBean.java @@ -162,8 +162,8 @@ class FlowRegistryFactoryBean implements FactoryBean, InitializingBean { } private FlowModelHolder createFlowModelHolder(FlowDefinitionResource resource) { - FlowModelHolder modelHolder = new DefaultFlowModelHolder(createFlowModelBuilder(resource), resource.getId()); - flowModelRegistry.registerFlowModel(modelHolder); + FlowModelHolder modelHolder = new DefaultFlowModelHolder(createFlowModelBuilder(resource)); + flowModelRegistry.registerFlowModel(resource.getId(), modelHolder); return modelHolder; } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistryImpl.java b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistryImpl.java index 7c1a0ca9..1999e822 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistryImpl.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/definition/registry/FlowDefinitionRegistryImpl.java @@ -23,7 +23,6 @@ import org.apache.commons.logging.LogFactory; import org.springframework.core.style.ToStringCreator; import org.springframework.util.Assert; import org.springframework.webflow.definition.FlowDefinition; -import org.springframework.webflow.engine.model.registry.FlowModelConstructionException; /** * A generic registry implementation for housing one or more flow definitions. @@ -54,11 +53,8 @@ public class FlowDefinitionRegistryImpl implements FlowDefinitionRegistry { public FlowDefinition getFlowDefinition(String id) throws NoSuchFlowDefinitionException, FlowDefinitionConstructionException { try { - if (id == null) { - throw new IllegalArgumentException("The id of the flow to lookup is required"); - } if (logger.isDebugEnabled()) { - logger.debug("Getting flow definition with id '" + id + "'"); + logger.debug("Getting FlowDefinition with id '" + id + "'"); } return getFlowDefinitionHolder(id).getFlowDefinition(); } catch (NoSuchFlowDefinitionException e) { @@ -67,8 +63,6 @@ public class FlowDefinitionRegistryImpl implements FlowDefinitionRegistry { return parent.getFlowDefinition(id); } throw e; - } catch (FlowModelConstructionException e) { - throw new FlowDefinitionConstructionException(e.getMessage(), e); } } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilder.java index 3fcd99a4..f0243b8c 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilder.java @@ -83,6 +83,7 @@ import org.springframework.webflow.engine.model.SubflowStateModel; import org.springframework.webflow.engine.model.TransitionModel; import org.springframework.webflow.engine.model.VarModel; import org.springframework.webflow.engine.model.ViewStateModel; +import org.springframework.webflow.engine.model.builder.FlowModelBuilderException; import org.springframework.webflow.engine.model.registry.FlowModelHolder; import org.springframework.webflow.engine.support.ActionExecutingViewFactory; import org.springframework.webflow.engine.support.BeanFactoryVariableValueFactory; @@ -122,7 +123,11 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder { * @throws FlowBuilderException an exception occurred building the flow */ protected void doInit() throws FlowBuilderException { - flowModel = flowModelHolder.getFlowModel(); + try { + flowModel = flowModelHolder.getFlowModel(); + } catch (FlowModelBuilderException e) { + throw new FlowBuilderException("Unable to get the model for this flow", e); + } if ("true".equals(flowModel.getAbstract())) { throw new FlowBuilderException("Abstract flow models cannot be instantiated."); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilder.java index 32925694..e86593ec 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilder.java @@ -103,7 +103,7 @@ public class XmlFlowModelBuilder implements FlowModelBuilder { document = documentLoader.loadDocument(resource); lastModifiedTimestamp = resource.getFile().lastModified(); } catch (IOException e) { - throw new FlowModelBuilderException("Could not access the XML flow definition resource at " + resource, e); + throw new FlowModelBuilderException("Could not access the XML flow definition at " + resource, e); } catch (ParserConfigurationException e) { throw new FlowModelBuilderException("Could not configure the parser to parse the XML flow definition at " + resource, e); diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/DefaultFlowModelHolder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/DefaultFlowModelHolder.java index 37f80bd7..eafc34e0 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/DefaultFlowModelHolder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/DefaultFlowModelHolder.java @@ -16,6 +16,8 @@ package org.springframework.webflow.engine.model.registry; import org.springframework.core.io.Resource; +import org.springframework.core.style.ToStringCreator; +import org.springframework.util.Assert; import org.springframework.webflow.engine.model.FlowModel; import org.springframework.webflow.engine.model.builder.FlowModelBuilder; import org.springframework.webflow.engine.model.builder.FlowModelBuilderException; @@ -40,11 +42,6 @@ public class DefaultFlowModelHolder implements FlowModelHolder { */ private FlowModel flowModel; - /** - * The flow mode identifier - */ - private String flowModelId; - /** * The flow model builder. */ @@ -54,18 +51,13 @@ public class DefaultFlowModelHolder implements FlowModelHolder { * Creates a new refreshable flow model holder that uses the configured assembler (GOF director) to drive flow * assembly, on initial use and on any resource change or refresh. * @param flowModelBuilder the flow model builder to use - * @param flowModelId the identifier of the flow model */ - public DefaultFlowModelHolder(FlowModelBuilder flowModelBuilder, String flowModelId) { + public DefaultFlowModelHolder(FlowModelBuilder flowModelBuilder) { + Assert.notNull(flowModelBuilder, "The flow model builder is required"); this.flowModelBuilder = flowModelBuilder; - this.flowModelId = flowModelId; } - public String getFlowModelId() { - return flowModelId; - } - - public synchronized FlowModel getFlowModel() throws FlowModelConstructionException { + public synchronized FlowModel getFlowModel() { if (flowModel == null) { assembleFlowModel(); } else { @@ -84,26 +76,23 @@ public class DefaultFlowModelHolder implements FlowModelHolder { return flowModelBuilder.hasFlowModelChanged(); } - public synchronized void refresh() throws FlowModelConstructionException { + public synchronized void refresh() { assembleFlowModel(); } // internal helpers - private void assembleFlowModel() throws FlowModelConstructionException { + private void assembleFlowModel() throws FlowModelBuilderException { try { flowModelBuilder.init(); flowModelBuilder.build(); flowModel = flowModelBuilder.getFlowModel(); - } catch (FlowModelBuilderException e) { - throw new FlowModelConstructionException(flowModelId, e); } finally { flowModelBuilder.dispose(); } } public String toString() { - return "'" + getFlowModelId() + "'"; + return new ToStringCreator(this).append("flowModelBuilder", flowModelBuilder).toString(); } - } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelConstructionException.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelConstructionException.java deleted file mode 100644 index 1e76c2f6..00000000 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelConstructionException.java +++ /dev/null @@ -1,51 +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.model.registry; - -import org.springframework.webflow.core.FlowException; - -/** - * Thrown when a flow model was found during a lookup operation but could not be constructed. - * - * @author Keith Donald - * @author Erwin Vervaet - * @author Scott Andrews - */ -public class FlowModelConstructionException extends FlowException { - - /** - * The id of the flow that could not be constructed. - */ - private String flowModelId; - - /** - * Creates an exception indicating a flow model could not be constructed. - * @param flowModelId the flow model identifier - * @param cause the underlying cause of the exception - */ - public FlowModelConstructionException(String flowModelId, Throwable cause) { - super("An exception occurred constructing the flow '" + flowModelId + "'", cause); - this.flowModelId = flowModelId; - } - - /** - * Returns the id of the flow model that could not be constructed. - * @return the flow id - */ - public String getFlowModelId() { - return flowModelId; - } -} \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelHolder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelHolder.java index 93ba364b..13335a6f 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelHolder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelHolder.java @@ -17,12 +17,13 @@ package org.springframework.webflow.engine.model.registry; import org.springframework.core.io.Resource; import org.springframework.webflow.engine.model.FlowModel; +import org.springframework.webflow.engine.model.builder.FlowModelBuilderException; /** * A holder holding a reference to a Flow model. Provides a layer of indirection, enabling things like "hot-reloadable" * flow models. * - * @see FlowModelRegistry#registerFlowModel(FlowModelHolder) + * @see FlowModelRegistry#registerFlowModel(String, FlowModelHolder) * * @author Keith Donald * @author Scott Andrews @@ -30,18 +31,10 @@ import org.springframework.webflow.engine.model.FlowModel; public interface FlowModelHolder { /** - * Returns the id of the flow model held by this holder. This is a lightweight method callers - * may call to obtain the id of the flow without triggering full flow definition assembly (which may be an expensive - * operation). + * Returns the flow model held by this holder. Calling this method the first time may trigger flow model assembly. + * @throws FlowModelBuilderException if an exception occurred building the flow model */ - public String getFlowModelId(); - - /** - * Returns the flow model held by this holder. Calling this method the first time may trigger flow assembly (which - * may be expensive). - * @throws FlowModelConstructionException if there is a problem constructing the target flow model - */ - public FlowModel getFlowModel() throws FlowModelConstructionException; + public FlowModel getFlowModel() throws FlowModelBuilderException; /** * Has the underlying flow model changed since it was last accessed via a call to {@link #getFlowModel()}. @@ -59,8 +52,8 @@ public interface FlowModelHolder { /** * Refresh the flow model held by this holder. Calling this method typically triggers flow re-assembly, which may * include a refresh from an externalized resource such as a file. - * @throws FlowModelConstructionException if there is a problem constructing the target flow model + * @throws FlowModelBuilderException if an exception occurred building the flow model */ - public void refresh() throws FlowModelConstructionException; + public void refresh() throws FlowModelBuilderException; } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelLocator.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelLocator.java index 5746dc32..e42e59c8 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelLocator.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelLocator.java @@ -32,7 +32,6 @@ public interface FlowModelLocator { * @param id the flow model identifier * @return the flow mode * @throws NoSuchFlowModelException when the flow model with the specified id does not exist - * @throws FlowModelConstructionException if there is a problem constructing the identified flow model */ - public FlowModel getFlowModel(String id) throws NoSuchFlowModelException, FlowModelConstructionException; + public FlowModel getFlowModel(String id) throws NoSuchFlowModelException; } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelRegistry.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelRegistry.java index 57c21f28..a3a1d71f 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelRegistry.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelRegistry.java @@ -38,8 +38,9 @@ public interface FlowModelRegistry extends FlowModelLocator { * Register a flow model in this registry. Registers a "holder", not the Flow model itself. This allows the actual * Flow model to be loaded lazily only when needed, and also rebuilt at runtime when its underlying resource changes * without re-deploy. + * @param id the id to register the flow model under * @param modelHolder a holder holding the flow model to register */ - public void registerFlowModel(FlowModelHolder modelHolder); + public void registerFlowModel(String id, FlowModelHolder modelHolder); } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelRegistryImpl.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelRegistryImpl.java index 285f5dfd..141efae4 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelRegistryImpl.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/registry/FlowModelRegistryImpl.java @@ -50,13 +50,10 @@ public class FlowModelRegistryImpl implements FlowModelRegistry { // implementing FlowModelLocator - public FlowModel getFlowModel(String id) throws NoSuchFlowModelException, FlowModelConstructionException { + public FlowModel getFlowModel(String id) throws NoSuchFlowModelException { try { - if (id == null) { - throw new IllegalArgumentException("The id of the flow to lookup is required"); - } if (logger.isDebugEnabled()) { - logger.debug("Getting flow model with id '" + id + "'"); + logger.debug("Getting FlowModel with id '" + id + "'"); } return getFlowModelHolder(id).getFlowModel(); @@ -75,12 +72,12 @@ public class FlowModelRegistryImpl implements FlowModelRegistry { this.parent = parent; } - public void registerFlowModel(FlowModelHolder modelHolder) { + public void registerFlowModel(String id, FlowModelHolder modelHolder) { Assert.notNull(modelHolder, "The holder of the flow model to register is required"); if (logger.isDebugEnabled()) { logger.debug("Registering flow model " + modelHolder); } - flowModels.put(modelHolder.getFlowModelId(), modelHolder); + flowModels.put(id, modelHolder); } // internal helpers diff --git a/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionListener.java b/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionListener.java index 24e3e7c9..54d79ec1 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionListener.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionListener.java @@ -113,6 +113,22 @@ public interface FlowExecutionListener { */ public void stateEntering(RequestContext context, StateDefinition state) throws EnterStateVetoException; + /** + * Called when a view is about to render in a view-state, before any render actions are executed. + * @param context the current request context + * @param view the view that is about to render + * @param viewState the current view state + */ + public void viewRendering(RequestContext context, View view, StateDefinition viewState); + + /** + * Called after a view has completed rendering. + * @param context the current request context + * @param view the view that rendered + * @param viewState the current view state + */ + public void viewRendered(RequestContext context, View view, StateDefinition viewState); + /** * Called when a state transitions, after the transition occurred. * @param context the source of the event diff --git a/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionListenerAdapter.java b/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionListenerAdapter.java index c86a164c..c5d0d012 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionListenerAdapter.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/execution/FlowExecutionListenerAdapter.java @@ -55,6 +55,12 @@ public abstract class FlowExecutionListenerAdapter implements FlowExecutionListe public void stateEntering(RequestContext context, StateDefinition state) throws EnterStateVetoException { } + public void viewRendered(RequestContext context, View view, StateDefinition viewState) { + } + + public void viewRendering(RequestContext context, View view, StateDefinition viewState) { + } + public void stateEntered(RequestContext context, StateDefinition previousState, StateDefinition newState) { } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/test/execution/AbstractXmlFlowExecutionTests.java b/spring-webflow/src/main/java/org/springframework/webflow/test/execution/AbstractXmlFlowExecutionTests.java index d4ce7292..3246adeb 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/test/execution/AbstractXmlFlowExecutionTests.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/test/execution/AbstractXmlFlowExecutionTests.java @@ -79,8 +79,8 @@ public abstract class AbstractXmlFlowExecutionTests extends AbstractExternalized protected final FlowBuilder createFlowBuilder(FlowDefinitionResource resource) { registerDependentFlowModels(); FlowModelBuilder modelBuilder = new XmlFlowModelBuilder(resource.getPath(), flowModelRegistry); - FlowModelHolder modelHolder = new DefaultFlowModelHolder(modelBuilder, resource.getId()); - flowModelRegistry.registerFlowModel(modelHolder); + FlowModelHolder modelHolder = new DefaultFlowModelHolder(modelBuilder); + flowModelRegistry.registerFlowModel(resource.getId(), modelHolder); return new FlowModelFlowBuilder(modelHolder) { protected void registerFlowBeans(ConfigurableBeanFactory flowBeanFactory) { registerMockFlowBeans(flowBeanFactory); @@ -116,7 +116,7 @@ public abstract class AbstractXmlFlowExecutionTests extends AbstractExternalized for (int i = 0; i < modelResources.length; i++) { FlowDefinitionResource modelResource = modelResources[i]; FlowModelBuilder modelBuilder = new XmlFlowModelBuilder(modelResource.getPath(), flowModelRegistry); - flowModelRegistry.registerFlowModel(new DefaultFlowModelHolder(modelBuilder, modelResource.getId())); + flowModelRegistry.registerFlowModel(modelResource.getId(), new DefaultFlowModelHolder(modelBuilder)); } } } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParserTests.java b/spring-webflow/src/test/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParserTests.java index 7a3708a2..389ef1a9 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParserTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/config/FlowRegistryBeanDefinitionParserTests.java @@ -53,7 +53,7 @@ public class FlowRegistryBeanDefinitionParserTests extends TestCase { try { registry.getFlowDefinition("bogus"); } catch (FlowDefinitionConstructionException e) { - + e.printStackTrace(); } } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilderTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilderTests.java index f13648f0..9bb45911 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilderTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/model/FlowModelFlowBuilderTests.java @@ -29,7 +29,6 @@ import org.springframework.webflow.engine.model.ViewStateModel; import org.springframework.webflow.engine.model.builder.xml.XmlFlowModelBuilder; import org.springframework.webflow.engine.model.builder.xml.XmlFlowModelBuilderTests; import org.springframework.webflow.engine.model.registry.DefaultFlowModelHolder; -import org.springframework.webflow.engine.model.registry.FlowModelConstructionException; import org.springframework.webflow.engine.model.registry.FlowModelHolder; import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl; import org.springframework.webflow.engine.support.ActionExecutingViewFactory; @@ -346,7 +345,7 @@ public class FlowModelFlowBuilderTests extends TestCase { private Flow getFlow(ClassPathResource resource) { FlowModelHolder holder = new DefaultFlowModelHolder(new XmlFlowModelBuilder(resource, - new FlowModelRegistryImpl()), "flow"); + new FlowModelRegistryImpl())); FlowModelFlowBuilder builder = new FlowModelFlowBuilder(holder); FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow")); return assembler.assembleFlow(); @@ -360,7 +359,7 @@ public class FlowModelFlowBuilderTests extends TestCase { this.model = model; } - public FlowModel getFlowModel() throws FlowModelConstructionException { + public FlowModel getFlowModel() { return model; } @@ -376,7 +375,7 @@ public class FlowModelFlowBuilderTests extends TestCase { return false; } - public void refresh() throws FlowModelConstructionException { + public void refresh() { } } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilderTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilderTests.java index 92be7637..fbee3558 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilderTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/XmlFlowModelBuilderTests.java @@ -4,6 +4,12 @@ import junit.framework.TestCase; import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.core.io.ClassPathResource; +import org.springframework.validation.BindingResult; +import org.springframework.webflow.definition.StateDefinition; +import org.springframework.webflow.engine.Flow; +import org.springframework.webflow.engine.builder.FlowAssembler; +import org.springframework.webflow.engine.builder.model.FlowModelFlowBuilder; +import org.springframework.webflow.engine.impl.FlowExecutionImplFactory; import org.springframework.webflow.engine.model.AbstractStateModel; import org.springframework.webflow.engine.model.AttributeModel; import org.springframework.webflow.engine.model.FlowModel; @@ -12,10 +18,17 @@ import org.springframework.webflow.engine.model.TransitionModel; import org.springframework.webflow.engine.model.VarModel; import org.springframework.webflow.engine.model.ViewStateModel; import org.springframework.webflow.engine.model.builder.FlowModelBuilder; +import org.springframework.webflow.engine.model.builder.FlowModelBuilderException; import org.springframework.webflow.engine.model.registry.DefaultFlowModelHolder; -import org.springframework.webflow.engine.model.registry.FlowModelConstructionException; import org.springframework.webflow.engine.model.registry.FlowModelRegistry; import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl; +import org.springframework.webflow.execution.FlowExecution; +import org.springframework.webflow.execution.FlowExecutionListenerAdapter; +import org.springframework.webflow.execution.RequestContext; +import org.springframework.webflow.execution.View; +import org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader; +import org.springframework.webflow.test.MockExternalContext; +import org.springframework.webflow.test.MockFlowBuilderContext; public class XmlFlowModelBuilderTests extends TestCase { @@ -148,10 +161,10 @@ public class XmlFlowModelBuilderTests extends TestCase { public void testMerge() { ClassPathResource resourceChild = new ClassPathResource("flow-inheritance-child.xml", getClass()); ClassPathResource resourceParent = new ClassPathResource("flow-inheritance-parent.xml", getClass()); - registry - .registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry), "child")); - registry.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, registry), - "parent")); + registry.registerFlowModel("child", + new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry))); + registry.registerFlowModel("parent", new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, + registry))); FlowModel flow = registry.getFlowModel("child"); assertEquals(1, flow.getGlobalTransitions().size()); assertEquals(2, flow.getStates().size()); @@ -161,14 +174,14 @@ public class XmlFlowModelBuilderTests extends TestCase { public void testMergeParentNotFound() { ClassPathResource resourceChild = new ClassPathResource("flow-inheritance-child.xml", getClass()); ClassPathResource resourceParent = new ClassPathResource("flow-inheritance-parent.xml", getClass()); - registry - .registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry), "child")); - registry.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, registry), - "parent-id-not-matching")); + registry.registerFlowModel("child", + new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry))); + registry.registerFlowModel("parent-id-not-matching", new DefaultFlowModelHolder(new XmlFlowModelBuilder( + resourceParent, registry))); try { registry.getFlowModel("child"); - fail("A FlowModelConstructionException was expected"); - } catch (FlowModelConstructionException e) { + fail("A FlowModelBuilderException was expected"); + } catch (FlowModelBuilderException e) { // we want this } } @@ -185,10 +198,10 @@ public class XmlFlowModelBuilderTests extends TestCase { public void testStateMerge() { ClassPathResource resourceChild = new ClassPathResource("flow-inheritance-state-child.xml", getClass()); ClassPathResource resourceParent = new ClassPathResource("flow-inheritance-state-parent.xml", getClass()); - registry - .registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry), "child")); - registry.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, registry), - "parent")); + registry.registerFlowModel("child", + new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry))); + registry.registerFlowModel("parent", new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, + registry))); FlowModel flow = registry.getFlowModel("child"); assertEquals(1, flow.getStates().size()); assertEquals("otherview", ((ViewStateModel) flow.getStates().get(0)).getView()); @@ -198,14 +211,14 @@ public class XmlFlowModelBuilderTests extends TestCase { ClassPathResource resourceChild = new ClassPathResource("flow-inheritance-state-invalid-parent-syntax.xml", getClass()); ClassPathResource resourceParent = new ClassPathResource("flow-inheritance-state-parent.xml", getClass()); - registry - .registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry), "child")); - registry.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, registry), - "parent")); + registry.registerFlowModel("child", + new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry))); + registry.registerFlowModel("parent", new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, + registry))); try { registry.getFlowModel("child"); fail("A FlowModelConstructionException was expected"); - } catch (FlowModelConstructionException e) { + } catch (FlowModelBuilderException e) { // we want this } } @@ -213,14 +226,14 @@ public class XmlFlowModelBuilderTests extends TestCase { public void testStateMergeParentFlowNotFound() { ClassPathResource resourceChild = new ClassPathResource("flow-inheritance-state-child.xml", getClass()); ClassPathResource resourceParent = new ClassPathResource("flow-inheritance-state-parent.xml", getClass()); - registry - .registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry), "child")); - registry.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, registry), - "parent-id-not-matching")); + registry.registerFlowModel("child", + new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry))); + registry.registerFlowModel("parent-id-not-matching", new DefaultFlowModelHolder(new XmlFlowModelBuilder( + resourceParent, registry))); try { registry.getFlowModel("child"); - fail("A FlowModelConstructionException was expected"); - } catch (FlowModelConstructionException e) { + fail("A FlowModelBuilderException was expected"); + } catch (FlowModelBuilderException e) { // we want this } } @@ -228,14 +241,14 @@ public class XmlFlowModelBuilderTests extends TestCase { public void testStateMergeParentStateNotFound() { ClassPathResource resourceChild = new ClassPathResource("flow-inheritance-state-child.xml", getClass()); ClassPathResource resourceParent = new ClassPathResource("flow-empty.xml", getClass()); - registry - .registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry), "child")); - registry.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, registry), - "parent")); + registry.registerFlowModel("child", + new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry))); + registry.registerFlowModel("parent", new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, + registry))); try { registry.getFlowModel("child"); - fail("A FlowModelConstructionException was expected"); - } catch (FlowModelConstructionException e) { + fail("A FlowModelBuilderException was expected"); + } catch (FlowModelBuilderException e) { // we want this } } @@ -243,16 +256,37 @@ public class XmlFlowModelBuilderTests extends TestCase { public void testStateMergeParentStateIncompatable() { ClassPathResource resourceChild = new ClassPathResource("flow-inheritance-state-child-alt.xml", getClass()); ClassPathResource resourceParent = new ClassPathResource("flow-inheritance-state-parent.xml", getClass()); - registry - .registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry), "child")); - registry.registerFlowModel(new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, registry), - "parent")); + registry.registerFlowModel("child", + new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceChild, registry))); + registry.registerFlowModel("parent", new DefaultFlowModelHolder(new XmlFlowModelBuilder(resourceParent, + registry))); try { registry.getFlowModel("child"); - fail("A FlowModelConstructionException was expected"); - } catch (FlowModelConstructionException e) { + fail("A FlowModelBuilderException was expected"); + } catch (FlowModelBuilderException e) { // we want this } } + public void testFormActionValidatorMethod() { + ClassPathResource resource = new ClassPathResource("flow-formaction-validatormethod.xml", getClass()); + XmlFlowModelBuilder builder = new XmlFlowModelBuilder(resource, registry); + DefaultFlowModelHolder holder = new DefaultFlowModelHolder(builder); + FlowModelFlowBuilder flowBuilder = new FlowModelFlowBuilder(holder); + FlowAssembler assembler = new FlowAssembler(flowBuilder, new MockFlowBuilderContext("flow")); + Flow flow = assembler.assembleFlow(); + FlowExecutionImplFactory factory = new FlowExecutionImplFactory(); + factory.setExecutionListenerLoader(new StaticFlowExecutionListenerLoader(new FlowExecutionListenerAdapter() { + public void viewRendering(RequestContext context, View view, StateDefinition viewState) { + BindingResult result = (BindingResult) context.getFlashScope().get( + "org.springframework.validation.BindingResult.formBean"); + assertEquals(1, result.getErrorCount()); + } + })); + FlowExecution execution = factory.createFlowExecution(flow); + execution.start(null, new MockExternalContext()); + MockExternalContext context = new MockExternalContext(); + context.setEventId("submit"); + execution.resume(context); + } } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/flow-formaction-validatormethod-beans.xml b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/flow-formaction-validatormethod-beans.xml new file mode 100644 index 00000000..916314c4 --- /dev/null +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/flow-formaction-validatormethod-beans.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/flow-formaction-validatormethod.xml b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/flow-formaction-validatormethod.xml new file mode 100644 index 00000000..2a306b26 --- /dev/null +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/builder/xml/flow-formaction-validatormethod.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/registry/DefaultFlowModelHolderTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/registry/DefaultFlowModelHolderTests.java index c5b00ff0..709ced8c 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/registry/DefaultFlowModelHolderTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/registry/DefaultFlowModelHolderTests.java @@ -17,7 +17,7 @@ public class DefaultFlowModelHolderTests extends TestCase { protected void setUp() { builder = new SimpleFlowBuilder(); - holder = new DefaultFlowModelHolder(builder, "flowId"); + holder = new DefaultFlowModelHolder(builder); } public void testGetFlowDefinition() { diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/registry/FlowModelRegistryImplTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/registry/FlowModelRegistryImplTests.java index e4ab111a..f1349576 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/model/registry/FlowModelRegistryImplTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/model/registry/FlowModelRegistryImplTests.java @@ -28,20 +28,20 @@ public class FlowModelRegistryImplTests extends TestCase { } public void testRegisterFlow() { - registry.registerFlowModel(new StaticFlowModelHolder(fooFlow, "foo")); + registry.registerFlowModel("foo", new StaticFlowModelHolder(fooFlow)); assertEquals(fooFlow, registry.getFlowModel("foo")); } public void testRegisterFlowSameIds() { - registry.registerFlowModel(new StaticFlowModelHolder(fooFlow, "foo")); + registry.registerFlowModel("foo", new StaticFlowModelHolder(fooFlow)); FlowModel newFlow = new FlowModel(); - registry.registerFlowModel(new StaticFlowModelHolder(newFlow, "foo")); + registry.registerFlowModel("foo", new StaticFlowModelHolder(newFlow)); assertSame(newFlow, registry.getFlowModel("foo")); } public void testRegisterMultipleFlows() { - registry.registerFlowModel(new StaticFlowModelHolder(fooFlow, "foo")); - registry.registerFlowModel(new StaticFlowModelHolder(barFlow, "bar")); + registry.registerFlowModel("foo", new StaticFlowModelHolder(fooFlow)); + registry.registerFlowModel("bar", new StaticFlowModelHolder(barFlow)); assertEquals(fooFlow, registry.getFlowModel("foo")); assertEquals(barFlow, registry.getFlowModel("bar")); } @@ -51,7 +51,7 @@ public class FlowModelRegistryImplTests extends TestCase { FlowModelRegistryImpl child = new FlowModelRegistryImpl(); child.setParent(registry); FlowModel fooFlow = new FlowModel(); - child.registerFlowModel(new StaticFlowModelHolder(fooFlow, "foo")); + child.registerFlowModel("foo", new StaticFlowModelHolder(fooFlow)); assertSame(fooFlow, child.getFlowModel("foo")); assertEquals(barFlow, child.getFlowModel("bar")); } @@ -59,21 +59,15 @@ public class FlowModelRegistryImplTests extends TestCase { private static class StaticFlowModelHolder implements FlowModelHolder { private FlowModel model; - private String id; - public StaticFlowModelHolder(FlowModel model, String id) { + public StaticFlowModelHolder(FlowModel model) { this.model = model; - this.id = id; } - public FlowModel getFlowModel() throws FlowModelConstructionException { + public FlowModel getFlowModel() { return model; } - public String getFlowModelId() { - return id; - } - public Resource getFlowModelResource() { return null; } @@ -82,7 +76,7 @@ public class FlowModelRegistryImplTests extends TestCase { return false; } - public void refresh() throws FlowModelConstructionException { + public void refresh() { } }