Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of @ExceptionHandler

I use @ControllerAdvice to handle all my app exceptions :

@ControllerAdvice
public class ExceptionHandlingController {

  @ExceptionHandler({UnauthorizedException.class})
  public String unauthorizedException()  {
        .........
  }


  @ExceptionHandler({UnauthorizedAjaxException.class})
  @ResponseBody
  public void unauthorizedAjaxException()  {
        .........
  }

  @ExceptionHandler({Exception.class})
  public String globalException(){
        .........
  }


}

And somewhere in my code i do throw new UnauthorizedException();

   @Around("@annotation(Authenticated)")
   public Object profilingAuthentication(ProceedingJoinPoint pjp) throws Throwable  {

       HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();

       if( request.getSession().getAttribute("idContact") == null ) {
            if( "XMLHttpRequest".equals(request.getHeader("X-Requested-With")) )
                throw new UnauthorizedAjaxException();
            throw new UnauthorizedException();
       } 
       return pjp.proceed();
   }

But sadly Spring MVC appears to be acting random by using the most generic case (Exception) rather than more specific ones (UnauthorizedException for example). And sometimes he choose the correct one !

How the order works works ? and is there any way to specify the order ?

UnauthorizedException is a custom exception

public class UnauthorizedException extends Exception {

    public UnauthorizedException(){
        super();
    }

    public UnauthorizedException(String message){
        super(message);
    }
}

UPDATE

i found out that the order it's not rondom actually the methods who throw UnauthorizedException works normally but the others not !

@Authenticated
@RequestMapping(value="/favoris") 
public String favoris(ModelMap model, HttpServletRequest request) 
      throws UnauthorizedException {
    ....
}

@Authenticated
@RequestMapping(value="/follow") 
public String follow(ModelMap model, HttpServletRequest request) {
    .....
}

So i have to add throws UnauthorizedException manually or there is some other solution ?

like image 540
Hayi Avatar asked Jul 19 '16 15:07

Hayi


People also ask

Can we have more than one controller advice?

Spring can process controller advice classes in any order unless we have annotated it with the @Order annotation. So, be mindful when you write a catch-all handler if you have more than one controller advice. Especially when you have not specified basePackages or annotations in the annotation.

What is @ExceptionHandler?

An exception handler is code that stipulates what a program will do when an anomalous event disrupts the normal flow of that program's instructions. An exception, in a computer context, is an unplanned event that occurs while a program is executing and disrupts the flow of its instructions.

What is the difference between ControllerAdvice and RestControllerAdvice?

The differences between @RestControllerAdvice and @ControllerAdvice is : @RestControllerAdvice = @ControllerAdvice + @ResponseBody . - we can use in REST web services. @ControllerAdvice - We can use in both MVC and Rest web services, need to provide the ResponseBody if we use this in Rest web services.

What is the use of ResponseEntityExceptionHandler?

Class ResponseEntityExceptionHandler. A convenient base class for @ControllerAdvice classes that wish to provide centralized exception handling across all @RequestMapping methods through @ExceptionHandler methods.


1 Answers

we are using exception handler in following way and never order get mixed and it work as expected. So it could be possible if you will use it as following example then it will solve your problems

**********handler class******************

@ControllerAdvice
public class GlobalExceptionHandler {

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(value = Exception.class)
    public boolean handle1(Exception exc) {
        System.out.println("#####Global Exception###" + exc);
        exc.printStackTrace(System.out);
        return true;
    }

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(value = CustomException.class)
    public boolean handle2(CustomException exc) {
        System.out.println("###custom exception######" + exc);
        exc.printStackTrace(System.out);
        return true;
    }
}

***************Controller class************

@RestController("test")
@RequestMapping("/test1")
public class TestController {

    @RequestMapping("/t1")
    public boolean test() {
        if (true) {
            throw new CustomException();
        }
        return true;
    }
}

In above example exception habdler is handle2 because 1st of all it will search for matching exception if not found then go for parrent handler

If we throw new NullPointerException() then it will search for matching handler but not found in this case then go for parrent that is handle1

for more you can refer here

I hope it will help you. Thanks

like image 145
sanjeevjha Avatar answered Oct 09 '22 01:10

sanjeevjha