Generic with check and catch

Suppose you have a @RestController with several calls to a repository (e.g. different attribute searches) and return the results in a list.

It might be useful to create a generic method in your controller so you don’t have that much duplicate code. In the method you can check for content, no content or some error.

Code can look like this:

protected <T> ResponseEntity<List<T>> getListEntriesWithCatch(String argument, Function<String, List<T>> retrievalFunction) {
    try {
        List<T> items = new ArrayList<>(retrievalFunction.apply(argument));
        return items.isEmpty()
                ? new ResponseEntity<>(HttpStatus.NO_CONTENT)
                : new ResponseEntity<>(items, HttpStatus.OK);
    } catch (Exception e) {
        logger.warn("Fetching list entries failes", e);
        return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

Now you can call it with the repository as argument, like this:

return this.<DomainClass>getListEntriesWithCatch(name, domainClassRepository::findByAttribute);

The generic method is protected, so it can be tested more easily. And because it accepts any repository, you can create a custom function in your test instead of mocking your repo.

@Test
void testGetListEntriesWithCatch() {
MyController controller = new MyController();
Function<String, List<String>> retrievalFunction = arg -> Arrays.asList(COLUMN1, COLUMN2);
ResponseEntity<List<String>> result = controller.getListEntriesWithCatch(SCHEMANAME, retrievalFunction);
assertEquals(HttpStatus.OK, result.getStatusCode());
assertEquals(2, Objects.requireNonNull(result.getBody()).size());
}