Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I have a parent class with an @ExceptionHandler and a subclass with it's own version. I am getting an ambiguous method error

The parent:

@ExceptionHandler(NoUserException.class)
protected ModelAndView handleException(NoUserException e) {
    Map<String, Object> model = new HashMap<String, Object>();

    model.put(ModelKeys.HOST_KEY, "message");

    return new ModelAndView("noAccess",model);
}

The child:

@ExceptionHandler(NoUserException.class)
protected void handleException(NoUserException e, HttpServletRequest request, HttpServletResponse response) throws IOException {
    logger.error("Invalid user.");
    respond(CLIENT_USER_ERROR,response);
}

Yes, I do need them to have different parameters and outputs.

like image 874
Nate Spector Avatar asked Jul 18 '12 16:07

Nate Spector


2 Answers

You can't have two methods with the same exception handler, sorry, it just isn't supported. The code that resolves them does not discern between super-subclasses and consider the subclass "more specific." The code is in org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver if you're interested. It would not be hard to make your own implementation of AbstractHandlerExceptionResolver based on that one that does consider a method directly on the controller a more specific result than an inherited method.

edit: personal comment, I have found over time it is better for me to suppress the urge to use "inheritance as templating tool" when making Spring MVC annotation driven controllers. View code is inherently clunky and procedural at times, this is why we make a separate "view layer" in the first place. An overly-micro approach to DRY and "re-use" does not avail you here. If it violates Liskov Substitution Principle, I don't do it. YMMV of course.

like image 152
Affe Avatar answered Oct 21 '22 22:10

Affe


Why not just delegate the implementation of handleException() to another method?

// superclass
protected ModelAndView handleExceptionImpl(
        NoUserException e,
        HttpServletResponse response) {
    Map<String, Object> model = new HashMap<String, Object>();
    model.put(ModelKeys.HOST_KEY, "message");
    return new ModelAndView("noAccess",model);
}

@ExceptionHandler(NoUserException.class)
protected ModelAndView handleException(
        NoUserException e,
        HttpServletResponse response) {
    return handleExceptionImpl(e, response);
}

// subclass
@Override
protected ModelAndView handleExceptionImpl(
        NoUserException e,
        HttpServletResponse response) {
    logger.error("Invalid user.");
    respond(CLIENT_USER_ERROR,response);
}
like image 36
candu Avatar answered Oct 21 '22 21:10

candu