0
votes

I'm trying to implement Error handling into my Rest API and testing with Postman, when I give an incorrect path postman returns a 404 but its a 404 HTML. I am using the @ControllerAdvice for the global exception handler.

the @ControllerAdvice class is RestResponseEntityExceptionHandler.java

@ControllerAdvice
public class RestResponseEntityExceptionHandler  
  extends ResponseEntityExceptionHandler {

    @ExceptionHandler(value  = { IllegalArgumentException.class, IllegalStateException.class })
    protected ResponseEntity<Object> handleConflict(
      RuntimeException ex, WebRequest request) {
        String bodyOfResponse = "This should be application specific";
        return handleExceptionInternal(ex, bodyOfResponse, 
          new HttpHeaders(), HttpStatus.CONFLICT, request);
    }
}

I was told that by default spring boot should return something like this

{
  "timestamp": 1436442596410,
  "status": 404,
  "error": "Not Found",
  "message": "No message available",
  "path": "/item"
}

the nonexistent path I give it is

http://localhost:8080/Assignment2C/breweriessdfsdf

the response I get is

    <!doctype html>
<html lang="en">

<head>
    <title>HTTP Status 404 – Not Found</title>
    <style type="text/css">
        h1 {
            font-family: Tahoma, Arial, sans-serif;
            color: white;
            background-color: #525D76;
            font-size: 22px;
        }

        h2 {
        font-family: Tahoma, Arial, sans-serif;
        color: white;
        background-color: #525D76;
        font-size: 16px;
    }

    h3 {
        font-family: Tahoma, Arial, sans-serif;
        color: white;
        background-color: #525D76;
        font-size: 14px;
    }

    body {
        font-family: Tahoma, Arial, sans-serif;
        color: black;
        background-color: white;
    }

    b {
        font-family: Tahoma, Arial, sans-serif;
        color: white;
        background-color: #525D76;
    }

    p {
        font-family: Tahoma, Arial, sans-serif;
        background: white;
        color: black;
        font-size: 12px;
    }

    a {
        color: black;
    }

    a.name {
        color: black;
    }

    .line {
        height: 1px;
        background-color: #525D76;
        border: none;
    }
</style>
</head>

    <body>
    <h1>HTTP Status 404 – Not Found</h1>
    <hr class="line" />
    <p><b>Type</b> Status Report</p>
    <p><b>Description</b> The origin server did not find a current representation for the target resource or is not
        willing to disclose that one exists.</p>
    <hr class="line" />
    <h3>Apache Tomcat/9.0.26</h3>
</body>

</html>

the spring boot dependency that I am using is

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.2.6.RELEASE</version>
    <type>pom</type>
    <scope>provided</scope>
</dependency>

my controller class is Breweries_Controller

  @RestController
@RequestMapping("/breweries")
public class Breweries_Controller {

    @Autowired
    Breweries_Service service;

    @GetMapping(produces = MediaTypes.HAL_JSON_VALUE)
    public Resources<Breweries> getAllBreweries(@RequestParam(name = "limit", required = false) Integer limit , @RequestParam(name = "offset", required = false) Integer offset) {

        List<Breweries> allBreweries = service.getAllBreweries();

        if(limit == null && offset == null){
            limit = 20;
            offset = 0;
        }
        List<Breweries> paginatedList = allBreweries.subList(offset, offset + limit);

        for (Breweries b : allBreweries) {
            int id = b.getResourceId();
            Link self = linkTo(this.getClass()).slash(id).withSelfRel();
            b.add(self);
            linkTo(methodOn(this.getClass()).getBrewerie(id));
        }
        Link link = linkTo(this.getClass()).withSelfRel();
        Resources<Breweries> result = new Resources<Breweries>(paginatedList, link);

        return result;

    }

    @GetMapping(value = "/{id}", produces = MediaTypes.HAL_JSON_VALUE)
    public Resource<Breweries> getBrewerie(@PathVariable("id") int id) {
        Resource<Breweries> brewerie = new Resource<Breweries>(service.getBrewerieById(id));
        ControllerLinkBuilder linkTo = linkTo(methodOn(this.getClass()).getAllBreweries(5, 50));
        brewerie.add(linkTo.withRel("all-breweries"));
        return brewerie;
    }

    @DeleteMapping(value = "/{id}")
    @ResponseStatus(HttpStatus.OK)
    public void delete(@PathVariable("id") int id) {
        Breweries brewerie = service.getBrewerieById(id);
        service.deleteBrewerie(brewerie);
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public void create(@RequestBody Breweries b) {
        b.setResourceId(0);
        b.setAddUser(0);
        b.setLastMod(new Date());
        service.addBrewerie(b);
    }

    @PutMapping(value = "/{id}")
    @ResponseStatus(HttpStatus.OK)
    public void update(@PathVariable("id") int id, @RequestBody Breweries b) {
        b.setResourceId(id);
        b.setAddUser(0);
        b.setLastMod(new Date());
        service.editBrewerie(b);
    }
}
1

1 Answers

1
votes

404 means that spring mvc has failed to find the appropriate end point (controller + method) to run your request.

@ControllerAdvice is relevant only if the method has actually been called and there was an exception. But in your case the flow doesn't even reach controller that's why controller advice doesn't work.

You can customize the error page by creating a controller the implements ErrorController.

This information does not strictly answer the question, but I realize that that's what you really need to resolve the issue so I'll just post a link to the relevant tutorial.