Merge pull request #14585 from JB Nizet

* gh-14585:
  Polish "Add Kotlin DSL examples to Gradle Plugin's documentation"
  Add Kotlin DSL examples to Gradle Plugin's documentation
pull/11125/merge
Andy Wilkinson 6 years ago
commit 35bb5abe1d

@ -26,6 +26,7 @@
<maven.version>3.5.4</maven.version> <maven.version>3.5.4</maven.version>
<maven-resolver.version>1.1.1</maven-resolver.version> <maven-resolver.version>1.1.1</maven-resolver.version>
<spock.version>1.0-groovy-2.4</spock.version> <spock.version>1.0-groovy-2.4</spock.version>
<dependency-management-plugin.version>1.0.6.RELEASE</dependency-management-plugin.version>
</properties> </properties>
<scm> <scm>
<url>http://github.com/spring-projects/spring-boot</url> <url>http://github.com/spring-projects/spring-boot</url>
@ -108,7 +109,7 @@
<dependency> <dependency>
<groupId>io.spring.gradle</groupId> <groupId>io.spring.gradle</groupId>
<artifactId>dependency-management-plugin</artifactId> <artifactId>dependency-management-plugin</artifactId>
<version>1.0.6.RELEASE</version> <version>${dependency-management-plugin.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>jline</groupId> <groupId>jline</groupId>

@ -128,6 +128,13 @@
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<pluginRepositories>
<pluginRepository>
<id>springio</id>
<name>Spring IO releases repository</name>
<url>https://repo.spring.io/release</url>
</pluginRepository>
</pluginRepositories>
<profiles> <profiles>
<profile> <profile>
<id>windows</id> <id>windows</id>
@ -275,6 +282,7 @@
<github-tag>${github-tag}</github-tag> <github-tag>${github-tag}</github-tag>
<version-type>${version-type}</version-type> <version-type>${version-type}</version-type>
<version>${project.version}</version> <version>${project.version}</version>
<dependency-management-plugin-version>${dependency-management-plugin.version}</dependency-management-plugin-version>
</attributes> </attributes>
</configuration> </configuration>
<dependencies> <dependencies>
@ -283,6 +291,11 @@
<artifactId>asciidoctorj-pdf</artifactId> <artifactId>asciidoctorj-pdf</artifactId>
<version>1.5.0-alpha.11</version> <version>1.5.0-alpha.11</version>
</dependency> </dependency>
<dependency>
<groupId>io.spring.asciidoctor</groupId>
<artifactId>spring-asciidoctor-extensions</artifactId>
<version>0.1.3.RELEASE</version>
</dependency>
</dependencies> </dependencies>
</plugin> </plugin>
<plugin> <plugin>

@ -6,21 +6,96 @@ To get started with the plugin it needs to be applied to your project.
ifeval::["{version-type}" == "RELEASE"] ifeval::["{version-type}" == "RELEASE"]
The plugin is https://plugins.gradle.org/plugin/org.springframework.boot[published to The plugin is https://plugins.gradle.org/plugin/org.springframework.boot[published to
Gradle's plugin portal] and can be applied using the `plugins` block: Gradle's plugin portal] and can be applied using the `plugins` block:
[source,groovy,indent=0,subs="verbatim,attributes"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/getting-started/apply-plugin-release.gradle[] include::../gradle/getting-started/apply-plugin-release.gradle[]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/getting-started/apply-plugin-release.gradle.kts[]
----
endif::[] endif::[]
ifeval::["{version-type}" == "MILESTONE"] ifeval::["{version-type}" == "MILESTONE"]
The plugin is published to the Spring milestones repository. For Gradle versions less
than 4.10, this means that you must apply the plugin imperatively:
[source,groovy,indent=0,subs="verbatim,attributes"] [source,groovy,indent=0,subs="verbatim,attributes"]
---- ----
include::../gradle/getting-started/apply-plugin-milestone.gradle[] include::../gradle/getting-started/apply-plugin-milestone.gradle[]
---- ----
For Gradle 4.10 and above, Gradle can be configured to use the milestones repository
and it can be applied using the `plugins` block. To configure Gradle to use the milestones
repository, add the following to your `settings.gradle` (Groovy) or `settings.gradle.kts`
(Kotlin):
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
----
include::../gradle/getting-started/milestone-settings.gradle[]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/getting-started/milestone-settings.gradle.kts[]
----
The plugin can then be applied using the `plugins` block:
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
----
include::../gradle/getting-started/apply-plugin-release.gradle[]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/getting-started/apply-plugin-release.gradle.kts[]
----
endif::[] endif::[]
ifeval::["{version-type}" == "SNAPSHOT"] ifeval::["{version-type}" == "SNAPSHOT"]
The plugin is published to the Spring snapshots repository. For Gradle versions less
than 4.10, this means that you must apply the plugin imperatively:
[source,groovy,indent=0,subs="verbatim,attributes"] [source,groovy,indent=0,subs="verbatim,attributes"]
---- ----
include::../gradle/getting-started/apply-plugin-snapshot.gradle[] include::../gradle/getting-started/apply-plugin-milestone.gradle[]
----
For Gradle 4.10 and above, Gradle can be configured to use the snapshots repository
and it can be applied using the `plugins` block. To configure Gradle to use the snapshots
repository, add the following to your `settings.gradle` (Groovy) or `settings.gradle.kts`
(Kotlin):
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
----
include::../gradle/getting-started/snapshot-settings.gradle[]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/getting-started/snapshot-settings.gradle.kts[]
----
The plugin can then be applied using the `plugins` block:
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
----
include::../gradle/getting-started/apply-plugin-release.gradle[]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/getting-started/apply-plugin-release.gradle.kts[]
---- ----
endif::[] endif::[]
@ -34,10 +109,18 @@ A typical Spring Boot project will apply the {groovy-plugin}[`groovy`],
plugin and the {dependency-management-plugin}[`io.spring.dependency-management`] plugin as plugin and the {dependency-management-plugin}[`io.spring.dependency-management`] plugin as
a minimum. For example: a minimum. For example:
[source,groovy,indent=0,subs="verbatim,attributes"]
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/getting-started/typical-plugins.gradle[tags=apply] include::../gradle/getting-started/typical-plugins.gradle[tags=apply]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/getting-started/typical-plugins.gradle.kts[tags=apply]
----
To learn more about how the Spring Boot plugin behaves when other plugins are applied To learn more about how the Spring Boot plugin behaves when other plugins are applied
please see the section on <<reacting-to-other-plugins, reacting to other plugins>>. please see the section on <<reacting-to-other-plugins, reacting to other plugins>>.

@ -37,7 +37,8 @@ Andy Wilkinson
The Spring Boot Gradle Plugin provides Spring Boot support in https://gradle.org[Gradle], The Spring Boot Gradle Plugin provides Spring Boot support in https://gradle.org[Gradle],
allowing you to package executable jar or war archives, run Spring Boot applications, and allowing you to package executable jar or war archives, run Spring Boot applications, and
use the dependency management provided by `spring-boot-dependencies`. Spring Boot's use the dependency management provided by `spring-boot-dependencies`. Spring Boot's
Gradle plugin requires Gradle 4.4 or later. Gradle plugin requires Gradle 4.4 or later. If you choose to use the newer Kotlin DSL,
it requires Gradle 4.10 or later.
In addition to this user guide, {api-documentation}[API documentation] is also available. In addition to this user guide, {api-documentation}[API documentation] is also available.

@ -10,11 +10,19 @@ build in the presence of a `META-INF/build-info.properties` file. A
{build-info-javadoc}[`BuildInfo`] task is provided to generate this file. The easiest way {build-info-javadoc}[`BuildInfo`] task is provided to generate this file. The easiest way
to use the task is via the plugin's DSL: to use the task is via the plugin's DSL:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/integrating-with-actuator/build-info-basic.gradle[tags=build-info] include::../gradle/integrating-with-actuator/build-info-basic.gradle[tags=build-info]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/integrating-with-actuator/build-info-basic.gradle.kts[tags=build-info]
----
This will configure a {build-info-javadoc}[`BuildInfo`] task named `bootBuildInfo` and, if This will configure a {build-info-javadoc}[`BuildInfo`] task named `bootBuildInfo` and, if
it exists, make the Java plugin's `classes` task depend upon it. The task's destination it exists, make the Java plugin's `classes` task depend upon it. The task's destination
directory will be `META-INF` in the output directory of the main source set's resources directory will be `META-INF` in the output directory of the main source set's resources
@ -45,11 +53,19 @@ By default, the generated build information is derived from the project:
The properties can be customized using the DSL: The properties can be customized using the DSL:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/integrating-with-actuator/build-info-custom-values.gradle[tags=custom-values] include::../gradle/integrating-with-actuator/build-info-custom-values.gradle[tags=custom-values]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/integrating-with-actuator/build-info-custom-values.gradle.kts[tags=custom-values]
----
The default value for `build.time` is the instant at which the project is being built. A The default value for `build.time` is the instant at which the project is being built. A
side-effect of this is that the task will never be up-to-date. As a result, builds will side-effect of this is that the task will never be up-to-date. As a result, builds will
take longer as more tasks, including the project's tests, will have to be executed. take longer as more tasks, including the project's tests, will have to be executed.
@ -59,7 +75,15 @@ than the accuracy of the `build.time` property, set `time` to `null` or a fixed
Additional properties can also be added to the build information: Additional properties can also be added to the build information:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/integrating-with-actuator/build-info-additional.gradle[tags=additional] include::../gradle/integrating-with-actuator/build-info-additional.gradle[tags=additional]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/integrating-with-actuator/build-info-additional.gradle.kts[tags=additional]
----

@ -10,11 +10,17 @@ 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 dependencies that are managed in the bom. To make use of this functionality, simply
declare dependencies in the usual way but omit the version number: declare dependencies in the usual way but omit the version number:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim",role="primary"]
.Groovy
---- ----
include::../gradle/managing-dependencies/dependencies.gradle[tags=dependencies] include::../gradle/managing-dependencies/dependencies.gradle[tags=dependencies]
---- ----
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
.Kotlin
----
include::../gradle/managing-dependencies/dependencies.gradle.kts[tags=dependencies]
----
[[managing-dependencies-customizing]] [[managing-dependencies-customizing]]
@ -28,11 +34,19 @@ for a complete list of these properties.
To customize a managed version you set its corresponding property. For example, to To customize a managed version you set its corresponding property. For example, to
customize the version of SLF4J which is controlled by the `slf4j.version` property: customize the version of SLF4J which is controlled by the `slf4j.version` property:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim",role="primary"]
.Groovy
---- ----
include::../gradle/managing-dependencies/custom-version.gradle[tags=custom-version] include::../gradle/managing-dependencies/custom-version.gradle[tags=custom-version]
---- ----
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
.Kotlin
----
include::../gradle/managing-dependencies/custom-version.gradle.kts[tags=custom-version]
----
WARNING: Each Spring Boot release is designed and tested against a specific set of WARNING: Each Spring Boot release is designed and tested against a specific set of
third-party dependencies. Overriding versions may cause compatibility issues and should third-party dependencies. Overriding versions may cause compatibility issues and should
be done with care. be done with care.
@ -50,21 +64,41 @@ artifact ID, or version.
First, configure the project to depend on the Spring Boot plugin but do not apply it: First, configure the project to depend on the Spring Boot plugin but do not apply it:
ifeval::["{version-type}" == "RELEASE"] ifeval::["{version-type}" == "RELEASE"]
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/managing-dependencies/depend-on-plugin-release.gradle[] include::../gradle/managing-dependencies/depend-on-plugin-release.gradle[]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/managing-dependencies/depend-on-plugin-release.gradle.kts[]
----
endif::[] endif::[]
ifeval::["{version-type}" == "MILESTONE"] ifeval::["{version-type}" == "MILESTONE"]
[source,groovy,indent=0,subs="verbatim,attributes"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/managing-dependencies/depend-on-plugin-milestone.gradle[] include::../gradle/managing-dependencies/depend-on-plugin-milestone.gradle[]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/managing-dependencies/depend-on-plugin-release.gradle.kts[]
----
endif::[] endif::[]
ifeval::["{version-type}" == "SNAPSHOT"] ifeval::["{version-type}" == "SNAPSHOT"]
[source,groovy,indent=0,subs="verbatim,attributes"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/managing-dependencies/depend-on-plugin-snapshot.gradle[] include::../gradle/managing-dependencies/depend-on-plugin-snapshot.gradle[]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/managing-dependencies/depend-on-plugin-release.gradle.kts[]
----
endif::[] endif::[]
The Spring Boot plugin's dependency on the dependency management plugin means that you The Spring Boot plugin's dependency on the dependency management plugin means that you
@ -74,11 +108,30 @@ management plugin as Spring Boot uses.
Apply the dependency management plugin and then configure it to import Spring Boot's bom: Apply the dependency management plugin and then configure it to import Spring Boot's bom:
[source,groovy,indent=0,subs="verbatim,attributes"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/managing-dependencies/configure-bom.gradle[tags=configure-bom] include::../gradle/managing-dependencies/configure-bom.gradle[tags=configure-bom]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/managing-dependencies/configure-bom.gradle.kts[tags=configure-bom]
----
The Kotlin code above is a bit awkward. That's because we're using the imperative way of
applying the dependency management plugin.
We can make the code less awkward by applying the plugin from the root parent project, or
by using the `plugins` block as we're doing for the Spring Boot plugin. A downside of this
method is that it forces us to specify the version of the dependency management plugin:
[source,kotlin,indent=0,subs="verbatim,attributes"]
----
include::../gradle/managing-dependencies/configure-bom-with-plugins.gradle.kts[tags=configure-bom]
----
[[managing-dependencies-learning-more]] [[managing-dependencies-learning-more]]

@ -33,11 +33,19 @@ A war file can be packaged such that it can be executed using `java -jar` and de
to an external container. To do so, the embedded servlet container dependencies should to an external container. To do so, the embedded servlet container dependencies should
be added to the `providedRuntime` configuration, for example: be added to the `providedRuntime` configuration, for example:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/war-container-dependency.gradle[tags=dependencies] include::../gradle/packaging/war-container-dependency.gradle[tags=dependencies]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/war-container-dependency.gradle.kts[tags=dependencies]
----
This ensures that they are package in the war file's `WEB-INF/lib-provided` directory This ensures that they are package in the war file's `WEB-INF/lib-provided` directory
from where they will not conflict with the external container's own classes. from where they will not conflict with the external container's own classes.
@ -54,20 +62,36 @@ By default, when the `bootJar` or `bootWar` tasks are configured, the `jar` or `
tasks are disabled. A project can be configured to build both an executable archive tasks are disabled. A project can be configured to build both an executable archive
and a normal archive at the same time by enabling the `jar` or `war` task: and a normal archive at the same time by enabling the `jar` or `war` task:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/boot-jar-and-jar.gradle[tags=enable-jar] include::../gradle/packaging/boot-jar-and-jar.gradle[tags=enable-jar]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-jar-and-jar.gradle.kts[tags=enable-jar]
----
To avoid the executable archive and the normal archive from being written to the same To avoid the executable archive and the normal archive from being written to the same
location, one or the other should be configured to use a different location. One way to location, one or the other should be configured to use a different location. One way to
do so is by configuring a classifier: do so is by configuring a classifier:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/boot-jar-and-jar.gradle[tags=classifier] include::../gradle/packaging/boot-jar-and-jar.gradle[tags=classifier]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-jar-and-jar.gradle.kts[tags=classifier]
----
[[packaging-executable-configuring]] [[packaging-executable-configuring]]
=== Configuring executable archive packaging === Configuring executable archive packaging
@ -88,34 +112,63 @@ the task's classpath.
The main class can also be configured explicitly using the task's `mainClassName` The main class can also be configured explicitly using the task's `mainClassName`
property: property:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/boot-jar-main-class.gradle[tags=main-class] include::../gradle/packaging/boot-jar-main-class.gradle[tags=main-class]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-jar-main-class.gradle.kts[tags=main-class]
----
Alternatively, the main class name can be configured project-wide using the Alternatively, the main class name can be configured project-wide using the
`mainClassName` property of the Spring Boot DSL: `mainClassName` property of the Spring Boot DSL:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/spring-boot-dsl-main-class.gradle[tags=main-class] include::../gradle/packaging/spring-boot-dsl-main-class.gradle[tags=main-class]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/spring-boot-dsl-main-class.gradle.kts[tags=main-class]
----
If the {application-plugin}[`application` plugin] has been applied its `mainClassName` If the {application-plugin}[`application` plugin] has been applied its `mainClassName`
project property can be used for the same purpose: project property can be used for the same purpose:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/application-plugin-main-class.gradle[tags=main-class] include::../gradle/packaging/application-plugin-main-class.gradle[tags=main-class]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/application-plugin-main-class.gradle.kts[tags=main-class]
----
Lastly, the `Start-Class` attribute can be configured on the task's manifest: Lastly, the `Start-Class` attribute can be configured on the task's manifest:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/boot-jar-manifest-main-class.gradle[tags=main-class] include::../gradle/packaging/boot-jar-manifest-main-class.gradle[tags=main-class]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-jar-manifest-main-class.gradle.kts[tags=main-class]
----
[[packaging-executable-configuring-excluding-devtools]] [[packaging-executable-configuring-excluding-devtools]]
@ -126,11 +179,17 @@ By default, Spring Boot's Devtools module,
or war. If you want to include Devtools in your archive set the `excludeDevtools` or war. If you want to include Devtools in your archive set the `excludeDevtools`
property to `false`: property to `false`:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/boot-war-include-devtools.gradle[tags=include-devtools] include::../gradle/packaging/boot-war-include-devtools.gradle[tags=include-devtools]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-war-include-devtools.gradle.kts[tags=include-devtools]
----
[[packaging-executable-configuring-unpacking]] [[packaging-executable-configuring-unpacking]]
@ -145,11 +204,19 @@ specific nested jars to a temporary folder when the executable archive is run. L
can be identified as requiring unpacking using Ant-style patterns that match against can be identified as requiring unpacking using Ant-style patterns that match against
the absolute path of the source jar file: the absolute path of the source jar file:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/boot-jar-requires-unpack.gradle[tags=requires-unpack] include::../gradle/packaging/boot-jar-requires-unpack.gradle[tags=requires-unpack]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-jar-requires-unpack.gradle.kts[tags=requires-unpack]
----
For more control a closure can also be used. The closure is passed a `FileTreeElement` For more control a closure can also be used. The closure is passed a `FileTreeElement`
and should return a `boolean` indicating whether or not unpacking is required. and should return a `boolean` indicating whether or not unpacking is required.
@ -165,28 +232,50 @@ other executable or to be installed as a service.
To use this feature, the inclusion of the launch script must be enabled: To use this feature, the inclusion of the launch script must be enabled:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/boot-jar-include-launch-script.gradle[tags=include-launch-script] include::../gradle/packaging/boot-jar-include-launch-script.gradle[tags=include-launch-script]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-jar-include-launch-script.gradle.kts[tags=include-launch-script]
----
This will add Spring Boot's default launch script to the archive. The default launch This will add Spring Boot's default launch script to the archive. The default launch
script includes several properties with sensible default values. The values can be script includes several properties with sensible default values. The values can be
customized using the `properties` property: customized using the `properties` property:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/boot-jar-launch-script-properties.gradle[tags=launch-script-properties] include::../gradle/packaging/boot-jar-launch-script-properties.gradle[tags=launch-script-properties]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-jar-launch-script-properties.gradle.kts[tags=launch-script-properties]
----
If the default launch script does not meet your needs, the `script` property can be used If the default launch script does not meet your needs, the `script` property can be used
to provide a custom launch script: to provide a custom launch script:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/boot-jar-custom-launch-script.gradle[tags=custom-launch-script] include::../gradle/packaging/boot-jar-custom-launch-script.gradle[tags=custom-launch-script]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-jar-custom-launch-script.gradle.kts[tags=custom-launch-script]
----
[[packaging-executable-configuring-properties-launcher]] [[packaging-executable-configuring-properties-launcher]]
@ -195,7 +284,15 @@ include::../gradle/packaging/boot-jar-custom-launch-script.gradle[tags=custom-la
To use the `PropertiesLauncher` to launch an executable jar or war, configure the task's To use the `PropertiesLauncher` to launch an executable jar or war, configure the task's
manifest to set the `Main-Class` attribute: manifest to set the `Main-Class` attribute:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/packaging/boot-war-properties-launcher.gradle[tags=properties-launcher] include::../gradle/packaging/boot-war-properties-launcher.gradle[tags=properties-launcher]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/packaging/boot-war-properties-launcher.gradle.kts[tags=properties-launcher]
----

@ -12,11 +12,19 @@ default, the `bootArchives` configuration contains the archive produced by the `
or `bootWar` task. The `uploadBootArchives` task can be configured to publish the archive or `bootWar` task. The `uploadBootArchives` task can be configured to publish the archive
to a Maven repository: to a Maven repository:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/publishing/maven.gradle[tags=upload] include::../gradle/publishing/maven.gradle[tags=upload]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/publishing/maven.gradle.kts[tags=upload]
----
[[publishing-your-application-maven-publish]] [[publishing-your-application-maven-publish]]
=== Publishing with the `maven-publish` plugin === Publishing with the `maven-publish` plugin
@ -25,11 +33,17 @@ method on `MavenPublication`. Pass the task that produces that artifact that you
to publish to the `artifact` method. For example, to publish the artifact produced by the to publish to the `artifact` method. For example, to publish the artifact produced by the
default `bootJar` task: default `bootJar` task:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/publishing/maven-publish.gradle[tags=publishing] include::../gradle/publishing/maven-publish.gradle[tags=publishing]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/publishing/maven-publish.gradle.kts[tags=publishing]
----
[[publishing-your-application-distribution]] [[publishing-your-application-distribution]]

@ -19,27 +19,49 @@ By default, the main class will be configured automatically by looking for a cla
The main class can also be configured explicitly using the task's `main` property: The main class can also be configured explicitly using the task's `main` property:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/running/boot-run-main.gradle[tags=main] include::../gradle/running/boot-run-main.gradle[tags=main]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/running/boot-run-main.gradle.kts[tags=main]
----
Alternatively, the main class name can be configured project-wide using the Alternatively, the main class name can be configured project-wide using the
`mainClassName` property of the Spring Boot DSL: `mainClassName` property of the Spring Boot DSL:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/running/spring-boot-dsl-main-class-name.gradle[tags=main-class] include::../gradle/running/spring-boot-dsl-main-class-name.gradle[tags=main-class]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/running/spring-boot-dsl-main-class-name.gradle.kts[tags=main-class]
----
If the {application-plugin}[`application` plugin] has been applied, its `mainClassName` If the {application-plugin}[`application` plugin] has been applied, its `mainClassName`
project property can be used for the same purpose: project property can be used for the same purpose:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/running/application-plugin-main-class-name.gradle[tags=main-class] include::../gradle/running/application-plugin-main-class-name.gradle[tags=main-class]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/running/application-plugin-main-class-name.gradle.kts[tags=main-class]
----
[[running-your-application-passing-arguments]] [[running-your-application-passing-arguments]]
@ -64,10 +86,18 @@ If devtools has been added to your project it will automatically monitor your
application for changes. Alternatively, you can configure `bootRun` such that your application for changes. Alternatively, you can configure `bootRun` such that your
application's static resources are loaded from their source location: application's static resources are loaded from their source location:
[source,groovy,indent=0,subs="verbatim"] [source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
---- ----
include::../gradle/running/boot-run-source-resources.gradle[tags=source-resources] include::../gradle/running/boot-run-source-resources.gradle[tags=source-resources]
---- ----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/running/boot-run-source-resources.gradle.kts[tags=source-resources]
----
This makes them reloadable in the live application which can be helpful at development This makes them reloadable in the live application which can be helpful at development
time. time.

@ -0,0 +1,14 @@
pluginManagement {
repositories {
maven {
url 'https://repo.spring.io/libs-milestone'
}
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == 'org.springframework.boot') {
useModule "org.springframework.boot:spring-boot-gradle-plugin:${requested.version}"
}
}
}
}

@ -0,0 +1,14 @@
pluginManagement {
repositories {
maven {
url = uri("https://repo.spring.io/libs-milestone")
}
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.springframework.boot") {
useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}")
}
}
}
}

