Project to reproduce issue at https://github.com/adib-samples/boot-issue-21569.git

I upgraded a project from Spring Boot 2.2.6 to 2.3.0 and run into an issue with the developmentOnly that is created automatically by the boot plugin.

pre upgrade setup - Spring Boot 2.2.6 - Gradle 6.4.1 with multiple projects - Using Gradle Java Platform Plugin instead of the spring boot dependency plugin

configuration of the the platform project

plugins {
    `java-platform`
}

javaPlatform {
    allowDependencies()
}

dependencies {
    api(enforcedPlatform("org.springframework.boot:spring-boot-dependencies:${Versions.SpringBootVersion}"))
    constraints {
        api("com.github.bbottema:emailaddress-rfc2822:2.1.4")
        api("com.icegreen:greenmail:1.5.11")
        api("nl.jqno.equalsverifier:equalsverifier:3.1.13")
        api("com.google.guava:guava:28.2-jre")
        api("io.rest-assured:rest-assured:4.3.0")
        api("org.awaitility:awaitility:4.0.2")
        api("org.threeten:threeten-extra:1.5.0")
        api("com.vladmihalcea:hibernate-types-52:2.9.7")
    }
}

Then in the gradle project with the main spring boot main class I have

plugins {
    `java-library-conventions`
    `spring-boot-conventions`
}

springBoot {
    mainClassName = "com.example.MyApplication"
}

dependencies {
    implementation(project(":common:core"))
    implementation(project(":common:email"))
    implementation(project(":common:security"))
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-validation")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
    developmentOnly("org.springframework.boot:spring-boot-devtools")

    testImplementation(testFixtures(project(":common:security")))
    testImplementation("org.flywaydb:flyway-core")
    testRuntimeOnly("org.postgresql:postgresql")
}

notice that developmentOnly("org.springframework.boot:spring-boot-devtools") does not specify the spring boot version it is being brought in via the java platform project applied using the java-library-conventions project pluginin frob buildSrc (reproduced at end of issue for reference). Before upgrading to Spring Boot 2.3.0 this used to work just fine, I had to define my own developmentOnly configuration in my java-library-conventions plugin in bulidSrc usind the kotlin-dsl

val developmentOnly by configurations.creating // used by spring boot devtools
configurations {
    runtimeClasspath {
        extendsFrom(developmentOnly)
    }
}

After upgrade to Boot 2.3.0 I got an error message that developmentOnly was being defined by the plugin so I removed my own definition. However now I get the error below. Which I can resolve by changing

developmentOnly("org.springframework.boot:spring-boot-devtools")

to

developmentOnly("org.springframework.boot:spring-bootdevtools:${Versions.SpringBootVersion}")

It seems that the developmentOnly configuration does not read the version constraints from the Java Platfrom defined in the project.

error message when the boot version is not explicitly set on devtools

./gradlew build --stacktrace
> Task :snapcoach:app:bootJar FAILED

During the build, one or more dependencies that were declared without a version failed to resolve:
    org.springframework.boot:spring-boot-devtools:

Did you forget to apply the io.spring.dependency-management plugin to the app project?


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':snapcoach:app:bootJar'.
> Could not resolve all files for configuration ':snapcoach:app:developmentOnly'.
   > Could not find org.springframework.boot:spring-boot-devtools:.
     Required by:
         project :snapcoach:app

