spring-boot/spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc

581 lines
19 KiB
Plaintext
Raw Normal View History

[[build-tool-plugins]]
= Build tool plugins
[partintro]
--
Spring Boot provides build tool plugins for Maven and Gradle. The plugins offer a
variety of features, including the packaging of executable jars. This section provides
more details on both plugins, as well as some help should you need to extend an
unsupported build system. If you are just getting started, you might want to read
``<<using-spring-boot.adoc#using-boot-build-systems>>'' from the
<<using-spring-boot.adoc#using-boot>> section first.
--
[[build-tool-plugins-maven-plugin]]
== Spring Boot Maven plugin
The Spring Boot Maven Plugin provides Spring Boot support in Maven, allowing you to
package executable jar or war archives and run an application ``in-place''. To use it you
must be using Maven 3 (or better).
[[build-tool-plugins-include-maven-plugin]]
=== Including the plugin
To use the Spring Boot Maven Plugin simply include the appropriate XML in the `plugins`
section of your `pom.xml`
[source,xml,indent=0,subs="verbatim,attributes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- ... -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>{spring-boot-version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
----
This configuration will repackage a jar or war that is built during the `package` phase of
the Maven lifecycle. The following example shows both the repackaged jar, as well as the
original jar, in the `target` directory:
[indent=0]
----
$ mvn package
$ ls target/*.jar
target/myproject-1.0.0.jar target/myproject-1.0.0.jar.original
----
If you don't include the `<execution/>` configuration as above, you can run the plugin on
its own (but only if the package goal is used as well). For example:
[indent=0]
----
$ mvn package spring-boot:repackage
$ ls target/*.jar
target/myproject-1.0.0.jar target/myproject-1.0.0.jar.original
----
If you are using a milestone or snapshot release you will also need to add appropriate
`pluginRepository` elements:
[source,xml,indent=0,subs="verbatim,attributes"]
----
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
----
[[build-tool-plugins-maven-packaging]]
=== Packaging executable jar and war files
Once `spring-boot-maven-plugin` has been included in your `pom.xml` it will automatically
attempt to rewrite archives to make them executable using the `spring-boot:repackage`
goal. You should configure your project to build a jar or war (as appropriate) using the
usual `packaging` element:
[source,xml,indent=0,subs="verbatim,attributes"]
----
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!-- ... -->
<packaging>jar</packaging>
<!-- ... -->
</project>
----
Your existing archive will be enhanced by Spring Boot during the `package` phase. The
main class that you want to launch can either be specified using a configuration option,
or by adding a `Main-Class` attribute to the manifest in the usual way. If you don't
specify a main class the plugin will search for a class with a
`public static void main(String[] args)` method.
To build and run a project artifact, you can type the following:
[indent=0]
----
$ mvn package
$ java -jar target/mymodule-0.0.1-SNAPSHOT.jar
----
[[build-tool-plugins-maven-packaging-configuration]]
=== Repackage configuration
The following configuration options are available for the `spring-boot:repackage` goal:
[[build-tool-plugins-maven-packaging-required-params]]
==== Required parameters
[cols="2,4"]
|===
|Name |Description
|`outputDirectory`
|Directory containing the generated archive (defaults to `${project.build.directory}`).
|`finalName`
|Name of the generated archive (defaults to `${project.build.finalName}`).
|===
[[build-tool-plugins-maven-packaging-optional-params]]
==== Optional parameters
[cols="2,4"]
|===
|Name |Description
|`classifier`
|Classifier to add to the generated artifact. If given, the artifact will be attached. If
this is not given, it will merely be written to the output directory according to the
`finalName`. Attaching the artifact allows to deploy it alongside to the original one,
see http://maven.apache.org/plugins/maven-deploy-plugin/examples/deploying-with-classifiers.html[
the maven documentation for more details]
|`mainClass`
|The name of the main class. If not specified will search for a single compiled class
that contains a `main` method.
|`layout`
|The type of archive (which corresponds to how the dependencies are laid out inside it).
Defaults to a guess based on the archive type.
|===
The plugin rewrites your manifest, and in particular it manages the `Main-Class` and
`Start-Class` entries, so if the defaults don't work you have to configure those there
(not in the jar plugin). The `Main-Class` in the manifest is actually controlled by the
`layout` property of the boot plugin, e.g.
[source,xml,indent=0,subs="verbatim,attributes"]
----
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>{spring-boot-version}</version>
<configuration>
<mainClass>${start-class}</mainClass>
<layout>ZIP</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
----
The layout property defaults to a guess based on the archive type (jar or war). For the
`PropertiesLauncher` the layout is ``ZIP'' (even though the output might be a jar file).
TIP: The executable jar format is <<appendix-executable-jar-format.adoc#executable-jar,
described in the appendix>>.
[[build-tool-plugins-maven-running-applications]]
=== Running applications
The Spring Boot Maven Plugin includes a `run` goal which can be used to launch your
application from the command line. Type the following from the root of your Maven
project:
[indent=0]
----
$ mvn spring-boot:run
----
By default, any `src/main/resources` folder will be added to the application classpath
when you run via the maven plugin. This allows hot refreshing of resources which can be
very useful when developing web applications. For example, you can work on HTML, CSS or
JavaScipt files and see your changes immediately without recompiling your application. It
is also a helpful way of allowing your front end developers to work without needing to
download and install a Java IDE.
[[build-tool-plugins-maven-run-configuration]]
=== Run configuration
The following configuration options are available for the `spring-boot:run` goal:
[[build-tool-plugins-maven-run-configuration-required-params]]
=== Required parameters
[cols="2,4"]
|===
|Name |Description
|`classesDirectrory`
|Directory containing the classes and resource files that should be packaged into the
archive (defaults to `${project.build.outputDirectory}`).
|===
[[build-tool-plugins-maven-run-configuration-optional-params]]
=== Optional parameters
[cols="2,4"]
|===
|Name |Description
|`arguments` or `-Drun.arguments`
|Arguments that should be passed to the application.
|`addResources` or `-Drun.addResources`
|Add Maven resources to the classpath directly, this allows live in-place editing or
resources. Since resources will be added directly, and via the target/classes folder
they will appear twice if `ClassLoader.getResources()` is called. In practice, however,
most applications call `ClassLoader.getResource()` which will always return the first
resource (defaults to `true`).
|`mainClass`
|The name of the main class. If not specified the first compiled class found that
contains a 'main' method will be used.
|`folders`
|Folders that should be added to the classpath (defaults to
`${project.build.outputDirectory}`).
|===
[[build-tool-plugins-gradle-plugin]]
== Spring Boot Gradle plugin
The Spring Boot Gradle Plugin provides Spring Boot support in Gradle, allowing you to
package executable jar or war archives, run Spring Boot applications and omit version
information from your `build.gradle` file for ``blessed'' dependencies.
[[build-tool-plugins-including-the-gradle-plugin]]
=== Including the plugin
To use the Spring Boot Gradle Plugin simply include a `buildscript` dependency and apply
the `spring-boot` plugin:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
buildscript {
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:{spring-boot-version}")
}
}
apply plugin: 'spring-boot'
----
If you are using a milestone or snapshot release you will also need to add appropriate
`repositories` reference:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
buildscript {
repositories {
maven.url "http://repo.spring.io/snapshot"
maven.url "http://repo.spring.io/milestone"
}
// ...
}
----
[[build-tool-plugins-gradle-dependencies-without-versions]]
=== Declaring dependencies without versions
The `spring-boot` plugin will register a custom Gradle `ResolutionStrategy` with your
build that allows you to omit version numbers when declaring dependencies to ``blessed''
artifacts. All artifacts with a `org.springframework.boot` group ID, and any of the
artifacts declared in the `managementDependencies` section of the
{github-code}/spring-boot-dependencies/pom.xml[`spring-dependencies`]
POM can have their version number resolved automatically.
Simply declare dependencies in the usual way, but leave the version number empty:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.thymeleaf:thymeleaf-spring4")
compile("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect")
}
----
[[build-tool-plugins-gradle-packaging]]
=== Packaging executable jar and war files
Once the `spring-boot` plugin has been applied to your project it will automatically
attempt to rewrite archives to make them executable using the `bootRepackage` task. You
should configure your project to build a jar or war (as appropriate) in the usual way.
The main class that you want to launch can either be specified using a configuration
option, or by adding a `Main-Class` attribute to the manifest. If you don't specify a
main class the plugin will search for a class with a
`public static void main(String[] args)` method.
To build and run a project artifact, you can type the following:
[indent=0]
----
$ gradle build
$ java -jar build/libs/mymodule-0.0.1-SNAPSHOT.jar
----
[[build-tool-plugins-gradle-running-applications]]
=== Running a project in-place
To run a project in place without building a jar first you can use the "bootRun" task:
[indent=0]
----
$ gradle bootRun
----
Running this way makes your static classpath resources (i.e. in `src/main/resources` by
default) reloadable in the live application, which can be helpful at development time.
[[build-tool-plugins-gradle-repackage-configuration]]
=== Repackage configuration
The gradle plugin automatically extends your build script DSL with a `springBoot` element
for configuration. Simply set the appropriate properties as you would with any other Gradle
extension (see below for a list of configuration options):
[source,groovy,indent=0,subs="verbatim,attributes"]
----
springBoot {
backupSource = false
}
----
[[build-tool-plugins-gradle-repackage-custom-configuration]]
=== Repackage with custom Gradle configuration
Sometimes it may be more appropriate to not package default dependencies resolved from
`compile`, `runtime` and `provided` scopes. If the created executable jar file
is intended to be run as it is, you need to have all dependencies nested inside it;
however, if the plan is to explode a jar file and run the main class manually, you may already
have some of the libraries available via `CLASSPATH`. This is a situation where
you can repackage your jar with a different set of dependencies.
Using a custom
configuration will automatically disable dependency resolving from
`compile`, `runtime` and `provided` scopes. Custom configuration can be either
defined globally (inside the `springBoot` section) or per task.
[source,groovy,indent=0,subs="verbatim,attributes"]
----
task clientJar(type: Jar) {
appendix = 'client'
from sourceSets.main.output
exclude('**/*Something*')
}
task clientBoot(type: BootRepackage, dependsOn: clientJar) {
withJarTask = clientJar
customConfiguration = "mycustomconfiguration"
}
----
In above example, we created a new `clientJar` Jar task to package a customized
file set from your compiled sources. Then we created a new `clientBoot`
BootRepackage task and instructed it to work with only `clientJar` task and
`mycustomconfiguration`.
[source,groovy,indent=0,subs="verbatim,attributes"]
----
configurations {
mycustomconfiguration.exclude group: 'log4j'
}
dependencies {
mycustomconfiguration configurations.runtime
}
----
The configuration that we are referring to in `BootRepackage` is a normal
http://www.gradle.org/docs/current/dsl/org.gradle.api.artifacts.Configuration.html[Gradle
configuration]. In the above example we created a new configuration named
`mycustomconfiguration` instructing it to derive from a `runtime` and exclude the `log4j`
group. If the `clientBoot` task is executed, the repackaged boot jar will have all
dependencies from `runtime` but no `log4j` jars.
[[build-tool-plugins-gradle-configuration-options]]
==== Configuration options
The following configuration options are available:
[cols="2,4"]
|===
|Name |Description
|`mainClass`
|The main class that should be run. If not specified the value from the manifest will be
used, or if no manifest entry is the archive will be searched for a suitable class.
|`providedConfiguration`
|The name of the provided configuration (defaults to `providedRuntime`).
|`backupSource`
|If the original source archive should be backed-up before being repackaged (defaults
to `true`).
|`customConfiguration`
|The name of the custom configuration.
|`layout`
|The type of archive, corresponding to how the dependencies are laid out inside
(defaults to a guess based on the archive type).
|===
[[build-tool-plugins-understanding-the-gradle-plugin]]
=== Understanding how the Gradle plugin works
When `spring-boot` is applied to your Gradle project a default task named `bootRepackage`
is created automatically. The `bootRepackage` task depends on Gradle `assemble` task, and
when executed, it tries to find all jar artifacts whose qualifier is empty (i.e. tests and
sources jars are automatically skipped).
Due to the fact that `bootRepackage` finds 'all' created jar artifacts, the order of
Gradle task execution is important. Most projects only create a single jar file, so
usually this is not an issue; however, if you are planning to create a more complex
project setup, with custom `Jar` and `BootRepackage` tasks, there are few tweaks to
consider.
If you are 'just' creating custom jar files from your project you can simply disables
default `jar` and `bootRepackage` tasks:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
jar.enabled = false
bootRepackage.enabled = false
----
Another option is to instruct the default `bootRepackage` task to only work with a
default `jar` task.
[source,groovy,indent=0,subs="verbatim,attributes"]
----
bootRepackage.withJarTask = jar
----
If you have a default project setup where the main jar file is created and repackaged,
'and' you still want to create additional custom jars, you can combine your custom
repackage tasks together and use `dependsOn` so that the `bootJars` task will run after
the default `bootRepackage` task is executed:
[source,groovy,indent=0,subs="verbatim,attributes"]
----
task bootJars
bootJars.dependsOn = [clientBoot1,clientBoot2,clientBoot3]
build.dependsOn(bootJars)
----
All the above tweaks are usually used to avoid situations where an already created boot
jar is repackaged again. Repackaging an existing boot jar will not break anything, but
you may find that it includes unnecessary dependencies.
[[build-tool-plugins-other-build-systems]]
== Supporting other build systems
If you want to use a build tool other than Maven or Gradle, you will likely need to develop
your own plugin. Executable jars need to follow a specific format and certain entries need
to be written in an uncompressed form (see the
'<<appendix-executable-jar-format.adoc#executable-jar, executable jar format>>' section
in the appendix for details).
The Spring Boot Maven and Gradle plugins both make use of `spring-boot-loader-tools` to
actually generate jars. You are also free to use this library directly yourself if you
need to.
[[build-tool-plugins-repackaging-archives]]
=== Repackaging archives
To repackage an existing archive so that it becomes a self-contained executable archive
use `org.springframework.boot.loader.tools.Repackager`. The `Repackager` class takes a
single constructor argument that refers to an existing jar or war archive. Use one of the
two available `repackage()` methods to either replace the original file or write to a new
destination. Various settings can also be configured on the repackager before it is
run.
[[build-tool-plugins-nested-libraries]]
=== Nested libraries
When repackaging an archive you can include references to dependency files using the
`org.springframework.boot.loader.tools.Libraries` interface. We don't provide any
concrete implementations of `Libraries` here as they are usually build system specific.
If your archive already includes libraries you can use `Libraries.NONE`.
[[build-tool-plugins-find-a-main-class]]
=== Finding a main class
If you don't use `Repackager.setMainClass()` to specify a main class, the repackager will
use http://asm.ow2.org/[ASM] to read class files and attempt to find a suitable class
with a `public static void main(String[] args)` method. An exception is thrown if more
than one candidate is found.
[[build-tool-plugins-repackage-implementation]]
=== Example repackage implementation
Here is a typical example repackage:
[source,java,indent=0]
----
Repackager repackager = new Repackager(sourceJarFile);
repackager.setBackupSource(false);
repackager.repackage(new Libraries() {
@Override
public void doWithLibraries(LibraryCallback callback) throws IOException {
// Build system specific implementation, callback for each dependency
// callback.library(nestedFile, LibraryScope.COMPILE);
}
});
----
[[build-tool-plugins-whats-next]]
== What to read next
If your interested to looking at how the build tool plugins were developed you can
look at the {github-code}/spring-boot-tools[`spring-boot-tools`] module on GitHub. More
technical details of the <<appendix-executable-jar-format.adoc#executable-jar, executable
jar format>> are covered in the appendix.
If you have specific build related questions, you can check out the
`<<howto.adoc#howto, how-to>>' guides.