I have multiple microservices that rely on the exact same classes and configuration beans.
Is it possible to externalize this configuration to be included as e.g. module or dependency?
So that e.g. if I would want to change the configuration of these classes all other microservices will have this change.
I think you could clarify your question.
If you want properties outside the jar, this is possible following what is described here https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/html/boot-features-external-config.html#boot-features-external-config-application-property-files
If you want to reuse a set of classes, you can create a separate maven module and add it as a dependency in your microservices.
Update #1 (Describing how to create maven module):
Create the module using this site: https://start.spring.io/
Move the reusable code to this new module
Run mvn clean install
Add the module as a dependency in your microservices
You can create a library in the "spring-boot-starter" style.
Here is how you do it:
https://docs.spring.io/spring-boot/docs/2.0.0.M3/reference/html/boot-features-developing-auto-configuration.html
Very short:
You will have a spring.factories file where you specify the beans which will be autoconfigured. I recommend you to create conditional beans in library so you will be able to create your own beans in the project, in case you need something else.
Related
I want to build a integration route in camel-k. But for better debugging (f.e. adding break-points) i have build the integration-route with camel in a maven project. This project now contains multiple classes as dependencies (logic and separate processors) in multiple files. The route works fine, now i want to deploy it in kubernetes with camel-k. Is there a convenient way for packing all needed classes when building the route with kamel cli? This way both uses (camel and camel k.) would be possible within the same project. In other discussions one solution that have been pointed out was to pack the classes as jar's and add them as maven dependencies in modline, but with that approach every time a change would be made everything had to be repacked. I also tried to load all classes with the kamel run command, but the integration could not connect the classes that way.
You could use this answer https://stackoverflow.com/a/69844968/6528166 which removes Maven as requirement. You can provide the jar directly.
So I am writing a library for some features and the inner library needs to use Spring. I don't want to put in the version of Spring in the inner library. I want that the application using the library defines the version of Spring to use.
Is this even possible? If yes, then how?
Maven wise, clearly your library needs to be dependent on spring because it has to be compiled somehow so at least spring annotations like #Autowire or #Configuration / #Bean need to be in the compilation classpath.
However in the pom.xml of the library you can declare the dependency on spring as "optional" (<optional>true</optional>)
So when maven will compile the application that has your library as a dependency won't need to "take" transitively the spring as well
You can read about optional dependencies here. Their example with ProjectA, ProjectB and ProjectX is relevant...
I got a multi module project with an arbitrary number of spring-boot rest services which all run on their own embedded tomcat and some web frontends which it self must not contain any business logic. These will be configured as Zuul proxies and therefore do not need any other dependencies.
So in my top level build.gradle I can declare all dependencies which are common to all projects which in that case would be spring-boot-starter and log4j. Though all the rest services share nearly all their dependencies.
Is there a way to cluster dependencies? So I can say you are a frontend with minimal dependencies and you are a basic JPA project?
I know I could define dependencies for all separate but then it's doubled in many files.
Take a look at the official user guide's "How to declare your dependencies", chapter 52.4.8. "Optional attributes". According to it, you are able to combine dependencies into some collections, which could be applied as project dependencies, as:
List groovy = ["org.codehaus.groovy:groovy-all:2.4.4#jar",
"commons-cli:commons-cli:1.0#jar",
"org.apache.ant:ant:1.9.4#jar"]
List hibernate = ['org.hibernate:hibernate:3.0.5#jar',
'somegroup:someorg:1.0#jar']
dependencies {
runtime groovy, hibernate
}
So, you can create in the root build script a number of dependencies groups for different configurations (I mean one for frontend, one for JPA project and etc.). And then the only thing you need, is to apply this groups to the subprojects, which are of the reauired type.
I understand the concept of Spring boot, but I am looking for the logic how it is implemented and where it is maintaining the configuration. When we add any Starter-pom immediately it is giving the dependency and the configuration needed for it. How it automated that feature and where is that automating code in the spring boot?
Thanks in advance
The configuration classes for Spring Boot are in the module spring-boot-autoconfigure. A starter POM has a dependency on that (through the general spring-boot-starter module) and the required 3rd party libraries, and then the autoconfiguration for that library is activated.
The SpringBoot project has been put there so to be more productive & build production ready app in no time. SpringBoot project referes many starter projects like spring-boot-starter-jdbc, spring-boot-starter-logging, etc. All these starter libraries are like maven sub module projects and they add a set of libraries to respective project in turn. Like the spring-boot-starter-jdbc library adds these libraries -> spring-jdbc,spring-tx,tomcat-jdbc.
Now for the configuration part, spring boot has maintained another library called spring-boot-autoconfigure which auto configures all needed configs depending on the libraries present on your pom and the initial set of config annotation been used on the app. For Eg. if it sees ojdbc jar present in your pom then it will autoconfigure oracle datasource to your project
From my bare understanding, this feature are not provided by Spring Boot. It is the power of Maven. Maven allow you to declare dependencies, and the dependencies themselves, PLUS the transitive dependencies will be retrieved.
The starter POMs are simply normal Maven POM-type artifact which declared essential dependencies, and hence, when you include in your own POM, related dependencies will be downloaded.
You may get some more understanding on Maven from Maven Site or Maven Guide by Sonatype
I am in need of separate jar of some classes existing in a multi-module project. I need to pull those classes out of existing module so that I can create a jar for them which I can then export to some other project. What I am thinking is what's the advantage of creating separate module in existing project or altogether creating a separate project?
I can't think of possible trade-off. Can you tell me the trade offs involved.
I would suggest you to create an another module instead of a separate project.
Justification:
1) You can pack this jar and use wherever you want it.
2) You can add this module as a dependency to the other modules
3) We will be following the the Maven general rule "one primary artifact per POM"
Conceptually, you should only create a new project if the set of classes you're moving are coherently useful. If this new project you're going to create can be used to solve a problem (with a good API), I think it's a good enough reason to create a new project.
Otherwise, it's perfectly fine for a maven artifact to be shared among other projects even it is just a module of a multi-module project.
Just my $0.02
module:
- easy to manage dependencies
- easy to support shared components. For example two modules use the same
database.
- build/ci process may take longer
project:
- you can easily deploy projects separately with their own versions and so on
- more convinient in case a dedicated team works on a seprated project
- easy to manage build system
- more complicated to handle dependencies