@ -0,0 +1,14 @@
pluginManagement {
repositories {
maven {
url 'https://repo.spring.io/libs-snapshot'
}
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == 'org.springframework.boot') {
useModule "org.springframework.boot:spring-boot-gradle-plugin:${requested.version}"
}
}
}
}

@ -0,0 +1,14 @@
pluginManagement {
repositories {
maven {
url = uri("https://repo.spring.io/libs-snapshot")
}
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.springframework.boot") {
useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}")
}
}
}
}

@ -0,0 +1,15 @@
// tag::apply[]
plugins {
java
id("org.springframework.boot") version "{version}"
}
apply(plugin = "io.spring.dependency-management")
// end::apply[]
task("verify") {
doLast {
project.plugins.getPlugin(JavaPlugin::class)
project.plugins.getPlugin(io.spring.gradle.dependencymanagement.DependencyManagementPlugin::class)
}
}

@ -0,0 +1,18 @@
plugins {
java
id("org.springframework.boot") version "{version}"
}
// tag::additional[]
springBoot {
buildInfo {
properties {
additional = mapOf(
"a" to "alpha",
"b" to "bravo"
)
}
}
}
// end::additional[]

@ -0,0 +1,10 @@
plugins {
java
id("org.springframework.boot") version "{version}"
}
// tag::build-info[]
springBoot {
buildInfo()
}
// end::build-info[]

