Revision: 1361
http://stripes.svn.sourceforge.net/stripes/?rev=1361&view=rev
Author: bengunter
Date: 2010-11-29 20:59:48 +0000 (Mon, 29 Nov 2010)
Log Message:
-----------
A better fix for STS-780. ActionBeanContext throws SourcePageNotFoundException
by default and never returns ValidationErrorReportResolution.
DefaultExceptionHandler now has a handler for SourcePageNotFoundException that
does return ValidationErrorReportResolution. To disable the error report, a
developer can simply override the appropriate handle(..) method in their
exception handler.
Modified Paths:
--------------
branches/1.5.x/stripes/src/net/sourceforge/stripes/action/ActionBeanContext.java
branches/1.5.x/stripes/src/net/sourceforge/stripes/exception/DefaultExceptionHandler.java
Added Paths:
-----------
branches/1.5.x/stripes/src/net/sourceforge/stripes/action/ValidationErrorReportResolution.java
Modified:
branches/1.5.x/stripes/src/net/sourceforge/stripes/action/ActionBeanContext.java
===================================================================
---
branches/1.5.x/stripes/src/net/sourceforge/stripes/action/ActionBeanContext.java
2010-11-29 15:08:09 UTC (rev 1360)
+++
branches/1.5.x/stripes/src/net/sourceforge/stripes/action/ActionBeanContext.java
2010-11-29 20:59:48 UTC (rev 1361)
@@ -14,12 +14,9 @@
*/
package net.sourceforge.stripes.action;
-import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@@ -27,12 +24,8 @@
import net.sourceforge.stripes.controller.FlashScope;
import net.sourceforge.stripes.controller.StripesConstants;
-import net.sourceforge.stripes.controller.StripesFilter;
import net.sourceforge.stripes.exception.SourcePageNotFoundException;
-import net.sourceforge.stripes.tag.ErrorsTag;
import net.sourceforge.stripes.util.CryptoUtil;
-import net.sourceforge.stripes.util.Log;
-import net.sourceforge.stripes.validation.ValidationError;
import net.sourceforge.stripes.validation.ValidationErrors;
/**
@@ -226,10 +219,7 @@
public Resolution getSourcePageResolution() throws
SourcePageNotFoundException {
String sourcePage = getSourcePage();
if (sourcePage == null) {
- if (StripesFilter.getConfiguration().isDebugMode())
- return new ValidationErrorReportResolution(this);
- else
- throw new SourcePageNotFoundException(this);
+ throw new SourcePageNotFoundException(this);
}
else {
return new ForwardResolution(sourcePage);
@@ -267,90 +257,3 @@
"}";
}
}
-
-class ValidationErrorReportResolution implements Resolution {
- private static final Log log =
Log.getInstance(ValidationErrorReportResolution.class);
- private ActionBeanContext context;
-
- /** Construct a new instance to report validation errors in the specified
context. */
- protected ValidationErrorReportResolution(ActionBeanContext context) {
- this.context = context;
- }
-
- public void execute(HttpServletRequest request, HttpServletResponse
response) throws Exception {
- // log an exception for the stack trace
- SourcePageNotFoundException exception = new
SourcePageNotFoundException(this.context);
- log.error(exception);
-
- // start the HTML error report
- response.setContentType("text/html");
- PrintWriter writer = response.getWriter();
- writer.println("<html>");
- writer.println("<head><title>Stripes validation error
report</title></head>");
- writer.println("<body style=\"font-family: Arial, sans-serif;
font-size: 10pt;\">");
- writer.println("<h1>Stripes validation error report</h1><p>");
- writer.println(exception.getMessage());
- writer.println("</p><h2>Validation errors</h2><p>");
- sendErrors(request, response);
- writer.println("</p></body></html>");
- }
-
- protected void sendErrors(HttpServletRequest request, HttpServletResponse
response)
- throws Exception {
- // Output all errors in a standard format
- Locale locale = request.getLocale();
- ResourceBundle bundle = null;
-
- try {
- bundle =
StripesFilter.getConfiguration().getLocalizationBundleFactory()
- .getErrorMessageBundle(locale);
- }
- catch (MissingResourceException mre) {
- log.warn(getClass().getName(), " could not find the error messages
resource bundle. ",
- "As a result default headers/footers etc. will be used.
Check that ",
- "you have a StripesResources.properties in your classpath
(unless ",
- "of course you have configured a different bundle).");
- }
-
- // Fetch the header and footer
- String header = getResource(bundle, "header",
ErrorsTag.DEFAULT_HEADER);
- String footer = getResource(bundle, "footer",
ErrorsTag.DEFAULT_FOOTER);
- String openElement = getResource(bundle, "beforeError", "<li>");
- String closeElement = getResource(bundle, "afterError", "</li>");
-
- // Write out the error messages
- PrintWriter writer = response.getWriter();
- writer.write(header);
-
- for (List<ValidationError> list :
this.context.getValidationErrors().values()) {
- for (ValidationError fieldError : list) {
- writer.write(openElement);
- writer.write(fieldError.getMessage(locale));
- writer.write(closeElement);
- }
- }
-
- writer.write(footer);
- }
-
- /**
- * Utility method that is used to lookup the resources used for the errors
header,
- * footer, and the strings that go before and after each error.
- *
- * @param bundle the bundle to look up the resource from
- * @param name the name of the resource to lookup (prefixes will be added)
- * @param fallback a value to return if no resource can be found
- * @return the value to use for the named resource
- */
- protected String getResource(ResourceBundle bundle, String name, String
fallback) {
- if (bundle == null) {
- return fallback;
- }
-
- String resource;
- try { resource = bundle.getString("stripes.errors." + name); }
- catch (MissingResourceException mre) { resource = fallback; }
-
- return resource;
- }
-}
Added:
branches/1.5.x/stripes/src/net/sourceforge/stripes/action/ValidationErrorReportResolution.java
===================================================================
---
branches/1.5.x/stripes/src/net/sourceforge/stripes/action/ValidationErrorReportResolution.java
(rev 0)
+++
branches/1.5.x/stripes/src/net/sourceforge/stripes/action/ValidationErrorReportResolution.java
2010-11-29 20:59:48 UTC (rev 1361)
@@ -0,0 +1,141 @@
+/* Copyright 2010 Ben Gunter
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sourceforge.stripes.action;
+
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.sourceforge.stripes.controller.StripesFilter;
+import net.sourceforge.stripes.exception.SourcePageNotFoundException;
+import net.sourceforge.stripes.tag.ErrorsTag;
+import net.sourceforge.stripes.util.Log;
+import net.sourceforge.stripes.validation.ValidationError;
+
+/**
+ * A resolution that streams a simple HTML response to the client detailing
the validation errors
+ * that apply for an {...@link ActionBeanContext}.
+ *
+ * @author Ben Gunter
+ * @since Stripes 1.5.5
+ */
+public class ValidationErrorReportResolution implements Resolution {
+ private static final Log log =
Log.getInstance(ValidationErrorReportResolution.class);
+ private ActionBeanContext context;
+
+ /** Construct a new instance to report validation errors in the specified
context. */
+ public ValidationErrorReportResolution(ActionBeanContext context) {
+ this.context = context;
+ }
+
+ /** Get the action bean context on which the validation errors occurred. */
+ public ActionBeanContext getContext() {
+ return context;
+ }
+
+ public void execute(HttpServletRequest request, HttpServletResponse
response) throws Exception {
+ // log an exception for the stack trace
+ SourcePageNotFoundException exception = new
SourcePageNotFoundException(getContext());
+ log.error(exception);
+
+ // start the HTML error report
+ response.setContentType("text/html");
+ PrintWriter writer = response.getWriter();
+ writer.println("<html>");
+ writer.println("<head><title>Stripes validation error
report</title></head>");
+ writer.println("<body style=\"font-family: Arial, sans-serif;
font-size: 10pt;\">");
+ writer.println("<h1>Stripes validation error report</h1><p>");
+ writer.println(exception.getMessage());
+ writer.println("</p><h2>Validation errors</h2><p>");
+ sendErrors(request, response);
+ writer.println("</p></body></html>");
+ }
+
+ /**
+ * Called by {...@link #execute(HttpServletRequest, HttpServletResponse)}
to write the actual
+ * validation errors to the client. The {...@code header}, {...@code
footer}, {...@code beforeError} and
+ * {...@code afterError} resources are used by this method.
+ *
+ * @param request The servlet request.
+ * @param response The servlet response.
+ */
+ protected void sendErrors(HttpServletRequest request, HttpServletResponse
response)
+ throws Exception {
+ // Output all errors in a standard format
+ Locale locale = request.getLocale();
+ ResourceBundle bundle = null;
+
+ try {
+ bundle =
StripesFilter.getConfiguration().getLocalizationBundleFactory()
+ .getErrorMessageBundle(locale);
+ }
+ catch (MissingResourceException mre) {
+ log.warn(getClass().getName(), " could not find the error messages
resource bundle. ",
+ "As a result default headers/footers etc. will be used.
Check that ",
+ "you have a StripesResources.properties in your classpath
(unless ",
+ "of course you have configured a different bundle).");
+ }
+
+ // Fetch the header and footer
+ String header = getResource(bundle, "header",
ErrorsTag.DEFAULT_HEADER);
+ String footer = getResource(bundle, "footer",
ErrorsTag.DEFAULT_FOOTER);
+ String openElement = getResource(bundle, "beforeError", "<li>");
+ String closeElement = getResource(bundle, "afterError", "</li>");
+
+ // Write out the error messages
+ PrintWriter writer = response.getWriter();
+ writer.write(header);
+
+ for (List<ValidationError> list :
getContext().getValidationErrors().values()) {
+ for (ValidationError fieldError : list) {
+ writer.write(openElement);
+ writer.write(fieldError.getMessage(locale));
+ writer.write(closeElement);
+ }
+ }
+
+ writer.write(footer);
+ }
+
+ /**
+ * Utility method that is used to lookup the resources used for the error
header, footer, and
+ * the strings that go before and after each error.
+ *
+ * @param bundle the bundle to look up the resource from
+ * @param name the name of the resource to lookup (prefixes will be added)
+ * @param fallback a value to return if no resource can be found
+ * @return the value to use for the named resource
+ */
+ protected String getResource(ResourceBundle bundle, String name, String
fallback) {
+ if (bundle == null) {
+ return fallback;
+ }
+
+ String resource;
+ try {
+ resource = bundle.getString("stripes.errors." + name);
+ }
+ catch (MissingResourceException mre) {
+ resource = fallback;
+ }
+
+ return resource;
+ }
+}
Modified:
branches/1.5.x/stripes/src/net/sourceforge/stripes/exception/DefaultExceptionHandler.java
===================================================================
---
branches/1.5.x/stripes/src/net/sourceforge/stripes/exception/DefaultExceptionHandler.java
2010-11-29 15:08:09 UTC (rev 1360)
+++
branches/1.5.x/stripes/src/net/sourceforge/stripes/exception/DefaultExceptionHandler.java
2010-11-29 20:59:48 UTC (rev 1361)
@@ -33,6 +33,7 @@
import net.sourceforge.stripes.action.FileBean;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
+import net.sourceforge.stripes.action.ValidationErrorReportResolution;
import net.sourceforge.stripes.config.Configuration;
import net.sourceforge.stripes.controller.DispatcherHelper;
import net.sourceforge.stripes.controller.ExecutionContext;
@@ -145,6 +146,12 @@
if (resolution != null)
resolution.execute(request, response);
}
+ else if (throwable instanceof SourcePageNotFoundException) {
+ Resolution resolution = handle((SourcePageNotFoundException)
throwable, request,
+ response);
+ if (resolution != null)
+ resolution.execute(request, response);
+ }
else {
// If there's no sensible proxy, rethrow the original
throwable,
// NOT the unwrapped one since they may add extra information
@@ -163,6 +170,33 @@
/**
* <p>
+ * A default handler for {...@link SourcePageNotFoundException}. That
exception is thrown when
+ * validation errors occur on a request but the source page cannot be
determined from the
+ * request parameters. Such a condition generally arises during
application development when,
+ * for example, a parameter is accidentally omitted from a generated
hyperlink or AJAX request.
+ * </p>
+ * <p>
+ * In the past, it was very difficult to determine what validation errors
triggered the
+ * exception. This method returns a {...@link
ValidationErrorReportResolution}, which sends a
+ * simple HTML response to the client that very clearly details the
validation errors.
+ * </p>
+ * <p>
+ * In production, most applications will provide their own handler for
+ * {...@link SourcePageNotFoundException} by extending this class and
overriding this method.
+ * </p>
+ *
+ * @param exception The exception.
+ * @param request The servlet request.
+ * @param response The servlet response.
+ * @return A {...@link ValidationErrorReportResolution}
+ */
+ protected Resolution handle(SourcePageNotFoundException exception,
HttpServletRequest request,
+ HttpServletResponse response) throws Exception {
+ return new
ValidationErrorReportResolution(exception.getActionBeanContext());
+ }
+
+ /**
+ * <p>
* {...@link FileUploadLimitExceededException} is notoriously difficult to
handle for several
* reasons:
* <ul>
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Increase Visibility of Your 3D Game App & Earn a Chance To Win $500!
Tap into the largest installed PC base & get more eyes on your game by
optimizing for Intel(R) Graphics Technology. Get started today with the
Intel(R) Software Partner Program. Five $500 cash prizes are up for grabs.
http://p.sf.net/sfu/intelisp-dev2dev
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development