5

In a spring boot application, I have an endpoint that returns a HTTP 200 response with an object if it exists, or a HTTP 404 reponse if not. Using spring-boot-starter-parent 1.5.7 I used to do that like this:

@Autowired private GroceryRepository groceryRepository;

@RequestMapping(value = "/get/{id}", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
public ResponseEntity<Object> get(@PathVariable final Integer id) {
    final Grocery grocery = groceryRepository.findOne(id);
    if (null == grocery) {
        return ResponseEntity
                .status(HttpStatus.NOT_FOUND)
                .body(MessageUtil.parse(MSG_404_GROCERY, id + ""));
    }
    return ResponseEntity.ok(grocery);
}

GroceryRepository extends JpaRepository<Grocery, Integer>

In spring-boot-starter-parent 2.0.0, findOne() has disappeared from JpaRepository, and findById() returns an Optional. I'm struggling a bit on how to 'port' the above code. The following doesn't build, since it has an unexpected return type:

groceryRepository.findById(id).ifPresent(grocery -> {
    return ResponseEntity.ok(grocery);
});

Can someone tell me what would be the proper way of returning the right Response?

Thanks for any help!

Mr. Wrong
  • 500
  • 7
  • 21

3 Answers3

7

ifPresent has a void return type so performing return ResponseEntity.ok(grocery); will not work as you've already witnessed.

That said, Optional has an isPresent() method which you can use:

Optional<Grocery> groceryOptional = groceryRepository.findById(id);
if(groceryOptional.isPresent()){
    return ResponseEntity.ok(groceryOptional.get());
}else {
    return ResponseEntity
            .status(HttpStatus.NOT_FOUND)
            .body(MessageUtil.parse(MSG_404_GROCERY, id + ""));
}

Another approach would be:

Optional<Grocery> groceryOptional = groceryRepository.findById(id);
 return groceryOptional.map(e -> ResponseEntity.ok(e))
                       .orElse(ResponseEntity
                              .status(HttpStatus.NOT_FOUND)
                              .body(MessageUtil.parse(MSG_404_GROCERY, id + "")));
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
3

Even though the above answer is correct I would go for an even better more functional solution.

Instead of calling Optional#isPresent to check whether the Grocery object is present I would something like:

public ResponseEntity<Object> get(@PathVariable final Integer id) {
    return groceryRepository.findOne(id)
                            .map(g -> ResponseEntity.ok(g))
                            .orElse(ResponseEntity.status(HttpStatus.NOT_FOUND).body(MessageUtil.parse(MSG_404_GROCERY, id + ""));

}
akortex
  • 5,067
  • 2
  • 25
  • 57
  • If I replace findOne() with "findById()", it fails to compile with "incompatible types: inference variable T has incompatible bounds". Can you explain how you meant this? – Mr. Wrong Jun 10 '18 at 15:16
0

I have found workaround for your issue in the following Stackoverflow link

How to properly handle empty resultset with Hibernate and Spring Boot It has a neatly designed solution for this! Hope it will help!