Skip to content
This repository has been archived by the owner on Feb 6, 2024. It is now read-only.

Cannot use plugin tasks due to "org.gradle.api.tasks.bundling.Jar.getArchivePath()" because "jar" is null #432

Closed
marceloverdijk opened this issue Aug 11, 2022 · 9 comments
Labels

Comments

@marceloverdijk
Copy link

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...

@marceloverdijk
Copy link
Author

I've removed the appengine plugin completely and was able to deploy the app using gcloud app deploy.

@elefeint
Copy link
Contributor

What version of gradle are you using? This seems related to #382; try running adding jar {} to your configuration.

@elefeint
Copy link
Contributor

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.

@marceloverdijk
Copy link
Author

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

@elefeint
Copy link
Contributor

What if you call ./gradlew clean bootJar appengineDeploy?

I think a thin jar might be getting created.

@marceloverdijk
Copy link
Author

./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.

@elefeint
Copy link
Contributor

Ah! Use this appengine configuration: GoogleCloudPlatform/appengine-plugins#1003

@marceloverdijk
Copy link
Author

Thx that did the trick!

@TWiStErRob
Copy link
Contributor

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:

Jar jar = (Jar) project.getProperties().get("jar");
stageExtension.setArtifact(jar.getArchivePath());

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants