- Revision
- 622
- Author
- mauro
- Date
- 2008-04-18 09:14:23 -0500 (Fri, 18 Apr 2008)
Log Message
WAFFLE-70: Action method invocation exceptions now handled via ErrorsContext. Added a failing runtime method to simple-example person controller to demostrate it's use.
Modified Paths
- trunk/.classpath
- trunk/examples/simple-example/src/main/java/org/codehaus/waffle/example/simple/action/PersonController.java
- trunk/examples/simple-example/src/main/webapp/person.jspx
- trunk/waffle-core/src/main/java/org/codehaus/waffle/monitor/AbstractWritingMonitor.java
- trunk/waffle-core/src/main/java/org/codehaus/waffle/monitor/ServletMonitor.java
- trunk/waffle-core/src/main/java/org/codehaus/waffle/servlet/WaffleServlet.java
- trunk/waffle-core/src/main/java/org/codehaus/waffle/validation/GlobalErrorMessage.java
- trunk/waffle-core/src/test/java/org/codehaus/waffle/servlet/WaffleServletTest.java
- trunk/waffle-core/src/test/java/org/codehaus/waffle/testmodel/StubMonitor.java
Diff
Modified: trunk/.classpath (621 => 622)
--- trunk/.classpath 2008-04-18 12:56:43 UTC (rev 621) +++ trunk/.classpath 2008-04-18 14:14:23 UTC (rev 622) @@ -35,6 +35,13 @@ <attribute name="maven.type" value="test"/> </attributes> </classpathentry> + <classpathentry kind="src" output="target-eclipse/classes" path="examples/simple-example/src/main/java"/> + <classpathentry kind="src" output="target-eclipse/classes" path="examples/simple-example/src/main/webapp"/> + <classpathentry kind="src" output="target-eclipse/test-classes" path="examples/simple-example/src/test/java"> + <attributes> + <attribute name="maven.type" value="test"/> + </attributes> + </classpathentry> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER/modules/profiles[examples,integration]"/> <classpathentry kind="output" path="target-eclipse/classes"/>
Modified: trunk/examples/simple-example/src/main/java/org/codehaus/waffle/example/simple/action/PersonController.java (621 => 622)
--- trunk/examples/simple-example/src/main/java/org/codehaus/waffle/example/simple/action/PersonController.java 2008-04-18 12:56:43 UTC (rev 621) +++ trunk/examples/simple-example/src/main/java/org/codehaus/waffle/example/simple/action/PersonController.java 2008-04-18 14:14:23 UTC (rev 622) @@ -37,6 +37,10 @@ person = null; } + public void fail(){ + throw new RuntimeException("I'm a failing method"); + } + public Person getPerson() { return person; } @@ -44,5 +48,5 @@ public void setPerson(Person person) { this.person = person; } - + }
Modified: trunk/examples/simple-example/src/main/webapp/person.jspx (621 => 622)
--- trunk/examples/simple-example/src/main/webapp/person.jspx 2008-04-18 12:56:43 UTC (rev 621) +++ trunk/examples/simple-example/src/main/webapp/person.jspx 2008-04-18 14:14:23 UTC (rev 622) @@ -27,6 +27,16 @@ <h3>Waffle example: Select Person</h3> + <c:if test="${errors.errorMessageCount > 0}"> + <div class="errors"> + <c:forEach var="error" items="${errors.allErrorMessages}"> + <div class="error"> + ${error.message} + </div> + </c:forEach> + </div> + </c:if> + <table> <tr> <th>Id</th> @@ -48,7 +58,8 @@ </c:forEach> </table> - <a href="" + <a href="" or + <a href="" to see a failing call</a> <!-- Example of partial page --> <div id="editArea">
Modified: trunk/waffle-core/src/main/java/org/codehaus/waffle/monitor/AbstractWritingMonitor.java (621 => 622)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/monitor/AbstractWritingMonitor.java 2008-04-18 12:56:43 UTC (rev 621) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/monitor/AbstractWritingMonitor.java 2008-04-18 14:14:23 UTC (rev 622) @@ -91,7 +91,7 @@ levels.put("componentRegistered", DEBUG); levels.put("instanceRegistered", DEBUG); levels.put("nonCachingComponentRegistered", DEBUG); - levels.put("servletServiceFailed", WARN); + levels.put("actionMethodInvocationFailed", WARN); levels.put("servletServiceRequested", DEBUG); levels.put("controllerValidatorNotFound", WARN); levels.put("methodDefinitionNotFound", WARN); @@ -144,7 +144,7 @@ messages.put("componentRegistered", "Registered component of type ''{1}'' with key ''{0}'' and parameters ''{2}''"); messages.put("instanceRegistered", "Registered instance ''{1}'' with key ''{0}''"); messages.put("nonCachingComponentRegistered", "Registered non-caching component of type ''{1}'' with key ''{0}'' and parameters ''{2}''"); - messages.put("servletServiceFailed", "Servlet service failed: {0}"); + messages.put("actionMethodInvocationFailed", "ActionMethod invocation failed: {0}"); messages.put("servletServiceRequested", "Servlet service requested with parameters: {0}"); messages.put("controllerValidatorNotFound", "Controller validator ''{0}'' not found: defaulting to controller ''{1}''"); messages.put("methodDefinitionNotFound", "Method definition not found in controller definition ''{0}''"); @@ -323,8 +323,8 @@ write("nonCachingComponentRegistered", key, type, asList(parameters)); } - public void servletServiceFailed(Exception cause){ - write("servletServiceFailed", cause); + public void actionMethodInvocationFailed(Exception cause){ + write("actionMethodInvocationFailed", cause); } public void servletServiceRequested(Map<String, List<String>> parameters){
Modified: trunk/waffle-core/src/main/java/org/codehaus/waffle/monitor/ServletMonitor.java (621 => 622)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/monitor/ServletMonitor.java 2008-04-18 12:56:43 UTC (rev 621) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/monitor/ServletMonitor.java 2008-04-18 14:14:23 UTC (rev 622) @@ -21,7 +21,7 @@ */ public interface ServletMonitor extends Monitor { - void servletServiceFailed(Exception cause); + void actionMethodInvocationFailed(Exception cause); void servletServiceRequested(Map<String, List<String>> parameters);
Modified: trunk/waffle-core/src/main/java/org/codehaus/waffle/servlet/WaffleServlet.java (621 => 622)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/servlet/WaffleServlet.java 2008-04-18 12:56:43 UTC (rev 621) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/servlet/WaffleServlet.java 2008-04-18 14:14:23 UTC (rev 622) @@ -41,6 +41,7 @@ import org.codehaus.waffle.controller.ControllerDefinitionFactory; import org.codehaus.waffle.monitor.ServletMonitor; import org.codehaus.waffle.validation.ErrorsContext; +import org.codehaus.waffle.validation.GlobalErrorMessage; import org.codehaus.waffle.validation.Validator; import org.codehaus.waffle.view.RedirectView; import org.codehaus.waffle.view.View; @@ -57,7 +58,6 @@ private static final String DEFAULT_VIEW_SUFFIX = ".jspx"; private static final String DEFAULT_VIEW_PREFIX = "/"; private static final String EMPTY = ""; - private static final String ERROR = "ERROR: "; private static final String POST = "POST"; private ActionMethodExecutor actionMethodExecutor; private ActionMethodResponseHandler actionMethodResponseHandler; @@ -169,12 +169,12 @@ dataBinder.bind(request, response, errorsContext, controllerDefinition.getController()); validator.validate(controllerDefinition, errorsContext); + ActionMethodResponse actionMethodResponse = new ActionMethodResponse(); + View view = null; + try { - ActionMethodResponse actionMethodResponse = new ActionMethodResponse(); - MethodDefinition methodDefinition = controllerDefinition.getMethodDefinition(); - View view = null; - if (errorsContext.hasErrorMessages() || methodDefinition == null) { + if (errorsContext.hasErrorMessages() || noMethodDefinition(controllerDefinition)) { view = buildReferringView(controllerDefinition); } else { actionMethodExecutor.execute(actionMethodResponse, controllerDefinition); @@ -185,7 +185,7 @@ // Null or VOID indicate a Waffle convention (return to referring page) // unless PRG is disabled if (request.getMethod().equalsIgnoreCase(POST)) { - if ( usePRG(methodDefinition) ){ + if ( usePRG(controllerDefinition.getMethodDefinition()) ){ // PRG (Post/Redirect/Get): see http://en.wikipedia.org/wiki/Post/Redirect/Get view = buildRedirectingView(request, controllerDefinition); } else { @@ -198,20 +198,25 @@ } } - if (view != null) { - actionMethodResponse.setReturnValue(view); - } + } catch (ActionMethodInvocationException e) { + errorsContext.addErrorMessage(new GlobalErrorMessage("Action method invocation failed: "+e.getMessage(), e)); + view = buildReferringView(controllerDefinition); + servletMonitor.actionMethodInvocationFailed(e); + } + + if (view != null) { + actionMethodResponse.setReturnValue(view); + } - requestAttributeBinder.bind(request, controllerDefinition.getController()); - actionMethodResponseHandler.handle(request, response, actionMethodResponse); + requestAttributeBinder.bind(request, controllerDefinition.getController()); + actionMethodResponseHandler.handle(request, response, actionMethodResponse); - } catch (ActionMethodInvocationException e) { - servletMonitor.servletServiceFailed(e); - log(ERROR + e.getMessage()); - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); - } } + private boolean noMethodDefinition(ControllerDefinition controllerDefinition) { + return controllerDefinition.getMethodDefinition() == null; + } + @SuppressWarnings("unchecked") private Map<String, List<String>> parametersOf(HttpServletRequest request) { Map<String, List<String>> parameters = new HashMap<String, List<String>>();
Modified: trunk/waffle-core/src/main/java/org/codehaus/waffle/validation/GlobalErrorMessage.java (621 => 622)
--- trunk/waffle-core/src/main/java/org/codehaus/waffle/validation/GlobalErrorMessage.java 2008-04-18 12:56:43 UTC (rev 621) +++ trunk/waffle-core/src/main/java/org/codehaus/waffle/validation/GlobalErrorMessage.java 2008-04-18 14:14:23 UTC (rev 622) @@ -10,6 +10,7 @@ *****************************************************************************/ package org.codehaus.waffle.validation; + /** * ErrorMessage associated to global validations. * @@ -17,9 +18,15 @@ */ public class GlobalErrorMessage implements ErrorMessage { private String message; + private Throwable cause; public GlobalErrorMessage(String message) { + this(message, null); + } + + public GlobalErrorMessage(String message, Throwable cause) { this.message = message; + this.cause = cause; } public Type getType() { @@ -29,5 +36,9 @@ public String getMessage() { return message; } + + public Throwable getCause(){ + return cause; + } }
Modified: trunk/waffle-core/src/test/java/org/codehaus/waffle/servlet/WaffleServletTest.java (621 => 622)
--- trunk/waffle-core/src/test/java/org/codehaus/waffle/servlet/WaffleServletTest.java 2008-04-18 12:56:43 UTC (rev 621) +++ trunk/waffle-core/src/test/java/org/codehaus/waffle/servlet/WaffleServletTest.java 2008-04-18 14:14:23 UTC (rev 622) @@ -49,6 +49,7 @@ import org.codehaus.waffle.i18n.MessagesContext; import org.codehaus.waffle.monitor.ServletMonitor; import org.codehaus.waffle.monitor.SilentMonitor; +import org.codehaus.waffle.validation.ErrorMessage; import org.codehaus.waffle.validation.ErrorsContext; import org.codehaus.waffle.validation.Validator; import org.codehaus.waffle.view.View; @@ -390,7 +391,7 @@ one(validator).validate(with(any(ControllerDefinition.class)), with(any(ErrorsContext.class))); }}); - // Mock + // Mock RequestAttributeBinder final RequestAttributeBinder requestAttributeBinder = mockery.mock(RequestAttributeBinder.class); mockery.checking(new Expectations() {{ one(requestAttributeBinder).bind(with(same(request)), with(any(NonDispatchingController.class))); @@ -422,7 +423,7 @@ @SuppressWarnings({"serial", "unchecked"}) @Test - public void canThrowExceptionInMethodInvocation() throws Exception { + public void canHandleExceptionsInMethodInvocation() throws Exception { // Mock ErrorsContext final ErrorsContext errorsContext = mockery.mock(ErrorsContext.class); final ContextContainer contextContainer = mockery.mock(ContextContainer.class); @@ -432,6 +433,7 @@ will(returnValue(errorsContext)); one(errorsContext).hasErrorMessages(); will(returnValue(false)); + one(errorsContext).addErrorMessage(with(any(ErrorMessage.class))); } }); @@ -450,23 +452,47 @@ atLeast(1).of(request).getParameterNames(); will(returnValue(enumeration)); }}); - + // Mock HttpServletResponse final HttpServletResponse response = mockery.mock(HttpServletResponse.class); + + // MethodDefinition + Method method = NonDispatchingController.class.getMethod("increment"); + final MethodDefinition methodDefinition = new MethodDefinition(method); + + // Mock ActionMethodResponseHandler + final ActionMethodResponseHandler actionMethodResponseHandler = mockery.mock(ActionMethodResponseHandler.class); mockery.checking(new Expectations() {{ - one(response).sendError(with(equal(HttpServletResponse.SC_INTERNAL_SERVER_ERROR)), with(any(String.class))); + one(actionMethodResponseHandler).handle(with(same(request)), with(same(response)), with(any(ActionMethodResponse.class))); }}); + // Mock Validator + final Validator validator = mockery.mock(Validator.class); + mockery.checking(new Expectations() {{ + allowing(validator).validate(with(any(ControllerDefinition.class)), with(any(ErrorsContext.class))); + }}); + + // Mock RequestAttributeBinder + final RequestAttributeBinder requestAttributeBinder = mockery.mock(RequestAttributeBinder.class); + mockery.checking(new Expectations() {{ + one(requestAttributeBinder).bind(with(same(request)), with(any(NonDispatchingController.class))); + }}); + // stub out what we don't want called ... execute it - WaffleServlet servlet = new WaffleServlet() { + WaffleServlet servlet = new WaffleServlet(null, + actionMethodResponseHandler, + new SilentMonitor(), + new OgnlDataBinder(new OgnlValueConverterFinder(), null, new SilentMonitor()), + requestAttributeBinder, + null, validator) { @Override protected ControllerDefinition getControllerDefinition(HttpServletRequest request, HttpServletResponse response) { - return new ControllerDefinition("no name", nonDispatchingController, new MethodDefinition(null)); - } + return new ControllerDefinition("no name", nonDispatchingController, methodDefinition); + } @Override public ServletConfig getServletConfig() { return servletConfig; - } + } @Override public void log(String string) { // ignore @@ -485,15 +511,9 @@ final ServletMonitor servletMonitor = mockery.mock(ServletMonitor.class); mockery.checking(new Expectations() {{ allowing(servletMonitor).servletServiceRequested(with(any(Map.class))); - allowing(servletMonitor).servletServiceFailed(actionMethodInvocationException); + allowing(servletMonitor).actionMethodInvocationFailed(actionMethodInvocationException); }}); - // Mock Validator - final Validator validator = mockery.mock(Validator.class); - mockery.checking(new Expectations() {{ - one(validator).validate(with(any(ControllerDefinition.class)), with(any(ErrorsContext.class))); - }}); - // Set up what normally would happen via "init()" Field dataBinderField = WaffleServlet.class.getDeclaredField("dataBinder"); dataBinderField.setAccessible(true); @@ -507,10 +527,6 @@ servletMonitorField.setAccessible(true); servletMonitorField.set(servlet, servletMonitor); - Field validatorFactoryField = WaffleServlet.class.getDeclaredField("validator"); - validatorFactoryField.setAccessible(true); - validatorFactoryField.set(servlet, validator); - servlet.service(request, response); }
Modified: trunk/waffle-core/src/test/java/org/codehaus/waffle/testmodel/StubMonitor.java (621 => 622)
--- trunk/waffle-core/src/test/java/org/codehaus/waffle/testmodel/StubMonitor.java 2008-04-18 12:56:43 UTC (rev 621) +++ trunk/waffle-core/src/test/java/org/codehaus/waffle/testmodel/StubMonitor.java 2008-04-18 14:14:23 UTC (rev 622) @@ -119,7 +119,7 @@ public void nonCachingComponentRegistered(Object key, Class<?> clazz, Object[] parameters) { } - public void servletServiceFailed(Exception cause) { + public void actionMethodInvocationFailed(Exception cause) { } public void servletServiceRequested(Map<String, List<String>> parameters) {
To unsubscribe from this list please visit:
