removed some overloaded bean: prefix support for view=, on=, and to=
This commit is contained in:
Keith Donald
2008-03-07 16:38:38 +00:00
parent 6e4c4236f6
commit 03007f9fc6
20 changed files with 135 additions and 181 deletions

View File

@@ -35,8 +35,7 @@ public class EvaluationException extends NestedRuntimeException {
* @param cause the underlying cause of this exception
*/
public EvaluationException(EvaluationAttempt evaluationAttempt, Throwable cause) {
super("Expression " + evaluationAttempt
+ " failed - make sure the expression is evaluatable in the context provided", cause);
super(evaluationAttempt + " failed - make sure the expression is evaluatable in the context provided", cause);
this.evaluationAttempt = evaluationAttempt;
}

View File

@@ -7,6 +7,7 @@ import javax.el.ValueExpression;
import org.springframework.binding.expression.EvaluationAttempt;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.SetValueAttempt;
import org.springframework.util.Assert;
/**
@@ -50,7 +51,7 @@ public class ELExpression implements Expression {
try {
valueExpression.setValue(ctx, value);
if (!ctx.isPropertyResolved()) {
throw new EvaluationException(new EvaluationAttempt(this, context), null);
throw new EvaluationException(new SetValueAttempt(this, context, value), null);
}
} catch (ELException ex) {
throw new EvaluationException(new EvaluationAttempt(this, context), ex);

View File

@@ -2,6 +2,8 @@
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry combineaccessrules="false" kind="src" path="/spring-binding"/>
<classpathentry combineaccessrules="false" kind="src" path="/spring-webflow"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/global/commons-logging.jar"/>
<classpathentry kind="lib" path="lib/global/ognl.jar"/>
@@ -25,7 +27,5 @@
<classpathentry kind="lib" path="lib/test/shale-test.jar"/>
<classpathentry kind="lib" path="lib/buildtime/servlet-api.jar"/>
<classpathentry kind="lib" path="lib/test/spring-test.jar"/>
<classpathentry kind="lib" path="lib/global/spring-webflow.jar"/>
<classpathentry kind="lib" path="lib/global/spring-binding.jar"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -50,14 +50,14 @@ public class JsfViewFactory implements ViewFactory {
private static final Log logger = LogFactory.getLog(JsfViewFactory.class);
private final Expression viewExpr;
private final Expression viewIdExpression;
private final ResourceLoader resourceLoader;
private final Lifecycle lifecycle;
public JsfViewFactory(Expression viewExpr, ResourceLoader resourceLoader, Lifecycle lifecycle) {
this.viewExpr = viewExpr;
public JsfViewFactory(Expression viewIdExpression, ResourceLoader resourceLoader, Lifecycle lifecycle) {
this.viewIdExpression = viewIdExpression;
this.resourceLoader = resourceLoader;
this.lifecycle = lifecycle;
}
@@ -135,7 +135,7 @@ public class JsfViewFactory implements ViewFactory {
}
private String resolveViewName(RequestContext context) {
String viewId = (String) viewExpr.getValue(context);
String viewId = (String) viewIdExpression.getValue(context);
if (viewId.startsWith("/")) {
return viewId;
} else {

View File

@@ -22,7 +22,6 @@ import javax.faces.lifecycle.LifecycleFactory;
import org.springframework.binding.expression.Expression;
import org.springframework.core.io.ResourceLoader;
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
import org.springframework.webflow.execution.Action;
import org.springframework.webflow.execution.ViewFactory;
/**
@@ -36,12 +35,12 @@ public class JsfViewFactoryCreator implements ViewFactoryCreator {
private Lifecycle lifecycle;
public Action createFinalResponseAction(Expression viewName, ResourceLoader resourceLoader) {
return new JsfFinalResponseAction(new JsfViewFactory(viewName, resourceLoader, getLifecycle()));
public ViewFactory createViewFactory(Expression viewIdExpression, ResourceLoader resourceLoader) {
return new JsfViewFactory(viewIdExpression, resourceLoader, getLifecycle());
}
public ViewFactory createViewFactory(Expression viewName, ResourceLoader resourceLoader) {
return new JsfViewFactory(viewName, resourceLoader, getLifecycle());
public String getViewIdByConvention(String viewStateId) {
return viewStateId + FACELETS_EXTENSION;
}
private Lifecycle createFlowFacesLifecycle() {
@@ -58,8 +57,4 @@ public class JsfViewFactoryCreator implements ViewFactoryCreator {
return lifecycle;
}
public String createViewIdByConvention(String viewStateId) {
return viewStateId + FACELETS_EXTENSION;
}
}

View File

@@ -2,6 +2,7 @@
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry combineaccessrules="false" kind="src" path="/spring-binding"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="lib/test/aopalliance.jar"/>
<classpathentry kind="lib" path="lib/buildtime/antlr.jar"/>
@@ -36,7 +37,6 @@
<classpathentry kind="lib" path="lib/buildtime/servlet-api.jar"/>
<classpathentry kind="lib" path="lib/test/spring-aop.jar"/>
<classpathentry kind="lib" path="lib/global/spring-beans.jar"/>
<classpathentry kind="lib" path="lib/global/spring-binding.jar"/>
<classpathentry kind="lib" path="lib/global/spring-context.jar"/>
<classpathentry kind="lib" path="lib/global/spring-core.jar"/>
<classpathentry kind="lib" path="lib/test/spring-jdbc.jar"/>

View File

@@ -29,16 +29,16 @@ 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 viewIdExpression 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 ViewFactory createViewFactory(Expression viewIdExpression, ResourceLoader viewResourceLoader);
/**
* Create the default id of the view to render in the provided view state by convention.
* Get the default id of the view to render in the provided view state by convention.
* @param viewStateId the view state id
* @return the default view id
*/
public String createViewIdByConvention(String viewStateId);
public String getViewIdByConvention(String viewStateId);
}

