ams
ams

Reputation: 62632

How to configure which controllers Spring @ControllerAdvice will be applied to?

I have two types of controllers in my spring application.

Both the API and View controllers are part of the same spring dispatcher servlet. Spring 3.2 introduced the @ControllerAdvice annotation to allow for a global location to handle exception.

The documentation implies that @ControllerAdvice will be applied to every controller associated with a Dispatcher Servlet.

Is there a way to configure which controllers @ControllerAdvice will apply to?

For example in my scenario I want a @ControllerAdvice for my View Controllers and separate @ControllerAdvice for my API controllers.

Upvotes: 13

Views: 15307

Answers (5)

Supun Wijerathne
Supun Wijerathne

Reputation: 12938

UPDATE

I am using spring 4. You can do one of 2 below options.

(1) You can add the packages you want. (Inside those packages you have controllers that you want to follow @ControllerAdvice).

Ex:

@ControllerAdvice(basePackages={"my.pkg.a", "my.pkg.b"})

(2) You can directly add the controller classes you want.

Ex:

@ControllerAdvice(basePackageClasses={MyControllerA.class, MyControllerB.class})

Upvotes: 8

Adam from WALCZAK.IT
Adam from WALCZAK.IT

Reputation: 1316

For people that will still find this question:

As from Spring 4 ControlerAdvice's can be limited to Controler's with the specified annotations. Take a look at:

http://blog.codeleak.pl/2013/11/controlleradvice-improvements-in-spring.html

(second half of this article) for more details.

Upvotes: 8

John Strickler
John Strickler

Reputation: 25421

Your exceptions should not dictate the content-type of your response. Instead check the request's Accept header for what the browser expects.

@ExceptionHandler(Throwable.class)
public @ResponseBody String handleThrowable(HttpServletRequest request, HttpServletResponse response, Throwable ex) throws IOException {

...

String header = request.getHeader("Accept");

if(supportsJsonResponse(header)) {

    //return response as JSON
    response.setContentType(JSON_MEDIA_TYPE.toString());

    return Json.stringify(responseMap);

} else {
    //return as HTML
    response.setContentType("text/html");
}

Upvotes: 3

rdm
rdm

Reputation: 330

@ExceptionHandler(value=Exception.class)    
    public ModelAndView error(Exception ex) {                                
        return new ModelAndView("redirect:/error/m");                
    }

...//ErrorController

@RequestMapping(value = "/m", produces="text/html")
public ModelAndView error()...

@RequestMapping(value = "/m", produces="application/json")
@ResponseBody
public Map errorJson()...

Upvotes: 1

krishnakumarp
krishnakumarp

Reputation: 9295

I do not think this is possible now. If you can make the API and View controllers throw different Exception types, then you could define two different @ExceptionHandlers and achieve what you want.

// For handling API Exceptions
@ExceptionHandler(APIException.class)  // Single API Exception 
@ExceptionHandler({APIException.class, ..., ,,,}) // Multiple API Exceptions

// For handling View Exceptions
@ExceptionHandler(ViewException.class) // Single View Exception
@ExceptionHandler({ViewException.class, ..., ...}) // Multiple View Exceptions

You could use aop to translate the Exceptions coming out of APIs to a standard APIException. See this thread on spring forums.

Hope it helps.

Upvotes: 3

Related Questions