@ -0,0 +1,17 @@
plugins {
java
id("org.springframework.boot") version "{version}"
}
// tag::custom-values[]
springBoot {
buildInfo {
properties {
artifact = "example-app"
version = "1.2.3"
group = "com.example"
name = "Example application"
}
}
}
// end::custom-values[]

@ -0,0 +1,27 @@
// tag::configure-bom[]
plugins {
java
id("org.springframework.boot") version "{version}" apply false
id("io.spring.dependency-management") version "{dependency-management-plugin-version}"
}
dependencyManagement {
imports {
mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
}
}
// end::configure-bom[]
dependencyManagement {
resolutionStrategy {
eachDependency {
if (requested.group == "org.springframework.boot") {
useVersion("{version}")
}
}
}
}
repositories {
mavenLocal()
}

@ -3,13 +3,21 @@ plugins {
id 'org.springframework.boot' version '{version}' id 'org.springframework.boot' version '{version}'
} }
// tag::configure-bom[]
apply plugin: 'io.spring.dependency-management' apply plugin: 'io.spring.dependency-management'
dependencyManagement {
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
}
}
// end::configure-bom[]
dependencyManagement { dependencyManagement {
resolutionStrategy { resolutionStrategy {
eachDependency { eachDependency {
if (it.requested.group == 'org.springframework.boot') { if (it.requested.group == 'org.springframework.boot') {
it.useVersion project.bootVersion it.useVersion '{version}'
} }
} }
} }
@ -18,13 +26,3 @@ dependencyManagement {
repositories { repositories {
mavenLocal() mavenLocal()
} }
// tag::configure-bom[]
apply plugin: 'io.spring.dependency-management'
dependencyManagement {
imports {
mavenBom org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES
}
}
// end::configure-bom[]

@ -0,0 +1,30 @@
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension
plugins {
java
id("org.springframework.boot") version "{version}"
}
// tag::configure-bom[]
apply(plugin = "io.spring.dependency-management")
the<DependencyManagementExtension>().apply {
imports {
mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
}
}
// end::configure-bom[]
the<DependencyManagementExtension>().apply {
resolutionStrategy {
eachDependency {
if (requested.group == "org.springframework.boot") {
useVersion("{version}")
}
}
}
}
repositories {
mavenLocal()
}

@ -8,7 +8,7 @@ dependencyManagement {
resolutionStrategy { resolutionStrategy {
eachDependency { eachDependency {
if (it.requested.group == 'org.springframework.boot') { if (it.requested.group == 'org.springframework.boot') {
it.useVersion project.bootVersion it.useVersion '{version}'
} }
} }
} }

@ -0,0 +1,31 @@
import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension
plugins {
id("org.springframework.boot") version "{version}"
}
apply(plugin = "io.spring.dependency-management")
the<DependencyManagementExtension>().apply {
resolutionStrategy {
eachDependency {
if (requested.group == "org.springframework.boot") {
useVersion("{version}")
}
}
}
}
// tag::custom-version[]
extra["slf4j.version"] = "1.7.20"
// end::custom-version[]
repositories {
mavenLocal()
}
task("slf4jVersion") {
doLast {
println(project.the<DependencyManagementExtension>().managedVersions["org.slf4j:slf4j-api"])
}
}

@ -0,0 +1,13 @@
plugins {
java
id("org.springframework.boot") version "{version}"
}
apply(plugin = "io.spring.dependency-management")
// tag::dependencies[]
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
}
// end::dependencies[]

@ -0,0 +1,11 @@
plugins {
java
application
id("org.springframework.boot") version "{version}"
}
// tag::main-class[]
application {
mainClassName = "com.example.ExampleApplication"
}
// end::main-class[]

@ -0,0 +1,22 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
java
id("org.springframework.boot") version "{version}"
}
// tag::enable-jar[]
tasks.getByName<Jar>("jar") {
enabled = true
}
// end::enable-jar[]
// tag::classifier[]
tasks.getByName<BootJar>("bootJar") {
classifier = "boot"
}
// end::classifier[]
tasks.getByName<BootJar>("bootJar") {
mainClassName = "com.example.Application"
}

@ -0,0 +1,18 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
java
id("org.springframework.boot") version "{version}"
}
tasks.getByName<BootJar>("bootJar") {
mainClassName = "com.example.ExampleApplication"
}
// tag::custom-launch-script[]
tasks.getByName<BootJar>("bootJar") {
launchScript {
script = file("src/custom.script")
}
}
// end::custom-launch-script[]

@ -0,0 +1,16 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
java
id("org.springframework.boot") version "{version}"
}
tasks.getByName<BootJar>("bootJar") {
mainClassName = "com.example.ExampleApplication"
}
// tag::include-launch-script[]
tasks.getByName<BootJar>("bootJar") {
launchScript()
}
// end::include-launch-script[]

