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.
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);
}