I have two projects that contain reusable code for many different services and web apps, such as CommonService and CommonWeb.
I want all my service projects to reuse as much pom configuration as possible from the common service, but I still want to leverage the spring boot starter poms in the common projects to help set them up. What would be the best way to organize the pom hierarchy?
CommonService and CommonWeb both have code, dependencies, and plugins like the AspectJ compiler. Would my AppService add CommonService as a dependency, or as a parent?
We solved it by having common parent that is inherited from Spring Boot parent. This common parent would be parent for each of projects. This was particularly handy for micro-services architecture.
If you have different types of projects, e.g. HTTP vs messaging service, you can have inheritance hierarchy of POM parents where root is always Spring Boot parent.
If you don't like idea of having inheritance hierarchy of parent POMs, I suggest to analyze Spring Boot project, how they organize POMs. It is very clever, but may be overkill if you don't have a lot of various types of services/projects.
Of course these POMs need to be properly versioned and deployed to some artifact repository as standalone artifacts.
Since a maven parent POM must be in pom packaging.
You should have a CommonParent maven project besides your CommonService and CommonWeb projects like this:
common (maven aggregate project)
+- common-service (module with `jar` packaging)
+- common-web (module with `jar` packaging)
\- common-parent (module with `pom` packaging,
and dependent on common-service, common-web)
Then you just have all your projects' POM be a child of your common-parent.
Furthermore, you should write your own AutoConfiguration classes and use the #ConfigurationProperites encapsulation provided by Spring Boot to construct your own application properties. So that a downstream project can control over your common configuration easily by settings property like common.web.feature1.enabled = false.
Related
There are many Maven artifacts named spring-boot-starter-*. As the names imply, they are very useful for an application project to get started with Spring Boot.
However, after the application project become stable, should it keep using these spring-boot-starter-*?
My concern is that doing so uses the Maven mechanism of "transitive dependencies", and it seems to violate the suggestion in Maven documentation:
Although transitive dependencies can implicitly include desired dependencies, it is a good practice to explicitly specify the dependencies you are directly using in your own source code.
For example, suppose an application project directly uses the Spring annotation #EventListener. The annotation is in the Maven artifact spring-context, and spring-context is included in spring-boot-starter. Should the application project directly specify the dependency on spring-context after it become stable?
The Spring Boot starter artifacts are just a shorthand for including several Spring Boot artifacts at once. My company has services in production that use starter artifacts. Of course, you could replace each starter with a list of the artifacts it contains, but I think the Maven suggestion is more about unrelated transitive dependencies, such as if your application inherited Guava from some JSON library as a transitive dependency.
When the transitive dependencies all come from the same source and are designed to work together, I don't think it's a problem. At least, I don't see it as such.
I have a parent Maven project (pom packaging) and 4 Maven modules (jar packaging) as children of that. Is there any way/plugin to create a importable dependency of the parent project including all the children? I mean that I want to create some kind of abstraction, so when somebody wants to import my project, it won't be necessary to import a specific childermodule (the module that he will use), he will just import the whole project (all the children modules)
The Maven parent project corresponds with inheritance. It is meant the children projects to inherit the settings, so you do not have to repeat them and you may set all the common stuff in a single place.
On other side, the convenience Maven project containing dependencies corresponds with composition.
You should not mix these two things together. Parent project is a common super-class of your modules. This convenience project you wish to have is a collection containing all your modules as dependencies. You should not want the theAnimal class to depend on all the animals.
Just accept the fact that you need two separate Maven projects:
the parent (if you need it), and
the convenience project for transitive dependencies.
The solution for your problem is described e.g. here: 3.6.1. Grouping Dependencies
If you have a set of dependencies which are logically grouped together. You can create a project with pom packaging that groups dependencies together. For example, let’s assume that your application uses Hibernate... Every project which uses Hibernate might also have a dependency on the Spring Framework and a MySQL JDBC driver. Instead of having to include these dependencies in every project that uses Hibernate, Spring, and MySQL you could create a special POM that does nothing more than declare a set of common dependencies. You could create a project called persistence-deps (short for Persistence Dependencies), and have every project that needs to do persistence depend on this convenience project.
I have four projects, Proj-A, Proj-B, Proj-C and Proj-D. Proj-B, Proj-C and Proj-D all have Proj-A as a dependency inside their POMs. B,C, and D are not dependent on each other. I have put profiles in Proj-A in order to allow parametrization of some settings (jpa settings for dev, test and prod db connections). That works fine.
Is there a way to build the other projects, and have them pass the proper build profile to use when building the dependent project? If so how? I would like to do this without putting properties in the settings.xml file for the maven repository.
I am familiar with Maven2 but by no means an expert, any ideas?
As far as I know there is no a beautiful way :/
You can inherit profiles from a parent to its children.
But the planned implementation of mixins is still open
What I've seen is that people create a parent containing the profiles and then use it as parent for the project-parent pom.xml
What is also possible is to use a different (released) parent for modules:
project-parent (having modules configured)
/module1 -> using webservice parent pom
/module2 -> using rest parent pom
That is not the usual structure but one way to share configuration for related modules in different projects.
If we have a multiple module project,
Parent Project
Model Module
Services Module
Web Module
And the parent project pom.xml, lists the 3 modules in <modules>...
And then Services pom.xml has a dependency on Model, and Web Module pom.xml has a dependency on Services...what does this mean?
Does it mean I can't reference in my Web Module, any of the Model classes?
i.e. does the dependency chain in Maven impact this type of scoping?
So I cant in appContext.xml in my web module control any of the injection of beans outside of Services/Web Module?
Many thanks (sorry for noob question)
i
Your question is not very clear but what I could gather is that you want to ask whether in your web module you can access your model class. Definitely you can because of transitive nature of your dependencies. Since Service module depends on Model and Web model depends on Service, you can definitely access Model classes in Web module. You can understand this better if you run the mvn dependency:tree command on your Web module. The Model would show up in the dependency tree or if you are using Eclipse Maven plugin you can view the Effective dependecy in a tree structure which is visually better to understand.
My project has different modules.
Each module has a pom.xml which specifies jar packaging.
Each pom refers to common parent.
In the parent module there is also a pom.xml which includes all the modules.
When I tried to package using the pom.xml of the parent module, it shows the error - "Packaging jar is invalid Aggregator project need pom as packaging".
What can I do to make an executable jar of the application from maven?
To make things short: if your parent-aggregator project don't contains source code (and it's a good practice), just add this to your parent pom.xml:
<packaging>pom</packaging>
If the parent project contains source code, I strongly suggest you to:
move this code in a new module (let's call it commons)
make commons a child module of your parent project
add the commons module as a dependency of all other modules requiring it (maybe all of them)
add <packaging>pom</packaging> in the parent pom.xml
Maven requires the parent to be of packaging pom.
You can make a pom project behave as if it were a jar project, by including a bunch of plugin executions and attaching them to their subsequent lifecycle phase. It's not a happy road. On the contrary, the following is.
From an object oriented standpoint, what is it that you want? You have one object that is made up out of a bunch of other objects, right? In other words composition, as opposed to inheritance.
Your final delivery is made up out of the other (jar) projects, i.e. the other projects are dependencies of the final delivery project. You will define the other projects each as dependency so that whomever uses your final delivery knows what (transitive) dependencies to get. Alternatively the final delivery jar could be packaged up as "uber-jar" and thus contain all its dependencies. That all really depends on how the final delivery is to be used.
At the same time the following two aspects (may) still exist:
The parent project (which is different than the final delivery project, in fact it may be the parent of the final delivery project also) defines commonalities between its subsequent children, as is what you should expect from inheritance. A child is any project that refers to the parent through the parent configuration in its POM.
A project that defines modules that are to be easily built in one go. Modules are projects that are referred by use of modules.module. This is typically (I guess >99%) done in the parent project, but not necessarily. You could put it in the final delivery project also (without affecting inheritance, because that is thus a different beast), but it's atypical and I would not go there.