From 41ab629934e08d1a831acb892e5ee51242944085 Mon Sep 17 00:00:00 2001 From: Keith Donald Date: Sun, 23 Mar 2008 03:40:43 +0000 Subject: [PATCH] retrofitting flow refresh checking responsibility of builder now... --- .../config/FlowRegistryFactoryBean.java | 6 +- ...tionHolder.java => DefaultFlowHolder.java} | 64 ++----------- .../webflow/engine/builder/FlowBuilder.java | 7 ++ .../builder/model/FlowModelFlowBuilder.java | 43 +++++---- .../builder/support/AbstractFlowBuilder.java | 4 + .../model/builder/FlowModelBuilder.java | 14 +++ .../builder/xml/XmlFlowModelBuilder.java | 20 ++++ .../registry/DefaultFlowModelHolder.java | 93 +++++-------------- .../model/registry/FlowModelHolder.java | 15 +++ .../AbstractXmlFlowExecutionTests.java | 2 +- ...Tests.java => DefaultFlowHolderTests.java} | 8 +- .../model/FlowModelFlowBuilderTests.java | 34 ++++++- .../registry/DefaultFlowModelHolderTests.java | 8 ++ .../registry/FlowModelRegistryImplTests.java | 43 +++++++-- 14 files changed, 196 insertions(+), 165 deletions(-) rename spring-webflow/src/main/java/org/springframework/webflow/engine/builder/{RefreshableFlowDefinitionHolder.java => DefaultFlowHolder.java} (59%) rename spring-webflow/src/test/java/org/springframework/webflow/engine/builder/{RefreshableFlowDefinitionHolderTests.java => DefaultFlowHolderTests.java} (88%) 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 0c8222fa..18f3c827 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 @@ -19,7 +19,7 @@ import org.springframework.webflow.definition.registry.FlowDefinitionRegistryImp import org.springframework.webflow.engine.builder.FlowAssembler; import org.springframework.webflow.engine.builder.FlowBuilder; import org.springframework.webflow.engine.builder.FlowBuilderContext; -import org.springframework.webflow.engine.builder.RefreshableFlowDefinitionHolder; +import org.springframework.webflow.engine.builder.DefaultFlowHolder; import org.springframework.webflow.engine.builder.model.FlowModelFlowBuilder; import org.springframework.webflow.engine.builder.support.FlowBuilderContextImpl; import org.springframework.webflow.engine.builder.support.FlowBuilderServices; @@ -127,7 +127,7 @@ class FlowRegistryFactoryBean implements FactoryBean, InitializingBean { FlowBuilderContext builderContext = new FlowBuilderContextImpl(flowResource.getId(), flowResource .getAttributes(), flowRegistry, flowBuilderServices); FlowAssembler assembler = new FlowAssembler(builder, builderContext); - return new RefreshableFlowDefinitionHolder(assembler); + return new DefaultFlowHolder(assembler); } private FlowDefinitionResource createResource(FlowLocation location) { @@ -148,7 +148,7 @@ class FlowRegistryFactoryBean implements FactoryBean, InitializingBean { } private FlowBuilder createFlowBuilder(FlowDefinitionResource resource) { - return new FlowModelFlowBuilder(createFlowModelHolder(resource), resource.getPath()); + return new FlowModelFlowBuilder(createFlowModelHolder(resource)); } private FlowModelHolder createFlowModelHolder(FlowDefinitionResource resource) { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/RefreshableFlowDefinitionHolder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/DefaultFlowHolder.java similarity index 59% rename from spring-webflow/src/main/java/org/springframework/webflow/engine/builder/RefreshableFlowDefinitionHolder.java rename to spring-webflow/src/main/java/org/springframework/webflow/engine/builder/DefaultFlowHolder.java index ba6cbe40..8194bf59 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/RefreshableFlowDefinitionHolder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/DefaultFlowHolder.java @@ -15,15 +15,11 @@ */ package org.springframework.webflow.engine.builder; -import java.io.IOException; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.core.io.Resource; import org.springframework.webflow.definition.FlowDefinition; import org.springframework.webflow.definition.registry.FlowDefinitionConstructionException; import org.springframework.webflow.definition.registry.FlowDefinitionHolder; -import org.springframework.webflow.util.ResourceHolder; /** * A flow definition holder that can detect changes on an underlying flow definition resource and refresh that resource @@ -39,9 +35,9 @@ import org.springframework.webflow.util.ResourceHolder; * * @author Keith Donald */ -public class RefreshableFlowDefinitionHolder implements FlowDefinitionHolder { +public class DefaultFlowHolder implements FlowDefinitionHolder { - private static final Log logger = LogFactory.getLog(RefreshableFlowDefinitionHolder.class); + private static final Log logger = LogFactory.getLog(DefaultFlowHolder.class); /** * The flow definition assembled by this assembler. @@ -53,12 +49,6 @@ public class RefreshableFlowDefinitionHolder implements FlowDefinitionHolder { */ private FlowAssembler assembler; - /** - * A last modified date for the backing flow definition resource, used to support automatic reassembly on resource - * change. - */ - private long lastModified; - /** * A flag indicating whether or not this holder is in the middle of the assembly process. */ @@ -69,7 +59,7 @@ public class RefreshableFlowDefinitionHolder implements FlowDefinitionHolder { * assembly, on initial use and on any resource change or refresh. * @param assembler the flow assembler to use */ - public RefreshableFlowDefinitionHolder(FlowAssembler assembler) { + public DefaultFlowHolder(FlowAssembler assembler) { this.assembler = assembler; } @@ -83,11 +73,13 @@ public class RefreshableFlowDefinitionHolder implements FlowDefinitionHolder { return getFlowBuilder().getFlow(); } if (flowDefinition == null) { - lastModified = calculateLastModified(); - logger.debug("Assembling the flow definition for the first time"); + logger.debug("Assembling the flow for the first time"); assembleFlow(); } else { - refreshIfChanged(); + if (getFlowBuilder().hasFlowChanged()) { + logger.debug("The flow has changed; reassembling..."); + assembleFlow(); + } } return flowDefinition; } @@ -98,29 +90,6 @@ public class RefreshableFlowDefinitionHolder implements FlowDefinitionHolder { // internal helpers - /** - * Helper that retrieves the last modified date by querying the backing flow resource. - * @return the last modified date, or 0L if it could not be retrieved - */ - private long calculateLastModified() { - if (getFlowBuilder() instanceof ResourceHolder) { - Resource resource = ((ResourceHolder) getFlowBuilder()).getResource(); - try { - long lastModified = resource.getFile().lastModified(); - if (logger.isDebugEnabled()) { - logger.debug("Flow definition [" + resource + "] was last modified on " + lastModified); - } - return lastModified; - } catch (IOException e) { - // ignore, last modified checks not supported - } - } - return 0L; - } - - /** - * Assemble the held flow definition, delegating to the configured FlowAssembler (director). - */ private void assembleFlow() throws FlowDefinitionConstructionException { try { assembling = true; @@ -132,23 +101,6 @@ public class RefreshableFlowDefinitionHolder implements FlowDefinitionHolder { } } - /** - * Reassemble the flow if its underlying resource has changed. - */ - private void refreshIfChanged() { - long calculatedLastModified = calculateLastModified(); - if (calculatedLastModified > lastModified) { - if (logger.isDebugEnabled()) { - logger.debug("Refreshing flow definition [" + flowDefinition.getId() + "]"); - } - assembleFlow(); - lastModified = calculatedLastModified; - } - } - - /** - * Returns the flow builder that actually builds the Flow definition. - */ private FlowBuilder getFlowBuilder() { return assembler.getFlowBuilder(); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilder.java index 6bcd870a..377c9800 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilder.java @@ -125,4 +125,11 @@ public interface FlowBuilder { * @throws FlowBuilderException an exception occurred building this flow */ public void dispose() throws FlowBuilderException; + + /** + * As the underlying flow resource managed by this builder changed since the last build occurred? + * @return true if changed, false if not + */ + public boolean hasFlowChanged(); + } \ No newline at end of file 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 32496cf0..e862b9ba 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 @@ -87,33 +87,30 @@ import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.ScopeType; import org.springframework.webflow.execution.ViewFactory; import org.springframework.webflow.security.SecurityRule; -import org.springframework.webflow.util.ResourceHolder; -public class FlowModelFlowBuilder extends AbstractFlowBuilder implements ResourceHolder { +/** + * Builds a runtime {@link Flow} definition object from a {@link FlowModel}. + * + * @author Keith Donald + */ +public class FlowModelFlowBuilder extends AbstractFlowBuilder { private FlowModelHolder flowModelHolder; private FlowModel flowModel; - private Resource resource; - private LocalFlowBuilderContext localFlowBuilderContext; public FlowModelFlowBuilder(FlowModelHolder flowModelHolder) { this.flowModelHolder = flowModelHolder; } - public FlowModelFlowBuilder(FlowModelHolder flowModelHolder, Resource resource) { - this.flowModelHolder = flowModelHolder; - this.resource = resource; - } - /** * Initialize this builder. This could cause the builder to open a stream to an externalized resource representing * the flow definition, for example. * @throws FlowBuilderException an exception occurred building the flow */ - public void doInit() throws FlowBuilderException { + protected void doInit() throws FlowBuilderException { flowModel = flowModelHolder.getFlowModel(); initLocalFlowContext(); } @@ -152,7 +149,7 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder implements Resourc */ public void buildStates() throws FlowBuilderException { if (flowModel.getStates() == null) { - throw new FlowBuilderException("At least one state is required to build a flow definition"); + throw new FlowBuilderException("At least one state is required to build a Flow"); } for (Iterator it = flowModel.getStates().iterator(); it.hasNext();) { AbstractStateModel state = (AbstractStateModel) it.next(); @@ -208,22 +205,20 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder implements Resourc parseExceptionHandlers(flowModel.getExceptionHandlers(), flowModel.getGlobalTransitions())); } + public boolean hasFlowChanged() { + return flowModelHolder.hasFlowModelChanged(); + } + /** * Shutdown the builder, releasing any resources it holds. A new flow construction process should start with another * call to the {@link #init(FlowBuilderContext)} method. * @throws FlowBuilderException an exception occurred building this flow */ - public void doDispose() throws FlowBuilderException { + protected void doDispose() throws FlowBuilderException { flowModel = null; setLocalContext(null); } - // implementing resource holder - - public Resource getResource() { - return resource; - } - // subclassing hooks protected Flow createFlow() { @@ -266,14 +261,15 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder implements Resourc private Resource[] parseContextResources(List beanImports) { if (beanImports != null && !beanImports.isEmpty()) { - if (getResource() == null) { - throw new FlowBuilderException("A resource must be defined in order to load bean-imports"); + Resource flowResource = flowModelHolder.getFlowModelResource(); + if (flowResource == null) { + throw new FlowBuilderException("The FlowModel must be Resource in order to load bean-imports"); } List resources = new ArrayList(beanImports.size()); for (Iterator it = getFlowModel().getBeanImports().iterator(); it.hasNext();) { BeanImportModel beanImport = (BeanImportModel) it.next(); try { - resources.add(getResource().createRelative(beanImport.getResource())); + resources.add(flowResource.createRelative(beanImport.getResource())); } catch (IOException e) { throw new FlowBuilderException("Could not access flow-relative artifact resource '" + beanImport.getResource() + "'", e); @@ -305,7 +301,10 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder implements Resourc flowContext.getBeanFactory().setParentBeanFactory(parent); } } - flowContext.setResourceLoader(new FlowRelativeResourceLoader(resource)); + Resource flowResource = flowModelHolder.getFlowModelResource(); + if (flowResource != null) { + flowContext.setResourceLoader(new FlowRelativeResourceLoader(flowResource)); + } if (JdkVersion.isAtLeastJava15()) { AnnotationConfigUtils.registerAnnotationConfigProcessors(flowContext); } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/AbstractFlowBuilder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/AbstractFlowBuilder.java index af3ab269..7a98b895 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/AbstractFlowBuilder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/AbstractFlowBuilder.java @@ -105,6 +105,10 @@ public abstract class AbstractFlowBuilder implements FlowBuilder { doDispose(); } + public boolean hasFlowChanged() { + return false; + } + /** * Flow builder destruction hook. Does nothing by default. May be overridden by subclasses. */ diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/FlowModelBuilder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/FlowModelBuilder.java index 54245f09..c66526cf 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/FlowModelBuilder.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/model/builder/FlowModelBuilder.java @@ -15,6 +15,7 @@ */ package org.springframework.webflow.engine.model.builder; +import org.springframework.core.io.Resource; import org.springframework.webflow.engine.model.FlowModel; /** @@ -67,4 +68,17 @@ public interface FlowModelBuilder { * @throws FlowModelBuilderException an exception occurred disposing this flow */ public void dispose() throws FlowModelBuilderException; + + /** + * Returns true if the underlying flow model has changed since the last call to {@link #init()}. + * @return true if the flow model has changed + */ + public boolean hasFlowModelChanged(); + + /** + * Get the underlying flow model resource accessed to build this flow model. Returns null if this builder does not + * construct the flow model from a resource. + * @return the flow model resource + */ + public Resource getFlowModelResource(); } \ No newline at end of file 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 2f039745..e7e8f7a9 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 @@ -78,6 +78,8 @@ public class XmlFlowModelBuilder implements FlowModelBuilder, ResourceHolder { private FlowModel flowModel; + private long lastModifiedTimestamp; + /** * Create a new XML flow model builder that will parse the XML document at the specified resource location and use * the provided locator to access parent flow models. @@ -89,6 +91,23 @@ public class XmlFlowModelBuilder implements FlowModelBuilder, ResourceHolder { this.modelLocator = modelLocator; } + public Resource getFlowModelResource() { + return resource; + } + + public boolean hasFlowModelChanged() { + try { + long lastModified = resource.getFile().lastModified(); + if (lastModified > lastModifiedTimestamp) { + return true; + } else { + return false; + } + } catch (IOException e) { + return false; + } + } + /** * Sets the loader that will load the XML-based flow definition document. Optional, defaults to * {@link DefaultDocumentLoader}. @@ -106,6 +125,7 @@ public class XmlFlowModelBuilder implements FlowModelBuilder, ResourceHolder { public void init() throws FlowModelBuilderException { try { document = documentLoader.loadDocument(resource); + lastModifiedTimestamp = getResource().getFile().lastModified(); } catch (IOException e) { throw new FlowModelBuilderException("Could not access the XML flow definition resource at " + resource, e); } catch (ParserConfigurationException 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 da1d96bb..61f5bbed 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 @@ -15,15 +15,12 @@ */ package org.springframework.webflow.engine.model.registry; -import java.io.IOException; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.core.io.Resource; import org.springframework.webflow.engine.model.FlowModel; import org.springframework.webflow.engine.model.builder.FlowModelBuilder; import org.springframework.webflow.engine.model.builder.FlowModelBuilderException; -import org.springframework.webflow.util.ResourceHolder; /** * A flow model holder that can detect changes on an underlying flow model resource and refresh that resource @@ -55,7 +52,7 @@ public class DefaultFlowModelHolder implements FlowModelHolder { /** * The flow model builder. */ - private FlowModelBuilder builder; + private FlowModelBuilder flowModelBuilder; /** * A last modified date for the backing flow definition resource, used to support automatic reassembly on resource @@ -66,21 +63,11 @@ 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 builder the flow model builder to use + * @param flowModelBuilder the flow model builder to use * @param flowModelId the identifier of the flow model */ - public DefaultFlowModelHolder(FlowModelBuilder builder, String flowModelId) { - this.builder = builder; - this.flowModelId = flowModelId; - } - - /** - * Creates a new static flow model holder - * @param flowModel the flow model to hold - * @param flowModelId the identifier of the flow model - */ - public DefaultFlowModelHolder(FlowModel flowModel, String flowModelId) { - this.flowModel = flowModel; + public DefaultFlowModelHolder(FlowModelBuilder flowModelBuilder, String flowModelId) { + this.flowModelBuilder = flowModelBuilder; this.flowModelId = flowModelId; } @@ -90,77 +77,41 @@ public class DefaultFlowModelHolder implements FlowModelHolder { public synchronized FlowModel getFlowModel() throws FlowModelConstructionException { if (flowModel == null) { - lastModified = calculateLastModified(); - logger.debug("Assembling the flow model for the first time"); - assembleFlow(); + assembleFlowModel(); } else { - refreshIfChanged(); + if (flowModelBuilder.hasFlowModelChanged()) { + assembleFlowModel(); + } } return flowModel; } + public Resource getFlowModelResource() { + return flowModelBuilder.getFlowModelResource(); + } + + public boolean hasFlowModelChanged() { + return flowModelBuilder.hasFlowModelChanged(); + } + public synchronized void refresh() throws FlowModelConstructionException { - assembleFlow(); + assembleFlowModel(); } // internal helpers - /** - * Helper that retrieves the last modified date by querying the backing flow resource. - * @return the last modified date, or 0L if it could not be retrieved - */ - private long calculateLastModified() { - if (getFlowModelBuilder() instanceof ResourceHolder) { - Resource resource = ((ResourceHolder) getFlowModelBuilder()).getResource(); - try { - long lastModified = resource.getFile().lastModified(); - if (logger.isDebugEnabled()) { - logger.debug("Flow definition [" + resource + "] was last modified on " + lastModified); - } - return lastModified; - } catch (IOException e) { - // ignore, last modified checks not supported - } - } - return 0L; - } - - /** - * Assemble the held flow definition, delegating to the configured FlowAssembler (director). - */ - private void assembleFlow() throws FlowModelConstructionException { + private void assembleFlowModel() throws FlowModelConstructionException { try { - builder.init(); - builder.build(); - flowModel = builder.getFlowModel(); + flowModelBuilder.init(); + flowModelBuilder.build(); + flowModel = flowModelBuilder.getFlowModel(); } catch (FlowModelBuilderException e) { throw new FlowModelConstructionException(flowModelId, e); } finally { - builder.dispose(); + flowModelBuilder.dispose(); } } - /** - * Reassemble the flow if its underlying resource has changed. - */ - private void refreshIfChanged() { - long calculatedLastModified = calculateLastModified(); - if (calculatedLastModified > lastModified) { - if (logger.isDebugEnabled()) { - logger.debug("Refreshing flow definition [" + flowModelId + "]"); - } - assembleFlow(); - lastModified = calculatedLastModified; - } - } - - /** - * Returns the flow builder that actually builds the Flow definition. - */ - private FlowModelBuilder getFlowModelBuilder() { - return builder; - } - public String toString() { return "'" + getFlowModelId() + "'"; } 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 fab3d4d7..93ba364b 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 @@ -15,6 +15,7 @@ */ package org.springframework.webflow.engine.model.registry; +import org.springframework.core.io.Resource; import org.springframework.webflow.engine.model.FlowModel; /** @@ -42,10 +43,24 @@ public interface FlowModelHolder { */ public FlowModel getFlowModel() throws FlowModelConstructionException; + /** + * Has the underlying flow model changed since it was last accessed via a call to {@link #getFlowModel()}. + * @return true if yes, false if not + */ + public boolean hasFlowModelChanged(); + + /** + * Returns the underlying resource defining the flow model. Will return null if the flow model did not originate + * from a file-based resource. + * @return the flow model resource, or null + */ + public Resource getFlowModelResource(); + /** * 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 */ public void refresh() throws FlowModelConstructionException; + } \ No newline at end of file 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 7b11ad9d..9499226d 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 @@ -81,7 +81,7 @@ public abstract class AbstractXmlFlowExecutionTests extends AbstractExternalized FlowModelBuilder modelBuilder = new XmlFlowModelBuilder(resource.getPath(), flowModelRegistry); FlowModelHolder modelHolder = new DefaultFlowModelHolder(modelBuilder, resource.getId()); flowModelRegistry.registerFlowModel(modelHolder); - return new FlowModelFlowBuilder(modelHolder, resource.getPath()) { + return new FlowModelFlowBuilder(modelHolder) { protected void registerFlowBeans(ConfigurableBeanFactory flowBeanFactory) { registerMockFlowBeans(flowBeanFactory); } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/RefreshableFlowDefinitionHolderTests.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/DefaultFlowHolderTests.java similarity index 88% rename from spring-webflow/src/test/java/org/springframework/webflow/engine/builder/RefreshableFlowDefinitionHolderTests.java rename to spring-webflow/src/test/java/org/springframework/webflow/engine/builder/DefaultFlowHolderTests.java index f521e0f8..aa3127d8 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/RefreshableFlowDefinitionHolderTests.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/builder/DefaultFlowHolderTests.java @@ -11,13 +11,13 @@ import org.springframework.webflow.engine.builder.support.AbstractFlowBuilder; import org.springframework.webflow.test.MockFlowBuilderContext; import org.springframework.webflow.util.ResourceHolder; -public class RefreshableFlowDefinitionHolderTests extends TestCase { - private RefreshableFlowDefinitionHolder holder; +public class DefaultFlowHolderTests extends TestCase { + private DefaultFlowHolder holder; private FlowAssembler assembler; protected void setUp() { FlowAssembler assembler = new FlowAssembler(new SimpleFlowBuilder(), new MockFlowBuilderContext("flowId")); - holder = new RefreshableFlowDefinitionHolder(assembler); + holder = new DefaultFlowHolder(assembler); } public void testGetFlowDefinition() { @@ -28,7 +28,7 @@ public class RefreshableFlowDefinitionHolderTests extends TestCase { public void testGetFlowDefinitionWithChangesRefreshed() { assembler = new FlowAssembler(new ChangeDetectableFlowBuilder(), new MockFlowBuilderContext("flowId")); - holder = new RefreshableFlowDefinitionHolder(assembler); + holder = new DefaultFlowHolder(assembler); FlowDefinition flow = holder.getFlowDefinition(); flow = holder.getFlowDefinition(); assertEquals("flowId", flow.getId()); 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 aa6a35cf..e31db345 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 @@ -4,6 +4,7 @@ import junit.framework.TestCase; import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import org.springframework.webflow.action.ExternalRedirectAction; import org.springframework.webflow.action.FlowDefinitionRedirectAction; import org.springframework.webflow.core.collection.LocalAttributeMap; @@ -28,6 +29,7 @@ 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; @@ -325,7 +327,7 @@ public class FlowModelFlowBuilderTests extends TestCase { } private Flow getFlow(FlowModel model) { - FlowModelHolder holder = new DefaultFlowModelHolder(model, "flow"); + FlowModelHolder holder = new StaticFlowModelHolder(model); FlowModelFlowBuilder builder = new FlowModelFlowBuilder(holder); FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow")); return assembler.assembleFlow(); @@ -334,9 +336,37 @@ public class FlowModelFlowBuilderTests extends TestCase { private Flow getFlow(ClassPathResource resource) { FlowModelHolder holder = new DefaultFlowModelHolder(new XmlFlowModelBuilder(resource, new FlowModelRegistryImpl()), "flow"); - FlowModelFlowBuilder builder = new FlowModelFlowBuilder(holder, resource); + FlowModelFlowBuilder builder = new FlowModelFlowBuilder(holder); FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow")); return assembler.assembleFlow(); } + private static class StaticFlowModelHolder implements FlowModelHolder { + + private FlowModel model; + + public StaticFlowModelHolder(FlowModel model) { + this.model = model; + } + + public FlowModel getFlowModel() throws FlowModelConstructionException { + return model; + } + + public String getFlowModelId() { + return "flow"; + } + + public Resource getFlowModelResource() { + return null; + } + + public boolean hasFlowModelChanged() { + return false; + } + + public void refresh() throws FlowModelConstructionException { + } + + } } 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 5c83e94a..c5b00ff0 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 @@ -58,6 +58,14 @@ public class DefaultFlowModelHolderTests extends TestCase { // no-op } + public Resource getFlowModelResource() { + return null; + } + + public boolean hasFlowModelChanged() { + return false; + } + } public class ChangeDetectableFlowBuilder extends SimpleFlowBuilder implements ResourceHolder { 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 38971875..e4ab111a 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 @@ -2,6 +2,7 @@ package org.springframework.webflow.engine.model.registry; import junit.framework.TestCase; +import org.springframework.core.io.Resource; import org.springframework.webflow.engine.model.FlowModel; public class FlowModelRegistryImplTests extends TestCase { @@ -27,20 +28,20 @@ public class FlowModelRegistryImplTests extends TestCase { } public void testRegisterFlow() { - registry.registerFlowModel(new DefaultFlowModelHolder(fooFlow, "foo")); + registry.registerFlowModel(new StaticFlowModelHolder(fooFlow, "foo")); assertEquals(fooFlow, registry.getFlowModel("foo")); } public void testRegisterFlowSameIds() { - registry.registerFlowModel(new DefaultFlowModelHolder(fooFlow, "foo")); + registry.registerFlowModel(new StaticFlowModelHolder(fooFlow, "foo")); FlowModel newFlow = new FlowModel(); - registry.registerFlowModel(new DefaultFlowModelHolder(newFlow, "foo")); + registry.registerFlowModel(new StaticFlowModelHolder(newFlow, "foo")); assertSame(newFlow, registry.getFlowModel("foo")); } public void testRegisterMultipleFlows() { - registry.registerFlowModel(new DefaultFlowModelHolder(fooFlow, "foo")); - registry.registerFlowModel(new DefaultFlowModelHolder(barFlow, "bar")); + registry.registerFlowModel(new StaticFlowModelHolder(fooFlow, "foo")); + registry.registerFlowModel(new StaticFlowModelHolder(barFlow, "bar")); assertEquals(fooFlow, registry.getFlowModel("foo")); assertEquals(barFlow, registry.getFlowModel("bar")); } @@ -50,9 +51,39 @@ public class FlowModelRegistryImplTests extends TestCase { FlowModelRegistryImpl child = new FlowModelRegistryImpl(); child.setParent(registry); FlowModel fooFlow = new FlowModel(); - child.registerFlowModel(new DefaultFlowModelHolder(fooFlow, "foo")); + child.registerFlowModel(new StaticFlowModelHolder(fooFlow, "foo")); assertSame(fooFlow, child.getFlowModel("foo")); assertEquals(barFlow, child.getFlowModel("bar")); } + private static class StaticFlowModelHolder implements FlowModelHolder { + + private FlowModel model; + private String id; + + public StaticFlowModelHolder(FlowModel model, String id) { + this.model = model; + this.id = id; + } + + public FlowModel getFlowModel() throws FlowModelConstructionException { + return model; + } + + public String getFlowModelId() { + return id; + } + + public Resource getFlowModelResource() { + return null; + } + + public boolean hasFlowModelChanged() { + return false; + } + + public void refresh() throws FlowModelConstructionException { + } + + } }