retrofitting flow refresh checking
responsibility of builder now...
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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() + "'";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user