variable autowiring
This commit is contained in:
@@ -52,8 +52,8 @@ public class SpringBeanWebFlowELResolver extends SpringBeanFacesELResolver {
|
||||
|
||||
protected BeanFactory getBeanFactory(ELContext elContext) {
|
||||
RequestContext rc = RequestContextHolder.getRequestContext();
|
||||
if (rc.getActiveFlow() instanceof BeanFactory) {
|
||||
return (BeanFactory) rc.getActiveFlow();
|
||||
if (rc.getActiveFlow().getBeanFactory() != null) {
|
||||
return rc.getActiveFlow().getBeanFactory();
|
||||
} else {
|
||||
return EMPTY_BEAN_FACTORY;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package org.springframework.webflow.definition;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
/**
|
||||
* The definition of a flow, a program that when executed carries out the orchestration of a task on behalf of a single
|
||||
* client.
|
||||
@@ -60,4 +63,15 @@ public interface FlowDefinition extends Annotated {
|
||||
* @throws IllegalArgumentException if a state with this id does not exist
|
||||
*/
|
||||
public StateDefinition getState(String id) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a reference to a bean factory hosting application objects needed by this flow definition.
|
||||
*/
|
||||
public BeanFactory getBeanFactory();
|
||||
|
||||
/**
|
||||
* Returns a reference to a resource loader capable of loading resources relative to this flow.
|
||||
*/
|
||||
public ResourceLoader getResourceLoader();
|
||||
|
||||
}
|
||||
@@ -21,14 +21,10 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
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;
|
||||
@@ -108,7 +104,7 @@ import org.springframework.webflow.execution.RequestContext;
|
||||
* @author Colin Sampaleanu
|
||||
* @author Jeremy Grelle
|
||||
*/
|
||||
public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory, ResourceLoader {
|
||||
public class Flow extends AnnotatedObject implements FlowDefinition {
|
||||
|
||||
/**
|
||||
* Logger, can be used in subclasses.
|
||||
@@ -138,7 +134,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory
|
||||
/**
|
||||
* The mapper to map flow input attributes.
|
||||
*/
|
||||
private AttributeMapper inputMapper = new NoInputMapper();
|
||||
private AttributeMapper inputMapper;
|
||||
|
||||
/**
|
||||
* The list of actions to execute when this flow starts.
|
||||
@@ -161,7 +157,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory
|
||||
/**
|
||||
* The mapper to map flow output attributes.
|
||||
*/
|
||||
private AttributeMapper outputMapper = new NoOutputMapper();
|
||||
private AttributeMapper outputMapper;
|
||||
|
||||
/**
|
||||
* The set of exception handlers for this flow.
|
||||
@@ -219,6 +215,14 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory
|
||||
return getStateInstance(stateId);
|
||||
}
|
||||
|
||||
public BeanFactory getBeanFactory() {
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
public ResourceLoader getResourceLoader() {
|
||||
return resourceLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given state definition to this flow definition. Marked protected, as this method is to be called by the
|
||||
* (privileged) state definition classes themselves during state construction as part of a FlowBuilder invocation.
|
||||
@@ -382,7 +386,6 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory
|
||||
* @param inputMapper the input mapper
|
||||
*/
|
||||
public void setInputMapper(AttributeMapper inputMapper) {
|
||||
Assert.notNull(inputMapper, "The input mapper cannot be null");
|
||||
this.inputMapper = inputMapper;
|
||||
}
|
||||
|
||||
@@ -417,7 +420,6 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory
|
||||
* @param outputMapper the output mapper
|
||||
*/
|
||||
public void setOutputMapper(AttributeMapper outputMapper) {
|
||||
Assert.notNull(outputMapper, "The output mapper cannot be null");
|
||||
this.outputMapper = outputMapper;
|
||||
}
|
||||
|
||||
@@ -498,7 +500,9 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory
|
||||
public void start(RequestControlContext context, MutableAttributeMap input) throws FlowExecutionException {
|
||||
assertStartStateSet();
|
||||
createVariables(context);
|
||||
inputMapper.map(input, context, null);
|
||||
if (inputMapper != null) {
|
||||
inputMapper.map(input, context, null);
|
||||
}
|
||||
startActionList.execute(context);
|
||||
startState.enter(context);
|
||||
}
|
||||
@@ -547,7 +551,9 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory
|
||||
*/
|
||||
public void end(RequestControlContext context, MutableAttributeMap output) throws FlowExecutionException {
|
||||
endActionList.execute(context);
|
||||
outputMapper.map(context, output, null);
|
||||
if (outputMapper != null) {
|
||||
outputMapper.map(context, output, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -560,52 +566,6 @@ 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() {
|
||||
@@ -653,31 +613,6 @@ public class Flow extends AnnotatedObject implements FlowDefinition, BeanFactory
|
||||
return (TransitionableState) currentState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps no input attributes. The default implementation.
|
||||
*/
|
||||
private class NoInputMapper implements AttributeMapper {
|
||||
public void map(Object source, Object target, MappingContext context) {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "none";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps no input attributes. The default implementation.
|
||||
*/
|
||||
private class NoOutputMapper implements AttributeMapper {
|
||||
public void map(Object source, Object target, MappingContext context) {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "none";
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("id", id).append("states", states).append("startState", startState)
|
||||
.append("variables", variables).append("inputMapper", inputMapper).append("startActionList",
|
||||
|
||||
@@ -15,12 +15,10 @@
|
||||
*/
|
||||
package org.springframework.webflow.engine;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.execution.FlowSession;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.ScopeType;
|
||||
|
||||
/**
|
||||
* A value object that defines a specification for a flow variable. Encapsulates information about the variable and the
|
||||
@@ -28,7 +26,7 @@ import org.springframework.webflow.execution.ScopeType;
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public abstract class FlowVariable extends AnnotatedObject implements Serializable {
|
||||
public class FlowVariable extends AnnotatedObject {
|
||||
|
||||
/**
|
||||
* The variable name.
|
||||
@@ -36,20 +34,27 @@ public abstract class FlowVariable extends AnnotatedObject implements Serializab
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The variable scope.
|
||||
* Is this flow variable local or global? Local variables go into flow scope. Global variables go into conversation
|
||||
* scope.
|
||||
*/
|
||||
private ScopeType scope;
|
||||
private Boolean local;
|
||||
|
||||
/**
|
||||
* The value factory that provides this variable's value.
|
||||
*/
|
||||
private VariableValueFactory valueFactory;
|
||||
|
||||
/**
|
||||
* Creates a new flow variable.
|
||||
* @param name the variable name
|
||||
* @param scope the variable scope type
|
||||
* @param local the local variable
|
||||
*/
|
||||
public FlowVariable(String name, ScopeType scope) {
|
||||
public FlowVariable(String name, VariableValueFactory valueFactory, boolean local) {
|
||||
Assert.hasText(name, "The variable name is required");
|
||||
Assert.notNull(scope, "The variable scope type is required");
|
||||
Assert.notNull(valueFactory, "The variable value factory is required");
|
||||
this.name = name;
|
||||
this.scope = scope;
|
||||
this.valueFactory = valueFactory;
|
||||
this.local = Boolean.valueOf(local);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,10 +65,10 @@ public abstract class FlowVariable extends AnnotatedObject implements Serializab
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scope of this variable.
|
||||
* Is this a local flow variable or a conversation-scoped flow variable?
|
||||
*/
|
||||
public ScopeType getScope() {
|
||||
return scope;
|
||||
public boolean isLocal() {
|
||||
return local.booleanValue();
|
||||
}
|
||||
|
||||
// name and scope based equality
|
||||
@@ -73,11 +78,11 @@ public abstract class FlowVariable extends AnnotatedObject implements Serializab
|
||||
return false;
|
||||
}
|
||||
FlowVariable other = (FlowVariable) o;
|
||||
return name.equals(other.name) && scope.equals(other.scope);
|
||||
return name.equals(other.name) && valueFactory.equals(other.valueFactory) && local.equals(other.local);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return name.hashCode() + scope.hashCode();
|
||||
return name.hashCode() + valueFactory.hashCode() + local.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,18 +90,26 @@ public abstract class FlowVariable extends AnnotatedObject implements Serializab
|
||||
* @param context the flow execution request context
|
||||
*/
|
||||
public final void create(RequestContext context) {
|
||||
scope.getScope(context).put(name, createVariableValue(context));
|
||||
Object value = valueFactory.createVariableValue(context);
|
||||
if (local == Boolean.TRUE) {
|
||||
context.getFlowScope().put(name, value);
|
||||
} else {
|
||||
context.getConversationScope().put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook method that needs to be implemented by subclasses to calculate the value of this flow variable based on the
|
||||
* information available in the request context.
|
||||
* @param context the flow execution request context
|
||||
* @return the flow variable value
|
||||
*/
|
||||
protected abstract Object createVariableValue(RequestContext context);
|
||||
public final Object restore(FlowSession session, RequestContext context) {
|
||||
Object value;
|
||||
if (local == Boolean.TRUE) {
|
||||
value = session.getScope().get(name);
|
||||
} else {
|
||||
value = context.getConversationScope().get(name);
|
||||
}
|
||||
return valueFactory.restoreReferences(value, context);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("name", name).append("scope", scope).toString();
|
||||
return new ToStringCreator(this).append("name", name).append("valueFactory", valueFactory).append("local",
|
||||
local).toString();
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ package org.springframework.webflow.engine.builder.xml;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.webflow.action.BeanInvokingActionFactory;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
@@ -35,9 +36,9 @@ class LocalFlowBuilderContext implements FlowBuilderContext {
|
||||
|
||||
private FlowBuilderContext parent;
|
||||
|
||||
private BeanFactory localFlowBeanFactory;
|
||||
private GenericApplicationContext localFlowBeanFactory;
|
||||
|
||||
public LocalFlowBuilderContext(FlowBuilderContext parent, BeanFactory localFlowBeanFactory) {
|
||||
public LocalFlowBuilderContext(FlowBuilderContext parent, GenericApplicationContext localFlowBeanFactory) {
|
||||
this.parent = parent;
|
||||
this.localFlowBeanFactory = localFlowBeanFactory;
|
||||
}
|
||||
@@ -100,10 +101,10 @@ class LocalFlowBuilderContext implements FlowBuilderContext {
|
||||
}
|
||||
|
||||
public ResourceLoader getResourceLoader() {
|
||||
return (ResourceLoader) getBeanFactory();
|
||||
return localFlowBeanFactory;
|
||||
}
|
||||
|
||||
public BeanFactory getBeanFactory() {
|
||||
return localFlowBeanFactory;
|
||||
return localFlowBeanFactory.getBeanFactory();
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import java.util.List;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
@@ -68,13 +69,13 @@ import org.springframework.webflow.engine.FlowVariable;
|
||||
import org.springframework.webflow.engine.TargetStateResolver;
|
||||
import org.springframework.webflow.engine.Transition;
|
||||
import org.springframework.webflow.engine.TransitionCriteria;
|
||||
import org.springframework.webflow.engine.VariableValueFactory;
|
||||
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.ActionExecutingViewFactory;
|
||||
import org.springframework.webflow.engine.support.BeanFactoryFlowVariable;
|
||||
import org.springframework.webflow.engine.support.BeanFactoryVariableValueFactory;
|
||||
import org.springframework.webflow.engine.support.BooleanExpressionTransitionCriteria;
|
||||
import org.springframework.webflow.engine.support.SimpleFlowVariable;
|
||||
import org.springframework.webflow.engine.support.TransitionCriteriaChain;
|
||||
import org.springframework.webflow.engine.support.TransitionExecutingFlowExecutionExceptionHandler;
|
||||
import org.springframework.webflow.execution.Action;
|
||||
@@ -437,7 +438,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
this.localFlowBuilderContext = new LocalFlowBuilderContext(getContext(), createFlowBeanFactory(resources));
|
||||
}
|
||||
|
||||
private BeanFactory createFlowBeanFactory(Resource[] resources) {
|
||||
private GenericApplicationContext createFlowBeanFactory(Resource[] resources) {
|
||||
// see if this factory has a parent
|
||||
BeanFactory parent = getContext().getBeanFactory();
|
||||
// determine the context implementation based on the current environment
|
||||
@@ -478,24 +479,20 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
private void parseAndAddFlowVariables(Element flowElement, Flow flow) {
|
||||
List varElements = DomUtils.getChildElementsByTagName(flowElement, VAR_ELEMENT);
|
||||
for (Iterator it = varElements.iterator(); it.hasNext();) {
|
||||
flow.addVariable(parseVariable((Element) it.next()));
|
||||
flow.addVariable(parseFlowVariable((Element) it.next()));
|
||||
}
|
||||
}
|
||||
|
||||
private FlowVariable parseVariable(Element element) {
|
||||
private FlowVariable parseFlowVariable(Element element) {
|
||||
Class clazz = (Class) fromStringTo(Class.class).execute(element.getAttribute(CLASS_ATTRIBUTE));
|
||||
VariableValueFactory valueFactory = new BeanFactoryVariableValueFactory(clazz,
|
||||
(AutowireCapableBeanFactory) getFlow().getBeanFactory());
|
||||
ScopeType scope = parseScope(element, ScopeType.FLOW);
|
||||
if (StringUtils.hasText(element.getAttribute(BEAN_ATTRIBUTE))) {
|
||||
return new BeanFactoryFlowVariable(element.getAttribute(NAME_ATTRIBUTE), element
|
||||
.getAttribute(BEAN_ATTRIBUTE), getLocalContext().getBeanFactory(), scope);
|
||||
} else {
|
||||
if (StringUtils.hasText(element.getAttribute(CLASS_ATTRIBUTE))) {
|
||||
Class variableClass = (Class) fromStringTo(Class.class).execute(element.getAttribute(CLASS_ATTRIBUTE));
|
||||
return new SimpleFlowVariable(element.getAttribute(NAME_ATTRIBUTE), variableClass, scope);
|
||||
} else {
|
||||
return new BeanFactoryFlowVariable(element.getAttribute(NAME_ATTRIBUTE), null, getLocalContext()
|
||||
.getBeanFactory(), scope);
|
||||
}
|
||||
if (!(scope == ScopeType.FLOW || scope == ScopeType.CONVERSATION)) {
|
||||
throw new IllegalArgumentException("Only " + ScopeType.FLOW + " or " + ScopeType.CONVERSATION
|
||||
+ " scope is allowed for flow variables");
|
||||
}
|
||||
return new FlowVariable(element.getAttribute("name"), valueFactory, scope == ScopeType.FLOW ? true : false);
|
||||
}
|
||||
|
||||
private void parseAndAddStartActions(Element element, Flow flow) {
|
||||
|
||||
@@ -259,7 +259,8 @@ The persistence context can be referenced from within this flow by the "entityMa
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
A flow variable definition. Flow variables are automatically created when an execution of this flow starts.
|
||||
A flow variable definition. Flow variables are automatically created when an execution of this flow starts.
|
||||
A flow variable can either be stored in 'flow' or 'conversation' scope.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
@@ -623,47 +624,33 @@ of a non-singleton bean in the configured Bean Factory to use as the initial var
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="scope" type="scopeType" default="default">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
This scope of this variable. The available scope types are:
|
||||
<ol>
|
||||
<li>request - The variable goes out of scope when a call to start this flow completes.
|
||||
<li>flash - The variable goes out of scope when the next user event is signaled.
|
||||
<li>flow - The variable goes out of scope when this flow session ends.
|
||||
<li>conversation - The variable goes out of scope when the overall conversation governing this flow ends.
|
||||
</ol>
|
||||
<br>
|
||||
If not specified the default scope type is used ('flow' by default).
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="class" type="xsd:string">
|
||||
<xsd:attribute name="class" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The implementation class of the variable's value. The class may be an alias (e.g 'int') or a
|
||||
fully-qualified class (e.g. 'java.lang.Integer'). The class cannot be abstract or an interface.
|
||||
Only required if the variable should be instantiated directly by calling the default constructor
|
||||
on its class rather than having the initial variable value returned by a Spring Bean Factory.
|
||||
|
||||
Use this or the 'bean' attribute, not both.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="bean" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
The bean defining the initial flow variable value. The bean *must* be a non-singleton prototype.
|
||||
Only required if the bean name differs from the variable name.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="scope" type="scopeType" default="default">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
This scope of this variable. The available scope types are:
|
||||
<ol>
|
||||
<li>request - The variable goes out of scope when a call to start this flow completes.
|
||||
<li>flash - The variable goes out of scope when the next user event is signaled.
|
||||
<li>flow - The variable goes out of scope when this flow session ends.
|
||||
<li>conversation - The variable goes out of scope when the overall conversation governing this flow ends.
|
||||
</ol>
|
||||
<br>
|
||||
If not specified the default scope type is used ('flow' by default).
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.support;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.webflow.engine.FlowVariable;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.ScopeType;
|
||||
|
||||
/**
|
||||
* A concrete flow variable subclass that obtains variable values from a Spring {@link BeanFactory}.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Erwin Vervaet
|
||||
*/
|
||||
public class BeanFactoryFlowVariable extends FlowVariable {
|
||||
|
||||
/**
|
||||
* The name of the bean whose value will be used as the flow variable. The bean should be a prototype.
|
||||
*/
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* The bean factory where initial variable values will be obtained.
|
||||
*/
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
/**
|
||||
* Convenience constructor to create a new bean factory flow variable. Defaults the bean name to the variable name.
|
||||
* @param name the variable name which will also be used as the bean name
|
||||
* @param beanFactory the bean factory where initial variable values will be obtained
|
||||
* @param scope the variable scope
|
||||
* @since 1.0.2
|
||||
*/
|
||||
public BeanFactoryFlowVariable(String name, BeanFactory beanFactory, ScopeType scope) {
|
||||
this(name, name, beanFactory, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new bean factory flow variable.
|
||||
* @param variableName the variable name
|
||||
* @param beanName the bean name, will default to the variable name if not specified
|
||||
* @param beanFactory the bean factory where initial variable values will be obtained
|
||||
* @param scope the variable scope
|
||||
*/
|
||||
public BeanFactoryFlowVariable(String variableName, String beanName, BeanFactory beanFactory, ScopeType scope) {
|
||||
super(variableName, scope);
|
||||
if (StringUtils.hasText(beanName)) {
|
||||
this.beanName = beanName;
|
||||
} else {
|
||||
this.beanName = variableName;
|
||||
}
|
||||
Assert.notNull(beanFactory, "The bean factory is required");
|
||||
Assert.isTrue(!beanFactory.isSingleton(this.beanName), "The bean with name '" + this.beanName
|
||||
+ "' must be a prototype (singleton=false)");
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
protected Object createVariableValue(RequestContext context) {
|
||||
return beanFactory.getBean(beanName);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.support;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.engine.FlowVariable;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.ScopeType;
|
||||
|
||||
/**
|
||||
* A trivial concrete flow variable subclass that creates new variable values using Java reflection.
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class SimpleFlowVariable extends FlowVariable {
|
||||
|
||||
/**
|
||||
* The concrete variable value class.
|
||||
*/
|
||||
private Class variableClass;
|
||||
|
||||
/**
|
||||
* Creates a new simple flow variable.
|
||||
* @param name the variable name
|
||||
* @param variableClass the concrete variable class
|
||||
* @param scope the variable scope
|
||||
*/
|
||||
public SimpleFlowVariable(String name, Class variableClass, ScopeType scope) {
|
||||
super(name, scope);
|
||||
Assert.notNull(variableClass, "The variable class is required");
|
||||
Assert.isTrue(!variableClass.isInterface(), "The variable class cannot be an interface");
|
||||
Assert.isTrue(!Modifier.isAbstract(variableClass.getModifiers()), "The variable class cannot be abstract");
|
||||
this.variableClass = variableClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the variable value class.
|
||||
*/
|
||||
public Class getVariableClass() {
|
||||
return variableClass;
|
||||
}
|
||||
|
||||
protected Object createVariableValue(RequestContext context) {
|
||||
return BeanUtils.instantiateClass(variableClass);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,8 @@ package org.springframework.webflow.definition.registry;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.StateDefinition;
|
||||
@@ -101,6 +103,16 @@ public class FlowDefinitionRegistryImplTests extends TestCase {
|
||||
public StateDefinition getState(String id) throws IllegalArgumentException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public BeanFactory getBeanFactory() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public ResourceLoader getResourceLoader() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
}
|
||||
|
||||
private static class BarFlow implements FlowDefinition {
|
||||
@@ -129,5 +141,15 @@ public class FlowDefinitionRegistryImplTests extends TestCase {
|
||||
public StateDefinition getState(String id) throws IllegalArgumentException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public BeanFactory getBeanFactory() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public ResourceLoader getResourceLoader() {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,19 +21,16 @@ import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.mapping.DefaultAttributeMapper;
|
||||
import org.springframework.binding.mapping.MappingBuilder;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.webflow.TestException;
|
||||
import org.springframework.webflow.action.TestMultiAction;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.core.expression.DefaultExpressionParserFactory;
|
||||
import org.springframework.webflow.engine.support.BeanFactoryFlowVariable;
|
||||
import org.springframework.webflow.engine.support.DefaultTargetStateResolver;
|
||||
import org.springframework.webflow.engine.support.EventIdTransitionCriteria;
|
||||
import org.springframework.webflow.engine.support.SimpleFlowVariable;
|
||||
import org.springframework.webflow.engine.support.TransitionExecutingFlowExecutionExceptionHandler;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.ScopeType;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.execution.TestAction;
|
||||
import org.springframework.webflow.test.MockRequestControlContext;
|
||||
|
||||
@@ -184,13 +181,17 @@ public class FlowTests extends TestCase {
|
||||
|
||||
public void testStartWithVariables() {
|
||||
MockRequestControlContext context = new MockRequestControlContext(flow);
|
||||
flow.addVariable(new SimpleFlowVariable("var1", ArrayList.class, ScopeType.FLOW));
|
||||
StaticApplicationContext beanFactory = new StaticApplicationContext();
|
||||
beanFactory.registerPrototype("bean", ArrayList.class);
|
||||
flow.addVariable(new BeanFactoryFlowVariable("var2", "bean", beanFactory, ScopeType.FLOW));
|
||||
flow.addVariable(new FlowVariable("var1", new VariableValueFactory() {
|
||||
public Object createVariableValue(RequestContext context) {
|
||||
return new ArrayList();
|
||||
}
|
||||
|
||||
public Object restoreReferences(Object value, RequestContext context) {
|
||||
return value;
|
||||
}
|
||||
}, true));
|
||||
flow.start(context, new LocalAttributeMap());
|
||||
context.getFlowScope().getRequired("var1", ArrayList.class);
|
||||
context.getFlowScope().getRequired("var2", ArrayList.class);
|
||||
}
|
||||
|
||||
public void testStartWithMapper() {
|
||||
|
||||
@@ -73,4 +73,15 @@ public class XmlFlowBuilderTests extends TestCase {
|
||||
assertNotNull(flow.getAttributes().get("persistenceContext"));
|
||||
assertTrue(((Boolean) flow.getAttributes().get("persistenceContext")).booleanValue());
|
||||
}
|
||||
|
||||
public void testFlowVariable() {
|
||||
ClassPathResource resource = new ClassPathResource("flow-var.xml", getClass());
|
||||
builder = new XmlFlowBuilder(resource);
|
||||
FlowAssembler assembler = new FlowAssembler(builder, new MockFlowBuilderContext("flow"));
|
||||
Flow flow = assembler.assembleFlow();
|
||||
assertEquals("flow-foo", flow.getVariables()[0].getName());
|
||||
assertEquals(true, flow.getVariables()[0].isLocal());
|
||||
assertEquals("conversation-foo", flow.getVariables()[1].getName());
|
||||
assertEquals(false, flow.getVariables()[1].isLocal());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.support;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.webflow.execution.ScopeType;
|
||||
import org.springframework.webflow.test.MockRequestContext;
|
||||
|
||||
public class BeanFactoryFlowVariableTests extends TestCase {
|
||||
private MockRequestContext context = new MockRequestContext();
|
||||
|
||||
public void testCreateValidFlowVariable() {
|
||||
StaticApplicationContext beanFactory = new StaticApplicationContext();
|
||||
beanFactory.registerPrototype("bean", Object.class);
|
||||
BeanFactoryFlowVariable variable = new BeanFactoryFlowVariable("var", "bean", beanFactory, ScopeType.FLOW);
|
||||
variable.create(context);
|
||||
context.getFlowScope().getRequired("var");
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.engine.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.webflow.execution.ScopeType;
|
||||
import org.springframework.webflow.test.MockRequestContext;
|
||||
|
||||
public class SimpleFlowVariableTests extends TestCase {
|
||||
private MockRequestContext context = new MockRequestContext();
|
||||
|
||||
public void testCreateValidFlowVariableCustomScope() {
|
||||
SimpleFlowVariable variable = new SimpleFlowVariable("var", ArrayList.class, ScopeType.REQUEST);
|
||||
variable.create(context);
|
||||
assertTrue(context.getRequestScope().contains("var"));
|
||||
context.getRequestScope().getRequired("var", ArrayList.class);
|
||||
}
|
||||
|
||||
public void testCreateVariableNoDefaultConstructor() {
|
||||
SimpleFlowVariable variable = new SimpleFlowVariable("var", Integer.class, ScopeType.FLOW);
|
||||
try {
|
||||
variable.create(context);
|
||||
fail("should have failed");
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user