@ -0,0 +1,18 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
java
id("org.springframework.boot") version "{version}"
}
tasks.getByName<BootJar>("bootJar") {
mainClassName = "com.example.ExampleApplication"
}
// tag::launch-script-properties[]
tasks.getByName<BootJar>("bootJar") {
launchScript {
properties(mapOf("logFilename" to "example-app.log"))
}
}
// end::launch-script-properties[]

@ -0,0 +1,12 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
java
id("org.springframework.boot") version "{version}"
}
// tag::main-class[]
tasks.getByName<BootJar>("bootJar") {
mainClassName = "com.example.ExampleApplication"
}
// end::main-class[]

@ -0,0 +1,14 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
java
id("org.springframework.boot") version "{version}"
}
// tag::main-class[]
tasks.getByName<BootJar>("bootJar") {
manifest {
attributes("Start-Class" to "com.example.ExampleApplication")
}
}
// end::main-class[]

@ -0,0 +1,24 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
java
id("org.springframework.boot") version "{version}"
}
repositories {
mavenCentral()
}
dependencies {
runtimeOnly("org.jruby:jruby-complete:1.7.25")
}
tasks.getByName<BootJar>("bootJar") {
mainClassName = "com.example.ExampleApplication"
}
// tag::requires-unpack[]
tasks.getByName<BootJar>("bootJar") {
requiresUnpack("**/jruby-complete-*.jar")
}
// end::requires-unpack[]

