Spirotrack
Spirotrack

Reputation: 77

SOLID IoC based on configuration in Spring Boot

I would like to have a collection of connections (REST, gRPC, RabbitMQ) for one or more different types of services. For example, with this configuration:

connections:
  http:
    - name: connectionA
      host: localhost
      port: 8081
      endpoints:
        - name: employees
          httpMethod: GET
          endpointType: EMPLOYEE
        - name: departments
          httpMethod: POST
          endpointType: DEPARTMENT
  grpc:
    - name: connectionB
      host: localhost
      port: 8084
      disableTls: true
      endpoints:
        - name: employees
          endpointType: EMPLOYEE

When using the EmployeeService I would have an EmployeeHttpClient and an EmployeeGrpcClient, as well as a DepartmentHttpClient in the DepartmentService. Those clients would have the concrete implementation using the specific connection details, but the service shouldn't care about that.

What do you think about this approach?

What would be the correct way of doing it in Spring Boot?

Upvotes: 2

Views: 89

Answers (1)

StepUp
StepUp

Reputation: 38189

It looks like this is a place where Strategy pattern can be used:

Strategy pattern is a behavioral software design pattern that enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.

Let me show an example via C#. I am sorry I am not Java guy, however I provided comments about how code could look in Java.

We need to have some common behaviour that will be shared across all strategies. In our case, it would be just one Get() method from different data providers:

public interface IDataProvider
{
    string Get();
}

And its concrete implementations. These are exchangeable strategies:

public class RabbitMQDataProvider : IDataProvider // implements in Java
{
    public string Get()
    {
        return "I am RabbitMQDataProvider";
    }
}

public class RestDataProvider : IDataProvider // implements in Java
{
    public string Get()
    {
        return "I am RestDataProvider";
    }
}

public class GrpcDataProvider : IDataProvider // implements in Java
{
    public string Get()
    {
        return "I am GrpcDataProvider";
    }
}

We need a place where all strategies can be stored. And we should be able to get necessary strategy from this store. So this is a place where simple factory can be used. Simple factory is not Factory method pattern and not Abstract factory.

public enum DataProviderType
{
    RabbitMq, Rest, Grpc
}

public class DataProviderFactory
{
    private Dictionary<DataProviderType, IDataProvider> _dataProviderByType
        = new Dictionary<DataProviderType, IDataProvider>()
        {
            { DataProviderType.RabbitMq, new RabbitMQDataProvider() },
            { DataProviderType.Rest, new RestDataProvider() },
            { DataProviderType.Grpc, new GrpcDataProvider() },
        };

    public IDataProvider GetInstanceByType(DataProviderType dataProviderType) =>
        _dataProviderByType[dataProviderType];
}

and then you can get instance of desired storage easier:

DataProviderFactory dataProviderFactory = new();
IDataProvider dataProvider = dataProviderFactory
    .GetInstanceByType(DataProviderType.Grpc);
string data = dataProvider.Get();

This design is compliant with the open/closed principle.

Upvotes: 2

Related Questions