Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Exception Handling - how to use ExceptionResolver and @ExceptionHandler at the same time

I developed a web application where form validation exceptions are supposed to be handled by @ExceptionHandler (needs to be flexible) and general system exceptions by SimpleMappingExceptionResolver (doing stuff like email notification etc.).

Problem is, that if I use both, exceptions that are mapped for @ExceptionHandler don't get to the @ExceptionHandler but are grabbed by ExceptionResolver as defaultError.

Any idea what to do to make it work together ?

@ExceptionHandler(ValidatorException.class)
public String handleFormException(ValidatorException ex, ActionRequest actionRequest) {
    logger.error(ex.getMessage());
    //TODO make conditions
    return "mainOrderForm";
}

@ActionMapping(params = "action=addDocOrder")
public void addDocOrder(@ModelAttribute("order") CstOrderBeanImpl orderBean,
        BindingResult result, ActionRequest actionRequest, ActionResponse response) 
        throws PortalException, SystemException, ValidatorException {
    logger.info("Adding Form Order");
    Calendar cal = TimeUtils.getEuDeadLine(orderBean);
    orderBean.setDeadLine(cal.getTime());
    ValidatorException ve = validateService.validate(orderBean, result, actionRequest, validator);
    if (ve != null) throw ve;
(...)

In DispatcherPortlet, there is

catch (Exception ex) {
    // Trigger after-completion for thrown exception.
    triggerAfterActionCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
(...)

Which checks for interceptors, but none exists, so it does the default...

I just point out, that it's Portlet environment, there is usually less "views"...driven by parameters..

like image 865
lisak Avatar asked Oct 26 '25 08:10

lisak


2 Answers

Maybe as a workaround in ExceptionResolver you could dynamically invoke a handler method of your choice.

public ModelAndView resolveException(RenderRequest req, RenderResponse res, Object handler,Exception exc) {
    if(exc instanceof ValidatorException) {
        try {
            java.lang.reflect.Method m = handler.getClass().getMethod("someMethod", (Class<?>)null /* method parameters? */);
            m.invoke(handler,new Object[]{(ValidatorException)exc,req/*, res - maybe?*/});
        } catch(Exception e) {
            // Handle exception
        }
    }

    // Send email of the error etc..
}

It's not exactly an elegant solution, but should work..

like image 55
heikkim Avatar answered Oct 28 '25 23:10

heikkim


As soon as you put at least one Exception Resolver to the app-context DispatcherServlet stops instantiating default ones (AnnotationMethodHandlerExceptionResolver in your case).

Be sure to put both AnnotationMethodHandlerExceptionResolver and SimpleMappingExceptionResolver to the app-context and also impose their ordering.

See my post for detailed explanation.

like image 27
Ihor Kaharlichenko Avatar answered Oct 28 '25 23:10

Ihor Kaharlichenko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!