DEV Community

Raja
Raja

Posted on

Generics and Functional Interfaces - A practical example

Problem Statement:

  1. On an multi-threaded environment a record shall be created in the database by one thread and another thread may be interested to fetch the record. Due to the multi threading nature, the second thread may need to wait or retry couple of times before getting hold of the record.
  2. After performing an action in remoete web service, we might need to poll the service for the updated status. (though this is inefficient than using the message or event based communication).

Both of the above problem statements have a common theme of "getting the latest data by polling". A simple implementation would be put an for loop for the number of retries to fetch the data. if the data is fetched, the value is immediately returned.

@SneakyThrows
public Optional<Employee> getRecord(Long id){
   for(int i=0; i< 10; i++){
      Optional<Employee> emp = employeeRepository.findById(id);
      if(emp.isPresent()) return emp;
      Thread.sleep(200)
   }
   return Optional.empty();
}
Enter fullscreen mode Exit fullscreen mode

Let us consider the scenario, where we would need to write the similar code block to retrieve the data from an external web serivces, a similar implementation needs to be written as well.

The above-retry logic can be implemented using Generics and functional interfaces as below.

Generic function

public class Utils{
 @SneakyThrows
    public static <T> Optional<T> getWithRetry( Supplier<Optional<T>> supplier, int retry){
        for(int i=0; i < retry; i++){
            Optional<T> data = supplier.get();
            if(data.isPresent())
                return data;
            Thread.sleep(200);
        }
        return Optional.empty();
    }
}
Enter fullscreen mode Exit fullscreen mode

Invoking the function

public Optional<Employee> getRecord(Long id){
   return Utils.getWithRetry(
        () -> employeeRepository.findById(id)
        , 10);
}
Enter fullscreen mode Exit fullscreen mode

Other data fetching functions can be defined as Supplier interfaces or lambda expressions and invoked using the 'getWithRetry' function. By implementing the Generic function, the retry logic can be reused across as needed.

Top comments (0)