Search code examples
javaspringrestspring-bootmicroservices

REST API Autowire remote or local implementation of a service automatically


I have a REST API built on Spring Boot consisting of 2 seperate web services. I don't know if those two web services will be hosted on the same machine so I want to make remote and local implementation for all services. Example below:

Local service implementation:

public class LocalExampleService implements ExampleService{

   public Item getItem(long id){
      //Get item using implementation from another local project
   }
}

Remote service implementation:

public class RemoteExampleService implements ExampleService{

   @Value("${serviceURL}")
   private String serviceURL;

   public Item getItem(long id){
      //Get item calling remote service
   }
}

Controller:

public class MyController{
    @Autowired
    private ExampleService exampleService;
}

Web service has many services with local and remote implementation and I want to let Spring know which type of implementation it should choose for all services.

I've been thinking about putting url in properties file and during intialization the app would check whether properties contain url and then autowire service approprietly. But then I would have to write logic for every service autowiring.

What's the best option to autowire correct service implementation automatically?


Solution

  • You can use Spring profiles to control which version of implementation should be used via spring properties.

    In spring properties add below entry

    spring.profiles.active=NAME_OF_ACTIVE_PROFILE
    

    Every service implementation needs profile annotation. That's how your services implementation should look like:

    @Component
    @Profile("local")
    public class LocalExampleService implements ExampleService{}
    
    @Component
    @Profile("remote")
    public class RemoteExampleService implements ExampleService{}
    

    If your project needs to use local implementation of a service then in properties instead of NAME_OF_ACTIVE_PROFILE insert local otherwise remote.

    For fully automatic auto-wiring you need to add method running at the startup that checks whether local implementation class exists and then set profile properly. To do this you need to modify code in spring boot main method:

    public static void main(String[] args){
        String profile = checkCurrentProfile(); //Method that decides which profile should be used
        System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, profile);
        SpringApplication.run(MyApplication.class, args);
    }
    

    If you choose this approach then you don't need previous entry in properties file.