Careeroza
Real World Example
A Generic API Response and Cache
Backend APIs (for example a Paytm or Zomato service) wrap every response in the same envelope: status, data and error. A generic ApiResponse<T> works for users, orders or lists, and a generic in-memory cache works for any key and value types.
Example
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public class Main {
record User(int id, String name) { }
record Order(String id, int amount) { }
public static void main(String[] args) {
ApiResponse<User> u = ApiResponse.ok(new User(7, "Asha"));
ApiResponse<List<Order>> orders = ApiResponse.ok(List.of(new Order("O1", 499), new Order("O2", 1299)));
ApiResponse<User> missing = ApiResponse.error("User 99 not found");
System.out.println(u);
System.out.println(orders);
System.out.println(missing);
SimpleCache<Integer, User> cache = new SimpleCache<>();
Function<Integer, User> loadFromDb = id -> {
System.out.println(" DB query for user " + id);
return new User(id, "User" + id);
};
System.out.println(cache.get(1, loadFromDb));
System.out.println(cache.get(1, loadFromDb)); // served from cache, no DB query
System.out.println(cache.get(2, loadFromDb));
}
}
class ApiResponse<T> {
private final boolean success;
private final T data;
private final String error;
private ApiResponse(boolean success, T data, String error) {
this.success = success;
this.data = data;
this.error = error;
}
static <T> ApiResponse<T> ok(T data) { return new ApiResponse<>(true, data, null); }
static <T> ApiResponse<T> error(String msg) { return new ApiResponse<>(false, null, msg); }
@Override
public String toString() {
return success ? "{success: true, data: " + data + "}" : "{success: false, error: " + error + "}";
}
}
class SimpleCache<K, V> {
private final Map<K, V> store = new LinkedHashMap<>();
V get(K key, Function<K, V> loader) {
return store.computeIfAbsent(key, loader);
}
}Output
{success: true, data: User[id=7, name=Asha]}
{success: true, data: [Order[id=O1, amount=499], Order[id=O2, amount=1299]]}
{success: false, error: User 99 not found}
DB query for user 1
User[id=1, name=User1]
User[id=1, name=User1]
DB query for user 2
User[id=2, name=User2]