[[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 "`<>`" from the <> section first. -- [[build-tool-plugins-maven-plugin]] == Spring Boot Maven plugin The {spring-boot-maven-plugin-site}/[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.2 (or better). NOTE: Refer to the {spring-boot-maven-plugin-site}/[Spring Boot Maven Plugin Site] for complete plugin documentation. [[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"] ---- 4.0.0 org.springframework.boot spring-boot-maven-plugin {spring-boot-version} repackage ---- 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 `` 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"] ---- spring-snapshots http://repo.spring.io/snapshot spring-milestones http://repo.spring.io/milestone ---- [[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"] ---- jar ---- 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 ---- To build a war file that is both executable and deployable into an external container you need to mark the embedded container dependencies as "`provided`", e.g: [source,xml,indent=0,subs="verbatim,attributes"] ---- war org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-tomcat provided ---- TIP: See the "`<>`" section for more details on how to create a deployable war file. Advanced configuration options and examples are available in the {spring-boot-maven-plugin-site}/[plugin info page]. [[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 use the dependency management provided by `spring-boot-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-dependency-management]] === Dependency management The `spring-boot` plugin automatically applies the {dependency-management-plugin}/[Dependency Management Plugin] and configures in to import the `spring-boot-starter-parent` bom. This provides a similar dependency management experience to the one that is enjoyed by Maven users. For example, it allows you to omit version numbers when declaring dependencies that are managed in the bom. To make use of this functionality, 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") } ---- NOTE: The version of the `spring-boot` gradle plugin that you declare determines the version of the `spring-boot-starter-parent` bom that is imported (this ensures that builds are always repeatable). You should always set the version of the `spring-boot` gradle plugin to the actual Spring Boot version that you wish to use. Details of the versions that are provided can be found in the <>. The dependency management plugin will only supply a version where one is not specified. To use a version of an artifact that differs from the one that the plugin would provide, simply specify the version when you declare the dependency as you usually would. For example: [source,groovy,indent=0,subs="verbatim,attributes"] ---- dependencies { compile("org.thymeleaf:thymeleaf-spring4:2.1.1.RELEASE") } ---- To learn more about the capabilities of the Dependency Management Plugin, please refer to its {dependency-management-plugin-documentation}[documentation]. [[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 ---- To build a war file that is both executable and deployable into an external container, you need to mark the embedded container dependencies as belonging to a configuration named "`providedRuntime`", e.g: [source,groovy,indent=0,subs="verbatim,attributes"] ---- ... apply plugin: 'war' war { baseName = 'myapp' version = '0.5.0' } repositories { jcenter() maven { url "http://repo.spring.io/libs-snapshot" } } configurations { providedRuntime } dependencies { compile("org.springframework.boot:spring-boot-starter-web") providedRuntime("org.springframework.boot:spring-boot-starter-tomcat") ... } ---- TIP: See the "`<>`" section for more details on how to create a deployable war file. [[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 ---- By default, 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. Making static classpath resources reloadable means that `bootRun` does not use the output of the `processResources` task, i.e., when invoked using `bootRun`, your application will use the resources in their unprocessed form. You can disable the direct use of your static classpath resources. This will mean that the resources are no longer reloadable but the output of the `processResources` task will be used. To do so, set `addResources` on the `bootRun` task to `false`: [source,groovy,indent=0,subs="verbatim,attributes"] ---- bootRun { addResources = false } ---- [[build-tool-plugins-gradle-global-configuration]] === Spring Boot plugin configuration The gradle plugin automatically extends your build script DSL with a `springBoot` element for global configuration of the Boot plugin. 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-configuration]] === Repackage configuration The plugin adds a `bootRepackage` task which you can also configure directly, e.g.: [source,groovy,indent=0,subs="verbatim,attributes"] ---- bootRepackage { mainClass = 'demo.Application' } ---- The following configuration options are available: [cols="2,4"] |=== |Name |Description |`enabled` |Boolean flag to switch the repackager off (sometimes useful if you want the other Boot features but not this one) |`mainClass` |The main class that should be run. If not specified the `mainClassName` project property will be used or, if the no `mainClassName` id defined the archive will be searched for a suitable class. "Suitable" means a unique class with a well-formed `main()` method (if more than one is found the build will fail). You should also be able to specify the main class name via the "run" task (`main` property) and/or the "startScripts" (`mainClassName` property) as an alternative to using the "springBoot" configuration. |`classifier` |A file name segment (before the extension) to add to the archive, so that the original is preserved in its original location. Defaults to null in which case the archive is repackaged in place. The default is convenient for many purposes, but if you want to use the original jar as a dependency in another project, it's best to use an extension to define the executable archive. |`withJarTask` |The name or value of the `Jar` task (defaults to all tasks of type `Jar`) which is used to locate the archive to repackage. |`customConfiguration` |The name of the custom configuration whuch is used to populate the nested lib directory (without specifying this you get all compile and runtime dependencies). |=== [[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 by the executable archive. |`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). |`requiresUnpack` |A list of dependencies (in the form "`groupId:artifactId`" that must be unpacked from fat jars in order to run. Items are still packaged into the fat jar, but they will be automatically unpacked when it runs. |=== [[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 disable 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-gradle-publishing-artifacts-to-a-maven-repository]] === Publishing artifacts to a Maven repository using Gradle If you are <> and you want to publish artifacts to a Maven repository you will need to configure the Maven publication with details of Spring Boot's dependency management. This can be achieved by configuring it to publish poms that inherit from `spring-boot-starter-parent` or that import dependency management from `spring-boot-dependencies`. The exact details of this configuration depend on how you're using Gradle and how you're trying to publish the artifacts. [[build-tool-plugins-gradle-publishing-artifacts-to-a-maven-repository-inherit]] ==== Configuring Gradle to produce a pom that inherits dependency management The following is an example of configuring Gradle to generate a pom that inherits from `spring-boot-starter-parent`. Please refer to the http://www.gradle.org/docs/current/userguide/userguide.html[Gradle User Guide] for further information. [source,groovy,indent=0,subs="verbatim,attributes"] ---- uploadArchives { repositories { mavenDeployer { pom { project { parent { groupId "org.springframework.boot" artifactId "spring-boot-starter-parent" version "{spring-boot-version}" } } } } } } ---- [[build-tool-plugins-gradle-publishing-artifacts-to-a-maven-repository-import]] ==== Configuring Gradle to produce a pom that imports dependency management The following is an example of configuring Gradle to generate a pom that imports the dependency management provided by `spring-boot-dependencies`. Please refer to the http://www.gradle.org/docs/current/userguide/userguide.html[Gradle User Guide] for further information. [source,groovy,indent=0,subs="verbatim,attributes"] ---- uploadArchives { repositories { mavenDeployer { pom { project { dependencyManagement { dependencies { dependency { groupId "org.springframework.boot" artifactId "spring-boot-dependencies" version "{spring-boot-version}" type "pom" scope "import" } } } } } } } } ---- [[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 _<>_ 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(new Library(nestedFile, LibraryScope.COMPILE)); } }); ---- [[build-tool-plugins-whats-next]] == What to read next If you're interested in how the build tool plugins work you can look at the {github-code}/spring-boot-tools[`spring-boot-tools`] module on GitHub. More technical details of the <> are covered in the appendix. If you have specific build-related questions you can check out the "`<>`" guides.