View File

@@ -20,6 +20,7 @@ import org.springframework.binding.convert.support.AbstractConverter;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.binding.expression.support.ParserContextImpl;
import org.springframework.util.StringUtils;
import org.springframework.webflow.engine.TargetStateResolver;
import org.springframework.webflow.engine.builder.FlowBuilderContext;
import org.springframework.webflow.engine.support.DefaultTargetStateResolver;
@@ -33,9 +34,8 @@ import org.springframework.webflow.execution.RequestContext;
* <ul>
* <li>"stateId" - will result in a TargetStateResolver that always resolves the same state. </li>
* <li>"${stateIdExpression} - will result in a TargetStateResolver that resolves the target state by evaluating an
* expression against the request context.</li>
* <li>"bean:&lt;id&gt;" - will result in usage of a custom TargetStateResolver bean implementation configured in an
* external context.</li>
* expression against the request context. The resolved value can be a target state identifier or a custom
* TargetStateResolver to delegate to.</li>
* </ul>
*
* @author Keith Donald
@@ -43,11 +43,6 @@ import org.springframework.webflow.execution.RequestContext;
*/
class TextToTargetStateResolver extends AbstractConverter {
/**
* Prefix used when the user wants to use a custom TargetStateResolver implementation managed by a factory.
*/
private static final String BEAN_PREFIX = "bean:";
/**
* Context for flow builder services.
*/
@@ -71,16 +66,13 @@ class TextToTargetStateResolver extends AbstractConverter {
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
String targetStateId = (String) source;
if (targetStateId == null) {
if (!StringUtils.hasText(targetStateId)) {
return null;
}
ExpressionParser parser = flowBuilderContext.getExpressionParser();
if (targetStateId.startsWith(BEAN_PREFIX)) {
return flowBuilderContext.getBeanFactory().getBean(targetStateId.substring(BEAN_PREFIX.length()));
} else {
Expression expression = parser.parseExpression(targetStateId, new ParserContextImpl().template().eval(
RequestContext.class).expect(String.class));
return new DefaultTargetStateResolver(expression);
}
Expression expression = parser.parseExpression(targetStateId, new ParserContextImpl().template().eval(
RequestContext.class).expect(String.class));
return new DefaultTargetStateResolver(expression);
}
}

View File

@@ -26,7 +26,7 @@ import org.springframework.util.StringUtils;
import org.springframework.webflow.engine.TransitionCriteria;
import org.springframework.webflow.engine.WildcardTransitionCriteria;
import org.springframework.webflow.engine.builder.FlowBuilderContext;
import org.springframework.webflow.engine.support.BooleanExpressionTransitionCriteria;
import org.springframework.webflow.engine.support.DefaultTransitionCriteria;
import org.springframework.webflow.execution.RequestContext;
/**
@@ -39,9 +39,8 @@ import org.springframework.webflow.execution.RequestContext;
* </li>
* <li>"eventId" - will result in a TransitionCriteria object that matches given event id ({@link org.springframework.webflow.engine.support.EventIdTransitionCriteria})
* </li>
* <li>"${...}" - will result in a TransitionCriteria object that evaluates given condition, expressed as an expression ({@link org.springframework.webflow.engine.support.BooleanExpressionTransitionCriteria})
* <li>"${...}" - will result in a TransitionCriteria object that evaluates given condition, expressed as an expression ({@link org.springframework.webflow.engine.support.DefaultTransitionCriteria})
* </li>
* <li>"bean:&lt;id&gt;" - will result in usage of a custom TransitionCriteria bean implementation.</li>
* </ul>
*
* @see org.springframework.webflow.engine.TransitionCriteria
@@ -51,11 +50,6 @@ import org.springframework.webflow.execution.RequestContext;
*/
class TextToTransitionCriteria extends AbstractConverter {
/**
* Prefix used when the user wants to use a custom TransitionCriteria implementation managed by a bean factory.
*/
private static final String BEAN_PREFIX = "bean:";
/**
* Context for flow builder services.
*/
@@ -83,9 +77,6 @@ class TextToTransitionCriteria extends AbstractConverter {
if (!StringUtils.hasText(encodedCriteria)
|| WildcardTransitionCriteria.WILDCARD_EVENT_ID.equals(encodedCriteria)) {
return WildcardTransitionCriteria.INSTANCE;
} else if (encodedCriteria.startsWith(BEAN_PREFIX)) {
return flowBuilderContext.getBeanFactory().getBean(encodedCriteria.substring(BEAN_PREFIX.length()),
TransitionCriteria.class);
} else {
return createBooleanExpressionTransitionCriteria(encodedCriteria, parser);
}
@@ -103,6 +94,6 @@ class TextToTransitionCriteria extends AbstractConverter {
ExpressionParser parser) throws ConversionException {
Expression expression = parser.parseExpression(encodedCriteria, new ParserContextImpl().template().eval(
RequestContext.class).variable(new ExpressionVariable("result", "lastEvent.id")));
return new BooleanExpressionTransitionCriteria(expression);
return new DefaultTransitionCriteria(expression);
}
}

View File

@@ -78,7 +78,7 @@ 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.BeanFactoryVariableValueFactory;
import org.springframework.webflow.engine.support.BooleanExpressionTransitionCriteria;
import org.springframework.webflow.engine.support.DefaultTransitionCriteria;
import org.springframework.webflow.engine.support.GenericSubflowAttributeMapper;
import org.springframework.webflow.engine.support.TransitionCriteriaChain;
import org.springframework.webflow.engine.support.TransitionExecutingFlowExecutionExceptionHandler;
@@ -593,7 +593,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
if (endState) {
return null;
} else {
encodedView = getLocalContext().getViewFactoryCreator().createViewIdByConvention(parseId(element));
encodedView = getLocalContext().getViewFactoryCreator().getViewIdByConvention(parseId(element));
Expression viewName = getExpressionParser().parseExpression(encodedView,
new ParserContextImpl().template().eval(RequestContext.class).expect(String.class));
return getLocalContext().getViewFactoryCreator().createViewFactory(viewName,
@@ -609,13 +609,10 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
Expression expression = getExpressionParser().parseExpression(flowRedirect,
new ParserContextImpl().template().eval(RequestContext.class).expect(String.class));
return new ActionExecutingViewFactory(new FlowDefinitionRedirectAction(expression));
} else if (encodedView.startsWith("bean:")) {
return (ViewFactory) getLocalContext().getBeanFactory().getBean(encodedView.substring("bean:".length()),
ViewFactory.class);
} else {
Expression viewName = getExpressionParser().parseExpression(encodedView,
Expression viewId = getExpressionParser().parseExpression(encodedView,
new ParserContextImpl().template().eval(RequestContext.class).expect(String.class));
return getLocalContext().getViewFactoryCreator().createViewFactory(viewName,
return getLocalContext().getViewFactoryCreator().createViewFactory(viewId,
getLocalContext().getResourceLoader());
}
}
@@ -782,7 +779,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
private Transition parseThen(Element element) {
Expression expression = getExpressionParser().parseExpression(element.getAttribute("test"),
new ParserContextImpl().eval(RequestContext.class).expect(Boolean.class));
TransitionCriteria matchingCriteria = new BooleanExpressionTransitionCriteria(expression);
TransitionCriteria matchingCriteria = new DefaultTransitionCriteria(expression);
TargetStateResolver targetStateResolver = (TargetStateResolver) fromStringTo(TargetStateResolver.class)
.execute(element.getAttribute("then"));
return getFlowArtifactFactory().createTransition(targetStateResolver, matchingCriteria, null, null);

View File

@@ -768,10 +768,6 @@ Sophisticated transitional expressions are also supported when enclosed in a del
<pre>
&lt;transition on="#{event == 'submit' &;amp;&amp flowScope.attribute == 'foo'}" to="state"/&gt;
</pre>
For exotic usage scenarios, custom TransitionCriteria beans can be plugged in as follows:
<pre>
&lt;transition on="bean:myCustomCriteriaBean" to="state"/&gt;
</pre>
]]>
</xsd:documentation>
</xsd:annotation>
@@ -794,8 +790,7 @@ Superclasses of the configured exception class match by default. Use this attri
<![CDATA[
The target state to transition to.
<br>
The value of this attribute may be a static state identifier (e.g. to="displayForm") or a dynamic eval expression (e.g. to="#{flowScope.previousViewState}").
For exotic usage scenarios, custom target state resolver beans can also be plugged in (e.g. to="bean:myCustomTargetStateResolver").
The value of this attribute may be a static state identifier (e.g. to="displayForm") or a dynamic expression (e.g. to="${flowScope.previousViewState}").
If no value is specified, this transition acts as a simple event handler and will not change the state of the flow.
]]>
</xsd:documentation>
@@ -905,11 +900,6 @@ Use the flowRedirect: prefix to redirect to another flow:
<pre>
flowRedirect:myOtherFlow?someData=#{flowScope.data}
</pre>
For exotic usages, use the bean: prefix to plug in a custom ViewFactory bean you define.
<pre>
bean:myCustomViewFactory
</pre>
<br>
When this attribute is not specified, the view to render will be determined by convention.
The default convention is to treat the id of this view state as the view identifier.
]]>
@@ -1241,9 +1231,9 @@ Use the flowRedirect: prefix to redirect to another flow:
<pre>
flowRedirect:myOtherFlow?someData=#{flowScope.data}
</pre>
For exotic usages, use the bean: prefix to plug in a custom ViewFactory bean you define:
For exotic usages, you may plug in a custom ViewFactory bean you define:
<pre>
bean:myCustomViewFactory
#{myCustomViewFactory}
</pre>
<br>
When this attribute is not specified, no final response will be issued. In this case,

View File

@@ -35,11 +35,11 @@ public class DefaultTargetStateResolver implements TargetStateResolver {
/**
* The expression for the target state identifier.
*/
private Expression targetStateIdExpression;
private Expression targetStateExpression;
/**
* Creates a new target state resolver that always returns the same target state id.
* @param targetStateId the id of the target state
* @param targetStateId a static target target state
*/
public DefaultTargetStateResolver(String targetStateId) {
this(new StaticExpression(targetStateId));
@@ -47,23 +47,23 @@ public class DefaultTargetStateResolver implements TargetStateResolver {
/**
* Creates a new target state resolver.
* @param targetStateIdExpression the target state id expression
* @param targetStateExpression the target state expression
*/
public DefaultTargetStateResolver(Expression targetStateIdExpression) {
Assert.notNull(targetStateIdExpression, "The target state id expression is required");
this.targetStateIdExpression = targetStateIdExpression;
public DefaultTargetStateResolver(Expression targetStateExpression) {
Assert.notNull(targetStateExpression, "The target state expression is required");
this.targetStateExpression = targetStateExpression;
}
public State resolveTargetState(Transition transition, State sourceState, RequestContext context) {
String stateId = String.valueOf(targetStateIdExpression.getValue(context));
if (stateId != null) {
return ((Flow) context.getActiveFlow()).getStateInstance(stateId);
String targetStateId = (String) targetStateExpression.getValue(context);
if (targetStateId != null) {
return ((Flow) context.getActiveFlow()).getStateInstance(targetStateId);
} else {
return null;
}
}
public String toString() {
return targetStateIdExpression.toString();
return targetStateExpression.toString();
}
}

View File

@@ -22,39 +22,41 @@ import org.springframework.webflow.execution.RequestContext;
/**
* Transition criteria that tests the value of an expression. The expression is used to express a condition that guards
* transition execution in a web flow. Expressions will be evaluated agains the request context and should return a
* boolean result.
* transition execution in a web flow. Expressions will be evaluated against the request context. Boolean, string, and
* custom TransitonCriteria evaluation results are supported.
*
* @author Keith Donald
* @author Erwin Vervaet
*/
public class BooleanExpressionTransitionCriteria implements TransitionCriteria {
public class DefaultTransitionCriteria implements TransitionCriteria {
/**
* The expression evaluator to use.
*/
private Expression booleanExpression;
private Expression expression;
/**
* Create a new expression based transition criteria object.
* @param booleanExpression the expression evaluator testing the criteria, this expression should be a condition
* that returns a Boolean value
* @param expression the expression evaluator testing the criteria
*/
public BooleanExpressionTransitionCriteria(Expression booleanExpression) {
Assert.notNull(booleanExpression, "The expression to test is required");
this.booleanExpression = booleanExpression;
public DefaultTransitionCriteria(Expression expression) {
Assert.notNull(expression, "The transition criteria expression to test is required");
this.expression = expression;
}
public boolean test(RequestContext context) {
Object result = booleanExpression.getValue(context);
if (result instanceof Boolean) {
Object result = expression.getValue(context);
if (result == null) {
return false;
} else if (result instanceof Boolean) {
return ((Boolean) result).booleanValue();
} else {
return context.getLastEvent().getId().equals(String.valueOf(result));
String eventId = String.valueOf(result);
return context.getLastEvent().getId().equals(eventId);
}
}
public String toString() {
return booleanExpression.toString();
return expression.toString();
}
}

View File

@@ -19,7 +19,8 @@ public class SpringBeanWebFlowELResolver extends SpringBeanELResolver {
protected BeanFactory getBeanFactory(ELContext elContext) {
RequestContext rc = RequestContextHolder.getRequestContext();
if (rc != null && rc.getActiveFlow().getBeanFactory() != null) {
return rc.getActiveFlow().getBeanFactory();
BeanFactory factory = rc.getActiveFlow().getBeanFactory();
return factory;
} else {
return EMPTY_BEAN_FACTORY;
}

View File

@@ -19,10 +19,8 @@ import org.springframework.util.ClassUtils;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceView;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.webflow.action.ViewFactoryActionAdapter;
import org.springframework.webflow.core.collection.ParameterMap;
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
import org.springframework.webflow.execution.Action;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;
import org.springframework.webflow.execution.View;
@@ -43,6 +41,7 @@ import org.springframework.webflow.execution.ViewFactory;
public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationContextAware {
private static final boolean jstlPresent = ClassUtils.isPresent("javax.servlet.jsp.jstl.fmt.LocalizationContext");
private static final boolean springSecurityPresent = ClassUtils
.isPresent("org.springframework.security.context.SecurityContextHolder");
@@ -50,23 +49,6 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon
private ApplicationContext applicationContext;
public Action createRenderViewAction(Expression viewId, ResourceLoader viewResourceLoader) {
return new ViewFactoryActionAdapter(createViewFactory(viewId, viewResourceLoader));
}
public ViewFactory createViewFactory(Expression viewId, ResourceLoader viewResourceLoader) {
if (viewResolvers != null) {
return new ViewResolvingMvcViewFactory(viewId, viewResolvers);
} else {
return new InternalFlowResourceMvcViewFactory(viewId, applicationContext, viewResourceLoader);
}
}
public String createViewIdByConvention(String viewStateId) {
// TODO - make configurable
return viewStateId + ".jsp";
}
/**
* Sets the view resolvers that will be used to resolve views selected by flows. If multiple resolvers are to be
* used, the resolvers should be ordered in the manner they should be applied.
@@ -80,27 +62,40 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon
this.applicationContext = context;
}
public ViewFactory createViewFactory(Expression viewIdExpression, ResourceLoader viewResourceLoader) {
if (viewResolvers != null) {
return new ViewResolvingMvcViewFactory(viewIdExpression, viewResolvers);
} else {
return new InternalFlowResourceMvcViewFactory(viewIdExpression, applicationContext, viewResourceLoader);
}
}
public String getViewIdByConvention(String viewStateId) {
// TODO - make configurable
return viewStateId + ".jsp";
}
/**
* View factory implementation that creates a Spring-MVC Internal Resource view to render a flow-relative view
* resource such as a JSP or Velocity template.
* @author Keith Donald
*/
static class InternalFlowResourceMvcViewFactory implements ViewFactory {
private Expression viewExpression;
private Expression viewIdExpression;
private ApplicationContext applicationContext;
private ResourceLoader resourceLoader;
public InternalFlowResourceMvcViewFactory(Expression viewExpression, ApplicationContext context,
public InternalFlowResourceMvcViewFactory(Expression viewIdExpression, ApplicationContext context,
ResourceLoader resourceLoader) {
this.viewExpression = viewExpression;
this.viewIdExpression = viewIdExpression;
this.applicationContext = context;
this.resourceLoader = resourceLoader;
}
public View getView(RequestContext context) {
String viewId = (String) viewExpression.getValue(context);
String viewId = (String) viewIdExpression.getValue(context);
if (viewId.startsWith("/")) {
return getViewInternal(viewId, context);
} else {
@@ -133,17 +128,17 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon
* @author Keith Donald
*/
private static class ViewResolvingMvcViewFactory implements ViewFactory {
private Expression viewId;
private Expression viewIdExpression;
private List viewResolvers;
public ViewResolvingMvcViewFactory(Expression viewId, List viewResolvers) {
this.viewId = viewId;
public ViewResolvingMvcViewFactory(Expression viewIdExpression, List viewResolvers) {
this.viewIdExpression = viewIdExpression;
this.viewResolvers = viewResolvers;
}
public View getView(RequestContext context) {
String view = (String) viewId.getValue(context);
String view = (String) viewIdExpression.getValue(context);
return new MvcView(resolveView(view), context);
}
@@ -190,7 +185,7 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon
Map model = new HashMap();
model.putAll(context.getConversationScope().union(context.getFlowScope()).union(context.getFlashScope())
.union(context.getRequestScope()).asMap());
model.put("flowExecutionRequestContext", context);
model.put("flowRequestContext", context);
model.put("flowExecutionKey", context.getFlowExecutionContext().getKey().toString());
model.put("flowExecutionUrl", context.getFlowExecutionUrl());
if (springSecurityPresent && !model.containsKey("currentUser")) {

View File

@@ -121,12 +121,18 @@ public class MockFlowExecutionContext implements FlowExecutionContext {
return outcome;
}
// convenience mock accessors
public Flow getDefinitionInternal() {
return (Flow) getDefinition();
}
// mutators
/**
* Sets the top-level flow definition.
*/
public void setFlow(Flow rootFlow) {
public void setFlow(FlowDefinition rootFlow) {
this.flow = rootFlow;
}

View File

@@ -185,7 +185,7 @@ public class MockRequestContext implements RequestContext {
}
}
// mutators
// mutators for configuring the mock
/**
* Sets the active flow session of the executing flow associated with this request. This will influence
@@ -243,8 +243,33 @@ public class MockRequestContext implements RequestContext {
attributes.remove(attributeName);
}
/**
* Adds a request parameter to the configured external context.
* @param parameterName the parameter name
* @param parameterValue the parameter value
*/
public void putRequestParameter(String parameterName, String parameterValue) {
getMockExternalContext().putRequestParameter(parameterName, parameterValue);
}
/**
* Adds a multi-valued request parameter to the configured external context.
* @param parameterName the parameter name
* @param parameterValues the parameter values
*/
public void putRequestParameter(String parameterName, String[] parameterValues) {
getMockExternalContext().putRequestParameter(parameterName, parameterValues);
}
// convenience accessors
/**
* Returns the root flow definition for this request context. Assumes a {@link Flow} implementation.
*/
public Flow getRootFlow() {
return getMockFlowExecutionContext().getDefinitionInternal();
}
/**
* Returns the contained mutable context {@link AttributeMap attribute map} allowing setting of mock context
* attributes.
@@ -268,22 +293,4 @@ public class MockRequestContext implements RequestContext {
return (MockExternalContext) externalContext;
}
/**
* Adds a request parameter to the configured external context.
* @param parameterName the parameter name
* @param parameterValue the parameter value
*/
public void putRequestParameter(String parameterName, String parameterValue) {
getMockExternalContext().putRequestParameter(parameterName, parameterValue);
}
/**
* Adds a multi-valued request parameter to the configured external context.
* @param parameterName the parameter name
* @param parameterValues the parameter values
*/
public void putRequestParameter(String parameterName, String[] parameterValues) {
getMockExternalContext().putRequestParameter(parameterName, parameterValues);
}
}

View File

@@ -40,7 +40,7 @@ class MockViewFactoryCreator implements ViewFactoryCreator {
return new MockViewFactory(viewId);
}
public String createViewIdByConvention(String viewStateId) {
public String getViewIdByConvention(String viewStateId) {
return viewStateId;
}

View File

@@ -51,7 +51,7 @@ public class FlowBuilderServicesBeanDefinitionParserTests extends TestCase {
throw new UnsupportedOperationException("Auto-generated method stub");
}
public String createViewIdByConvention(String viewStateId) {
public String getViewIdByConvention(String viewStateId) {
return viewStateId;
}

View File

@@ -17,7 +17,6 @@ package org.springframework.webflow.engine.builder.support;
import junit.framework.TestCase;
import org.springframework.binding.convert.ConversionException;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.TransitionCriteria;
import org.springframework.webflow.engine.WildcardTransitionCriteria;
@@ -27,7 +26,6 @@ import org.springframework.webflow.execution.RequestContextHolder;
import org.springframework.webflow.test.MockFlowBuilderContext;
import org.springframework.webflow.test.MockRequestContext;
// TODO - 2 expected failures do to limitations in OgnlExpressionParser
public class TextToTransitionCriteriaTests extends TestCase {
private MockFlowBuilderContext serviceLocator = new MockFlowBuilderContext("flowId");
@@ -43,6 +41,7 @@ public class TextToTransitionCriteriaTests extends TestCase {
assertTrue("Criterion should evaluate to true", criterion.test(ctx));
assertSame(WildcardTransitionCriteria.INSTANCE, converter.convert("*"));
assertSame(WildcardTransitionCriteria.INSTANCE, converter.convert(""));
assertSame(WildcardTransitionCriteria.INSTANCE, converter.convert(null));
}
public void testStaticEventId() {
@@ -66,43 +65,22 @@ public class TextToTransitionCriteriaTests extends TestCase {
assertFalse("Criterion should evaluate to false", criterion.test(ctx));
}
/*
* public void testNonBooleanEvaluation() throws Exception { String expression = "${flowScope.foo}";
* TransitionCriteria criterion = (TransitionCriteria) converter.convert(expression); RequestContext ctx =
* getRequestContext(); try { criterion.test(ctx); fail("Non-boolean evaluations are not allowed"); } catch
* (IllegalArgumentException e) { // success } }
*/
public void testInvalidSyntax() throws Exception {
try {
String expression = "${&foo<<m}";
converter.convert(expression);
fail("Syntax error should throw ExpressionSyntaxException");
} catch (ConversionException ex) {
// success
}
public void testNonStringEvaluation() throws Exception {
String expression = "${3 + 4}";
TransitionCriteria criterion = (TransitionCriteria) converter.convert(expression);
MockRequestContext ctx = getRequestContext();
ctx.setLastEvent(new Event(this, "7"));
assertTrue("Criterion should evaluate to true", criterion.test(ctx));
}
/*
* public void testEventId() throws Exception { String expression = "${lastEvent.id == 'sample'}";
* TransitionCriteria criterion = (TransitionCriteria) converter.convert(expression); RequestContext ctx =
* getRequestContext(); assertTrue("Criterion should evaluate to true", criterion.test(ctx)); expression =
* "${#result == 'sample'}"; criterion = (TransitionCriteria) converter.convert(expression); assertTrue("Criterion
* should evaluate to true", criterion.test(ctx)); }
*/
public void testBean() {
TransitionCriteria myTransitionCriteria = new TransitionCriteria() {
public boolean test(RequestContext context) {
return false;
}
};
serviceLocator.registerBean("myTransitionCriteria", myTransitionCriteria);
TransitionCriteria criteria = (TransitionCriteria) converter.convert("bean:myTransitionCriteria");
assertSame(myTransitionCriteria, criteria);
public void testNullExpressionEvaluation() throws Exception {
String expression = "${null}";
TransitionCriteria criterion = (TransitionCriteria) converter.convert(expression);
RequestContext ctx = getRequestContext();
assertFalse("Criterion should evaluate to false", criterion.test(ctx));
}
private RequestContext getRequestContext() {
private MockRequestContext getRequestContext() {
Flow flow = new Flow("id");
MockRequestContext ctx = new MockRequestContext(flow);
RequestContextHolder.setRequestContext(ctx);