Recently, I wondered what would happen if a Spring Boot RestController returned a java.util.Optional
instead of a regular POJO.
I invested 30 minutes of my life to find out, and created an over-engineered example on GitHub.
Here is the controller.
@Slf4j
@RestController
@RequiredArgsConstructor
public class MusicController {
private final MusicService musicService;
@GetMapping(path = "/value")
Album getValue(@RequestParam("isNull") boolean isNull) {
log.info("Request album value (is null: {})", isNull);
return musicService.getAlbumAsValue(isNull);
}
@GetMapping(path = "/optional")
Optional<Album> getOptional(@RequestParam("isNull") boolean isNull) {
log.info("Request album optional (is null: {})", isNull);
return musicService.getAlbumAsOptional(isNull);
}
}
The first question I had was if Spring Boot would even start up. You never know. It does, and with this hurdle out of the way, here’s the output of a couple of curl commands.
~ % curl -i 'http://localhost:8080/value?isNull=false'
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 24 Jul 2022 08:24:50 GMT
{"artist":"Insomnium","title":"Winter's Gate","genre":"Melodic Death Metal","year":2016}
~ % curl -i 'http://localhost:8080/value?isNull=true'
HTTP/1.1 200
Content-Length: 0
Date: Sun, 24 Jul 2022 08:24:55 GMT
~ % curl -i 'http://localhost:8080/optional?isNull=false'
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 24 Jul 2022 08:25:00 GMT
{"artist":"Insomnium","title":"Winter's Gate","genre":"Melodic Death Metal","year":2016}
~ % curl -i 'http://localhost:8080/optional?isNull=true'
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sun, 24 Jul 2022 08:25:06 GMT
null
Everything works as expected except for the null-case with the Optional. It returns the string “null” instead of nothing.
The moral of the story: Do not return java.util.Optional
from a @RestController
, or you need to do more work to unpack it.
Thank you for reading.