* Try:
Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':snapcoach:app:bootJar'.
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:38)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:370)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:357)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:350)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
Caused by: org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration$ArtifactResolveException: Could not resolve all files for configuration ':snapcoach:app:developmentOnly'.
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.rethrowFailure(DefaultConfiguration.java:1265)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.access$1800(DefaultConfiguration.java:141)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.visitContents(DefaultConfiguration.java:1242)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration$ConfigurationFileCollection.getFiles(DefaultConfiguration.java:1229)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration.getFiles(DefaultConfiguration.java:484)
        at org.gradle.api.internal.artifacts.configurations.DefaultConfiguration_Decorated.getFiles(Unknown Source)
        at org.gradle.api.internal.file.SubtractingFileCollection.getFiles(SubtractingFileCollection.java:56)
        at org.gradle.api.internal.file.SubtractingFileCollection.getFiles(SubtractingFileCollection.java:57)
        at org.gradle.api.internal.file.AbstractFileCollection.iterator(AbstractFileCollection.java:111)
        at org.gradle.api.internal.file.FilteredFileCollection.iterator(FilteredFileCollection.java:69)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext$FileTreeConverter.convertInto(DefaultFileCollectionResolveContext.java:165)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.doResolve(DefaultFileCollectionResolveContext.java:103)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.resolveAsFileTrees(DefaultFileCollectionResolveContext.java:89)
        at org.gradle.api.internal.file.FileCollectionBackFileTree.visitContents(FileCollectionBackFileTree.java:41)
        at org.gradle.api.internal.file.FilteredFileTree.visitContents(FilteredFileTree.java:59)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.add(DefaultFileCollectionResolveContext.java:61)
        at org.gradle.api.internal.file.collections.UnpackingVisitor.add(UnpackingVisitor.java:44)
        at org.gradle.api.internal.file.collections.UnpackingVisitor.add(UnpackingVisitor.java:76)
        at org.gradle.api.internal.file.DefaultFileCollectionFactory$ResolvingFileCollection.visitContents(DefaultFileCollectionFactory.java:306)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.add(DefaultFileCollectionResolveContext.java:61)
        at org.gradle.api.internal.tasks.PropertyFileCollection.visitContents(PropertyFileCollection.java:47)
        at org.gradle.api.internal.file.collections.DefaultFileCollectionResolveContext.add(DefaultFileCollectionResolveContext.java:61)
        at org.gradle.api.internal.tasks.properties.DefaultTaskProperties$2.visitContents(DefaultTaskProperties.java:130)
        at org.gradle.api.internal.file.CompositeFileCollection.getSourceCollections(CompositeFileCollection.java:145)
        at org.gradle.api.internal.file.CompositeFileCollection.isEmpty(CompositeFileCollection.java:100)
        at org.gradle.api.internal.tasks.execution.DefaultEmptySourceTaskSkipper.skipIfEmptySources(DefaultEmptySourceTaskSkipper.java:66)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.skipIfInputsEmpty(ExecuteActionsTaskExecuter.java:519)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:47)
        at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:34)
        at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:39)
        at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:40)
        at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:28)
        at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:194)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:186)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:114)
        at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
        at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:370)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:357)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:350)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:336)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
        at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
Caused by: org.gradle.internal.resolve.ModuleVersionNotFoundException: Could not find org.springframework.boot:spring-boot-devtools:.
Required by:
    project :snapcoach:app

buildSrc/src/main/kotlin/java-library-conventions.gradle.kts used by all projects in the build to apply the standard configuration

plugins {
    `java-library`
    jacoco
    checkstyle
    id("com.diffplug.gradle.spotless")
    id("com.gorylenko.gradle-git-properties")
}

java {
    sourceCompatibility = JavaVersion.VERSION_11
    targetCompatibility = JavaVersion.VERSION_11
}

dependencies {
    implementation(platform(project(":platform")))
    implementation("org.springframework.boot:spring-boot-starter")
    api("com.google.guava:guava")
    testImplementation("nl.jqno.equalsverifier:equalsverifier")
    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
    }
}

tasks.jar {
    // take the project path name and use it as the jar file name, for example a project
    // :shared:core wolud generate a jar file sharde-core-version.jar
    archiveBaseName.set(project.path.replace(":","-").substring(1))
}

tasks.test {
    useJUnitPlatform()
    finalizedBy("jacocoTestReport")
    testLogging {
        showStandardStreams = false
        events("failed")
        showCauses = true
        showStackTraces = true
        setExceptionFormat("full")
    }
}

tasks.jacocoTestReport {
    reports {
        xml.isEnabled = true
        xml.destination = file("${buildDir}/jacoco/test.xml")
        html.isEnabled = true
        html.destination = file("${buildDir}/jacoco/html")
    }
}

tasks.jacocoTestCoverageVerification {
    violationRules {
        rule {
            limit {
                minimum = "0.1".toBigDecimal()
            }
        }
    }
}

tasks.compileJava {
    options.compilerArgs.add(element = "-parameters");
}

checkstyle {
    toolVersion = "8.32"
    configDirectory.set(rootProject.file("buildSrc/src/main/resources/checkstyle"))
    isShowViolations = true
    maxErrors = 0
    maxWarnings = 0
    isIgnoreFailures = false
}

