I was going to couple of blogs to get the basics of maven, in the mean time I was confused when I can use the multi module project. It will be great if the answer includes example.
The main idea is that you have small modules that are dependent on each other and can be grouped together. Its not necessary that all sub-modules in a multi-module project be dependent on every other sub-module.
Lets consider you have multiple modules for an application (e.g a social networking application) that belong together. These modules can range from smaller modules like a client consumer module or a server module that will serve requests initiated by the client module, an ejb module that will hold your beans that are used by both the server and the client module and a deploy-able web module that would comprise of your front-end application etc.
This is usually handled via a multi-module build which means all modules have the same version number, are bound together under a similar platform (a social networking application in our example) but can be accessed and used by other separately.
Please check How to assemble multimodule maven project into one WAR? to know how to package a multi module project in a war file. also, you can check maven official site on Introduction to pom file
Related
Need some best practice recommendations to a classic requirement around modularising Springboot application based on layers.
Some background info:
Small- medium size Spring boot project with less than 10 developers
2 different Spring-boot applications and shared Service, Repo layer and also shared models
Bit too late to go with micro service approach with full Model/ Controller/ Service/ Repo per API.
Currently there is just one web application exposing the APIs for a frontend application.
Requirement is to add new set of APIs which are used for B2B integration, so the request/ response formats will be quite different to the already available APIs. i.e. /webapi/v1/orders for frontend client and /b2b/v1/orders will need to return different response format.
The Service and Repository layer along with the models need to be shared among the 2 applications, so 3 modules identified as similar to how it's explained in https://stackoverflow.com/a/50352532/907032
-- Main app
-- Webapi (Got dependency to common, jar packaging)
-- b2b (Got dependency to common, jar packaging)
-- common (jar packaging)
The two applications need to be deployed separately and also separated from CICD perspective not to build all the sub modules every time (A change to b2b controller should not affect common/ Webapi)
A change to common module which is only required to the latest b2b module, preferably should not trigger a build and deploy of webapi. i.e. webapi uses common-1.01 and b2b module uses common-1.02. Understood the new version common-1.02 should not break any feature from common-1.01 but just trying to save unnecessary build & deploy for that module until required if that makes sense.
The challenge
Should the modules defined in the same Repo or 3 different Repos?
All the talks about mono vs multi repo is about whether to keep all different projects in same or not, but here as you can see these are modules which are kind of related to each other.
If we define these as sub-modules in same Repo, how versioning of the common module handled? If it's always triggering a build of all three sub modules, do we even have any advantage of modularising the code?
As per your description, the module named "common" is not not that comon to the other two. I'd go with the multi-modudle way by doing so:
first break that common module in three: common, utils-webapi, utils-b2b
The first will strictly contains the thing both webapi and b2b need at the same version. Utils-webapi will be dedicated strictly to the things in api. Same goes for utils-b2b
B2b depends on utils-b2b with depends on common. Webapi depends on utils-webapi with depends on common
Versionning of common module is always consistant, only utils-X module version change from the X module perspective
CI is thus independant for each build.
Note: You can go further and simply consider utils-webapi utils-b2b and get rid of common. At the cost of some deduped code.
Experts,
I need some expert advice on how to approach the below use case in spring boot.
I need to have a maven multi-module approach to my project.
I need to have a single jar as output of the final build process.
There are to be common modules for controllers, data access and other functionality
Other modules are to be created based on functionality domain for eg a module for Payroll, a module for Admin etc etc.
Each domain functional module will then have their own controllers extending the common controller, exception handler and so on.
Each module will also have its own set of thyme leaf pages.
The reason for following such an approach is we have development in phases and we will be rolling out based on functional modules.
Here are the issues that I can sense using this approach.
Where do I add the spring web dependency? If I add to the parent pom - it gets replicated across the children and there will be port conflict issues as each module loads. the same issue will also be there the moment I add it to two child modules.
How do I build the fat jar which has all the jars from all modules and works as the final deployment?
All the text that I read i can't see anything even close to what I am trying to achieve.
AD1. They will not unless you are trying to setup independent application context in each module. Of course you can do that(it might be complicated but I believe it's achievable), but for me it's an overkill. Personally I think it's better to have one application context and rely on scanning components that are present in classpath.
AD2. The structure in maven might be a little bit complicated and overwhelming at first glance but it makes sense. Here's how I see it:
Create a parent module that will aggregate each module in project and will declare library/plugin dependencies for submodules.
Create 1-N shared submodules that will be used in other modules. With come common logic, utils, etc.
Create 1-N submodules that will be handling your business logic
Create an application submodule that creates application context and loads configuration and components from classpath
Create a submodule that will be responsible for packaging process, either to war, jar, uber-jar or whatever else you desire. Maven jar plugin should do that for you. For executable uber-jar, you have dedicated tool from spring.
Now you can choose three ways(these ways I know) of loading your modules.
1. Include some modules in maven build based on the build configuration via maven profiles and let spring IoC container load all the components he finds in the classpath
2. Include all of the modules in maven build and load them depending on spring active profiles - you can think about it as of feature flag. You annotate your components or configuration class with #Profile("XYZ") telling spring IoC container whether to instantiate component or not. You will need (most flexible solution) to provide a property file which tells spring which profiles are active and thus which modules should be loaded
3. Mix of these two above.
Solution 1 pros:
build is faster (modules that are not included will be skipped during build)
final build file is light (modules that are not included are... not included ;))
nobody can run module that is not present
Solution 1 contras:
project descriptor in maven may explode as you might have many different profiles
Solution 2 pros:
it's fairly easy and fun to maintain modules from code
less mess in project descriptor
Solution 2 contras:
somebody can run module that is not intended to be run as it's present in classpath, but just excluded during runtime via spring active profiles
final build file might be overweight - unused code is still present in code
build might take longer - unused code will be compiled
Summary:
It's not easy to build well structured project from scratch. It's much more easier to create a monolith and then split it into modules. It's because if you already created a project, you've probably already identified all the domains and relations between them.
Over past 8 years of using maven, I honestly and strongly recommend using gradle as it's far more flexible than maven. Maven is really great tool, but when it comes to weird customization it often fails as it's build capabilities rely on plugins. You can't write a piece of code on the fly to perform some custom build behaviour while buidling your project, you must have a dedicated plugin for doing that. If such plugin exists it's fine, if it's not you will probably end up writing your own and handling its shipment, so anyone in your company can easily perform project build.
I hope it helps. Have fun ;)
I'm creating a new java web project. This web application will have many modules such as core/commons, business service, repository, security, integration, ldap, user management,.... I wonder if I should separate each module into each maven project (jar file) or create project that include all java packages of all modules into single one maven project.
Structure of Multi modules maven project
mycompany-core
mycompany-repository
mycompany-api
mycompany-usermanagement
mycompany-business
mycompany-web
Structure of Single module project:
mycompany-web
|___ src
|____ main
|____ java
|____ com.mycompany.core
|____ com.mycompany.repository
|____ com.mycompany.business
|____ com.mycompany.controller
When should we apply multi-modules or single-module project> Please give me some advice.
All products I've worked on in Maven were multi-module. This is because they tended to be big. However, when I create my own pet projects, they are normally single-module ones.
As a rule, as products grow, they will need to be organized into multi-modules. Some projects start as a single module and are split as they grow. Others, created by developers with more experience, are already divided up, because the developers already know how the code will grow and how it needs to be organized.
Specifically, from your list, "core/commons, business service, repository, security, integration, ldap, user management", I would separate "commons" into its own module, because it smells like it could be reused on other projects. The other parts could all fit into one module, but I'd need more insight into the project.
It is depend on your requirement. If you want to run this using .sh or .bat you should have single target(single jar with other libraries).
If your project build as an API it is better to have your build as multi module one.
I have created a multi module maven project as below
- root module(parent module. Building this will build the below children modules)
dao
service
web
dao and service modules creates the jar file. web module creates the final war file to be deployed. service module has the dependency of dao module. web module has the dependency of service module.
Whenever I implement new functionality, I have to modify all the modules from dao to web. I have a maven jetty plugin configured in web module. To test any new implemented functionality in UI I end up building dao and service modules always. Are there anyway to avoid this process and reflect the changes from dao and service modules whenever I run mvn jetty:run in web module?
No, there is no way to da that, and this is the intended behavior.
If you have these 3 projects, this means the have their own lifecycle. If not, the best is to have only one project.
However, you could avoid mentioning a version number in the project, and rely on a parent version number (your root module could also be the parent).
So, you could rebuild everything from the multi-module project.
However, I don't really see the point.
Why do you have 3 projects ?
I have some years of experience with maven projects, even with multi modules ones (which has made me hate the multi modules feature of maven (so the disclaimer is now done)) and even if I really like maven there is something I cannot get a clear answer about :
What is a typical usecase of a multi module maven project ? What is the added value of such a structure compared to simple dependencies and parent pom ?
I have seen a lot of configuration of multi module projects but all of them could have clearly been addressed by creating a simple structure of dependency library living their own life as deliverables (even with a parent pom, as a separate deliverable : factorising depedencies and configuration) and I haven't found any usecase where I can clearly see an added value of the multi module structure.
I have always found that this kind of structure brings an overkilling complexity with no real benefit : where am I missing something ? (to be truly honest, I can get that some ear can benefit from this kind of structure but except from that particular usecase, any other real use and benefit ?)
Here's a real life case.
I have a multi-module project (and to your rant... I haven't seen any complications with it.) The end result is a webapp but I have different modules for api, impl, and webapp.
12 months after creating the project I find that I have to integrate with Amazon S3 using a stand-alone process run from a jar. I add a new module which depends on api/impl and write my code for the integration in the new module. I use the assembly plugin (or something like it) to create a runnable jar and now I have a war I can deploy in tomcat and a process I can deploy on another server. I have no web classes in my S3 integration process and I have no Amazon dependencies in my webapp but I can share all the stuff in api and impl.
3 months after that we decide to create a REST webapp. We want to do it as a separate app instead of just new URL mappings in the existing webapp. Simple. One more module, another webapp created as the result of the maven build with no special tinkering. Business logic is shared easily between webapp and rest-webapp and I can deploy them as needed.
The major benefit of multi modules are
one single maven command to build all your modules at once.
and the most important : maven take care of the build order for you.
configuring your CI-server is also very easy: one single jenkins job to build everything.
I already worked in a project with about 30 submodules. Sometimes, you need to change something in more than module, and running one single command and being sure that everything that need to be compiled is compiled in the correct order is a must.
EDIT
Why 30 submodules ?
Huge framework with lot's a features, lot's of developers, separation of features on a module base. It's a real life use case and the separation of the code into module was really meaningful.
I think you are correct in that most project that use multi modules, actually don't need them.
At where I work we use multimodule projects (and I think that for a good reason). We have something similar to a service oriented architecture, so each application
A client module
An interface module (which has shared objects between the client and implementation)
an implementation module
a war module
I agree that putting that implementation and war module in the same actual module would be ok, but the (arguably) benefit of this is that is very clear division between the classes that solve the problem and how the application communicates with the external world.
In previous projects that involved just a web application, I've tried to put everything in the same module, as it made testing easier, given the modules I was using.
Multi modules can help you with re-use your code.
It's one of the best benefits you'll feel in work.
Imagine if you have 3 web projects with a security layer, You'll have to copy paste your code 3 times and trying connect it with each project.
But what if you create a security module a project with a specific job.
It'll be easy to use it by injecting it to your app and then boom it works.
Also as mentioned in #ben75's answer the one maven build command and the correct order of building all your used jars. You'll think no more about which depends on another.
I find maven modules extremely useful for the following reasons:
Architecture layering and boundaries
For example, I make a maven module application-contract which contains the interfaces my presentation layer sees. So I have UI->Presenter-> application-contract <-application-impl <- infrastructure -> domain. This way, I know that my presentation/UI layer will not have access to classes from my Domain/application layers. If domain classes are not in classpath when I code in UI, I cant use them. And I like it this way (utilizing the class path restrictions). Perhaps Java 9 modules can solve this problem too, but (unfortunately) I have work with Java 8.
Running tests in one module each time
When I change code to a layer which is a module (as mentioned previously) I can run its tests only, without re-runing tests from code I did not change. This gives me speed. My presentation layer tests need ~3 seconds (for 300 tests). Every time I change code to a Presenter or whatever below application layer, I don't want my database H2 integration tests to run. Or My Image processing tests to run. Because these do IO and they are slow.
Building
Pretty much the same thing. When I change code to UI, i have only to build and deploy UI stuff (my UI is in Java).