getModelResource is required to return non-null on FlowModelHolder

This commit is contained in:
Keith Donald
2008-10-17 15:39:11 +00:00
parent 2e6d19f4af
commit 9e115f7aac
10 changed files with 54 additions and 39 deletions

View File

@@ -34,6 +34,14 @@ public interface FlowDefinitionHolder {
*/
public String getFlowDefinitionId();
/**
* Returns a descriptive string that identifies the source of this FlowDefinition. This is also a lightweight method
* callers may call to obtain the logical resource where the flow definition resides without triggering flow
* definition assembly. Used for informational purposes.
* @return the flow definition resource string
*/
public String getFlowDefinitionResourceString();
/**
* Returns the flow definition held by this holder. Calling this method the first time may trigger flow assembly
* (which may be expensive).
@@ -47,4 +55,5 @@ public interface FlowDefinitionHolder {
* @throws FlowDefinitionConstructionException if there is a problem constructing the target flow definition
*/
public void refresh() throws FlowDefinitionConstructionException;
}

View File

@@ -92,8 +92,8 @@ public class FlowDefinitionRegistryImpl implements FlowDefinitionRegistry {
public void registerFlowDefinition(FlowDefinitionHolder definitionHolder) {
Assert.notNull(definitionHolder, "The holder of the flow definition to register is required");
if (logger.isDebugEnabled()) {
logger.debug("Registering flow definition held by " + definitionHolder + " under id '"
+ definitionHolder.getFlowDefinitionId() + "'");
logger.debug("Registering flow definition '" + definitionHolder.getFlowDefinitionResourceString()
+ "' under id '" + definitionHolder.getFlowDefinitionId() + "'");
}
flowDefinitions.put(definitionHolder.getFlowDefinitionId(), definitionHolder);
}

View File

@@ -41,6 +41,10 @@ class StaticFlowDefinitionHolder implements FlowDefinitionHolder {
return flowDefinition.getId();
}
public String getFlowDefinitionResourceString() {
return flowDefinition.getClass().getName();
}
public FlowDefinition getFlowDefinition() throws FlowDefinitionConstructionException {
return flowDefinition;
}

View File

@@ -70,6 +70,10 @@ public class DefaultFlowHolder implements FlowDefinitionHolder {
return assembler.getFlowBuilderContext().getFlowId();
}
public String getFlowDefinitionResourceString() {
return assembler.getFlowBuilder().getFlowResourceString();
}
public synchronized FlowDefinition getFlowDefinition() throws FlowDefinitionConstructionException {
if (assembling) {
// must return early assembly result for when a flow calls itself recursively

View File

@@ -20,20 +20,19 @@ import org.springframework.webflow.engine.Flow;
/**
* Builder interface used to build a flow definition. The process of building a flow consists of the following steps:
* <ol>
* <li> Initialize this builder, creating the initial flow definition, by calling {@link #init(FlowBuilderContext)}.
* <li> Call {@link #buildVariables()} to create any variables of the flow and add them to the flow definition.
* <li> Call {@link #buildInputMapper()} to create and set the input mapper for the flow.
* <li> Call {@link #buildStartActions()} to create and add any start actions to the flow.
* <li> Call {@link #buildStates()} to create the states of the flow and add them to the flow definition.
* <li> Call {@link #buildGlobalTransitions()} to create any transitions shared by all states of the flow and add them
* to the flow definition.
* <li> Call {@link #buildEndActions()} to create and add any end actions to the flow.
* <li> Call {@link #buildOutputMapper()} to create and set the output mapper for the flow.
* <li> Call {@link #buildExceptionHandlers()} to create the exception handlers of the flow and add them to the flow
* <li>Initialize this builder, creating the initial flow definition, by calling {@link #init(FlowBuilderContext)}.
* <li>Call {@link #buildVariables()} to create any variables of the flow and add them to the flow definition.
* <li>Call {@link #buildInputMapper()} to create and set the input mapper for the flow.
* <li>Call {@link #buildStartActions()} to create and add any start actions to the flow.
* <li>Call {@link #buildStates()} to create the states of the flow and add them to the flow definition.
* <li>Call {@link #buildGlobalTransitions()} to create any transitions shared by all states of the flow and add them to
* the flow definition.
* <li>Call {@link #buildEndActions()} to create and add any end actions to the flow.
* <li>Call {@link #buildOutputMapper()} to create and set the output mapper for the flow.
* <li>Call {@link #buildExceptionHandlers()} to create the exception handlers of the flow and add them to the flow
* definition.
* <li> Call {@link #getFlow()} to return the fully-built {@link Flow} definition.
* <li> Dispose this builder, releasing any resources allocated during the building process by calling
* {@link #dispose()}.
* <li>Call {@link #getFlow()} to return the fully-built {@link Flow} definition.
* <li>Dispose this builder, releasing any resources allocated during the building process by calling {@link #dispose()}.
* </ol>
* <p>
* Implementations should encapsulate flow construction logic, either for a specific kind of flow, for example, an
@@ -127,9 +126,16 @@ public interface FlowBuilder {
public void dispose() throws FlowBuilderException;
/**
* As the underlying flow resource managed by this builder changed since the last build occurred?
* As the underlying flow managed by this builder changed since the last build occurred?
* @return true if changed, false if not
*/
public boolean hasFlowChanged();
/**
* Returns a string describing the location of the flow resource; the logical location where the source code can be
* found. Used for informational purposes.
* @return the flow resource string
*/
public String getFlowResourceString();
}

View File

@@ -257,6 +257,10 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
return flowModelHolder.hasFlowModelChanged();
}
public String getFlowResourceString() {
return flowModelHolder.getFlowModelResource().getDescription();
}
/**
* Shutdown the builder, releasing any resources it holds. A new flow construction process should start with another
* call to the {@link #init(FlowBuilderContext)} method.
@@ -303,9 +307,6 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
private Resource[] parseContextResources(List beanImports) {
if (beanImports != null && !beanImports.isEmpty()) {
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();
@@ -339,9 +340,7 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
flowContext.getBeanFactory().registerScope("flow", new FlowScope());
flowContext.getBeanFactory().registerScope("conversation", new ConversationScope());
Resource flowResource = flowModelHolder.getFlowModelResource();
if (flowResource != null) {
flowContext.setResourceLoader(new FlowRelativeResourceLoader(flowResource));
}
flowContext.setResourceLoader(new FlowRelativeResourceLoader(flowResource));
if (JdkVersion.isAtLeastJava15()) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(flowContext);
}
@@ -359,7 +358,7 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
private void registerMessageSource(GenericApplicationContext flowContext, Resource flowResource) {
boolean localMessageSourcePresent = flowContext
.containsLocalBean(AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME);
if (flowResource != null && !localMessageSourcePresent) {
if (!localMessageSourcePresent) {
Resource messageBundle;
try {
messageBundle = flowResource.createRelative("messages.properties");
@@ -968,7 +967,7 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
}
public String toString() {
return new ToStringCreator(this).append("resource", flowModelHolder.getFlowModelResource()).toString();
return new ToStringCreator(this).append("flowModelResource", flowModelHolder.getFlowModelResource()).toString();
}
}
}

View File

@@ -109,6 +109,10 @@ public abstract class AbstractFlowBuilder implements FlowBuilder {
return false;
}
public String getFlowResourceString() {
return getClass().getName();
}
/**
* Flow builder destruction hook. Does nothing by default. May be overridden by subclasses.
*/

View File

@@ -41,9 +41,8 @@ public interface FlowModelHolder {
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
* Returns the underlying resource defining the flow model.
* @return the flow model resource
*/
public Resource getFlowModelResource();

View File

@@ -18,8 +18,6 @@ package org.springframework.webflow.engine.model.registry;
import java.util.Map;
import java.util.TreeMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.style.ToStringCreator;
import org.springframework.util.Assert;
import org.springframework.webflow.engine.model.FlowModel;
@@ -32,8 +30,6 @@ import org.springframework.webflow.engine.model.FlowModel;
*/
public class FlowModelRegistryImpl implements FlowModelRegistry {
private static final Log logger = LogFactory.getLog(FlowModelRegistryImpl.class);
/**
* The map of loaded Flow models maintained in this registry.
*/
@@ -52,9 +48,6 @@ public class FlowModelRegistryImpl implements FlowModelRegistry {
public FlowModel getFlowModel(String id) throws NoSuchFlowModelException {
try {
if (logger.isDebugEnabled()) {
logger.debug("Getting FlowModel with id '" + id + "'");
}
return getFlowModelHolder(id).getFlowModel();
} catch (NoSuchFlowModelException e) {
@@ -74,9 +67,6 @@ public class FlowModelRegistryImpl implements FlowModelRegistry {
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(id, modelHolder);
}

View File

@@ -338,7 +338,7 @@ public class FlowModelFlowBuilderTests extends TestCase {
}
public Resource getFlowModelResource() {
return null;
return new ClassPathResource("", getClass());
}
public boolean hasFlowModelChanged() {