skip to Main Content

I have a REST Controller

@GetMapping("/getByClientId/{clientId}")
 public ResponseEntity<Optional<List<EquityFeeds>>> getByClientId(@PathVariable("clientId") final String clientId) {

 Optional<List<EquityFeeds>> cId = Optional.ofNullable(equityFeedsService.findByClientId(clientId));

  System.out.println("Client Id: "+cId);

        if(cId.isPresent()) {
           return ResponseEntity.ok(cId);
        } else {
           cId.orElseThrow(() -> new ClientIdNotFoundException(clientId));
        }
        return ResponseEntity.ok(cId);
     }

Service Class Code:

public List<EquityFeeds> findByClientId(String clientId) {

        List<EquityFeeds> cId = equityFeedsRedisRepositoryImpl.findByClientId(clientId);
        System.out.println("In EquityFeedService "+cId);
        return cId;
    }

Impl. Code (REDIS):

public List<EquityFeeds> findByClientId(String clientId) {
      return (List<EquityFeeds>) listOperations.range(clientId, 0, -1);
}

Issue:
1) When the getClientId is called using a REST Controller and the clientId is not present in the REDIS Cache then:

Service class Code returns: In EquityFeedService []

The REST Controller returns: Client Id: Optional[[]] 

In the REST Controller the code goes inside the if loop and displays nothing on the screen since the List is empty i.e.

if(cId.isPresent()) {
           return ResponseEntity.ok(cId);
 }

Why? Why cId.isPresent() returns true and the code goes inside the if loop. Ideally the code should go inside the else loop and throw an Exception since the List is empty. This is happening in case of List only it seems as my other method which has a return type of POJO doesn’t have this issue.

Please help me understand this behavior and what should be done to fix this.

2

Answers


  1. cId.isPresent() return true because
    List<EquityFeeds> is not null , it’s empty list

    if(!cId.get().isEmpty()) {
       return ResponseEntity.ok(cId);
    } else {
       throw new ClientIdNotFoundException(clientId);
    }
    
    Login or Signup to reply.
  2. The reason the Optional.isPresent returns true is that there is an actual value – an empty List. The Optional checks whether the value it holds is a null or not, nothing else. The isPresent checks whether the value is present inside the Optional, not inside the List itself.

    So you have to treat Optional a bit different. Moreover, don’t use Optional like that as substitution to the if-else constructs.

    Here is a way to go:

    return cId.filter(Predicate.not(List::Empty))            // if the list is not empty
              .map(ResponseEntity::ok)                       // create a response
              .orElseThrow(() ->                             // or else throw an exception
                   new ClientIdNotFoundException(clientId)); 
    

    By the way, you don’t want to return Optional wrapped inside the ResponseEntity. Unwrap it and return the List itself. If it is empty or null was already handled and the exception would be thrown first.

    return cId.filter(Predicate.not(List::Empty))            
              .map(Optional::get)                            // exctract from the Optional
              .map(ResponseEntity::ok)
              .orElseThrow(() -> new ClientIdNotFoundException(clientId)); 
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search