java – Can I store interfaces in a hash map?

I have a Spring Boot application with a rather ugly function in one of my controllers:

@GetMapping(path = "/details/{typeLabel}")
    public Optional getDetails(@PathVariable String typeLabel, @RequestParam String id)
            throws NullPointerException {
        Type type = Type.findService(typeLabel);
        switch (type) {
            case BAGS: {
                return bagRepository.findById(new BigInteger(id));
            case BLANKETS: {
                return blanketRepository.findById(new BigInteger(id));
            case HATS: {
                return hatRepository.findById(new BigInteger(id));
            case QUILTS: {
                return quiltRepository.findById(new BigInteger(id));
            default: {
                throw new NullPointerException("Type " + type + "is not recognised, item details could mot be retrieved.");

The repositories are all extensions of the PagingAndSortingRepository. Thanks to the magic of Spring, I can see the interfaces for the repositories, but instantiations seem to be done behind the scenes.

The method shown above works, but it feels a far cry from the Clean Code ideals I am trying to live up to. The constructor for the controller this method sits in is also frightful, as it needs to list each repository and then assign it to a class variable. If I were to expand my database to include many other types of item, each with their own repository, it could become very difficult to read and maintain.

I had a similar issue with my services for each of these item types, but managed to whittle it down to something much easier to work with. The method which used to have a giant switch block now uses a ServiceFinder class to figure out which service to use, depending on the type of item we’re working with:

    @GetMapping(path = "/deletions")
    public Iterable getAllDeleted(@RequestParam String type) {
        // The switch block was here.
        InventoryService service = serviceFinder.findService(type);
        return service.findByDeleteStatus(true);

ServiceFinder holds the logic for picking which server to use:

public class ServiceFinder {

    private final HashMap<String, InventoryService> services = new HashMap<>();

    public ServiceFinder(BagService bagService, BlanketService blanketService,
                         HatService hatService, QuiltService quiltService) {
        services.put(Type.BAGS.getLabel(), bagService);
        services.put(Type.BLANKETS.getLabel(), blanketService);
        services.put(Type.HATS.getLabel(), hatService);
        services.put(Type.QUILTS.getLabel(), quiltService);

    public InventoryService findService(String typeLabel) throws NullPointerException {
        if (!services.containsKey(typeLabel)) {
            throw new NullPointerException("Type " +  typeLabel + " is not recognised.");
        return services.get(typeLabel);


This all feels much less cumbersome and easier on the eye. However, when I try to do similar with the repositories it doesn’t work. There are no squiggly warnings or errors in IntelliJ, but my hash map doesn’t populate so findRepositories() always throws an error 🙁

public class RepositoryFinder {

    private static final HashMap<String, PagingAndSortingRepository> repositories = new HashMap<>();

    public RepositoryFinder(BagRepository bagRepository, BlanketRepository blanketRepository,
                            HatRepository hatRepository, QuiltRepository quiltRepository) {
        repositories.put(Type.BAGS.getLabel(), bagRepository);
        repositories.put(Type.BLANKETS.getLabel(), blanketRepository);
        repositories.put(Type.HATS.getLabel(), hatRepository);
        repositories.put(Type.QUILTS.getLabel(), quiltRepository);

    public static PagingAndSortingRepository findRepository(String typeLabel) throws NullPointerException {
        if (!repositories.containsKey(typeLabel)) {
            throw new NullPointerException("Type " + typeLabel + " is not recognised, item details could mot be retrieved.");
        return repositories.get(typeLabel);


Any suggestions on what I am missing, what I could try instead, or why what I am aiming for will just never work with interfaces instead of concrete classes?