Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compile multiple jars that uses same application file with different controllers

I am writing a weather service with 2 providers weather-1 and weather-2. I have two Spring Controller classes controller-1 and controller-2 that call both the services respectively.

My intention is to switch between the two weather service jars, like if I want to get weather data from weather-1 then controller-1 has to compile with the weather-1.jar file while controller-2 remains untouched.

I have tried with two different Gradle files for both the services like build-weather-1.gradle and build-weather-2.gradle.

Both will have the jar dependencies of their own.

build-weather-1.gradle

implementation 'com.xxx.weather:weather-1:0.0.1'

build-weather-2.gradle

implementation 'com.xxx.weather:weather-2:0.0.1'

I ran the build-weather-1.gradle with the command - gradle -b build-weather-1.gradle build. Unfortunately, this build file expects the other service class controller as well.

error: package com.xxx.weather.weather-2 does not exist

I have excluded the package as below,

sourceSets {
 main {
 java {
 exclude 'com/xxxx/weatherservice/controller/Weather2Controller.java'
 }
    }
}

But this interface(weather-2) is declared as a bean in the Application.java file which throws package not found error.

How to resolve this error?

like image 493
r123 Avatar asked Apr 20 '20 11:04

r123


1 Answers

You could consider the following pattern:

  1. Define a common WeatherService interface.
  2. Both weather service implement this interface.
  3. Implement a single controller, inject an implementation of the WeatherService via it's constructor.

This is an example where the dependency-inversion principle applies, from the SOLID principles:

High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces). Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.

In your application, the controller (implementation) depends on the WeatherService interface (abstraction), rather than the specific weather service implementations.

Once you've done the above, there are many options for deploying controllers that make use of the desired weather service implementation. These include:

  • In your main() method or using your chosen dependency-injection approach: construct an instance of the desired weather service implementation, and construct your controller using that instance.
  • Make each weather service implementation a plugin, using something like PF4J
  • Use reflection to find and construct whichever weather service implementation has been placed on the runtime classpath (assuming you compile each weather service implementation as a separate JAR, in addition to a core JAR containing the WeatherService interface and the controller).
like image 175
grantn Avatar answered Oct 09 '22 22:10

grantn