Better solution to call method from interface in every service

Viewed 36

I would like to create service which searching and returns objects from repositories, so: I created interface which has method:

public interface ShapeServicesInterface {
    List<ShapeEntity> getAll();
    String getName();
}

and few services which implements that interface:

@Service
@RequiredArgsConstructor
public class CircleEntityService implements ShapeServicesInterface {
    private final CircleEntityRepository circleEntityRepository;

    @Override
    public List<ShapeEntity> getAll() {
        return new ArrayList<>(circleEntityRepository.findAll());
    }

    @Override
    public String getName() {
        return "circle";
    }
}

and second one:

@Service
@RequiredArgsConstructor
public class SquareEntityService implements ShapeServicesInterface {
    private final SquareEntityRepository squareEntityRepository;

    @Override
    public List<ShapeEntity> getAll() {
        return new ArrayList<>(squareEntityRepository.findAll());
    }

    @Override
    public String getName() {
        return "square";
    }
}

and next in other service I would like to call that method for getting all entites from that repositories (entites extend abstract class ShapeEntity) - found solution like that:

@Service
@RequiredArgsConstructor
public class TestService {
    private final ShapeServiceFacade facade;
    private final ExecutorService executorService;

    public List<ShapeEntity> getAll() throws ExecutionException, InterruptedException {
        List<ShapeEntity> allShapes = new ArrayList<>();
        List<Future<List<ShapeEntity>>> futures = new ArrayList<>();

        for (ShapeServicesInterface shapeDownloader : facade.getServices()) {
            futures.add(executorService.submit(new ShapeTask(shapeDownloader)));
        }

        for (Future<List<ShapeEntity>> future : futures) {
            allShapes.addAll(future.get());
        }
        return allShapes;
    }

ShapeTask is:

@RequiredArgsConstructor
private static class ShapeTask implements Callable<List<ShapeEntity>> {
    private final ShapeServicesInterface servicesInterface;

    @Override
    public List<ShapeEntity> call() {
        return servicesInterface.getAll();
    }
}

Facade is:

@Service
public class ShapeServiceFacade {
    private final Map<String, ShapeServicesInterface> shapeServices;

    public ShapeServiceFacade(Set<ShapeServicesInterface> allServices) {
        this.shapeServices = allServices.stream()
            .collect(Collectors.toMap(ShapeServicesInterface::getName,Function.identity()));
    }

    public List<ShapeServicesInterface> getServices() {
        return new ArrayList<>(shapeServices.values());
    }
}

but it is a little complicated. Is there a easier way to call that methods? I would like to add more methods so I will have to implement another task and another method in service, and in interface. I care about searching in every repostiory.

1 Answers

Maybe the ShapeServiceFacade can be omitted, if you are using spring boot, like that

@Service
@RequiredArgsConstructor
public class TestService {
    @Autowired
    private final List<ShapeServicesInterface> serviceList;
    private final ExecutorService executorService;

    public List<ShapeEntity> getAll() throws ExecutionException, InterruptedException {
        List<ShapeEntity> allShapes = new ArrayList<>();
        List<Future<List<ShapeEntity>>> futures = new ArrayList<>();

        for (ShapeServicesInterface shapeDownloader : serviceList) {
            futures.add(executorService.submit(new ShapeTask(shapeDownloader)));
        }

        for (Future<List<ShapeEntity>> future : futures) {
            allShapes.addAll(future.get());
        }
        return allShapes;
    }
Related