@ -0,0 +1,17 @@
import org.springframework.boot.gradle.tasks.bundling.BootWar
plugins {
war
id("org.springframework.boot") version "{version}"
}
tasks.getByName<BootWar>("bootWar") {
mainClassName = "com.example.ExampleApplication"
classpath(file("spring-boot-devtools-1.2.3.RELEASE.jar"))
}
// tag::include-devtools[]
tasks.getByName<BootWar>("bootWar") {
isExcludeDevtools = false
}
// end::include-devtools[]

@ -0,0 +1,18 @@
import org.springframework.boot.gradle.tasks.bundling.BootWar
plugins {
war
id("org.springframework.boot") version "{version}"
}
tasks.getByName<BootWar>("bootWar") {
mainClassName = "com.example.ExampleApplication"
}
// tag::properties-launcher[]
tasks.getByName<BootWar>("bootWar") {
manifest {
attributes("Main-Class" to "org.springframework.boot.loader.PropertiesLauncher")
}
}
// end::properties-launcher[]

@ -0,0 +1,10 @@
plugins {
war
id("org.springframework.boot") version "{version}"
}
// tag::main-class[]
springBoot {
mainClassName = "com.example.ExampleApplication"
}
// end::main-class[]

@ -0,0 +1,13 @@
plugins {
war
id("org.springframework.boot") version "{version}"
}
apply(plugin = "io.spring.dependency-management")
// tag::dependencies[]
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
}
// end::dependencies[]

@ -0,0 +1,27 @@
plugins {
java
`maven-publish`
id("org.springframework.boot") version "{version}"
}
// tag::publishing[]
publishing {
publications {
create<MavenPublication>("bootJava") {
artifact(tasks.getByName("bootJar"))
}
}
repositories {
maven {
url = uri("https://repo.example.com")
}
}
}
// end::publishing[]
task("publishingConfiguration") {
doLast {
println(publishing.publications["bootJava"])
println(publishing.repositories.getByName<MavenArtifactRepository>("maven").url)
}
}

@ -0,0 +1,26 @@
plugins {
java
maven
id("org.springframework.boot") version "{version}"
}
// tag::upload[]
tasks.getByName<Upload>("uploadBootArchives") {
repositories.withGroovyBuilder {
"mavenDeployer" {
"repository"("url" to "https://repo.example.com")
}
}
}
// end::upload[]
val url = tasks.getByName<Upload>("uploadBootArchives")
.repositories
.withGroovyBuilder { getProperty("mavenDeployer") }
.withGroovyBuilder { getProperty("repository") }
.withGroovyBuilder { getProperty("url") }
task("deployerRepository") {
doLast {
println(url)
}
}

@ -0,0 +1,19 @@
import org.springframework.boot.gradle.tasks.run.BootRun
plugins {
java
application
id("org.springframework.boot") version "{version}"
}
// tag::main-class[]
application {
mainClassName = "com.example.ExampleApplication"
}
// end::main-class[]
task("configuredMainClass") {
doLast {
println(tasks.getByName<BootRun>("bootRun").main)
}
}

@ -0,0 +1,18 @@
import org.springframework.boot.gradle.tasks.run.BootRun
plugins {
java
id("org.springframework.boot") version "{version}"
}
// tag::main[]
tasks.getByName<BootRun>("bootRun") {
main = "com.example.ExampleApplication"
}
// end::main[]
task("configuredMainClass") {
doLast {
println(tasks.getByName<BootRun>("bootRun").main)
}
}

@ -0,0 +1,18 @@
import org.springframework.boot.gradle.tasks.run.BootRun
plugins {
java
id("org.springframework.boot") version "{version}"
}
// tag::source-resources[]
tasks.getByName<BootRun>("bootRun") {
sourceResources(sourceSets["main"])
}
// end::source-resources[]
task("configuredClasspath") {
doLast {
println(tasks.getByName<BootRun>("bootRun").classpath.files)
}
}

@ -0,0 +1,19 @@
import org.springframework.boot.gradle.tasks.run.BootRun
plugins {
java
application
id("org.springframework.boot") version "{version}"
}
// tag::main-class[]
springBoot {
mainClassName = "com.example.ExampleApplication"
}
// end::main-class[]
task("configuredMainClass") {
doLast {
println(tasks.getByName<BootRun>("bootRun").main)
}
}

