12

For some hours I'm trying to create a custom global error handler in Spring Boot/MVC. I've read a lot of articles and nothing.

That is my error class:

I tried create a class like that

@Controller
public class ErrorPagesController {

    @RequestMapping("/404")
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String notFound() {
        return "/error/404";
    }

    @RequestMapping("/403")
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public String forbidden() {
        return "/error/403";
    }

    @RequestMapping("/500")
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public String internalServerError() {
        return "/error/500";
    }

}
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Ismael Ezequiel
  • 174
  • 1
  • 1
  • 12

5 Answers5

8

Additional to @Arash You could add a new BaseController class that you can extends,that handles the conversion from exception to http response.

     import com.alexfrndz.pojo.ErrorResponse;
     import com.alexfrndz.pojo.Error;
     import com.alexfrndz.pojo.exceptions.NotFoundException;
     import org.springframework.http.HttpStatus;
     import org.springframework.http.ResponseEntity;
     import org.springframework.web.bind.annotation.ExceptionHandler;
     import org.springframework.web.bind.annotation.ResponseBody;
     import org.springframework.web.bind.annotation.ResponseStatus;

     import javax.persistence.NoResultException;
     import javax.servlet.http.HttpServletRequest;
     import java.util.List;

     @Slf4j
     public class BaseController {

    @ExceptionHandler(NoResultException.class)
    public ResponseEntity<Exception> handleNoResultException(
            NoResultException nre) {
        log.error("> handleNoResultException");
        log.error("- NoResultException: ", nre);
        log.error("< handleNoResultException");
        return new ResponseEntity<Exception>(HttpStatus.NOT_FOUND);
    }


    @ExceptionHandler(Exception.class)
    public ResponseEntity<Exception> handleException(Exception e) {
        log.error("> handleException");
        log.error("- Exception: ", e);
        log.error("< handleException");
        return new ResponseEntity<Exception>(e,
                HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(NotFoundException.class)
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    @ResponseBody
    public ErrorResponse handleNotFoundError(HttpServletRequest req, NotFoundException exception) {
        List<Error> errors = Lists.newArrayList();
        errors.add(new Error(String.valueOf(exception.getCode()), exception.getMessage()));
        return new ErrorResponse(errors);
    }
   }
Community
  • 1
  • 1
Alex Fernandez
  • 1,892
  • 14
  • 17
8

You may try the following code:

@ControllerAdvice
public class ExceptionController {
    @ExceptionHandler(Exception.class)
    public ModelAndView handleError(HttpServletRequest request, Exception e)   {
        Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Request: " + request.getRequestURL() + " raised " + e);
        return new ModelAndView("error");
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public ModelAndView handleError404(HttpServletRequest request, Exception e)   {
        Logger.getLogger(getClass().getName()).log(Level.SEVERE, "Request: " + request.getRequestURL() + " raised " + e);
        return new ModelAndView("404");
    }
}
  • 3
    This gives me an `Ambiguous @ExceptionHandler method mapped for [class org.springframework.web.servlet.NoHandlerFoundException]` exception. It seems like Spring cannot decide which method to choose for `NoHandlerFoundException`, because both `ExceptionHandler` annotations match... – slartidan May 14 '19 at 09:24
6

Update for spring boot

Custom error pages

If you want to display a custom HTML error page for a given status code, you add a file to an /error folder. Error pages can either be static HTML (i.e. added under any of the static resource folders) or built using templates. The name of the file should be the exact status code or a series mask.

For example, to map 404 to a static HTML file, your folder structure would look like this

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

Source

Eduardo
  • 2,070
  • 21
  • 26
4
@ControllerAdvice
 public class ErrorHandler {

public RestErrorHandler() {
}

@ExceptionHandler(YourException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public XXX processException(Exception ex){}

You need a class like this. Add a method for each exception, and annotate it as you please - @ResponseBody etc.

xav
  • 5,452
  • 7
  • 48
  • 57
Arash
  • 11,697
  • 14
  • 54
  • 81
2

Hope this will help: Create a class say: NoProductsFoundException that extends runtimexception.

    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.annotation.ResponseStatus;

    @ResponseStatus(value=HttpStatus.NOT_FOUND, reason="No products found under this category")
    public class NoProductsFoundException extends RuntimeException{

    private static final long serialVersionUID =3935230281455340039L;
    }

Then in your productcontroller:

    @RequestMapping("/{category}")
    public String getProductsByCategory(Model
    model,@PathVariable("category") String category) {

   List<Product> products = productService.getProductsByCategory(category);

   if (products == null || products.isEmpty()) {
   throw new NoProductsFoundException ();
   }
   model.addAttribute("products", products);
   return "products";
}

enter image description here

AchillesVan
  • 4,156
  • 3
  • 35
  • 47
  • Thanks for the answers, but what I need is to create a custom and global error handler for each type of error like 404, 403, 500 etc, for example: When I go to - localhost:8080/anything I receive 404 error or when some internal error occurs throw 500 error. Understood? – Ismael Ezequiel Aug 04 '16 at 22:10
  • yes, i know wat you want. My example is just a "skeleton". If you have some basic Java EE or Spring mvc knowledge you should find your to figure out the rest. – AchillesVan Aug 04 '16 at 22:14
  • or http://stackoverflow.com/questions/23580509/how-to-write-a-proper-global-error-handler-with-spring-mvc-spring-boot?rq=1 – AchillesVan Aug 04 '16 at 22:16
  • here a good example: http://stackoverflow.com/questions/27386261/spring-boot-custom-404-page-with-standalone-tomcat?rq=1 – AchillesVan Aug 04 '16 at 22:26
  • Thanks for everything, I'll try. – Ismael Ezequiel Aug 04 '16 at 22:29
  • Thanks so much. I tried that and works fine (I edit my question with the answer). – Ismael Ezequiel Aug 04 '16 at 22:51