url encoding for flow execution / definition urls

This commit is contained in:
Keith Donald
2009-04-16 14:49:20 +00:00
parent 8ec2371e25
commit 5349616d67
6 changed files with 54 additions and 5 deletions

View File

@@ -17,6 +17,8 @@ Bug Fixes
* Made FlowExecutionSnapshotGroup public for serialization reasons
* Fixed bug where a flow execution snapshot id was not always incremented, which could lead to collisions between multiple windows sharing the same execution (SWF-1098).
* Fixed bug where updating ViewState history could result in exceptions if no flow execution key was assigned or no snapshot had been taken (SWF-1099).
* Fixed bug where ExternalContext.getFlowExecutionUrl method was not encoding execution URL for rendering by views
* Fixed bugs where FlowHandlerAdapter was not encoding flow definition URLs in its default flow outcome and exception handler routines
Improvements
* Added userEventQueued and getUserEventState methods to View SPI, which simplified ViewState and View object interaction.

View File

@@ -94,7 +94,7 @@ public interface ExternalContext {
/**
* Get a flow execution URL for the execution with the provided key. Typically used by response writers that write
* out references to the flow execution to support postback on a subsequent request.
* out references to the flow execution to support postback on a subsequent request. The URL returned is encoded.
* @param flowId the flow definition id
* @param flowExecutionKey the flow execution key
* @return the flow execution URL

View File

@@ -202,7 +202,7 @@ public class ServletExternalContext implements ExternalContext {
}
public String getFlowExecutionUrl(String flowId, String flowExecutionKey) {
return flowUrlHandler.createFlowExecutionUrl(flowId, flowExecutionKey, request);
return response.encodeURL(flowUrlHandler.createFlowExecutionUrl(flowId, flowExecutionKey, request));
}
public Writer getResponseWriter() throws IllegalStateException {

View File

@@ -273,7 +273,8 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
logger.debug("Ended flow '" + flowId + "' did not commit a response; "
+ "attempting to start a new flow execution as a default outcome handler");
}
response.sendRedirect(flowUrlHandler.createFlowDefinitionUrl(flowId, outcome.getOutput(), request));
String flowUrl = flowUrlHandler.createFlowDefinitionUrl(flowId, outcome.getOutput(), request);
sendRedirect(flowUrl, request, response);
}
}
@@ -296,7 +297,8 @@ public class FlowHandlerAdapter extends WebContentGenerator implements HandlerAd
logger.debug("Restarting a new execution of previously ended flow '" + flowId + "'");
}
// by default, attempt to restart the flow
response.sendRedirect(flowUrlHandler.createFlowDefinitionUrl(flowId, null, request));
String flowUrl = flowUrlHandler.createFlowDefinitionUrl(flowId, null, request);
sendRedirect(flowUrl, request, response);
}
} else {
throw e;

View File

@@ -74,6 +74,12 @@ public class ServletExternalContextTests extends TestCase {
assertEquals(response, context.getNativeResponse());
}
public void testGetExecutionUrl() {
request.setRequestURI("/foo");
String url = context.getFlowExecutionUrl("foo", "e1s1");
assertEquals("/foo?execution=e1s1", url);
}
public void testNotAnAjaxRequest() {
assertFalse(context.isAjaxRequest());
}

View File

@@ -77,7 +77,6 @@ public class FlowHandlerAdapterTests extends TestCase {
}
}
};
request = new MockHttpServletRequest();
response = new MockHttpServletResponse();
context = new ServletExternalContext(servletContext, request, response, flowHandlerAdapter.getFlowUrlHandler());
@@ -117,6 +116,28 @@ public class FlowHandlerAdapterTests extends TestCase {
EasyMock.verify(new Object[] { flowExecutor });
}
public void testLaunchFlowRequestEndsAfterProcessingAjaxRequest() throws Exception {
request.setContextPath("/springtravel");
request.setServletPath("/app");
request.setPathInfo("/whatever");
request.setRequestURI("/springtravel/app/whatever");
request.setMethod("GET");
Map parameters = new HashMap();
request.setParameters(parameters);
context.setAjaxRequest(true);
flowExecutor.launchExecution("foo", flowInput, context);
LocalAttributeMap output = new LocalAttributeMap();
output.put("bar", "baz");
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
EasyMock.expectLastCall().andReturn(result);
EasyMock.replay(new Object[] { flowExecutor });
request.addHeader("Accept", "text/html;type=ajax");
flowHandlerAdapter.handle(request, response, flowHandler);
assertEquals("/springtravel/app/foo?bar=baz", response.getHeader("Spring-Redirect-URL"));
EasyMock.verify(new Object[] { flowExecutor });
}
public void testResumeFlowRequest() throws Exception {
request.setContextPath("/springtravel");
request.setServletPath("/app");
@@ -412,6 +433,24 @@ public class FlowHandlerAdapterTests extends TestCase {
EasyMock.verify(new Object[] { flowExecutor });
}
public void testDefaultHandleNoSuchFlowExecutionExceptionAjaxRequest() throws Exception {
request.setContextPath("/springtravel");
request.setServletPath("/app");
request.setPathInfo("/foo");
request.setRequestURI("/springtravel/app/foo");
request.setMethod("GET");
request.addParameter("execution", "12345");
flowExecutor.resumeExecution("12345", context);
FlowException flowException = new NoSuchFlowExecutionException(new MockFlowExecutionKey("12345"), null);
EasyMock.expectLastCall().andThrow(flowException);
EasyMock.replay(new Object[] { flowExecutor });
context.setAjaxRequest(true);
request.addHeader("Accept", "text/html;type=ajax");
flowHandlerAdapter.handle(request, response, flowHandler);
assertEquals("/springtravel/app/foo", response.getHeader("Spring-Redirect-URL"));
EasyMock.verify(new Object[] { flowExecutor });
}
public void testHandleFlowOutcomeCustomFlowHandler() throws Exception {
handleExecutionOutcome = true;
request.setContextPath("/springtravel");