@ -18,25 +18,29 @@ package org.springframework.boot.gradle.docs;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.gradle.junit.GradleMultiDslSuite;
import org.springframework.boot.gradle.testkit.GradleBuild; import org.springframework.boot.gradle.testkit.GradleBuild;
/** /**
* Tests for the getting started documentation. * Tests for the getting started documentation.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Jean-Baptiste Nizet
*/ */
@RunWith(GradleMultiDslSuite.class)
public class GettingStartedDocumentationTests { public class GettingStartedDocumentationTests {
@Rule @Rule
public GradleBuild gradleBuild = new GradleBuild(); public GradleBuild gradleBuild;
// NOTE: We can't run any `apply-plugin` tests because during a release the // NOTE: We can't run any `apply-plugin` tests because during a release the
// jar won't be there // jar won't be there
@Test @Test
public void typicalPluginsAppliesExceptedPlugins() { public void typicalPluginsAppliesExceptedPlugins() {
this.gradleBuild.script("src/main/gradle/getting-started/typical-plugins.gradle") this.gradleBuild.script("src/main/gradle/getting-started/typical-plugins")
.build("verify"); .build("verify");
} }

@ -23,7 +23,9 @@ import java.util.Properties;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.gradle.junit.GradleMultiDslSuite;
import org.springframework.boot.gradle.testkit.GradleBuild; import org.springframework.boot.gradle.testkit.GradleBuild;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -32,16 +34,18 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for the generating build info documentation. * Tests for the generating build info documentation.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Jean-Baptiste Nizet
*/ */
@RunWith(GradleMultiDslSuite.class)
public class IntegratingWithActuatorDocumentationTests { public class IntegratingWithActuatorDocumentationTests {
@Rule @Rule
public GradleBuild gradleBuild = new GradleBuild(); public GradleBuild gradleBuild;
@Test @Test
public void basicBuildInfo() throws IOException { public void basicBuildInfo() throws IOException {
this.gradleBuild.script( this.gradleBuild
"src/main/gradle/integrating-with-actuator/build-info-basic.gradle") .script("src/main/gradle/integrating-with-actuator/build-info-basic")
.build("bootBuildInfo"); .build("bootBuildInfo");
assertThat(new File(this.gradleBuild.getProjectDir(), assertThat(new File(this.gradleBuild.getProjectDir(),
"build/resources/main/META-INF/build-info.properties")).isFile(); "build/resources/main/META-INF/build-info.properties")).isFile();
@ -50,7 +54,7 @@ public class IntegratingWithActuatorDocumentationTests {
@Test @Test
public void buildInfoCustomValues() throws IOException { public void buildInfoCustomValues() throws IOException {
this.gradleBuild.script( this.gradleBuild.script(
"src/main/gradle/integrating-with-actuator/build-info-custom-values.gradle") "src/main/gradle/integrating-with-actuator/build-info-custom-values")
.build("bootBuildInfo"); .build("bootBuildInfo");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/resources/main/META-INF/build-info.properties"); "build/resources/main/META-INF/build-info.properties");
@ -64,8 +68,8 @@ public class IntegratingWithActuatorDocumentationTests {
@Test @Test
public void buildInfoAdditional() throws IOException { public void buildInfoAdditional() throws IOException {
this.gradleBuild.script( this.gradleBuild
"src/main/gradle/integrating-with-actuator/build-info-additional.gradle") .script("src/main/gradle/integrating-with-actuator/build-info-additional")
.build("bootBuildInfo"); .build("bootBuildInfo");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/resources/main/META-INF/build-info.properties"); "build/resources/main/META-INF/build-info.properties");

@ -16,9 +16,13 @@
package org.springframework.boot.gradle.docs; package org.springframework.boot.gradle.docs;
import org.junit.Assume;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.gradle.junit.GradleMultiDslSuite;
import org.springframework.boot.gradle.testkit.Dsl;
import org.springframework.boot.gradle.testkit.GradleBuild; import org.springframework.boot.gradle.testkit.GradleBuild;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -27,30 +31,40 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for the managing dependencies documentation. * Tests for the managing dependencies documentation.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Jean-Baptiste Nizet
*/ */
@RunWith(GradleMultiDslSuite.class)
public class ManagingDependenciesDocumentationTests { public class ManagingDependenciesDocumentationTests {
@Rule @Rule
public GradleBuild gradleBuild = new GradleBuild(); public GradleBuild gradleBuild;
@Test @Test
public void dependenciesExampleEvaluatesSuccessfully() { public void dependenciesExampleEvaluatesSuccessfully() {
this.gradleBuild this.gradleBuild.script("src/main/gradle/managing-dependencies/dependencies")
.script("src/main/gradle/managing-dependencies/dependencies.gradle")
.build(); .build();
} }
@Test @Test
public void customManagedVersions() { public void customManagedVersions() {
assertThat(this.gradleBuild assertThat(this.gradleBuild
.script("src/main/gradle/managing-dependencies/custom-version.gradle") .script("src/main/gradle/managing-dependencies/custom-version")
.build("slf4jVersion").getOutput()).contains("1.7.20"); .build("slf4jVersion").getOutput()).contains("1.7.20");
} }
@Test @Test
public void dependencyManagementInIsolation() { public void dependencyManagementInIsolation() {
assertThat(this.gradleBuild assertThat(this.gradleBuild
.script("src/main/gradle/managing-dependencies/configure-bom.gradle") .script("src/main/gradle/managing-dependencies/configure-bom")
.build("dependencyManagement").getOutput())
.contains("org.springframework.boot:spring-boot-starter ");
}
@Test
public void dependencyManagementInIsolationWithPluginsBlock() {
Assume.assumeTrue(this.gradleBuild.getDsl() == Dsl.KOTLIN);
assertThat(this.gradleBuild.script(
"src/main/gradle/managing-dependencies/configure-bom-with-plugins")
.build("dependencyManagement").getOutput()) .build("dependencyManagement").getOutput())
.contains("org.springframework.boot:spring-boot-starter "); .contains("org.springframework.boot:spring-boot-starter ");
} }

@ -25,7 +25,10 @@ import java.util.jar.JarFile;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.gradle.junit.GradleMultiDslSuite;
import org.springframework.boot.gradle.testkit.Dsl;
import org.springframework.boot.gradle.testkit.GradleBuild; import org.springframework.boot.gradle.testkit.GradleBuild;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
@ -35,22 +38,25 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for the packaging documentation. * Tests for the packaging documentation.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Jean-Baptiste Nizet
*/ */
@RunWith(GradleMultiDslSuite.class)
public class PackagingDocumentationTests { public class PackagingDocumentationTests {
@Rule @Rule
public GradleBuild gradleBuild = new GradleBuild(); public GradleBuild gradleBuild;
public Dsl dsl;
@Test @Test
public void warContainerDependencyEvaluatesSuccessfully() { public void warContainerDependencyEvaluatesSuccessfully() {
this.gradleBuild this.gradleBuild.script("src/main/gradle/packaging/war-container-dependency")
.script("src/main/gradle/packaging/war-container-dependency.gradle")
.build(); .build();
} }
@Test @Test
public void bootJarMainClass() throws IOException { public void bootJarMainClass() throws IOException {
this.gradleBuild.script("src/main/gradle/packaging/boot-jar-main-class.gradle") this.gradleBuild.script("src/main/gradle/packaging/boot-jar-main-class")
.build("bootJar"); .build("bootJar");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
@ -63,8 +69,7 @@ public class PackagingDocumentationTests {
@Test @Test
public void bootJarManifestMainClass() throws IOException { public void bootJarManifestMainClass() throws IOException {
this.gradleBuild this.gradleBuild.script("src/main/gradle/packaging/boot-jar-manifest-main-class")
.script("src/main/gradle/packaging/boot-jar-manifest-main-class.gradle")
.build("bootJar"); .build("bootJar");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
@ -77,8 +82,7 @@ public class PackagingDocumentationTests {
@Test @Test
public void applicationPluginMainClass() throws IOException { public void applicationPluginMainClass() throws IOException {
this.gradleBuild this.gradleBuild.script("src/main/gradle/packaging/application-plugin-main-class")
.script("src/main/gradle/packaging/application-plugin-main-class.gradle")
.build("bootJar"); .build("bootJar");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
@ -91,8 +95,7 @@ public class PackagingDocumentationTests {
@Test @Test
public void springBootDslMainClass() throws IOException { public void springBootDslMainClass() throws IOException {
this.gradleBuild this.gradleBuild.script("src/main/gradle/packaging/spring-boot-dsl-main-class")
.script("src/main/gradle/packaging/spring-boot-dsl-main-class.gradle")
.build("bootJar"); .build("bootJar");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
@ -107,8 +110,7 @@ public class PackagingDocumentationTests {
public void bootWarIncludeDevtools() throws IOException { public void bootWarIncludeDevtools() throws IOException {
new File(this.gradleBuild.getProjectDir(), new File(this.gradleBuild.getProjectDir(),
"spring-boot-devtools-1.2.3.RELEASE.jar").createNewFile(); "spring-boot-devtools-1.2.3.RELEASE.jar").createNewFile();
this.gradleBuild this.gradleBuild.script("src/main/gradle/packaging/boot-war-include-devtools")
.script("src/main/gradle/packaging/boot-war-include-devtools.gradle")
.build("bootWar"); .build("bootWar");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".war"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".war");
@ -121,8 +123,7 @@ public class PackagingDocumentationTests {
@Test @Test
public void bootJarRequiresUnpack() throws IOException { public void bootJarRequiresUnpack() throws IOException {
this.gradleBuild this.gradleBuild.script("src/main/gradle/packaging/boot-jar-requires-unpack")
.script("src/main/gradle/packaging/boot-jar-requires-unpack.gradle")
.build("bootJar"); .build("bootJar");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
@ -137,7 +138,7 @@ public class PackagingDocumentationTests {
@Test @Test
public void bootJarIncludeLaunchScript() throws IOException { public void bootJarIncludeLaunchScript() throws IOException {
this.gradleBuild this.gradleBuild
.script("src/main/gradle/packaging/boot-jar-include-launch-script.gradle") .script("src/main/gradle/packaging/boot-jar-include-launch-script")
.build("bootJar"); .build("bootJar");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
@ -148,8 +149,8 @@ public class PackagingDocumentationTests {
@Test @Test
public void bootJarLaunchScriptProperties() throws IOException { public void bootJarLaunchScriptProperties() throws IOException {
this.gradleBuild.script( this.gradleBuild
"src/main/gradle/packaging/boot-jar-launch-script-properties.gradle") .script("src/main/gradle/packaging/boot-jar-launch-script-properties")
.build("bootJar"); .build("bootJar");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
@ -164,8 +165,7 @@ public class PackagingDocumentationTests {
"src/custom.script"); "src/custom.script");
customScriptFile.getParentFile().mkdirs(); customScriptFile.getParentFile().mkdirs();
FileCopyUtils.copy("custom", new FileWriter(customScriptFile)); FileCopyUtils.copy("custom", new FileWriter(customScriptFile));
this.gradleBuild this.gradleBuild.script("src/main/gradle/packaging/boot-jar-custom-launch-script")
.script("src/main/gradle/packaging/boot-jar-custom-launch-script.gradle")
.build("bootJar"); .build("bootJar");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");
@ -175,8 +175,7 @@ public class PackagingDocumentationTests {
@Test @Test
public void bootWarPropertiesLauncher() throws IOException { public void bootWarPropertiesLauncher() throws IOException {
this.gradleBuild this.gradleBuild.script("src/main/gradle/packaging/boot-war-properties-launcher")
.script("src/main/gradle/packaging/boot-war-properties-launcher.gradle")
.build("bootWar"); .build("bootWar");
File file = new File(this.gradleBuild.getProjectDir(), File file = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".war"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".war");
@ -188,8 +187,8 @@ public class PackagingDocumentationTests {
} }
@Test @Test
public void bootJarAndJar() throws IOException { public void bootJarAndJar() {
this.gradleBuild.script("src/main/gradle/packaging/boot-jar-and-jar.gradle") this.gradleBuild.script("src/main/gradle/packaging/boot-jar-and-jar")
.build("assemble"); .build("assemble");
File jar = new File(this.gradleBuild.getProjectDir(), File jar = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar"); "build/libs/" + this.gradleBuild.getProjectDir().getName() + ".jar");

@ -20,7 +20,9 @@ import java.io.IOException;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.gradle.junit.GradleMultiDslSuite;
import org.springframework.boot.gradle.testkit.GradleBuild; import org.springframework.boot.gradle.testkit.GradleBuild;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -29,23 +31,24 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for the publishing documentation. * Tests for the publishing documentation.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Jean-Baptiste Nizet
*/ */
@RunWith(GradleMultiDslSuite.class)
public class PublishingDocumentationTests { public class PublishingDocumentationTests {
@Rule @Rule
public GradleBuild gradleBuild = new GradleBuild(); public GradleBuild gradleBuild;
@Test @Test
public void mavenUpload() throws IOException { public void mavenUpload() throws IOException {
assertThat(this.gradleBuild.script("src/main/gradle/publishing/maven.gradle") assertThat(this.gradleBuild.script("src/main/gradle/publishing/maven")
.build("deployerRepository").getOutput()) .build("deployerRepository").getOutput())
.contains("https://repo.example.com"); .contains("https://repo.example.com");
} }
@Test @Test
public void mavenPublish() throws IOException { public void mavenPublish() throws IOException {
assertThat( assertThat(this.gradleBuild.script("src/main/gradle/publishing/maven-publish")
this.gradleBuild.script("src/main/gradle/publishing/maven-publish.gradle")
.build("publishingConfiguration").getOutput()) .build("publishingConfiguration").getOutput())
.contains("MavenPublication") .contains("MavenPublication")
.contains("https://repo.example.com"); .contains("https://repo.example.com");

@ -21,7 +21,9 @@ import java.io.IOException;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.gradle.junit.GradleMultiDslSuite;
import org.springframework.boot.gradle.testkit.GradleBuild; import org.springframework.boot.gradle.testkit.GradleBuild;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -30,23 +32,25 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for the documentation about running a Spring Boot application. * Tests for the documentation about running a Spring Boot application.
* *
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Jean-Baptiste Nizet
*/ */
@RunWith(GradleMultiDslSuite.class)
public class RunningDocumentationTests { public class RunningDocumentationTests {
@Rule @Rule
public GradleBuild gradleBuild = new GradleBuild(); public GradleBuild gradleBuild;
@Test @Test
public void bootRunMain() throws IOException { public void bootRunMain() throws IOException {
assertThat(this.gradleBuild.script("src/main/gradle/running/boot-run-main.gradle") assertThat(this.gradleBuild.script("src/main/gradle/running/boot-run-main")
.build("configuredMainClass").getOutput()) .build("configuredMainClass").getOutput())
.contains("com.example.ExampleApplication"); .contains("com.example.ExampleApplication");
} }
@Test @Test
public void applicationPluginMainClassName() throws IOException { public void applicationPluginMainClassName() {
assertThat(this.gradleBuild.script( assertThat(this.gradleBuild
"src/main/gradle/running/application-plugin-main-class-name.gradle") .script("src/main/gradle/running/application-plugin-main-class-name")
.build("configuredMainClass").getOutput()) .build("configuredMainClass").getOutput())
.contains("com.example.ExampleApplication"); .contains("com.example.ExampleApplication");
} }
@ -54,7 +58,7 @@ public class RunningDocumentationTests {
@Test @Test
public void springBootDslMainClassName() throws IOException { public void springBootDslMainClassName() throws IOException {
assertThat(this.gradleBuild assertThat(this.gradleBuild
.script("src/main/gradle/running/spring-boot-dsl-main-class-name.gradle") .script("src/main/gradle/running/spring-boot-dsl-main-class-name")
.build("configuredMainClass").getOutput()) .build("configuredMainClass").getOutput())
.contains("com.example.ExampleApplication"); .contains("com.example.ExampleApplication");
} }
@ -62,7 +66,7 @@ public class RunningDocumentationTests {
@Test @Test
public void bootRunSourceResources() throws IOException { public void bootRunSourceResources() throws IOException {
assertThat(this.gradleBuild assertThat(this.gradleBuild
.script("src/main/gradle/running/boot-run-source-resources.gradle") .script("src/main/gradle/running/boot-run-source-resources")
.build("configuredClasspath").getOutput()) .build("configuredClasspath").getOutput())
.contains(new File("src/main/resources").getPath()); .contains(new File("src/main/resources").getPath());
} }

@ -0,0 +1,86 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.gradle.junit;
import java.util.ArrayList;
import java.util.List;
import org.gradle.api.Rule;
import org.junit.runner.Runner;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.Suite;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.springframework.boot.gradle.testkit.Dsl;
import org.springframework.boot.gradle.testkit.GradleBuild;
/**
* Custom {@link Suite} that runs tests against the Groovy and the Kotlin DSLs. Test
* classes using the suite must have a public {@link GradleBuild} field named
* {@code gradleBuild} and annotated with {@link Rule}.
*
* @author Jean-Baptiste Nizet
* @author Andy Wilkinson
*/
public final class GradleMultiDslSuite extends Suite {
public GradleMultiDslSuite(Class<?> clazz) throws InitializationError {
super(clazz, createRunners(clazz));
}
private static List<Runner> createRunners(Class<?> clazz) throws InitializationError {
List<Runner> runners = new ArrayList<>();
runners.add(new GradleDslClassRunner(clazz, new GradleBuild(Dsl.GROOVY)));
runners.add(new GradleDslClassRunner(clazz, new GradleBuild(Dsl.KOTLIN)));
return runners;
}
private static final class GradleDslClassRunner extends BlockJUnit4ClassRunner {
private final GradleBuild gradleBuild;
private GradleDslClassRunner(Class<?> klass, GradleBuild gradleBuild)
throws InitializationError {
super(klass);
this.gradleBuild = gradleBuild;
}
@Override
protected Object createTest() throws Exception {
Object test = super.createTest();
configureTest(test);
return test;
}
private void configureTest(Object test) throws Exception {
test.getClass().getField("gradleBuild").set(test, this.gradleBuild);
}
@Override
protected String getName() {
return this.gradleBuild.getDsl().getName() + " DSL";
}
@Override
protected String testName(FrameworkMethod method) {
return method.getName() + " [" + getName() + "]";
}
}
}

@ -0,0 +1,48 @@
/*
* Copyright 2012-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.gradle.testkit;
/**
* The DSLs supported by Gradle and demonstrated in the documentation samples
*/
public enum Dsl {
GROOVY("Groovy", ".gradle"), KOTLIN("Kotlin", ".gradle.kts");
private final String name;
private final String extension;
Dsl(String name, String extension) {
this.name = name;
this.extension = extension;
}
/**
* Gets the user-friendly name of the DSL
*/
public String getName() {
return this.name;
}
/**
* Gets the file extension of build scripts (starting with a dot)
*/
String getExtension() {
return this.extension;
}
}

@ -26,6 +26,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath; import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory; import javax.xml.xpath.XPathFactory;
@ -43,6 +44,9 @@ import org.junit.rules.TemporaryFolder;
import org.junit.rules.TestRule; import org.junit.rules.TestRule;
import org.junit.runner.Description; import org.junit.runner.Description;
import org.junit.runners.model.Statement; import org.junit.runners.model.Statement;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.springframework.asm.ClassVisitor; import org.springframework.asm.ClassVisitor;
@ -61,12 +65,26 @@ public class GradleBuild implements TestRule {
private final TemporaryFolder temp = new TemporaryFolder(); private final TemporaryFolder temp = new TemporaryFolder();
private final Dsl dsl;
private File projectDir; private File projectDir;
private String script; private String script;
private String gradleVersion; private String gradleVersion;
public GradleBuild() {
this(Dsl.GROOVY);
}
public GradleBuild(Dsl dsl) {
this.dsl = dsl;
}
public Dsl getDsl() {
return this.dsl;
}
@Override @Override
public Statement apply(Statement base, Description description) { public Statement apply(Statement base, Description description) {
URL scriptUrl = findDefaultScript(description); URL scriptUrl = findDefaultScript(description);
@ -99,7 +117,8 @@ public class GradleBuild implements TestRule {
private URL getScriptForTestMethod(Description description) { private URL getScriptForTestMethod(Description description) {
String name = description.getTestClass().getSimpleName() + "-" String name = description.getTestClass().getSimpleName() + "-"
+ removeGradleVersion(description.getMethodName()) + ".gradle"; + removeGradleVersion(description.getMethodName())
+ this.dsl.getExtension();
return description.getTestClass().getResource(name); return description.getTestClass().getResource(name);
} }
@ -108,7 +127,7 @@ public class GradleBuild implements TestRule {
} }
private URL getScriptForTestClass(Class<?> testClass) { private URL getScriptForTestClass(Class<?> testClass) {
return testClass.getResource(testClass.getSimpleName() + ".gradle"); return testClass.getResource(testClass.getSimpleName() + this.dsl.getExtension());
} }
private void before() throws IOException { private void before() throws IOException {
@ -138,7 +157,8 @@ public class GradleBuild implements TestRule {
} }
public GradleBuild script(String script) { public GradleBuild script(String script) {
this.script = script; this.script = script.endsWith(this.dsl.getExtension()) ? script
: script + this.dsl.getExtension();
return this; return this;
} }
@ -162,15 +182,23 @@ public class GradleBuild implements TestRule {
public GradleRunner prepareRunner(String... arguments) throws IOException { public GradleRunner prepareRunner(String... arguments) throws IOException {
String scriptContent = FileCopyUtils.copyToString(new FileReader(this.script)) String scriptContent = FileCopyUtils.copyToString(new FileReader(this.script))
.replace("{version}", getBootVersion()); .replace("{version}", getBootVersion())
FileCopyUtils.copy(scriptContent, .replace("{dependency-management-plugin-version}",
new FileWriter(new File(this.projectDir, "build.gradle"))); getDependencyManagementPluginVersion());
FileCopyUtils.copy(scriptContent, new FileWriter(
new File(this.projectDir, "build" + this.dsl.getExtension())));
GradleRunner gradleRunner = GradleRunner.create().withProjectDir(this.projectDir) GradleRunner gradleRunner = GradleRunner.create().withProjectDir(this.projectDir)
.withDebug(true).withPluginClasspath(pluginClasspath()); .withPluginClasspath(pluginClasspath());
if (this.dsl != Dsl.KOTLIN) {
// see https://github.com/gradle/gradle/issues/6862
gradleRunner.withDebug(true);
}
if (this.gradleVersion != null) { if (this.gradleVersion != null) {
gradleRunner.withGradleVersion(this.gradleVersion); gradleRunner.withGradleVersion(this.gradleVersion);
} }
else if (this.dsl == Dsl.KOTLIN) {
gradleRunner.withGradleVersion("4.10.2");
}
List<String> allArguments = new ArrayList<>(); List<String> allArguments = new ArrayList<>();
allArguments.add("-PbootVersion=" + getBootVersion()); allArguments.add("-PbootVersion=" + getBootVersion());
allArguments.add("--stacktrace"); allArguments.add("--stacktrace");
@ -201,13 +229,34 @@ public class GradleBuild implements TestRule {
+ "/text()"); + "/text()");
} }
private static String getDependencyManagementPluginVersion() {
try (FileReader pomReader = new FileReader(".flattened-pom.xml")) {
Document pom = DocumentBuilderFactory.newInstance().newDocumentBuilder()
.parse(new InputSource(pomReader));
NodeList dependencyElements = pom.getElementsByTagName("dependency");
for (int i = 0; i < dependencyElements.getLength(); i++) {
Element dependency = (Element) dependencyElements.item(i);
if (dependency.getElementsByTagName("artifactId").item(0).getTextContent()
.equals("dependency-management-plugin")) {
return dependency.getElementsByTagName("version").item(0)
.getTextContent();
}
}
throw new IllegalStateException(
"dependency management plugin version not found");
}
catch (Exception ex) {
throw new IllegalStateException(
"Failed to find dependency management plugin version", ex);
}
}
private static String evaluateExpression(String expression) { private static String evaluateExpression(String expression) {
try { try (FileReader pomReader = new FileReader(".flattened-pom.xml")) {
XPathFactory xPathFactory = XPathFactory.newInstance(); XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xpath = xPathFactory.newXPath(); XPath xpath = xPathFactory.newXPath();
XPathExpression expr = xpath.compile(expression); XPathExpression expr = xpath.compile(expression);
String version = expr String version = expr.evaluate(new InputSource(pomReader));
.evaluate(new InputSource(new FileReader(".flattened-pom.xml")));
return version; return version;
} }
catch (Exception ex) { catch (Exception ex) {

Loading…
Cancel
Save