Cannot use plugin tasks due to "org.gradle.api.tasks.bundling.Jar.getArchivePath()" because "jar" is null
marceloverdijk opened this issue · comments
I've a minimal Spring Boot application using Java 17 and I'm trying to get AppEngine Gradle plugin to work...
As documented I have set it up like:
settings.gradle:
pluginManagement {
repositories {
gradlePluginPortal()
mavenCentral()
}
resolutionStrategy {
eachPlugin {
if (requested.id.id.startsWith("com.google.cloud.tools.appengine")) {
useModule("com.google.cloud.tools:appengine-gradle-plugin:${requested.version}")
}
}
}
}
build.gradle:
plugins {
id "java"
id "com.google.cloud.tools.appengine-appyaml" version "2.4.4"
id "io.spring.dependency-management" version "1.0.12.RELEASE"
id "org.springframework.boot" version "2.6.10"
}
group = "com.github.marceloverdijk"
version = "0.0.1-SNAPSHOT"
sourceCompatibility = "17"
ext {
set("springCloudVersion", "2021.0.3")
set("springCloudGcpVersion", "3.3.0")
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencyManagement {
imports {
mavenBom "com.google.cloud:spring-cloud-gcp-dependencies:${springCloudGcpVersion}"
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
dependencies {
// implementation "com.google.cloud:spring-cloud-gcp-starter"
implementation "org.apache.commons:commons-lang3"
implementation "org.springframework.boot:spring-boot-starter-actuator"
implementation "org.springframework.boot:spring-boot-starter-jetty"
implementation("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
developmentOnly "org.springframework.boot:spring-boot-devtools"
testImplementation "org.springframework.boot:spring-boot-starter-test"
}
appengine {
tools {
// https://github.com/GoogleCloudPlatform/app-gradle-plugin/issues/431
cloudSdkHome = "/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk"
}
deploy {
projectId = "GCLOUD_CONFIG"
version = "GCLOUD_CONFIG"
promote = true
stopPreviousVersion = true
}
}
tasks.named("test") {
useJUnitPlatform()
}
but when running any GAE tasks I get:
❯ ./gradlew appengineShowConfiguration
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring root project 'aircraft-notifier'.
> Cannot invoke "org.gradle.api.tasks.bundling.Jar.getArchivePath()" because "jar" is null
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 587ms
Even the bootRun
tasks now fails:
❯ ./gradlew bootRun
FAILURE: Build failed with an exception.
* What went wrong:
A problem occurred configuring root project 'aircraft-notifier'.
> Cannot invoke "org.gradle.api.tasks.bundling.Jar.getArchivePath()" because "jar" is null
If I remove just the appengine { .. }
configuration block from build.gradle (so GAE plugin itself still configured) the app starts up again with bootRun
...
I've removed the appengine plugin completely and was able to deploy the app using gcloud app deploy
.
What version of gradle are you using? This seems related to #382; try running adding jar {}
to your configuration.
Ah, I see from the other issue it's Gradle 7.5. Yes, try adding the empty jar configuration to see if that's the same issue.
with the empty jar {}
I can run appengineShowConfiguration
now.
But appengineDeploy
then fails later:
❯ ./gradlew appengineDeploy
> Task :appengineDeploy
Services to deploy:
..
target service account: [App Engine default service account]
Beginning deployment of service [default]...
Created .gcloudignore file. See `gcloud topic gcloudignore` for details.
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 1 file to Google Cloud Storage ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...
.........................................................................................................................failed.
ERROR: (gcloud.app.deploy) Error Response: [9] Cloud build 0026a2d5-195a-4ec3-bfaa-8e818f985d7a status: FAILURE
did not find any jar files with a Main-Class manifest entry
What if you call ./gradlew clean bootJar appengineDeploy
?
I think a thin jar might be getting created.
./gradlew clean bootJar appengineDeploy
gives:
Beginning deployment of service [default]...
Created .gcloudignore file. See `gcloud topic gcloudignore` for details.
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 1 file to Google Cloud Storage ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...
......................................................................................................................failed.
ERROR: (gcloud.app.deploy) Error Response: [9] Cloud build 6f3721f3-a1b4-4942-b6a2-9bc9ef544344 status: FAILURE
did not find any jar files with a Main-Class manifest entry
Maybe this is bc Boot generates 2 jars , 1 normal jar and 1 plain jar.
The plain one can be disabled as documented here: https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/htmlsingle/#packaging-executable.and-plain-archives
So adding:
tasks.named("jar") {
enabled = false
}
Note I had to add this as well when deploying using Cloud Build (gcloud app deploy
).
But then ./gradlew clean bootJar appengineDeploy
gives:
❯ ./gradlew clean bootJar appengineDeploy
> Task :appengineStage FAILED
FAILURE: Build failed with an exception.
* What went wrong:
A problem was found with the configuration of task ':appengineStage' (type 'StageAppYamlTask').
- In plugin 'com.google.cloud.tools.appengine-appyaml' type 'com.google.cloud.tools.gradle.appengine.appyaml.StageAppYamlTask' property 'stagingExtension.artifact' specifies file '/Users/marceloverdijk/workspace/an/build/libs/an-0.0.1-SNAPSHOT-plain.jar' which doesn't exist.
Reason: An input file was expected to be present but it doesn't exist.
Possible solutions:
1. Make sure the file exists before the task is called.
2. Make sure that the task which produces the file is declared as an input.
Please refer to https://docs.gradle.org/7.5/userguide/validation_problems.html#input_file_does_not_exist for more details about this problem.
Ah! Use this appengine configuration: GoogleCloudPlatform/appengine-plugins#1003
Thx that did the trick!
If anyone is interested the reason why jar {}
worked, is because it forced Gradle to eagerly create and configure (with nothing) the jar
Task. This task is used by:
Notice the getProperties().get("jar")
, that triggers some magical Groovy path to resolve the property, but since Gradle is lazy, the task is not materialized yet as a property. If this plugin used tasks.named
or tasks.getByName
directly, then that would look in the right (Task) container and the plugin would not get null.