Home > Back-end >  Spring ContollerAdvice does not add body to returned error
Spring ContollerAdvice does not add body to returned error

Time:09-18

I am new to spring and I am trying to figure out global exception handling. What I am trying to achieve here is when a request is made with an unexisting primary key, I want to return an HTTP_NO_CONTENT with the body including timestamp and given id of the said request.

Here is my Controller Advice

@ControllerAdvice
public class ControllerAdvisor {

    @ExceptionHandler(NoLevelFoundException.class)
    public ResponseEntity<ResponseBody> handleNoLevelFoundException( NoLevelFoundException ex) {
        ex.printStackTrace();

        ResponseBody error = new ResponseBody();
        error.setTime(Timestamp.from(Instant.now()));
        error.setMessage(ex.getMessage());

        return new ResponseEntity<>(error, HttpStatus.NO_CONTENT);
    }
}

And these are my custom exception and respondBody

public class NoLevelFoundException extends RuntimeException{
    public NoLevelFoundException(int id) {
        super("No level with id "   id   " found!");
    }
}

public class ResponseBody {
    private Timestamp time;
    private String message;

    ...
}

When I make a request to an unexisting item via postman I receive this. Status code is right but body is empty

With return ResponseEntity.noContent().build(); I still get the right status code but I could not find any way to add body.

I also tried this piece of code

ResponseBody error = new ResponseBody();
error.setTime(Timestamp.from(Instant.now()));
error.setMessage(ex.getMessage());

return ResponseEntity.status(HttpStatus.NO_CONTENT).body(error);

With this style, I explicitly add body yet the outcome is still same. Right HTTP status but empty body.

#EDIT

This is how I throw my error in the first place

first request is captured by RestContorller

@RestController
@RequestMapping("/levels")
public class LevelRestApi {

    private ServiceLayer service;

    @Autowired
    public LevelRestApi(ServiceLayer service, LevelRepository repo) {
        this.service = service;
    }

    @GetMapping("/{stage}")
    public Level getLevel(@PathVariable int stage){
        return service.getLevel(stage);
    }
}

calls service layer which checks if the item exists or not. I throw the error in here.

@Service
public class AlienInvadersServiceLayer implements ServiceLayer {

    JpaRepository levelRepository;

    @Autowired
    public AlienInvadersServiceLayer(@Qualifier(value = "levelRepository") JpaRepository levelRepository) {
        this.levelRepository = levelRepository;
    }

    @Override
    public Level getLevel(int levelId) {
        Optional<Level> result = levelRepository.findById(levelId);
        if (result.isPresent()){
            return result.get();
        }
        else {
            throw new NoLevelFoundException(levelId);
        }
    }
}

CodePudding user response:

Problem is with the return new ResponseEntity<>(error, HttpStatus.NO_CONTENT); of handleNoLevelFoundException method.

When you say NO_CONTENT it just empty your response body and does makes sense. I would suggest use HttpStatus.NOT_FOUND instead.

So your code should looks like this

@ExceptionHandler(NoLevelFoundException.class)
public ResponseEntity<ResponseBody> handleNoLevelFoundException( NoLevelFoundException ex) {
    // other code
    return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
  • Related