portlet refinements
This commit is contained in:
@@ -15,11 +15,11 @@
|
||||
*/
|
||||
package org.springframework.webflow.mvc.portlet;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
|
||||
import org.springframework.web.portlet.ModelAndView;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
@@ -32,19 +32,19 @@ import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
*/
|
||||
public class AbstractFlowHandler implements FlowHandler {
|
||||
|
||||
public MutableAttributeMap createExecutionInputMap(PortletRequest request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getFlowId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModelAndView handleException(FlowException e, RenderRequest request, RenderResponse response) {
|
||||
public MutableAttributeMap createExecutionInputMap(RenderRequest request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String handleFlowOutcome(FlowExecutionOutcome outcome, RenderRequest request, RenderResponse response) {
|
||||
public boolean handleExecutionOutcome(FlowExecutionOutcome outcome, ActionRequest request, ActionResponse response) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String handleException(FlowException e, RenderRequest request, RenderResponse response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
*/
|
||||
package org.springframework.webflow.mvc.portlet;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.PortletModeException;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
|
||||
import org.springframework.web.portlet.ModelAndView;
|
||||
import org.springframework.webflow.core.FlowException;
|
||||
import org.springframework.webflow.core.collection.MutableAttributeMap;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
@@ -50,17 +51,18 @@ public interface FlowHandler {
|
||||
* @param request the current request
|
||||
* @return the input map
|
||||
*/
|
||||
public MutableAttributeMap createExecutionInputMap(PortletRequest request);
|
||||
public MutableAttributeMap createExecutionInputMap(RenderRequest request);
|
||||
|
||||
/**
|
||||
* Handles a specific flow execution outcome. Used to select a new view to render after the flow ends.
|
||||
* Handles a specific flow execution outcome. Used to change portlet modes after the flow ends.
|
||||
* @param outcome the outcome that was reached
|
||||
* @param request the current render request
|
||||
* @param response the current render response
|
||||
* @return the id of the flow to start after handling the outcome, or null if the outcome should be handled by the
|
||||
* caller
|
||||
* @return whether this outcome was handled, or whether the caller should handle it
|
||||
* @throws PortletModeException if this handler tries to change the portlet mode to something invalid
|
||||
*/
|
||||
public String handleFlowOutcome(FlowExecutionOutcome outcome, RenderRequest request, RenderResponse response);
|
||||
public boolean handleExecutionOutcome(FlowExecutionOutcome outcome, ActionRequest request, ActionResponse response)
|
||||
throws PortletModeException;
|
||||
|
||||
/**
|
||||
* Handles a flow exception that was not handled by the Web Flow system. Used by a Controller to handle a specific
|
||||
@@ -69,8 +71,8 @@ public interface FlowHandler {
|
||||
* the flow executor system if no execution could be restored.
|
||||
* @param request the current request
|
||||
* @param response the current response
|
||||
* @return the model and view to render on the occurrence of this exception, or null if the exception is not handled
|
||||
* @return the name of a specific error view to render, or null if the exception should be handled by the caller
|
||||
*/
|
||||
public ModelAndView handleException(FlowException e, RenderRequest request, RenderResponse response);
|
||||
public String handleException(FlowException e, RenderRequest request, RenderResponse response);
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.Map;
|
||||
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.PortletModeException;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletResponse;
|
||||
import javax.portlet.PortletSession;
|
||||
@@ -43,9 +44,7 @@ import org.springframework.webflow.executor.FlowExecutor;
|
||||
|
||||
public class FlowHandlerAdapter extends PortletApplicationObjectSupport implements HandlerAdapter {
|
||||
|
||||
private static final String ACTION_FLOW_EXCEPTION_ATTRIBUTE = "actionFlowException";
|
||||
|
||||
private static final String FLOW_EXECUTION_RESULT_ATTRIBUTE = "flowExecutionResult";
|
||||
private static final String ACTION_REQUEST_FLOW_EXCEPTION_ATTRIBUTE = "actionRequestFlowException";
|
||||
|
||||
private FlowExecutor flowExecutor;
|
||||
|
||||
@@ -65,41 +64,22 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen
|
||||
populateConveniencePortletProperties(request);
|
||||
PortletSession session = request.getPortletSession(false);
|
||||
if (session != null) {
|
||||
FlowException e = (FlowException) session.getAttribute(ACTION_FLOW_EXCEPTION_ATTRIBUTE);
|
||||
FlowException e = (FlowException) session.getAttribute(ACTION_REQUEST_FLOW_EXCEPTION_ATTRIBUTE);
|
||||
if (e != null) {
|
||||
session.removeAttribute(ACTION_FLOW_EXCEPTION_ATTRIBUTE);
|
||||
ModelAndView mv = flowHandler.handleException(e, request, response);
|
||||
return mv != null ? mv : defaultHandleResumeFlowException(flowHandler, e, request, response);
|
||||
session.removeAttribute(ACTION_REQUEST_FLOW_EXCEPTION_ATTRIBUTE);
|
||||
return handleException(e, flowHandler, request, response);
|
||||
}
|
||||
}
|
||||
String flowExecutionKey = urlHandler.getFlowExecutionKey(request);
|
||||
if (flowExecutionKey != null) {
|
||||
PortletExternalContext context = createPortletExternalContext(request, response);
|
||||
try {
|
||||
flowExecutor.resumeExecution(flowExecutionKey, context);
|
||||
return null;
|
||||
} catch (FlowException e) {
|
||||
ModelAndView mv = flowHandler.handleException(e, request, response);
|
||||
return mv != null ? mv : defaultHandleResumeFlowException(flowHandler, e, request, response);
|
||||
}
|
||||
return resumeFlow(flowExecutionKey, flowHandler, request, response);
|
||||
} else {
|
||||
if (session != null) {
|
||||
FlowExecutionResult result = (FlowExecutionResult) session
|
||||
.getAttribute(FLOW_EXECUTION_RESULT_ATTRIBUTE);
|
||||
if (result != null) {
|
||||
session.removeAttribute(FLOW_EXECUTION_RESULT_ATTRIBUTE);
|
||||
String flowId = flowHandler.handleFlowOutcome(result.getOutcome(), request, response);
|
||||
return defaultHandleFlowOutcome(flowHandler, result.getOutcome(), flowId, request, response);
|
||||
} else {
|
||||
return startFlow(request, response, flowHandler);
|
||||
}
|
||||
} else {
|
||||
return startFlow(request, response, flowHandler);
|
||||
}
|
||||
return startFlow(flowHandler, request, response);
|
||||
}
|
||||
}
|
||||
|
||||
public void handleAction(ActionRequest request, ActionResponse response, Object handler) throws Exception {
|
||||
FlowHandler flowHandler = (FlowHandler) handler;
|
||||
populateConveniencePortletProperties(request);
|
||||
String flowExecutionKey = urlHandler.getFlowExecutionKey(request);
|
||||
PortletExternalContext context = createPortletExternalContext(request, response);
|
||||
@@ -107,11 +87,13 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen
|
||||
FlowExecutionResult result = flowExecutor.resumeExecution(flowExecutionKey, context);
|
||||
if (result.isPaused()) {
|
||||
urlHandler.setFlowExecutionRenderParameter(result.getPausedKey(), response);
|
||||
} else if (result.isEnded()) {
|
||||
handleFlowExecutionOutcome(result.getOutcome(), flowHandler, request, response);
|
||||
} else {
|
||||
request.getPortletSession().setAttribute(FLOW_EXECUTION_RESULT_ATTRIBUTE, result);
|
||||
throw new IllegalStateException("Execution result should have been one of [paused] or [ended]");
|
||||
}
|
||||
} catch (FlowException e) {
|
||||
request.getPortletSession().setAttribute(ACTION_FLOW_EXCEPTION_ATTRIBUTE, e);
|
||||
request.getPortletSession().setAttribute(ACTION_REQUEST_FLOW_EXCEPTION_ATTRIBUTE, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +108,7 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen
|
||||
return new PortletExternalContext(getPortletContext(), request, response);
|
||||
}
|
||||
|
||||
protected MutableAttributeMap defaultFlowExecutionInputMap(PortletRequest request) {
|
||||
protected MutableAttributeMap defaultCreateFlowExecutionInputMap(PortletRequest request) {
|
||||
LocalAttributeMap inputMap = new LocalAttributeMap();
|
||||
Map parameterMap = request.getParameterMap();
|
||||
Iterator it = parameterMap.entrySet().iterator();
|
||||
@@ -143,29 +125,19 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen
|
||||
return inputMap;
|
||||
}
|
||||
|
||||
protected ModelAndView defaultHandleFlowOutcome(FlowHandler flowHandler, FlowExecutionOutcome outcome,
|
||||
String nextFlowId, RenderRequest request, RenderResponse response) throws IOException {
|
||||
if (nextFlowId == null) {
|
||||
nextFlowId = flowHandler.getFlowId();
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Starting a new execution of flow '" + nextFlowId + "'");
|
||||
}
|
||||
PortletExternalContext context = createPortletExternalContext(request, response);
|
||||
flowExecutor.launchExecution(nextFlowId, new LocalAttributeMap(outcome.getOutput().asMap()), context);
|
||||
return null;
|
||||
protected void defaultHandleExecutionOutcome(FlowExecutionOutcome outcome, FlowHandler flowHandler,
|
||||
ActionRequest request, ActionResponse response) throws PortletModeException {
|
||||
}
|
||||
|
||||
protected ModelAndView defaultHandleResumeFlowException(FlowHandler flowHandler, FlowException e,
|
||||
RenderRequest request, RenderResponse response) throws IOException {
|
||||
protected ModelAndView defaultHandleException(FlowHandler flowHandler, FlowException e, RenderRequest request,
|
||||
RenderResponse response) {
|
||||
if (e instanceof NoSuchFlowExecutionException) {
|
||||
String flowId = flowHandler.getFlowId();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Restarting a new execution of previously expired/ended flow '" + flowId + "'");
|
||||
logger.debug("Restarting a new execution of previously expired/ended flow '" + flowHandler.getFlowId()
|
||||
+ "'");
|
||||
}
|
||||
// by default, attempt to restart the flow
|
||||
PortletExternalContext context = createPortletExternalContext(request, response);
|
||||
flowExecutor.launchExecution(flowId, null, context);
|
||||
startFlow(flowHandler, null, request, response);
|
||||
return null;
|
||||
} else {
|
||||
throw e;
|
||||
@@ -174,12 +146,34 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen
|
||||
|
||||
// helpers
|
||||
|
||||
private ModelAndView startFlow(RenderRequest request, RenderResponse response, FlowHandler flowHandler)
|
||||
throws Exception {
|
||||
private ModelAndView handleException(FlowException e, FlowHandler flowHandler, RenderRequest request,
|
||||
RenderResponse response) {
|
||||
String viewName = flowHandler.handleException(e, request, response);
|
||||
if (viewName != null) {
|
||||
return new ModelAndView(viewName);
|
||||
} else {
|
||||
return defaultHandleException(flowHandler, e, request, response);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleFlowExecutionOutcome(FlowExecutionOutcome outcome, FlowHandler flowHandler,
|
||||
ActionRequest request, ActionResponse response) throws PortletModeException {
|
||||
boolean handled = flowHandler.handleExecutionOutcome(outcome, request, response);
|
||||
if (!handled) {
|
||||
defaultHandleExecutionOutcome(outcome, flowHandler, request, response);
|
||||
}
|
||||
}
|
||||
|
||||
private ModelAndView startFlow(FlowHandler flowHandler, RenderRequest request, RenderResponse response) {
|
||||
MutableAttributeMap input = flowHandler.createExecutionInputMap(request);
|
||||
if (input == null) {
|
||||
input = defaultFlowExecutionInputMap(request);
|
||||
input = defaultCreateFlowExecutionInputMap(request);
|
||||
}
|
||||
return startFlow(flowHandler, input, request, response);
|
||||
}
|
||||
|
||||
private ModelAndView startFlow(FlowHandler flowHandler, MutableAttributeMap input, RenderRequest request,
|
||||
RenderResponse response) {
|
||||
PortletExternalContext context = createPortletExternalContext(request, response);
|
||||
try {
|
||||
FlowExecutionResult result = flowExecutor.launchExecution(flowHandler.getFlowId(), input, context);
|
||||
@@ -188,12 +182,19 @@ public class FlowHandlerAdapter extends PortletApplicationObjectSupport implemen
|
||||
}
|
||||
return null;
|
||||
} catch (FlowException e) {
|
||||
ModelAndView mv = flowHandler.handleException(e, request, response);
|
||||
if (mv != null) {
|
||||
return mv;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
return handleException(e, flowHandler, request, response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ModelAndView resumeFlow(String flowExecutionKey, FlowHandler flowHandler, RenderRequest request,
|
||||
RenderResponse response) throws IOException {
|
||||
PortletExternalContext context = createPortletExternalContext(request, response);
|
||||
try {
|
||||
flowExecutor.resumeExecution(flowExecutionKey, context);
|
||||
return null;
|
||||
} catch (FlowException e) {
|
||||
return handleException(e, flowHandler, request, response);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.springframework.webflow.mvc.portlet;
|
||||
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletResponse;
|
||||
import javax.portlet.PortletSession;
|
||||
@@ -43,6 +44,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
private LocalAttributeMap flowInput = new LocalAttributeMap();
|
||||
private boolean handleException;
|
||||
private boolean handleExecutionOutcome;
|
||||
private boolean handleExecutionOutcomeCalled;
|
||||
|
||||
protected void setUp() {
|
||||
executor = (FlowExecutor) EasyMock.createMock(FlowExecutor.class);
|
||||
@@ -68,25 +70,27 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
controller.setApplicationContext(new StaticWebApplicationContext());
|
||||
controller.setPortletContext(portletContext);
|
||||
flowHandler = new FlowHandler() {
|
||||
public MutableAttributeMap createExecutionInputMap(PortletRequest request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getFlowId() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public ModelAndView handleException(FlowException e, RenderRequest request, RenderResponse response) {
|
||||
if (handleException) {
|
||||
return new ModelAndView("error");
|
||||
public MutableAttributeMap createExecutionInputMap(RenderRequest request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean handleExecutionOutcome(FlowExecutionOutcome outcome, ActionRequest request,
|
||||
ActionResponse response) {
|
||||
handleExecutionOutcomeCalled = true;
|
||||
if (handleExecutionOutcome) {
|
||||
return true;
|
||||
} else {
|
||||
return null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String handleFlowOutcome(FlowExecutionOutcome outcome, RenderRequest request, RenderResponse response) {
|
||||
if (handleExecutionOutcome) {
|
||||
return "home";
|
||||
public String handleException(FlowException e, RenderRequest request, RenderResponse response) {
|
||||
if (handleException) {
|
||||
return "error";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -144,7 +148,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
PortletSession session = renderRequest.getPortletSession();
|
||||
final FlowException flowException = new FlowException("Error") {
|
||||
};
|
||||
session.setAttribute("actionFlowException", flowException);
|
||||
session.setAttribute("actionRequestFlowException", flowException);
|
||||
try {
|
||||
controller.handleRender(renderRequest, renderResponse, flowHandler);
|
||||
fail("Should have thrown exception");
|
||||
@@ -161,28 +165,25 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
EasyMock.expectLastCall().andThrow(flowException);
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
controller.handleAction(actionRequest, actionResponse, flowHandler);
|
||||
assertNotNull(actionRequest.getPortletSession().getAttribute("actionFlowException"));
|
||||
assertNotNull(actionRequest.getPortletSession().getAttribute("actionRequestFlowException"));
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
Exception e = (Exception) actionRequest.getPortletSession().getAttribute("actionFlowException");
|
||||
Exception e = (Exception) actionRequest.getPortletSession().getAttribute("actionRequestFlowException");
|
||||
assertTrue(e instanceof NoSuchFlowExecutionException);
|
||||
}
|
||||
|
||||
public void testHandleFlowOutcomeCustomFlowHandler() throws Exception {
|
||||
handleExecutionOutcome = true;
|
||||
renderRequest.setContextPath("/springtravel");
|
||||
actionRequest.setContextPath("/springtravel");
|
||||
actionRequest.addParameter("execution", "12345");
|
||||
LocalAttributeMap output = new LocalAttributeMap();
|
||||
output.put("bar", "baz");
|
||||
FlowExecutionOutcome outcome = new FlowExecutionOutcome("finish", output);
|
||||
FlowExecutionResult result = FlowExecutionResult.createEndedResult("foo", outcome);
|
||||
PortletSession session = renderRequest.getPortletSession();
|
||||
session.setAttribute("flowExecutionResult", result);
|
||||
executor.launchExecution("home", output, renderContext);
|
||||
executor.resumeExecution("12345", actionContext);
|
||||
EasyMock.expectLastCall().andReturn(FlowExecutionResult.createEndedResult("bar", outcome));
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRender(renderRequest, renderResponse, flowHandler);
|
||||
assertNull(mv);
|
||||
controller.handleAction(actionRequest, actionResponse, flowHandler);
|
||||
assertTrue(handleExecutionOutcomeCalled);
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
|
||||
}
|
||||
|
||||
public void testHandleFlowExceptionCustomFlowHandler() throws Exception {
|
||||
@@ -195,6 +196,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
EasyMock.replay(new Object[] { executor });
|
||||
ModelAndView mv = controller.handleRender(renderRequest, renderResponse, flowHandler);
|
||||
assertNotNull(mv);
|
||||
assertEquals("error", mv.getViewName());
|
||||
EasyMock.verify(new Object[] { executor });
|
||||
}
|
||||
|
||||
@@ -203,7 +205,7 @@ public class FlowHandlerAdapterTests extends TestCase {
|
||||
PortletSession session = renderRequest.getPortletSession();
|
||||
final FlowException flowException = new FlowException("Error") {
|
||||
};
|
||||
session.setAttribute("actionFlowException", flowException);
|
||||
session.setAttribute("actionRequestFlowException", flowException);
|
||||
ModelAndView mv = controller.handleRender(renderRequest, renderResponse, flowHandler);
|
||||
assertEquals("error", mv.getViewName());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user