Skip to content

Latest commit

 

History

History
270 lines (183 loc) · 13.5 KB

File metadata and controls

270 lines (183 loc) · 13.5 KB

Packaging Executable Archives

Packaging an executable archive is performed by the repackage goal, as shown in the following example:

link:../maven/packaging/repackage-pom.xml[role=include]
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 dependency exclusion for more details.

The original (i.e. 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:

link:../maven/packaging/non-default-pom.xml[role=include]

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.

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:

link:../maven/packaging/disable-layers-pom.xml[role=include]

[[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:

link:../maven/packaging/custom-layers-pom.xml[role=include]

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:

link:../maven/packaging/layers.xml[role=include]

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.

Examples

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:

link:../maven/packaging/different-classifier-pom.xml[role=include]

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:

link:../maven/packaging/repackage-configuration-pom.xml[role=include]

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:

link:../maven/packaging/classified-artifact-pom.xml[role=include]

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:

link:../maven/packaging/jar-plugin-first-pom.xml[role=include]

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:

link:../maven/packaging/custom-name-pom.xml[role=include]

This configuration will generate the repackaged artifact in target/my-app.jar.

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:

link:../maven/packaging/local-repackaged-artifact-pom.xml[role=include]

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.

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:

link:../maven/packaging/custom-layout-pom.xml[role=include]

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 layout is set.

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:

link:../maven/packaging/exclude-artifact-pom.xml[role=include]

This example excludes any artifact belonging to the com.example group:

link:../maven/packaging/exclude-artifact-group-pom.xml[role=include]

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:

link:../maven/packaging/exclude-dependency-pom.xml[role=include]

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:

link:../maven/packaging/layers-configuration.xml[role=include]

The configuration above creates an additional company-dependencies layer with all libraries with the com.acme groupId.