flow redirect bug fix

This commit is contained in:
Keith Donald
2008-02-29 23:30:36 +00:00
parent 4924ca1008
commit 4bebc59460
4 changed files with 61 additions and 80 deletions

View File

@@ -1,51 +1,53 @@
package org.springframework.webflow.action; package org.springframework.webflow.action;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.springframework.binding.expression.Expression; import org.springframework.binding.expression.Expression;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.webflow.core.collection.AttributeMap; import org.springframework.util.StringUtils;
import org.springframework.webflow.core.collection.LocalAttributeMap; import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext; import org.springframework.webflow.execution.RequestContext;
public class FlowDefinitionRedirectAction extends AbstractAction { public class FlowDefinitionRedirectAction extends AbstractAction {
private Expression flowId; private Expression expression;
private Map input;
public FlowDefinitionRedirectAction(Expression flowId, Map input) { public FlowDefinitionRedirectAction(Expression expression) {
Assert.notNull(flowId, "The flow id to redirect to is required"); Assert.notNull(expression, "The flow definition redirect expression is required");
this.flowId = flowId; this.expression = expression;
this.input = input;
} }
protected Event doExecute(RequestContext context) throws Exception { protected Event doExecute(RequestContext context) throws Exception {
String flowId = (String) this.flowId.getValue(context); String encodedRedirect = (String) expression.getValue(context);
AttributeMap input = evaluateInput(context); if (encodedRedirect == null) {
context.getExternalContext().requestFlowDefinitionRedirect(flowId, input); throw new IllegalStateException(
"Flow definition redirect expression evaluated to [null], the expression was " + expression);
}
// the encoded FlowDefinitionRedirect should look something like
// "flowDefinitionId?param0=value0&param1=value1"
// now parse that and build a corresponding view selection
int index = encodedRedirect.indexOf('?');
String flowDefinitionId;
LocalAttributeMap executionInput = null;
if (index != -1) {
flowDefinitionId = encodedRedirect.substring(0, index);
String[] parameters = StringUtils.delimitedListToStringArray(encodedRedirect.substring(index + 1), "&");
executionInput = new LocalAttributeMap(parameters.length, 1);
for (int i = 0; i < parameters.length; i++) {
String nameAndValue = parameters[i];
index = nameAndValue.indexOf('=');
if (index != -1) {
executionInput.put(nameAndValue.substring(0, index), nameAndValue.substring(index + 1));
} else {
executionInput.put(nameAndValue, "");
}
}
} else {
flowDefinitionId = encodedRedirect;
}
if (!StringUtils.hasText(flowDefinitionId)) {
// equivalent to restart
flowDefinitionId = context.getFlowExecutionContext().getDefinition().getId();
}
context.getExternalContext().requestFlowDefinitionRedirect(flowDefinitionId, executionInput);
return success(); return success();
} }
private AttributeMap evaluateInput(RequestContext context) {
if (this.input == null) {
return null;
} else {
Map input = new HashMap();
for (Iterator it = this.input.entrySet().iterator(); it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
Expression name = (Expression) entry.getKey();
Expression value = (Expression) entry.getValue();
String paramName = (String) name.getValue(context);
Object paramValue = value.getValue(context);
input.put(paramName, paramValue);
}
return new LocalAttributeMap(input);
}
}
public static FlowDefinitionRedirectAction create(String encodedFlowRedirect) {
throw new UnsupportedOperationException("Not yet implemented");
}
} }

View File

@@ -16,7 +16,9 @@ public class ViewFactoryActionAdapter extends AbstractAction {
} }
protected Event doExecute(RequestContext context) throws Exception { protected Event doExecute(RequestContext context) throws Exception {
viewFactory.getView(context).render(); if (viewFactory != null) {
viewFactory.getView(context).render();
}
return new Event(this, "success"); return new Event(this, "success");
} }
} }

View File

