Skip to content

Commit 44cf4e2

Browse files
committed
SPR-5633 - Portlet-version of @ExceptionHandler
1 parent db487b6 commit 44cf4e2

File tree

5 files changed

+754
-182
lines changed

5 files changed

+754
-182
lines changed

org.springframework.web.portlet/src/main/java/org/springframework/web/portlet/DispatcherPortlet.properties

+2
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ org.springframework.web.portlet.HandlerMapping=org.springframework.web.portlet.m
77
org.springframework.web.portlet.HandlerAdapter=org.springframework.web.portlet.mvc.SimpleControllerHandlerAdapter,\
88
org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
99

10+
org.springframework.web.portlet.HandlerExceptionResolver=org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver
11+
1012
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/*
2+
* Copyright 2002-2009 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.web.portlet.handler;
18+
19+
import java.util.Set;
20+
import javax.portlet.PortletRequest;
21+
import javax.portlet.WindowState;
22+
import javax.portlet.RenderRequest;
23+
import javax.portlet.RenderResponse;
24+
import javax.portlet.ResourceRequest;
25+
import javax.portlet.ResourceResponse;
26+
import javax.portlet.MimeResponse;
27+
28+
import org.apache.commons.logging.Log;
29+
import org.apache.commons.logging.LogFactory;
30+
31+
import org.springframework.web.portlet.HandlerExceptionResolver;
32+
import org.springframework.web.portlet.ModelAndView;
33+
import org.springframework.core.Ordered;
34+
35+
/**
36+
* Abstract base class for {@link HandlerExceptionResolver} implementations. <p>Provides a set of mapped handlers that
37+
* the resolver should map to, and the {@link Ordered} implementation.
38+
*
39+
* @author Arjen Poutsma
40+
* @since 3.0
41+
*/
42+
public abstract class AbstractHandlerExceptionResolver implements HandlerExceptionResolver, Ordered {
43+
44+
/** Logger available to subclasses */
45+
protected final Log logger = LogFactory.getLog(getClass());
46+
47+
private int order = Ordered.LOWEST_PRECEDENCE;
48+
49+
private Set mappedHandlers;
50+
51+
private Class[] mappedHandlerClasses;
52+
53+
private Log warnLogger;
54+
55+
private boolean renderWhenMinimized = false;
56+
57+
public void setOrder(int order) {
58+
this.order = order;
59+
}
60+
61+
public int getOrder() {
62+
return this.order;
63+
}
64+
65+
/**
66+
* Specify the set of handlers that this exception resolver should map.
67+
* The exception mappings and the default error view will only apply
68+
* to the specified handlers.
69+
* <p>If no handlers set, both the exception mappings and the default error
70+
* view will apply to all handlers. This means that a specified default
71+
* error view will be used as fallback for all exceptions; any further
72+
* HandlerExceptionResolvers in the chain will be ignored in this case.
73+
*/
74+
public void setMappedHandlers(Set mappedHandlers) {
75+
this.mappedHandlers = mappedHandlers;
76+
}
77+
78+
/**
79+
* Specify the set of classes that this exception resolver should apply to.
80+
* The exception mappings and the default error view will only apply
81+
* to handlers of the specified type; the specified types may be interfaces
82+
* and superclasses of handlers as well.
83+
* <p>If no handlers and handler classes are set, the exception mappings
84+
* and the default error view will apply to all handlers. This means that
85+
* a specified default error view will be used as fallback for all exceptions;
86+
* any further HandlerExceptionResolvers in the chain will be ignored in
87+
* this case.
88+
*/
89+
public void setMappedHandlerClasses(Class[] mappedHandlerClasses) {
90+
this.mappedHandlerClasses = mappedHandlerClasses;
91+
}
92+
93+
/**
94+
* Set the log category for warn logging. The name will be passed to the
95+
* underlying logger implementation through Commons Logging, getting
96+
* interpreted as log category according to the logger's configuration.
97+
* <p>Default is no warn logging. Specify this setting to activate
98+
* warn logging into a specific category. Alternatively, override
99+
* the {@link #logException} method for custom logging.
100+
* @see org.apache.commons.logging.LogFactory#getLog(String)
101+
* @see org.apache.log4j.Logger#getLogger(String)
102+
* @see java.util.logging.Logger#getLogger(String)
103+
*/
104+
public void setWarnLogCategory(String loggerName) {
105+
this.warnLogger = LogFactory.getLog(loggerName);
106+
}
107+
108+
/**
109+
* Set if the resolver should render a view when the portlet is in
110+
* a minimized window. The default is "false".
111+
* @see javax.portlet.RenderRequest#getWindowState()
112+
* @see javax.portlet.WindowState#MINIMIZED
113+
*/
114+
public void setRenderWhenMinimized(boolean renderWhenMinimized) {
115+
this.renderWhenMinimized = renderWhenMinimized;
116+
}
117+
118+
/**
119+
* Checks whether this resolver is supposed to apply (i.e. the handler
120+
* matches in case of "mappedHandlers" having been specified), then
121+
* delegates to the {@link #doResolveException} template method.
122+
*/
123+
public ModelAndView resolveException(
124+
RenderRequest request, RenderResponse response, Object handler, Exception ex) {
125+
126+
if (shouldApplyTo(request, handler)) {
127+
return doResolveException(request, response, handler, ex);
128+
}
129+
else {
130+
return null;
131+
}
132+
}
133+
134+
public ModelAndView resolveException(
135+
ResourceRequest request, ResourceResponse response, Object handler, Exception ex) {
136+
137+
if (shouldApplyTo(request, handler)) {
138+
return doResolveException(request, response, handler, ex);
139+
}
140+
else {
141+
return null;
142+
}
143+
}
144+
145+
/**
146+
* Check whether this resolver is supposed to apply to the given handler.
147+
* <p>The default implementation checks against the specified mapped handlers
148+
* and handler classes, if any, and alspo checks the window state (according
149+
* to the "renderWhenMinimize" property).
150+
* @param request current portlet request
151+
* @param handler the executed handler, or <code>null</code> if none chosen at the
152+
* time of the exception (for example, if multipart resolution failed)
153+
* @return whether this resolved should proceed with resolving the exception
154+
* for the given request and handler
155+
* @see #setMappedHandlers
156+
* @see #setMappedHandlerClasses
157+
*/
158+
protected boolean shouldApplyTo(PortletRequest request, Object handler) {
159+
// If the portlet is minimized and we don't want to render then return null.
160+
if (WindowState.MINIMIZED.equals(request.getWindowState()) && !this.renderWhenMinimized) {
161+
return false;
162+
}
163+
// Check mapped handlers...
164+
if (handler != null) {
165+
if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) {
166+
return true;
167+
}
168+
if (this.mappedHandlerClasses != null) {
169+
for (Class mappedClass : this.mappedHandlerClasses) {
170+
if (mappedClass.isInstance(handler)) {
171+
return true;
172+
}
173+
}
174+
}
175+
}
176+
// Else only apply if there are no explicit handler mappings.
177+
return (this.mappedHandlers == null && this.mappedHandlerClasses == null);
178+
}
179+
180+
/**
181+
* Log the given exception at warn level, provided that warn logging has been
182+
* activated through the {@link #setWarnLogCategory "warnLogCategory"} property.
183+
* <p>Calls {@link #buildLogMessage} in order to determine the concrete message
184+
* to log. Always passes the full exception to the logger.
185+
* @param ex the exception that got thrown during handler execution
186+
* @param request current portlet request (useful for obtaining metadata)
187+
* @see #setWarnLogCategory
188+
* @see #buildLogMessage
189+
* @see org.apache.commons.logging.Log#warn(Object, Throwable)
190+
*/
191+
protected void logException(Exception ex, PortletRequest request) {
192+
if (this.warnLogger != null && this.warnLogger.isWarnEnabled()) {
193+
this.warnLogger.warn(buildLogMessage(ex, request), ex);
194+
}
195+
}
196+
197+
/**
198+
* Build a log message for the given exception, occured during processing
199+
* the given request.
200+
* @param ex the exception that got thrown during handler execution
201+
* @param request current portlet request (useful for obtaining metadata)
202+
* @return the log message to use
203+
*/
204+
protected String buildLogMessage(Exception ex, PortletRequest request) {
205+
return "Handler execution resulted in exception";
206+
}
207+
208+
/**
209+
* Actually resolve the given exception that got thrown during on handler execution,
210+
* returning a ModelAndView that represents a specific error page if appropriate.
211+
*
212+
* <p>Must be overridden in subclasses, in order to apply specific exception checks. Note that this template method
213+
* will be invoked <i>after</i> checking whether this resolved applies ("mappedHandlers" etc), so an implementation
214+
* may simply proceed with its actual exception handling.
215+
216+
* @param request current portlet request
217+
* @param response current portlet response
218+
* @param handler the executed handler, or null if none chosen at the time of
219+
* the exception (for example, if multipart resolution failed)
220+
* @param ex the exception that got thrown during handler execution
221+
* @return a corresponding ModelAndView to forward to, or null for default processing
222+
*/
223+
protected abstract ModelAndView doResolveException(PortletRequest request,
224+
MimeResponse response,
225+
Object handler,
226+
Exception ex);
227+
228+
}

0 commit comments

Comments
 (0)