271 lines
14 KiB
Plaintext
271 lines
14 KiB
Plaintext
[[packaging]]
|
|
= Packaging Executable Archives
|
|
The plugin can create executable archives (jar files and war files) that contain all of an application's dependencies and can then be run with `java -jar`.
|
|
|
|
Packaging an executable archive is performed by the `repackage` goal, as shown in the following example:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/repackage-pom.xml[tags=repackage]
|
|
----
|
|
|
|
TIP: If you are using `spring-boot-starter-parent`, such execution is already pre-configured with a `repackage` execution ID so that only the plugin definition should be added.
|
|
|
|
The example above repackages a `jar` or `war` archive that is built during the package phase of the Maven lifecycle, including any `provided` dependencies that are defined in the project.
|
|
If some of these dependencies need to be excluded, you can use one of the `exclude` options; see the <<packaging.examples.exclude-dependency,dependency exclusion>> for more details.
|
|
|
|
The original (that is non-executable) artifact is renamed to `.original` by default but it is also possible to keep the original artifact using a custom classifier.
|
|
|
|
NOTE: The `outputFileNameMapping` feature of the `maven-war-plugin` is currently not supported.
|
|
|
|
Devtools is automatically excluded by default (you can control that using the `excludeDevtools` property).
|
|
In order to make that work with `war` packaging, the `spring-boot-devtools` dependency must be set as `optional` or with the `provided` scope.
|
|
|
|
The plugin rewrites your manifest, and in particular it manages the `Main-Class` and `Start-Class` entries.
|
|
If the defaults don't work you have to configure the values in the Spring Boot plugin, not in the jar plugin.
|
|
The `Main-Class` in the manifest is controlled by the `layout` property of the Spring Boot plugin, as shown in the following example:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/non-default-pom.xml[tags=non-default]
|
|
----
|
|
|
|
The `layout` property defaults to a value determined by the archive type (`jar` or `war`). The following layouts are available:
|
|
|
|
* `JAR`: regular executable JAR layout.
|
|
* `WAR`: executable WAR layout. `provided` dependencies are placed in `WEB-INF/lib-provided` to avoid any clash when the `war` is deployed in a servlet container.
|
|
* `ZIP` (alias to `DIR`): similar to the `JAR` layout using `PropertiesLauncher`.
|
|
* `NONE`: Bundle all dependencies and project resources. Does not bundle a bootstrap loader.
|
|
|
|
|
|
|
|
[[packaging.layers]]
|
|
== Layered Jar or War
|
|
A repackaged jar contains the application's classes and dependencies in `BOOT-INF/classes` and `BOOT-INF/lib` respectively.
|
|
Similarly, an executable war contains the application's classes in `WEB-INF/classes` and dependencies in `WEB-INF/lib` and `WEB-INF/lib-provided`.
|
|
For cases where a docker image needs to be built from the contents of a jar or war, it's useful to be able to separate these directories further so that they can be written into distinct layers.
|
|
|
|
Layered archives use the same layout as a regular repackaged jar or war, but include an additional meta-data file that describes each layer.
|
|
|
|
By default, the following layers are defined:
|
|
|
|
* `dependencies` for any dependency whose version does not contain `SNAPSHOT`.
|
|
* `spring-boot-loader` for the loader classes.
|
|
* `snapshot-dependencies` for any dependency whose version contains `SNAPSHOT`.
|
|
* `application` for local module dependencies, application classes, and resources.
|
|
|
|
Module dependencies are identified by looking at all of the modules that are part of the current build.
|
|
If a module dependency can only be resolved because it has been installed into Maven's local cache and it is not part of the current build, it will be identified as regular dependency.
|
|
|
|
The layers order is important as it determines how likely previous layers can be cached when part of the application changes.
|
|
The default order is `dependencies`, `spring-boot-loader`, `snapshot-dependencies`, `application`.
|
|
Content that is least likely to change should be added first, followed by layers that are more likely to change.
|
|
|
|
The repackaged archive includes the `layers.idx` file by default.
|
|
To disable this feature, you can do so in the following manner:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/disable-layers-pom.xml[tags=disable-layers]
|
|
----
|
|
|
|
|
|
|
|
[[packaging.layers.configuration]]
|
|
=== Custom Layers Configuration
|
|
Depending on your application, you may want to tune how layers are created and add new ones.
|
|
This can be done using a separate configuration file that should be registered as shown below:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/custom-layers-pom.xml[tags=custom-layers]
|
|
----
|
|
|
|
The configuration file describes how an archive can be separated into layers, and the order of those layers.
|
|
The following example shows how the default ordering described above can be defined explicitly:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/layers.xml[tags=layers]
|
|
----
|
|
|
|
The `layers` XML format is defined in three sections:
|
|
|
|
* The `<application>` block defines how the application classes and resources should be layered.
|
|
* The `<dependencies>` block defines how dependencies should be layered.
|
|
* The `<layerOrder>` block defines the order that the layers should be written.
|
|
|
|
Nested `<into>` blocks are used within `<application>` and `<dependencies>` sections to claim content for a layer.
|
|
The blocks are evaluated in the order that they are defined, from top to bottom.
|
|
Any content not claimed by an earlier block remains available for subsequent blocks to consider.
|
|
|
|
The `<into>` block claims content using nested `<include>` and `<exclude>` elements.
|
|
The `<application>` section uses Ant-style path matching for include/exclude expressions.
|
|
The `<dependencies>` section uses `group:artifact[:version]` patterns.
|
|
It also provides `<includeModuleDependencies />` and `<excludeModuleDependencies />` elements that can be used to include or exclude local module dependencies.
|
|
|
|
If no `<include>` is defined, then all content (not claimed by an earlier block) is considered.
|
|
|
|
If no `<exclude>` is defined, then no exclusions are applied.
|
|
|
|
Looking at the `<dependencies>` example above, we can see that the first `<into>` will claim all module dependencies for the `application.layer`.
|
|
The next `<into>` will claim all SNAPSHOT dependencies for the `snapshot-dependencies` layer.
|
|
The final `<into>` will claim anything left (in this case, any dependency that is not a SNAPSHOT) for the `dependencies` layer.
|
|
|
|
The `<application>` block has similar rules.
|
|
First claiming `org/springframework/boot/loader/**` content for the `spring-boot-loader` layer.
|
|
Then claiming any remaining classes and resources for the `application` layer.
|
|
|
|
NOTE: The order that `<into>` blocks are defined is often different from the order that the layers are written.
|
|
For this reason the `<layerOrder>` element must always be included and _must_ cover all layers referenced by the `<into>` blocks.
|
|
|
|
include::goals/repackage.adoc[leveloffset=+1]
|
|
|
|
|
|
|
|
[[packaging.examples]]
|
|
== Examples
|
|
|
|
|
|
|
|
[[packaging.examples.custom-classifier]]
|
|
=== Custom Classifier
|
|
By default, the `repackage` goal replaces the original artifact with the repackaged one.
|
|
That is a sane behavior for modules that represent an application but if your module is used as a dependency of another module, you need to provide a classifier for the repackaged one.
|
|
The reason for that is that application classes are packaged in `BOOT-INF/classes` so that the dependent module cannot load a repackaged jar's classes.
|
|
|
|
If that is the case or if you prefer to keep the original artifact and attach the repackaged one with a different classifier, configure the plugin as shown in the following example:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/different-classifier-pom.xml[tags=different-classifier]
|
|
----
|
|
|
|
If you are using `spring-boot-starter-parent`, the `repackage` goal is executed automatically in an execution with id `repackage`.
|
|
In that setup, only the configuration should be specified, as shown in the following example:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/repackage-configuration-pom.xml[tags=repackage-configuration]
|
|
----
|
|
|
|
This configuration will generate two artifacts: the original one and the repackaged counter part produced by the repackage goal.
|
|
Both will be installed/deployed transparently.
|
|
|
|
You can also use the same configuration if you want to repackage a secondary artifact the same way the main artifact is replaced.
|
|
The following configuration installs/deploys a single `task` classified artifact with the repackaged application:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/classified-artifact-pom.xml[tags=classified-artifact]
|
|
----
|
|
|
|
As both the `maven-jar-plugin` and the `spring-boot-maven-plugin` runs at the same phase, it is important that the jar plugin is defined first (so that it runs before the repackage goal).
|
|
Again, if you are using `spring-boot-starter-parent`, this can be simplified as follows:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/jar-plugin-first-pom.xml[tags=jar-plugin-first]
|
|
----
|
|
|
|
|
|
|
|
[[packaging.examples.custom-name]]
|
|
=== Custom Name
|
|
If you need the repackaged jar to have a different local name than the one defined by the `artifactId` attribute of the project, use the standard `finalName`, as shown in the following example:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/custom-name-pom.xml[tags=custom-name]
|
|
----
|
|
|
|
This configuration will generate the repackaged artifact in `target/my-app.jar`.
|
|
|
|
|
|
|
|
[[packaging.examples.local-artifact]]
|
|
=== Local Repackaged Artifact
|
|
By default, the `repackage` goal replaces the original artifact with the executable one.
|
|
If you need to only deploy the original jar and yet be able to run your app with the regular file name, configure the plugin as follows:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/local-repackaged-artifact-pom.xml[tags=local-repackaged-artifact]
|
|
----
|
|
|
|
This configuration generates two artifacts: the original one and the executable counter part produced by the `repackage` goal.
|
|
Only the original one will be installed/deployed.
|
|
|
|
|
|
|
|
[[packaging.examples.custom-layout]]
|
|
=== Custom Layout
|
|
Spring Boot repackages the jar file for this project using a custom layout factory defined in the additional jar file, provided as a dependency to the build plugin:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/custom-layout-pom.xml[tags=custom-layout]
|
|
----
|
|
|
|
The layout factory is provided as an implementation of `LayoutFactory` (from `spring-boot-loader-tools`) explicitly specified in the pom.
|
|
If there is only one custom `LayoutFactory` on the plugin classpath and it is listed in `META-INF/spring.factories` then it is unnecessary to explicitly set it in the plugin configuration.
|
|
|
|
Layout factories are always ignored if an explicit <<goals-repackage-parameters-details-layoutFactory,layout>> is set.
|
|
|
|
|
|
|
|
[[packaging.examples.exclude-dependency]]
|
|
=== Dependency Exclusion
|
|
By default, both the `repackage` and the `run` goals will include any `provided` dependencies that are defined in the project.
|
|
A Spring Boot project should consider `provided` dependencies as "container" dependencies that are required to run the application.
|
|
|
|
Some of these dependencies may not be required at all and should be excluded from the executable jar.
|
|
For consistency, they should not be present either when running the application.
|
|
|
|
There are two ways one can exclude a dependency from being packaged/used at runtime:
|
|
|
|
* Exclude a specific artifact identified by `groupId` and `artifactId`, optionally with a `classifier` if needed.
|
|
* Exclude any artifact belonging to a given `groupId`.
|
|
|
|
The following example excludes `com.example:module1`, and only that artifact:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/exclude-artifact-pom.xml[tags=exclude-artifact]
|
|
----
|
|
|
|
This example excludes any artifact belonging to the `com.example` group:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/exclude-artifact-group-pom.xml[tags=exclude-artifact-group]
|
|
----
|
|
|
|
|
|
|
|
[[packaging.examples.layered-archive-tools]]
|
|
=== Layered Archive Tools
|
|
When a layered jar or war is created, the `spring-boot-jarmode-layertools` jar will be added as a dependency to your archive.
|
|
With this jar on the classpath, you can launch your application in a special mode which allows the bootstrap code to run something entirely different from your application, for example, something that extracts the layers.
|
|
If you wish to exclude this dependency, you can do so in the following manner:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/exclude-dependency-pom.xml[tags=exclude-dependency]
|
|
----
|
|
|
|
|
|
|
|
[[packaging.examples.custom-layers-configuration]]
|
|
=== Custom Layers Configuration
|
|
The default setup splits dependencies into snapshot and non-snapshot, however, you may have more complex rules.
|
|
For example, you may want to isolate company-specific dependencies of your project in a dedicated layer.
|
|
The following `layers.xml` configuration shown one such setup:
|
|
|
|
[source,xml,indent=0,subs="verbatim,attributes",tabsize=4]
|
|
----
|
|
include::../maven/packaging/layers-configuration.xml[tags=layers-configuration]
|
|
----
|
|
|
|
The configuration above creates an additional `company-dependencies` layer with all libraries with the `com.acme` groupId.
|