ive set up a simple exception handler in my spring 2.5 app. Currently it catches all Exception
s and shows a stacktrace page.
this is well and good, but now spring security does not properly kick the non-logged in user to the login page, instead my exception page is shown with the spring security exception:
org.springframework.security.AccessDeniedException
The problem is that this application doesnt have its own Exception subclass that it uses for all its Exceptions, so i must map Exception
but unmap AccessDeniedException
is this possible in spring 2.5?
edit: with spring security 2.0.1
my bean looks like this
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.RuntimeException">common/error</prop>
</props>
</property>
</bean>**
The only exception that cannot be caught directly is (a framework thrown) StackOverflowException. This makes sense, logically, as you don't have the space in the stack to handle the exception at that point.
The order of catch statements is important. Put catch blocks targeted to specific exceptions before a general exception catch block or the compiler might issue an error. The proper catch block is determined by matching the type of the exception to the name of the exception specified in the catch block.
Altogether, the most common implementation is to use @ExceptionHandler on methods of @ControllerAdvice classes so that the Spring Boot exception handling will be applied globally or to a subset of controllers. ControllerAdvice is an annotation in Spring and, as the name suggests, is “advice” for multiple controllers.
Global Exception Handler - Exception Handling is a cross-cutting concern, it should be done for all the pointcuts in our application. We have already looked into Spring AOP and that's why Spring provides @ControllerAdvice annotation that we can use with any class to define our global exception handler.
One way to handle this is to create another handler implementing the org.springframework.web.servlet.HandlerExceptionResolver and org.springframework.core.Ordered -interfaces. In your own implementation, you do something like the following:
public class AccessDeniedExceptionResolver implements HandlerExceptionResolver, Ordered
{
private int order;
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception)
{
if(exception instanceof AccessDeniedException)
{
return new ModelAndView("redirect:/login"); //Replace with redirect to your login-page
}
return null; //Null-return = pass the exception to next handler in order
}
public void setOrder(int order)
{
this.order = order;
}
@Override
public int getOrder()
{
return order;
}
}
Now, the Ordered-interface implementation allows you to tell the order the exception handlers are invoked in. The SimpleMappingExceptionResolver implements the Ordered interface also, so you could do something like following in your bean-definitions:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.RuntimeException">common/error</prop>
</props>
</property>
<property name="order" value="1"/>
</bean>
<bean class="package.to.your.handler.AccessDeniedExceptionResolver">
<property name="order" value="0"/>
</bean>
The bean with the LOWER order-value has HIGHER priority (meaning it will be invoked BEFORE the ones with larger values, in this case AccessDeniedExceptionResolver is invoked before SimpleMappingExceptionResolver.
Hope this helped.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With