spotless {
    java {
        googleJavaFormat()
        @Suppress("INACCESSIBLE_TYPE")
        licenseHeaderFile("${rootDir}/buildSrc/src/main/resources/spotless/masteryway.license.java")
    }
    sql {
        target("**/*.sql")
        dbeaver().configFile("${rootDir}/buildSrc/src/main/resources/spotless/dbeaver.properties")
    }
}

Comment From: philwebb

@asaikali Do you have a sample project that we can use to save us trying to recreate something from the snippets?

Comment From: asaikali

I will put a sample app together asap.

Comment From: asaikali

Project to reproduce issue at https://github.com/adib-samples/boot-issue-21569.git

Comment From: wilkinsona

Thanks for the sample. As far as I can tell, it doesn't work with Spring Boot 2.2.x either. Here are the changes that I made to the sample:

diff --git a/app/app.gradle.kts b/app/app.gradle.kts
index b734c8c..901416b 100644
--- a/app/app.gradle.kts
+++ b/app/app.gradle.kts
@@ -7,6 +7,12 @@ springBoot {
     mainClassName = "com.example.ExampleApplication"
 }

+val developmentOnly by configurations.creating // used by spring boot devtools
+configurations {
+    runtimeClasspath {
+        extendsFrom(developmentOnly)
+    }
+}

 dependencies {
     implementation(project(":components:util"))
diff --git a/buildSrc/src/main/resources/springBootVersion.txt b/buildSrc/src/main/resources/springBootVersion.txt
index bb9e92b..3634f93 100644
--- a/buildSrc/src/main/resources/springBootVersion.txt
+++ b/buildSrc/src/main/resources/springBootVersion.txt
@@ -1 +1 @@
-2.3.0.RELEASE
+2.2.7.RELEASE

And here's what happens when trying to resolve the dependencies of the developmentOnly configuration:

$ ./gradlew app:dependencies --configuration developmentOnly

> Task :app:dependencies

------------------------------------------------------------
Project :app
------------------------------------------------------------

developmentOnly
\--- org.springframework.boot:spring-boot-devtools FAILED

I see that exact same behaviour when I revert my changes.

I would expect the behaviour to be the same in both cases as, in 2.3.0, Boot's plugin creates the developmentOnly configuration in the same way as the Kotlin snippet above.

Unlike the dependency management plugin, which typically applies version constraints to every configuration, Gradle's Platform support applies version constraints to individual configurations via platform or enforcedPlatform dependencies. You haven't declared a platform dependency in the developmentOnly configuration and it doesn't extend from any configurations so it doesn't not inherit such a dependency either. As a result, there's no version available for the spring-boot-devtools dependency so resolution fails.

You can fix the problem by adding a platform dependency to the developmentOnly configuration:

diff --git a/app/app.gradle.kts b/app/app.gradle.kts
index b734c8c..41100d0 100644
--- a/app/app.gradle.kts
+++ b/app/app.gradle.kts
@@ -12,8 +12,7 @@ dependencies {
     implementation(project(":components:util"))
     implementation("org.springframework.boot:spring-boot-starter-web")
     implementation("org.springframework.boot:spring-boot-starter-actuator")
+    developmentOnly(platform(project(":platform")))
     developmentOnly("org.springframework.boot:spring-boot-devtools")
-    // line below works, line above does not
-   // developmentOnly("org.springframework.boot:spring-boot-devtools:${Versions.SpringBootVersion}")
     testImplementation(testFixtures(project(":components:util")))
 }

The version constraints are then available and the dependency will resolve:

./gradlew app:dependencies --configuration developmentOnly

> Task :app:dependencies

------------------------------------------------------------
Project :app
------------------------------------------------------------

developmentOnly - Configuration for development-only dependencies such as Spring Boot's DevTools.
+--- project :platform
|    \--- org.springframework.boot:spring-boot-dependencies:2.3.0.RELEASE
|         +--- org.springframework.boot:spring-boot-devtools:2.3.0.RELEASE (c)
|         +--- org.springframework.boot:spring-boot:2.3.0.RELEASE (c)
|         +--- org.springframework.boot:spring-boot-autoconfigure:2.3.0.RELEASE (c)
|         +--- org.springframework:spring-core:5.2.6.RELEASE (c)
|         +--- org.springframework:spring-context:5.2.6.RELEASE (c)
|         +--- org.springframework:spring-jcl:5.2.6.RELEASE (c)
|         +--- org.springframework:spring-aop:5.2.6.RELEASE (c)
|         +--- org.springframework:spring-beans:5.2.6.RELEASE (c)
|         \--- org.springframework:spring-expression:5.2.6.RELEASE (c)
\--- org.springframework.boot:spring-boot-devtools -> 2.3.0.RELEASE
     +--- org.springframework.boot:spring-boot:2.3.0.RELEASE
     |    +--- org.springframework.boot:spring-boot-dependencies:2.3.0.RELEASE (*)
     |    +--- org.springframework:spring-core -> 5.2.6.RELEASE
     |    |    \--- org.springframework:spring-jcl:5.2.6.RELEASE
     |    \--- org.springframework:spring-context -> 5.2.6.RELEASE
     |         +--- org.springframework:spring-aop:5.2.6.RELEASE
     |         |    +--- org.springframework:spring-beans:5.2.6.RELEASE
     |         |    |    \--- org.springframework:spring-core:5.2.6.RELEASE (*)
     |         |    \--- org.springframework:spring-core:5.2.6.RELEASE (*)
     |         +--- org.springframework:spring-beans:5.2.6.RELEASE (*)
     |         +--- org.springframework:spring-core:5.2.6.RELEASE (*)
     |         \--- org.springframework:spring-expression:5.2.6.RELEASE
     |              \--- org.springframework:spring-core:5.2.6.RELEASE (*)
     +--- org.springframework.boot:spring-boot-autoconfigure:2.3.0.RELEASE
     |    +--- org.springframework.boot:spring-boot:2.3.0.RELEASE (*)
     |    \--- org.springframework.boot:spring-boot-dependencies:2.3.0.RELEASE (*)
     \--- org.springframework.boot:spring-boot-dependencies:2.3.0.RELEASE (*)

(c) - dependency constraint
(*) - dependencies omitted (listed previously)

Comment From: asaikali

The commit that shows this working with boot 2.2.6 is at https://github.com/adib-samples/boot-issue-21569/commit/659543cb1048c704221fc1601b9361c2d1344af6.

Below is the output from the linked boot project as you can see the output indicates that devtools is running 2020-05-26 11:25:37.314 INFO 52023 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable I am running the application from inside intellij I wonder if that is why it's picking up devtools when it should not have. I never tested it from the CLI.

I hope the docs can be enhanced to explain how to use the Java Platform plugin without the Spring Dependency Management Plugin. I have opened an issue #21570 for docs enhancement.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.0.RELEASE)

2020-05-26 11:25:37.260  INFO 52023 --- [  restartedMain] com.example.util.ExampleApplication      : Starting ExampleApplication on adib.local with PID 52023 (/Users/adib/dev/bugs/boot-issue-21569/app/out/production/classes started by adib in /Users/adib/dev/bugs/boot-issue-21569)
2020-05-26 11:25:37.264  INFO 52023 --- [  restartedMain] com.example.util.ExampleApplication      : No active profile set, falling back to default profiles: default
2020-05-26 11:25:37.314  INFO 52023 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable
2020-05-26 11:25:37.314  INFO 52023 --- [  restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG'
2020-05-26 11:25:38.420  INFO 52023 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2020-05-26 11:25:38.429  INFO 52023 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-05-26 11:25:38.430  INFO 52023 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.35]
2020-05-26 11:25:38.490  INFO 52023 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-05-26 11:25:38.491  INFO 52023 --- [  restartedMain] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1177 ms
2020-05-26 11:25:38.714  INFO 52023 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2020-05-26 11:25:38.976  INFO 52023 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2020-05-26 11:25:38.979  INFO 52023 --- [  restartedMain] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 13 endpoint(s) beneath base path '/actuator'
2020-05-26 11:25:39.027  INFO 52023 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2020-05-26 11:25:39.043  INFO 52023 --- [  restartedMain] com.example.util.ExampleApplication      : Started ExampleApplication in 2.226 seconds (JVM running for 3.254)
2020-05-26 11:25:41.955  INFO 52023 --- [on(1)-127.0.0.1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-05-26 11:25:41.956  INFO 52023 --- [on(1)-127.0.0.1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2020-05-26 11:25:41.964  INFO 52023 --- [on(1)-127.0.0.1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 8 ms