Hey there,
I'm currently working with the new layered jar feature that came with spring boot 2.3. While it is awesome I wonder if a small change would be worth a consideration.
At the moment the default layers in my project are
- dependencies
- spring-boot-loader
- snapshot-dependencies
- application
In https://spring.io/blog/2020/01/27/creating-docker-images-with-spring-boot-2-3-0-m1 it is stated that the layers are sorted top to down on how likely they are to change. But I personally see one problem here. When you are in a multi module project the dependencies that are generated from another module, like some kind of shared or model module should not be in the top layer (dependencies) but more likely in the application layer.
I know one could move those dependencies with custom layer configuration but I think this should be somehow done by default as it kind of breaks this feature having part of the project that is likely in the dependencies layer that should barely change.
Comment From: snicoll
Thanks for the suggestion.
When you are in a multi module project the dependencies that are generated from another module, like some kind of shared or model module should not be in the top layer (dependencies) but more likely in the application layer.
If there are in the dependencies
layer, it means they aren't snapshot builds (otherwise they'd be in the snapshot-dependencies
that just before application
). Just to make sure I understood the request, those shared or model modules are fixed releases (GA) and you release them more often than the rest of the libraries?
FTR, we can't put libraries in the application
layer, this layer is for classes and resources, not libraries.
Comment From: dodgex
Let say we have "project-x" the maven module hierarchy is
project-x (parent) -> project-x-models -> project-x-shared -> project-x-something -> project-x-webapp
the project-x-webapp
is the spring boot based module that is to be build to a Docker container. It has the other 3 modules as dependencies.
Currently when i build a layered jar and extract the layer i have the jars for my first 3 modules in the dependencies
layer. Those are no snapshot dependencies as in our release process we remove the -SNAPSHOT
from the version, build, and increment the version and adding snapshot back for the next iteration.
Now we have a new dependencies layer in our docker container each time we change one of our project modules (e.g. adding a field to the model). And this can happen way more often than updating our other company util dependencies or other external dependencies.
Comment From: snicoll
Those are no snapshot dependencies as in our release process we remove the -SNAPSHOT from the version, build, and increment the version and adding snapshot back for the next iteration.
That's a bit of an unusual setup and the main reason the current arrangement doesn't work for you out-of-the box. I am still confused. Are you increasing the version number for every build?
Comment From: dodgex
Are you increasing the version number for every build?
Just for "release" builds.
We work on our develop branch (having -SNAPSHOT as our project versoin), for each push our jenkins triggers a build. those builds keep the version and publish a SNAPSHOT to our artifactory.
Once we finished a feature set we have a release job that takes the state of the develop branch, removes the snapshot from the the version, builds the project and then merges that state into master. finally it increments patch level and puts the snapshot back.
The process is more or less "gitflow"
During the "develop" builds with snapshot versions the other project modules are in the snapshot-dependencies
layer as the whole project is a snapshot version. but for our release builds where our whole maven project has no longer a -SNAPSHOT version the modules move to the dependencies layer.
With the next release that e.g. only fixed somethin in the models
module the whole image with all external dependencies has to be recreated instead of just the a lower layer that contains application/project related stuff
Comment From: philwebb
We discussed this a little bit today on our team call. Although it might be nice to offer an easier way to always pull related modules into the application layer, we don't think it's possible to do consistently with Maven. If you build a multi-module project from the root, then we think that we can tell which projects are modules in the Maven reactor. If, however, you just build a single project directly, we can't tell that a dependency is part of the reactor. Having the plugin behave differently depending on how you trigger the build would be less than ideal.
We did also consider if the groupId
could be used as an indicator. It's pretty common (but not required) for all modules in a multi-module build to share the same groupId
. Unfortunately, it's also pretty common to have a company-wide shared library that also happens to share the same groupId
. These two situations would want different behavior.
All things considered, we'd rather keep things as they are for now and suggest that custom layers are defined for your use-case.