Optional<List<T>> for Empty List in Repository Layer Returns Optional.empty . How do I change it to return Optional[[]]

Viewed 10287

I have a JPA Query like this.

PersonRepository.java

public Optional<List<PersonEntity>> findByStatus(int status);

PersonService.java

System.out.println(“Optional value is ”+findByStatus(1));

The output is Optional value is Optional.empty

Now I changed my query PersonRepository.java

public List<PersonEntity> findByStatus(int status);

PersonService.java

Optional<List<PersonEntity>> optional = Optional.of(findByStatus(1));
System.out.println("Optional value is "+optional);

The output is Optional value is Optional[[]]

In my database, there is no value for status 1 . I want my output as Optional[[]] for the 1st query. How do I achieve this?

Now, I want to achieve this because, whenever an optional.get() throws a NoSuchElementException, I will handle it using my Exception Controller and expose it as 404 to the REST Layer. But, when a List<Object> is fetched, the response is only a empty List, but optional.get() still throws a NoSuchElementException. I want to avoid this. In short, the optional fetch of Single Entity from Repository throws NoSuchElementException if no value is found which is perfect. But for the optional fetch of a list of Entities which is empty is should be returned as Empty and not throw NoSuchElementException as it is not a 404 error. It just means that the list is empty at present.

3 Answers
 public Optional<List<PersonEntity>> findByStatus(int status);

doesn't make sense.

The correct signature is

 List<PersonEntity> findByStatus(int status);

if there is no PersonEntity the list will be empty.

I suggest you stop thinking technique-oriented and start thinking meaning-oriented.

By the latter, I mean : the essence of a lookup function where the user provides a precisely-known identifier and the result is expected to be at most, or exactly, one entity is that it is fundamentally different from that of a lookup function where the user provides some search criteria and any number of matching entities could be returned.

The former is where there is a logical need for return null; or for throw new NotFoundException(); or for return Optional.ofNullable(null);

The latter is where there is no logical need for any such thing because both arrays and collections already cover for every possible number from zero to infini ... well however much you're likely to ever need.

Focusing on the essence of the functionality is way more important than focusing on particular techniques.

EDIT

And if you absolutely want (begs the question 'why' though) the same return type for both sorts of lookup function, then Collection<...> is the "right" option, with an empty collection denoting "Not found" in the "single entity lookup" scenario.

You are doing different things.

Optional<List<PersonEntity>>

means that the value it holds is empty.

I can only assume that Spring does something like:

if(list == null || list.isEmpty()) {
    return Optional.empty();
}

In the second case that List<PersonEntity> is an Optional from an empty List.

Related