diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/Flow.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/Flow.java index f7b7db97..6fd1af75 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/Flow.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/Flow.java @@ -27,6 +27,9 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.support.StaticListableBeanFactory; import org.springframework.binding.mapping.AttributeMapper; import org.springframework.binding.mapping.MappingContext; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; import org.springframework.core.style.StylerUtils; import org.springframework.core.style.ToStringCreator; import org.springframework.util.Assert; @@ -105,7 +108,7 @@ import org.springframework.webflow.execution.RequestContext; * @author Colin Sampaleanu * @author Jeremy Grelle */ -public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory { +public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory, ResourceLoader { /** * Logger, can be used in subclasses. @@ -166,9 +169,14 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory private FlowExecutionExceptionHandlerSet exceptionHandlerSet = new FlowExecutionExceptionHandlerSet(); /** - * The local bean factory for this flow + * An optional bean factory hosting services needed by this flow. */ - private BeanFactory localBeanFactory = new StaticListableBeanFactory(); + private BeanFactory beanFactory = new StaticListableBeanFactory(); + + /** + * An optional resource loader capable of loading resources relative to this flow. + */ + private ResourceLoader resourceLoader = new DefaultResourceLoader(); /** * Construct a new flow definition with the given id. The id should be unique among all flows. @@ -433,6 +441,22 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory return globalTransitionSet; } + /** + * Sets a reference to a bean factory hosting application objects needed by this flow. + * @param beanFactory the bean factory + */ + public void setBeanFactory(BeanFactory beanFactory) { + this.beanFactory = beanFactory; + } + + /** + * Sets a reference to a resource loader capable of loading resources relative to this flow. + * @param resourceLoader the resource loader + */ + public void setResourceLoader(ResourceLoader resourceLoader) { + this.resourceLoader = resourceLoader; + } + // id based equality public boolean equals(Object o) { @@ -536,6 +560,52 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory return getExceptionHandlerSet().handleException(exception, context); } + // implementing bean factory + + public boolean containsBean(String name) { + return beanFactory.containsBean(name); + } + + public String[] getAliases(String name) { + return beanFactory.getAliases(name); + } + + public Object getBean(String name, Class requiredType) throws BeansException { + return beanFactory.getBean(name, requiredType); + } + + public Object getBean(String name, Object[] args) throws BeansException { + return beanFactory.getBean(name, args); + } + + public Object getBean(String name) throws BeansException { + return beanFactory.getBean(name); + } + + public Class getType(String name) throws NoSuchBeanDefinitionException { + return beanFactory.getType(name); + } + + public boolean isPrototype(String name) throws NoSuchBeanDefinitionException { + return beanFactory.isPrototype(name); + } + + public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { + return beanFactory.isSingleton(name); + } + + public boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException { + return beanFactory.isTypeMatch(name, targetType); + } + + public ClassLoader getClassLoader() { + return resourceLoader.getClassLoader(); + } + + public Resource getResource(String name) { + return resourceLoader.getResource(name); + } + // internal helpers private void assertStartStateSet() { @@ -616,44 +686,4 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory "outputMapper", outputMapper).toString(); } - public void setLocalBeanFactory(BeanFactory localBeanFactory) { - this.localBeanFactory = localBeanFactory; - } - - public boolean containsBean(String name) { - return localBeanFactory.containsBean(name); - } - - public String[] getAliases(String name) { - return localBeanFactory.getAliases(name); - } - - public Object getBean(String name, Class requiredType) throws BeansException { - return localBeanFactory.getBean(name, requiredType); - } - - public Object getBean(String name, Object[] args) throws BeansException { - return localBeanFactory.getBean(name, args); - } - - public Object getBean(String name) throws BeansException { - return localBeanFactory.getBean(name); - } - - public Class getType(String name) throws NoSuchBeanDefinitionException { - return localBeanFactory.getType(name); - } - - public boolean isPrototype(String name) throws NoSuchBeanDefinitionException { - return localBeanFactory.isPrototype(name); - } - - public boolean isSingleton(String name) throws NoSuchBeanDefinitionException { - return localBeanFactory.isSingleton(name); - } - - public boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException { - return localBeanFactory.isTypeMatch(name, targetType); - } - } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowArtifactFactory.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowArtifactFactory.java index 202c92ba..42477416 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowArtifactFactory.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowArtifactFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007 the original author or authors. + * Copyright 2004-2008 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. diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowAssembler.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowAssembler.java index a142bd54..149eb521 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowAssembler.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowAssembler.java @@ -1,5 +1,5 @@ /* - * Copyright 2004-2007 the original author or authors. + * Copyright 2004-2008 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. @@ -27,7 +27,8 @@ import org.springframework.webflow.engine.Flow; * *
* FlowBuilder builder = ...;
- * Flow flow = new FlowAssembler("myFlow", builder, null).assembleFlow();
+ * FlowBuilder context = ...;
+ * Flow flow = new FlowAssembler(builder, builderContext).assembleFlow();
*
*
* @see org.springframework.webflow.engine.builder.FlowBuilder
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 ee8ab56e..6bcd870a 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 the original author or authors.
+ * Copyright 2004-2008 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.
@@ -25,8 +25,8 @@ import org.springframework.webflow.engine.Flow;
*
- * This is an example of the classic GoF builder pattern.
+ * This is a good example of the classic GoF builder pattern.
*
* @see Flow
+ * @see FlowBuilderContext
* @see FlowAssembler
*
* @author Keith Donald
@@ -111,15 +112,17 @@ public interface FlowBuilder {
public void buildExceptionHandlers() throws FlowBuilderException;
/**
- * Get the fully constructed and configured Flow object - called by the builder's assembler (director) after
+ * Get the fully constructed and configured Flow object. Called by the builder's assembler (director) after
* assembly. When this method is called by the assembler, it is expected flow construction has completed and the
- * returned flow is ready for use.
+ * returned flow is fully configured and ready for use.
+ * @throws FlowBuilderException an exception occurred building this flow
*/
- public Flow getFlow();
+ public Flow getFlow() throws FlowBuilderException;
/**
* 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 dispose();
+ public void dispose() throws FlowBuilderException;
}
\ No newline at end of file
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderContext.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderContext.java
index 1a2614be..b16a4e52 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderContext.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderContext.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2004-2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.springframework.webflow.engine.builder;
import org.springframework.beans.factory.BeanFactory;
@@ -8,6 +23,10 @@ import org.springframework.webflow.action.BeanInvokingActionFactory;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
+/**
+ * Provides services needed to a direct a flow builder through building a flow definition.
+ * @author Keith Donald
+ */
public interface FlowBuilderContext {
/**
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderException.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderException.java
index 0a689151..c9abe42a 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderException.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/FlowBuilderException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 the original author or authors.
+ * Copyright 2004-2008 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.
@@ -20,7 +20,7 @@ import org.springframework.webflow.core.FlowException;
/**
* Exception thrown to indicate a problem while building a flow.
*
- * @see org.springframework.webflow.engine.builder.FlowBuilder
+ * @see FlowBuilder
*
* @author Erwin Vervaet
*/
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/RefreshableFlowDefinitionHolder.java
index 522ee7d5..77e85024 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/RefreshableFlowDefinitionHolder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 the original author or authors.
+ * Copyright 2004-2008 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.
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/ViewFactoryCreator.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/ViewFactoryCreator.java
index fef563c6..3c6ce9ca 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/ViewFactoryCreator.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/ViewFactoryCreator.java
@@ -1,14 +1,38 @@
+/*
+ * Copyright 2004-2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package org.springframework.webflow.engine.builder;
import org.springframework.binding.expression.Expression;
import org.springframework.core.io.ResourceLoader;
-import org.springframework.webflow.execution.Action;
+import org.springframework.webflow.execution.View;
import org.springframework.webflow.execution.ViewFactory;
+/**
+ * A factory for ViewFactory objects. This is an SPI interface and conceals specific types of view factories from the
+ * flow builder infrastructure.
+ */
public interface ViewFactoryCreator {
+ /**
+ * Create a view factory capable of creating {@link View} objects that can render the view template with the
+ * provided identifier.
+ * @param viewId an expression that resolves the id of the view template
+ * @param viewResourceLoader an optional resource loader to use to load the view template from an input stream
+ * @return the view factory
+ */
public ViewFactory createViewFactory(Expression viewId, ResourceLoader viewResourceLoader);
- public Action createFinalResponseAction(Expression viewId, ResourceLoader viewResourceLoader);
-
}
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 776495ac..af3ab269 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2007 the original author or authors.
+ * Copyright 2004-2008 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.
@@ -36,8 +36,15 @@ public abstract class AbstractFlowBuilder implements FlowBuilder {
*/
private Flow flow;
+ /**
+ * The flow builder context providing access to services needed to build the flow.
+ */
private FlowBuilderContext context;
+ /**
+ * Returns this flow builder's context.
+ * @return the flow builder context
+ */
protected FlowBuilderContext getContext() {
return context;
}
@@ -48,10 +55,18 @@ public abstract class AbstractFlowBuilder implements FlowBuilder {
this.flow = createFlow();
}
+ /**
+ * Flow builder initialization hook. Does nothing by default. May be overridden by subclasses.
+ */
protected void doInit() {
}
+ /**
+ * Factory method that initially creates the flow implementation during flow builder initialization. Simply
+ * delegates to the configured flow artifact factory by default.
+ * @return the flow instance, initially created but not yet built
+ */
protected Flow createFlow() {
String id = getContext().getFlowId();
AttributeMap attributes = getContext().getFlowAttributes();
@@ -81,15 +96,18 @@ public abstract class AbstractFlowBuilder implements FlowBuilder {
public void buildExceptionHandlers() throws FlowBuilderException {
}
- public Flow getFlow() {
+ public Flow getFlow() throws FlowBuilderException {
return flow;
}
- public void dispose() {
+ public void dispose() throws FlowBuilderException {
flow = null;
doDispose();
}
+ /**
+ * Flow builder destruction hook. Does nothing by default. May be overridden by subclasses.
+ */
protected void doDispose() {
}
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/ActionExecutingViewFactory.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/ActionExecutingViewFactory.java
new file mode 100644
index 00000000..21a1ad47
--- /dev/null
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/ActionExecutingViewFactory.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2004-2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.webflow.engine.builder.support;
+
+import org.springframework.webflow.engine.ActionExecutor;
+import org.springframework.webflow.execution.Action;
+import org.springframework.webflow.execution.Event;
+import org.springframework.webflow.execution.RequestContext;
+import org.springframework.webflow.execution.View;
+import org.springframework.webflow.execution.ViewFactory;
+
+/**
+ * A view factory implementation that creates views that execute an action when rendered. Used mainly to encapsulate an
+ * action that renders a response. Examples include flow redirect and external redirect actions.
+ */
+public class ActionExecutingViewFactory implements ViewFactory {
+
+ /**
+ * The action to execute.
+ */
+ private Action action;
+
+ /**
+ * Create a new action invoking view factory
+ * @param action the action to execute
+ */
+ public ActionExecutingViewFactory(Action action) {
+ this.action = action;
+ }
+
+ public View getView(RequestContext context) {
+ return new ActionExecutingView(action, context);
+ }
+
+ private static class ActionExecutingView implements View {
+
+ private Action action;
+
+ private RequestContext context;
+
+ private ActionExecutingView(Action action, RequestContext context) {
+ this.action = action;
+ this.context = context;
+ }
+
+ public boolean eventSignaled() {
+ return context.getExternalContext().getRequestParameterMap().contains("_eventId");
+ }
+
+ public Event getEvent() {
+ return new Event(this, context.getExternalContext().getRequestParameterMap().get("_eventId"));
+ }
+
+ public void render() {
+ ActionExecutor.execute(action, context);
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/ActionInvokingViewFactory.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/ActionInvokingViewFactory.java
deleted file mode 100644
index d34dad86..00000000
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/ActionInvokingViewFactory.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package org.springframework.webflow.engine.builder.support;
-
-import org.springframework.webflow.execution.Action;
-import org.springframework.webflow.execution.Event;
-import org.springframework.webflow.execution.RequestContext;
-import org.springframework.webflow.execution.View;
-import org.springframework.webflow.execution.ViewFactory;
-
-public class ActionInvokingViewFactory implements ViewFactory {
-
- private Action action;
-
- public ActionInvokingViewFactory(Action action) {
- this.action = action;
- }
-
- public View getView(RequestContext context) {
- return new ActionExecutingView(action, context);
- }
-
- private static class ActionExecutingView implements View {
-
- private Action action;
-
- private RequestContext context;
-
- private ActionExecutingView(Action action, RequestContext context) {
- this.action = action;
- this.context = context;
- }
-
- public boolean eventSignaled() {
- return context.getExternalContext().getRequestParameterMap().contains("_eventId");
- }
-
- public Event getEvent() {
- return new Event(this, context.getExternalContext().getRequestParameterMap().get("_eventId"));
- }
-
- public void render() {
- try {
- action.execute(context);
- } catch (Exception e) {
- // TODO
- }
- }
-
- }
-
-}
\ No newline at end of file
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderContextImpl.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderContextImpl.java
index 05e2d02e..add4358e 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderContextImpl.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderContextImpl.java
@@ -12,6 +12,10 @@ import org.springframework.webflow.engine.builder.FlowArtifactFactory;
import org.springframework.webflow.engine.builder.FlowBuilderContext;
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
+/**
+ * Generic implementation of a flow builder context, suitable for use by most flow assembly systems.
+ * @author Keith Donald
+ */
public class FlowBuilderContextImpl implements FlowBuilderContext {
private String flowId;
@@ -24,6 +28,13 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
private GenericConversionService flowConversionService;
+ /**
+ * Creates a new flow builder context.
+ * @param flowId the id to assign the flow being built
+ * @param flowAttributes attributes to assign the flow being built
+ * @param flowDefinitionLocator a locator to find dependent subflows
+ * @param flowBuilderServices a parameter object providing access to additional services needed by the flow builder
+ */
public FlowBuilderContextImpl(String flowId, AttributeMap flowAttributes,
FlowDefinitionLocator flowDefinitionLocator, FlowBuilderServices flowBuilderServices) {
this.flowId = flowId;
@@ -36,6 +47,12 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
flowConversionService.setParent(this.flowBuilderServices.getConversionService());
}
+ public FlowBuilderServices getFlowBuilderServices() {
+ return flowBuilderServices;
+ }
+
+ // implementing flow builder context
+
public String getFlowId() {
return flowId;
}
@@ -76,7 +93,4 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
return flowDefinitionLocator;
}
- public FlowBuilderServices getFlowBuilderServices() {
- return flowBuilderServices;
- }
}
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderServices.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderServices.java
index 1563a5f5..49499ddd 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderServices.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/FlowBuilderServices.java
@@ -14,9 +14,16 @@ import org.springframework.webflow.core.expression.DefaultExpressionParserFactor
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.State;
import org.springframework.webflow.engine.builder.FlowArtifactFactory;
+import org.springframework.webflow.engine.builder.FlowBuilderContext;
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
import org.springframework.webflow.execution.Action;
+/**
+ * A simple holder for services needed by a flow builder. These services are typically exposed via a Flow Builder's
+ * {@link FlowBuilderContext}.
+ *
+ * @author Keith Donald
+ */
public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAware {
/**
@@ -32,17 +39,19 @@ public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAwar
private BeanInvokingActionFactory beanInvokingActionFactory = new BeanInvokingActionFactory();
/**
- * The view factory creator.
+ * The view factory creator for creating views to render during flow execution. The default is null
+ * and this service must be configured externally.
*/
private ViewFactoryCreator viewFactoryCreator;
/**
- * The conversion service.
+ * The conversion service for converting from one object type to another.
*/
private ConversionService conversionService = new DefaultConversionService();
/**
- * The parser for parsing expression strings into expression objects.
+ * The parser for parsing expression strings into expression objects. The default is Web Flow's default expression
+ * parser implementation.
*/
private ExpressionParser expressionParser = DefaultExpressionParserFactory.getExpressionParser();
@@ -52,7 +61,7 @@ public class FlowBuilderServices implements ResourceLoaderAware, BeanFactoryAwar
private ResourceLoader resourceLoader;
/**
- * The Spring bean factory used.
+ * The Spring bean factory that provides access to the services of the user application.
*/
private BeanFactory beanFactory;
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/LocalFlowBuilderContext.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/LocalFlowBuilderContext.java
index 42e1eaae..22926c22 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/LocalFlowBuilderContext.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/LocalFlowBuilderContext.java
@@ -26,6 +26,11 @@ import org.springframework.webflow.engine.builder.FlowArtifactFactory;
import org.springframework.webflow.engine.builder.FlowBuilderContext;
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
+/**
+ * A builder context that delegates to a flow-local bean factory for builder services. Such builder services override
+ * the services of the external "parent" context.
+ * @author Keith Donald
+ */
class LocalFlowBuilderContext implements FlowBuilderContext {
private FlowBuilderContext parent;
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java
index d7060d2b..94c8682a 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/XmlFlowBuilder.java
@@ -57,6 +57,7 @@ import org.springframework.webflow.action.EvaluateAction;
import org.springframework.webflow.action.ExternalRedirectAction;
import org.springframework.webflow.action.FlowDefinitionRedirectAction;
import org.springframework.webflow.action.SetAction;
+import org.springframework.webflow.action.ViewFactoryActionAdapter;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
@@ -71,7 +72,7 @@ import org.springframework.webflow.engine.TransitionCriteria;
import org.springframework.webflow.engine.builder.FlowArtifactFactory;
import org.springframework.webflow.engine.builder.FlowBuilderException;
import org.springframework.webflow.engine.builder.support.AbstractFlowBuilder;
-import org.springframework.webflow.engine.builder.support.ActionInvokingViewFactory;
+import org.springframework.webflow.engine.builder.support.ActionExecutingViewFactory;
import org.springframework.webflow.engine.support.BeanFactoryFlowVariable;
import org.springframework.webflow.engine.support.BooleanExpressionTransitionCriteria;
import org.springframework.webflow.engine.support.SimpleFlowVariable;
@@ -96,13 +97,13 @@ import org.xml.sax.SAXException;
* <flow xmlns="http://www.springframework.org/schema/webflow"
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
* xsi:schemaLocation="http://www.springframework.org/schema/webflow
- * http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd">
+ * http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
* <!-- Define your states here -->
* </flow>
*
*
*
- * Consult the web flow XML schema + * Consult the web flow XML schema * for more information on the XML-based flow definition format. *
* This builder will setup a flow-local bean factory for the flow being constructed. That flow-local bean factory will
@@ -125,8 +126,6 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
private static final String FLOW_ELEMENT = "flow";
- private static final String START_STATE_ELEMENT = "start-state";
-
private static final String ACTION_STATE_ELEMENT = "action-state";
private static final String ACTION_ELEMENT = "action";
@@ -323,7 +322,8 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
protected Flow createFlow() {
Flow flow = parseFlow(getDocumentElement());
- flow.setLocalBeanFactory(getLocalContext().getBeanFactory());
+ flow.setBeanFactory(getLocalContext().getBeanFactory());
+ flow.setResourceLoader(getLocalContext().getResourceLoader());
return flow;
}
@@ -542,12 +542,27 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
private void parseAndSetStartState(Element element, Flow flow) {
String startStateId = getStartStateId(element);
- flow.setStartState(startStateId);
+ if (StringUtils.hasText(startStateId)) {
+ flow.setStartState(startStateId);
+ }
}
private String getStartStateId(Element element) {
- Element startStateElement = DomUtils.getChildElementByTagName(element, START_STATE_ELEMENT);
- return startStateElement.getAttribute(IDREF_ATTRIBUTE);
+ String startState = "start-state";
+ if (element.hasAttribute(startState)) {
+ Element startStateElement = DomUtils.getChildElementByTagName(element, startState);
+ Assert
+ .isNull(startStateElement,
+ "Define either a flow 'start-state' attribute or use the classic 'start-state' element. Do not use both.");
+ return element.getAttribute(startState);
+ } else {
+ Element startStateElement = DomUtils.getChildElementByTagName(element, startState);
+ if (startStateElement != null) {
+ return startStateElement.getAttribute(IDREF_ATTRIBUTE);
+ } else {
+ return null;
+ }
+ }
}
private void parseAndAddActionState(Element element, Flow flow) {
@@ -614,11 +629,11 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
String encodedUrl = encodedView.substring(EXTERNAL_REDIRECT_PREFIX.length());
Expression externalUrl = getExpressionParser().parseExpression(encodedUrl,
new ParserContextImpl().eval(RequestContext.class).expect(String.class));
- ViewFactory viewFactory = new ActionInvokingViewFactory(new ExternalRedirectAction(externalUrl));
+ ViewFactory viewFactory = new ActionExecutingViewFactory(new ExternalRedirectAction(externalUrl));
return new ViewInfo(viewFactory, Boolean.FALSE);
} else if (encodedView.startsWith(FLOW_DEFINITION_REDIRECT_PREFIX)) {
String flowRedirect = encodedView.substring(FLOW_DEFINITION_REDIRECT_PREFIX.length());
- ViewFactory viewFactory = new ActionInvokingViewFactory(FlowDefinitionRedirectAction.create(flowRedirect));
+ ViewFactory viewFactory = new ActionExecutingViewFactory(FlowDefinitionRedirectAction.create(flowRedirect));
return new ViewInfo(viewFactory, Boolean.FALSE);
} else if (encodedView.startsWith(BEAN_PREFIX)) {
ViewFactory viewFactory = (ViewFactory) getLocalContext().getBeanFactory().getBean(
@@ -652,8 +667,8 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
} else {
Expression viewName = getExpressionParser().parseExpression(encodedView,
new ParserContextImpl().eval(RequestContext.class).expect(String.class));
- return getLocalContext().getViewFactoryCreator().createFinalResponseAction(viewName,
- getLocalContext().getResourceLoader());
+ return new ViewFactoryActionAdapter(getLocalContext().getViewFactoryCreator().createViewFactory(viewName,
+ getLocalContext().getResourceLoader()));
}
}
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/spring-webflow-2.0.xsd b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/spring-webflow-2.0.xsd
index 8ea7c86d..4129d309 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/spring-webflow-2.0.xsd
+++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/xml/spring-webflow-2.0.xsd
@@ -280,11 +280,16 @@ Defines flow startup logic to execute. This logic will always execute when this
-