I have 10+ Spring Boot applications that can be built as war files and deployed within and application server, or run individually as standalone. Each application contains unique code, functionality, and RESTful services required for business operations.
My package structure is as follows:
WebServices (Gradle project)
|---A (Gradle project)
|---B (Gradle project)
|---C (Gradle project)
Services A, B, and C are all packaged and runnable as wars.
However, I also want to provide the option to start up one "large" server that contains all the services without having to start each application separately or bogging down the primary application server with the large Spring Boot wars.
Ideally this was going to be via another Spring Boot application that utilized the ComponentScan to include functionality from all other services. I was going to have Spring Boot application X that referenced functionality within services A, B, and C.
The issue with this is with context. Each of my services, when started via an application server, are automatically assigned a context based on the name of the war file. For example, if I have security functionality in application A since it contains sensitive information I log in with:
/security/login
Where security is the is the name of the war file (security.war).
To compensate for this while running standalone I have an application property set for the context to match the war file name server.servlet.context-path: /security
. This allows me to maintain the same endpoint weather deployed with either of my deployment methods.
Now, when I start server X that references projects A, B, and C with the component scan @ComponentScan(basePackages = {"com.package.a.*", "com.package.b.*", "com.package.c.*"})
I loose my context of security within application A and my endpoint now is accessed as:
/login
There is no differentiation between applications A, B, or C.
So, my question is how can I maintain individual contexts, or even route based on context, based on the components being scanned?
I resolved this in another manner.
I placed a default RequestMapping("${serviceContext}")
on each of my individual controllers. Where service changes for each controller. i.e. aContext, bContext, and cContext.
In my environments that are already bound by a context, within an application server and standalone via the application.yml, this property is not set and results in the already existing binding.
In my bundle application I was able to keep my component scan of @ComponentScan(basePackages = {"com.package.a.*", "com.package.b.*", "com.package.c.*"})
. The change then became adding additional properties during the startup of the application.
Properties used to bind context
Properties properties = new Properties(); properties.put("aContext", "/security"); properties.put("bContext", "/b"); properties.put("cContext", "/c");
I added this to Spring's setDefaultProperties
before running the application. Then when I startup each as a bundle I get the expected context binding.