@@ -572,7 +572,7 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
} }
private void parseAndAddViewState(Element element, Flow flow) { private void parseAndAddViewState(Element element, Flow flow) {
ViewFactory viewFactory = parseViewFactory(element); ViewFactory viewFactory = parseViewFactory(element, false);
boolean redirect = false; boolean redirect = false;
if (element.hasAttribute("redirect")) { if (element.hasAttribute("redirect")) {
redirect = ((Boolean) fromStringTo(Boolean.class).execute(element.getAttribute("redirect"))).booleanValue(); redirect = ((Boolean) fromStringTo(Boolean.class).execute(element.getAttribute("redirect"))).booleanValue();
@@ -607,8 +607,8 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
MutableAttributeMap attributes = parseAttributes(element); MutableAttributeMap attributes = parseAttributes(element);
parseAndSetSecuredAttribute(element, attributes); parseAndSetSecuredAttribute(element, attributes);
getFlowArtifactFactory().createEndState(parseId(element), flow, parseEntryActions(element), getFlowArtifactFactory().createEndState(parseId(element), flow, parseEntryActions(element),
parseFinalResponseAction(element), parseOutputMapper(element), parseExceptionHandlers(element), new ViewFactoryActionAdapter(parseViewFactory(element, true)), parseOutputMapper(element),
attributes); parseExceptionHandlers(element), attributes);
} }
private String parseId(Element element) { private String parseId(Element element) {
@@ -640,14 +640,18 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
} }
} }
private ViewFactory parseViewFactory(Element element) { private ViewFactory parseViewFactory(Element element, boolean endState) {
String encodedView = element.getAttribute(VIEW_ATTRIBUTE); String encodedView = element.getAttribute(VIEW_ATTRIBUTE);
if (!StringUtils.hasText(encodedView)) { if (!StringUtils.hasText(encodedView)) {
encodedView = createViewId(element.getAttribute(ID_ATTRIBUTE)); if (endState) {
Expression viewName = getExpressionParser().parseExpression(encodedView, return null;
new ParserContextImpl().eval(RequestContext.class).expect(String.class)); } else {
return getLocalContext().getViewFactoryCreator().createViewFactory(viewName, encodedView = createViewId(element.getAttribute(ID_ATTRIBUTE));
getLocalContext().getResourceLoader()); Expression viewName = getExpressionParser().parseExpression(encodedView,
new ParserContextImpl().eval(RequestContext.class).expect(String.class));
return getLocalContext().getViewFactoryCreator().createViewFactory(viewName,
getLocalContext().getResourceLoader());
}
} else if (encodedView.startsWith(EXTERNAL_REDIRECT_PREFIX)) { } else if (encodedView.startsWith(EXTERNAL_REDIRECT_PREFIX)) {
String encodedUrl = encodedView.substring(EXTERNAL_REDIRECT_PREFIX.length()); String encodedUrl = encodedView.substring(EXTERNAL_REDIRECT_PREFIX.length());
Expression externalUrl = getExpressionParser().parseExpression(encodedUrl, Expression externalUrl = getExpressionParser().parseExpression(encodedUrl,
@@ -655,7 +659,9 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
return new ActionExecutingViewFactory(new ExternalRedirectAction(externalUrl)); return new ActionExecutingViewFactory(new ExternalRedirectAction(externalUrl));
} else if (encodedView.startsWith(FLOW_DEFINITION_REDIRECT_PREFIX)) { } else if (encodedView.startsWith(FLOW_DEFINITION_REDIRECT_PREFIX)) {
String flowRedirect = encodedView.substring(FLOW_DEFINITION_REDIRECT_PREFIX.length()); String flowRedirect = encodedView.substring(FLOW_DEFINITION_REDIRECT_PREFIX.length());
return new ActionExecutingViewFactory(FlowDefinitionRedirectAction.create(flowRedirect)); Expression expression = getExpressionParser().parseExpression(flowRedirect,
new ParserContextImpl().eval(RequestContext.class).expect(String.class));
return new ActionExecutingViewFactory(new FlowDefinitionRedirectAction(expression));
} else if (encodedView.startsWith(BEAN_PREFIX)) { } else if (encodedView.startsWith(BEAN_PREFIX)) {
return (ViewFactory) getLocalContext().getBeanFactory().getBean( return (ViewFactory) getLocalContext().getBeanFactory().getBean(
encodedView.substring(BEAN_PREFIX.length()), ViewFactory.class); encodedView.substring(BEAN_PREFIX.length()), ViewFactory.class);
@@ -1070,30 +1076,6 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
return null; return null;
} }
private Action parseFinalResponseAction(Element element) {
String encodedView = element.getAttribute(VIEW_ATTRIBUTE);
if (encodedView == null || encodedView.length() == 0) {
// null final responses are allowed
return null;
} else if (encodedView.startsWith(EXTERNAL_REDIRECT_PREFIX)) {
String encodedUrl = encodedView.substring(EXTERNAL_REDIRECT_PREFIX.length());
Expression externalUrl = getExpressionParser().parseExpression(encodedUrl,
new ParserContextImpl().eval(RequestContext.class).expect(String.class));
return new ExternalRedirectAction(externalUrl);
} else if (encodedView.startsWith(FLOW_DEFINITION_REDIRECT_PREFIX)) {
String flowRedirect = encodedView.substring(FLOW_DEFINITION_REDIRECT_PREFIX.length());
return FlowDefinitionRedirectAction.create(flowRedirect);
} else if (encodedView.startsWith(BEAN_PREFIX)) {
return (Action) getLocalContext().getBeanFactory().getBean(encodedView.substring(BEAN_PREFIX.length()),
Action.class);
} else {
Expression viewName = getExpressionParser().parseExpression(encodedView,
new ParserContextImpl().eval(RequestContext.class).expect(String.class));
return new ViewFactoryActionAdapter(getLocalContext().getViewFactoryCreator().createViewFactory(viewName,
getLocalContext().getResourceLoader()));
}
}
private FlowExecutionExceptionHandler[] parseExceptionHandlers(Element element) { private FlowExecutionExceptionHandler[] parseExceptionHandlers(Element element) {
FlowExecutionExceptionHandler[] transitionExecutingHandlers = parseTransitionExecutingExceptionHandlers(element); FlowExecutionExceptionHandler[] transitionExecutingHandlers = parseTransitionExecutingExceptionHandlers(element);
FlowExecutionExceptionHandler[] customHandlers = parseCustomExceptionHandlers(element); FlowExecutionExceptionHandler[] customHandlers = parseCustomExceptionHandlers(element);

View File

@@ -1,8 +1,5 @@
package org.springframework.webflow.action; package org.springframework.webflow.action;
import java.util.HashMap;
import java.util.Map;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.springframework.binding.expression.Expression; import org.springframework.binding.expression.Expression;
@@ -13,10 +10,8 @@ public class FlowDefinitionRedirectActionTests extends TestCase {
private FlowDefinitionRedirectAction action; private FlowDefinitionRedirectAction action;
public void testExecute() throws Exception { public void testExecute() throws Exception {
Expression flowId = new StaticExpression("user"); Expression flowId = new StaticExpression("user?foo=bar");
Map input = new HashMap(); action = new FlowDefinitionRedirectAction(flowId);
input.put(new StaticExpression("foo"), new StaticExpression("bar"));
action = new FlowDefinitionRedirectAction(flowId, input);
MockRequestContext context = new MockRequestContext(); MockRequestContext context = new MockRequestContext();
action.execute(context); action.execute(context);
assertEquals("user", context.getMockExternalContext().getFlowRedirectFlowId()); assertEquals("user", context.getMockExternalContext().getFlowRedirectFlowId());
@@ -25,7 +20,7 @@ public class FlowDefinitionRedirectActionTests extends TestCase {
public void testExecuteWithNullRequestFields() throws Exception { public void testExecuteWithNullRequestFields() throws Exception {
Expression flowId = new StaticExpression("user"); Expression flowId = new StaticExpression("user");
action = new FlowDefinitionRedirectAction(flowId, null); action = new FlowDefinitionRedirectAction(flowId);
MockRequestContext context = new MockRequestContext(); MockRequestContext context = new MockRequestContext();
action.execute(context); action.execute(context);
assertEquals("user", context.getMockExternalContext().getFlowRedirectFlowId()); assertEquals("user", context.getMockExternalContext().getFlowRedirectFlowId());
@@ -33,7 +28,7 @@ public class FlowDefinitionRedirectActionTests extends TestCase {
public void testExecuteWithNullFlowId() throws Exception { public void testExecuteWithNullFlowId() throws Exception {
try { try {
action = new FlowDefinitionRedirectAction(null, null); action = new FlowDefinitionRedirectAction(null);
fail("Should have failed"); fail("Should have failed");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {