Java 8 has reached end of support
and will be
deprecated
on January 31, 2026. After deprecation, you won't be able to deploy Java 8
applications, even if your organization previously used an organization policy to
re-enable deployments of legacy runtimes. Your existing Java
8 applications will continue to run and receive traffic after their
deprecation date. We recommend that
you
migrate to the latest supported version of Java.
Migrating to the gcloud CLI-based Gradle plugin
Stay organized with collections
Save and categorize content based on your preferences.
If you previously used the Java App Engine SDK-based plugin
(com.google.appengine.appengine-gradle
) and want to move to the new
Google Cloud CLI, migrate to the gcloud CLI-based
(com.google.cloud.tools.appengine-gradle
) plugin.
Benefits of the gcloud CLI-based plugin
Upgrading to the new plugin provides the following benefits:
Uses the same authentication credentials as all other gcloud CLI
-based commands, which are produced from the standard gcloud auth login
flow.
Supports the App Engine flexible environment.
Updates the local development server automatically as part of the standard
gcloud CLI update flow.
Supports deploying App Engine service (cron, queues, dos, dispatch)
configurations, independently from your service.
Notable differences
Before you migrate, be aware of these notable differences:
- gcloud CLI dependency
- The old plugin runs without any specific local environment dependencies,
besides Java, but the new plugin requires that you have the
gcloud CLI installed.
- No Endpoints discovery doc generation
- The new plugin does not generate Endpoints discovery docs, a
feature available in a separate plugin. Running your Endpoints
backend no longer requires generating this file in a build step as the server
now generates it at runtime. You should use the new plugin only if you need
to generate client libraries such as for iOS or Android. Learn more about the
new plugins by reviewing the Migrating to Endpoints Frameworks for
App Engine
guide.
- EAR file format no longer supported
- The new plugin no longer supports the
EAR file format for running and deploying multiple services at the same time.
- New deployment command
- The old plugin calls the
appcfg
command to deploy
applications, while the new plugin deploys using the new gcloud CLI.
- JPA/JDO Datanucleus enhancement must be manually configured
- If your project
uses the
gradle-appengine-plugin
’s JPA/JDO Datanucleus enhancement, you must
manually configure Datanucleus enhancement after switching to the
gcloud CLI-based plugin. See an example from Stackoverflow.
- Android Studio is not supported
- You can switch your Android Studio project to use the new plugin, but the
Android Studio App Engine development server and deployment support
does not work with this new plugin. To run and deploy your app, you have to
invoke Gradle directly.
Use of XML configuration files is supported, but not YAML.
Migrating to the new plugin
Remove the old gradle-appengine-plugin
configuration and imports from your
build.gradle
file.
Add the new plugin to the classpath
of your build.gradle
file's
buildscript
section:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.0.1'
}
}
At the root of your service, run the following command to verify that you can
run your app locally:
gradle appengineRun
In your build.gradle
file's buildscript
section, configure your
deployment by specifying your project ID and version:
appengine {
deploy {
version = 'v1'
project = "your GCP project ID"
}
}
The new tooling ignores the application and version elements in your
appengine-web.xml
file.
At the root of your service, run the following command to verify that you can
deploy your application:
gradle appengineDeploy
Migrating EAR based multi-service configurations
The new plugin does not support EAR packaging. Instead, it supports running
multiple services locally without any special packaging steps.
To migrate your EAR-based Gradle project:
Pick a primary service that will be responsible for running the rest of the
services. You should select your default service, but it can be any of the
services that are run together.
In your appengine
configuration, modify the run.services
entry to include
all the services that should be run by the local development server.
An example project structure:
../{projectRoot}/
build.gradle
settings.gradle (includes default-service & secondary-service)
{your-default-service}/build.gradle {includes appengine-gradle-plugin}
….
{your-default-service}/src/main/webapp/WEB-INF/appengine-web.xml
{your-secondary-service}build.gradle {includes appengine-gradle-plugin}
….
{your-secondary-service}/src/main/webapp/WEB-INF/appengine-web.xml
An example build.gradle
buildscript:
appengine {
run {
// configure the app to point to the right service directories
services = [
projectAsService(project),
projectAsService(":another-module")
]
}
}
// helper method to obtain correct directory and set up dependencies
def getExplodedAppDir(Project serverProject) {
// if not 'this' module, then do some setup.
if (serverProject != project) {
// make sure we evaluate other modules first so we get the right value
evaluationDependsOn(serverProject.path)
// make sure we build "run" depends on the other modules exploding wars
project.tasks.appengineRun.dependsOn serverProject.tasks.explodeWar
}
return serverProject.tasks.explodeWar.explodedAppDirectory
}
App Engine SDK-based vs gcloud CLI-based Gradle commands
The following table shows the different ways you invoke the Gradle plugin,
depending on whether you use the App Engine SDK-based Gradle plugin or
the gcloud CLI-based Gradle
plugin.
Action |
App Engine SDK-based |
gcloud CLI-based |
Run the app locally |
appengine:devserver |
appengineRun |
Deploy a new app, version, or service. |
appengine:update |
appengineDeploy |
Set the default application version. |
appengine:set_default_version |
gcloud app services set-traffic or gcloud app versions migrate |
Update application cron jobs. |
appengine:update_cron |
appengineDeployCron |
Update the application dispatch configuration. |
appengine:update_dispatch |
appengineDeployDispatch |
Update application DoS protection configuration. |
appengine:update_dos |
appengineDeployDos |
Update application task queue definitions. |
appengine:update_queues |
appengineDeployQueue |
Update Datastore Indexes. |
appengine:update_indexes |
appengineDeployIndex |
Delete unused indexes from application. |
appengine:vacuum_indexes |
gcloud datastore indexes cleanup |
Start the specified module version. |
appengine:start_module_version |
gcloud app versions start |
Stop the specified module version. |
appengine:stop_module_version |
gcloud app versions stop |
Rollback an in-progress update. |
appengine:rollback |
gcloud app versions start, gcloud app versions stop |
What's next
- Now that you have migrated to the new plugin successfully, you can
test and
deploy
your application.
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-08-25 UTC.
[[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Hard to understand","hardToUnderstand","thumb-down"],["Incorrect information or sample code","incorrectInformationOrSampleCode","thumb-down"],["Missing the information/samples I need","missingTheInformationSamplesINeed","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2025-08-25 UTC."],[[["\u003cp\u003eMigrate from the Java App Engine SDK-based plugin (\u003ccode\u003ecom.google.appengine.appengine-gradle\u003c/code\u003e) to the gcloud CLI-based plugin (\u003ccode\u003ecom.google.cloud.tools.appengine-gradle\u003c/code\u003e) for enhanced benefits, including unified authentication, flexible environment support, and automatic updates.\u003c/p\u003e\n"],["\u003cp\u003eThe new gcloud CLI-based plugin requires the gcloud CLI to be installed and no longer supports Endpoints discovery doc generation within the plugin, as it's now handled at runtime, nor does it support the EAR file format for multiple services.\u003c/p\u003e\n"],["\u003cp\u003eManual configuration of Datanucleus enhancement is necessary if your project uses JPA/JDO, and Android Studio's built-in App Engine support is incompatible, requiring direct Gradle invocation.\u003c/p\u003e\n"],["\u003cp\u003eMigrating from EAR-based multi-service configurations to the new plugin involves selecting a primary service and configuring the \u003ccode\u003erun.services\u003c/code\u003e entry in your \u003ccode\u003ebuild.gradle\u003c/code\u003e to include all services for local development, replacing EAR packaging entirely.\u003c/p\u003e\n"],["\u003cp\u003eThe gcloud CLI-based plugin uses new Gradle commands like \u003ccode\u003eappengineRun\u003c/code\u003e for local development and \u003ccode\u003eappengineDeploy\u003c/code\u003e for deployment, replacing the old SDK-based commands such as \u003ccode\u003eappengine:devserver\u003c/code\u003e and \u003ccode\u003eappengine:update\u003c/code\u003e.\u003c/p\u003e\n"]]],[],null,["# Migrating to the gcloud CLI-based Gradle plugin\n\nIf you previously used the Java App Engine SDK-based plugin\n(`com.google.appengine.appengine-gradle`) and want to move to the new\n[Google Cloud CLI](/sdk/downloads), migrate to the gcloud CLI-based\n(`com.google.cloud.tools.appengine-gradle`) plugin.\n\nBenefits of the gcloud CLI-based plugin\n---------------------------------------\n\nUpgrading to the new plugin provides the following benefits:\n\n- Uses the same authentication credentials as all other gcloud CLI\n -based commands, which are produced from the standard `gcloud auth login`\n flow.\n\n- Supports the App Engine flexible environment.\n\n- Updates the local development server automatically as part of the standard\n gcloud CLI update flow.\n\n- Supports deploying App Engine service (cron, queues, dos, dispatch)\n configurations, independently from your service.\n\nNotable differences\n-------------------\n\nBefore you migrate, be aware of these notable differences:\n\ngcloud CLI dependency\n: The old plugin runs without any specific local environment dependencies,\n besides Java, but the new plugin requires that you have the\n gcloud CLI installed.\n\nNo Endpoints discovery doc generation\n: The new plugin does not generate Endpoints discovery docs, a\n feature available in a separate plugin. Running your Endpoints\n backend no longer requires generating this file in a build step as the server\n now generates it at runtime. You should use the new plugin only if you need\n to generate client libraries such as for iOS or Android. Learn more about the\n new plugins by reviewing the [Migrating to Endpoints Frameworks for\n App Engine](/endpoints/docs/frameworks/legacy/v1/java/migrating)\n guide.\n\nEAR file format no longer supported\n: The new plugin no longer supports the\n EAR file format for running and deploying multiple services at the same time.\n\nNew deployment command\n: The old plugin calls the `appcfg` command to deploy\n applications, while the new plugin deploys using the new gcloud CLI.\n\nJPA/JDO Datanucleus enhancement must be manually configured\n: If your project\n uses the `gradle-appengine-plugin`'s JPA/JDO Datanucleus enhancement, you must\n manually configure Datanucleus enhancement after switching to the\n gcloud CLI-based plugin. See an [example from Stackoverflow](https://stackoverflow.com/questions/29279503/how-can-i-run-datanucleus-enhancer-from-gradle).\n\nAndroid Studio is not supported\n: You can switch your Android Studio project to use the new plugin, but the\n Android Studio App Engine development server and deployment support\n does not work with this new plugin. To run and deploy your app, you have to\n invoke Gradle directly.\n\nUse of XML configuration files is supported, but not YAML.\n\nMigrating to the new plugin\n---------------------------\n\n1. Remove the old `gradle-appengine-plugin` configuration and imports from your\n `build.gradle` file.\n\n2. Add the new plugin to the `classpath` of your `build.gradle` file's\n `buildscript` section:\n\n buildscript {\n repositories {\n mavenCentral()\n }\n\n dependencies {\n classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.0.1'\n }\n }\n\n3. At the root of your service, run the following command to verify that you can\n run your app locally:\n\n gradle appengineRun\n\n4. In your `build.gradle` file's `buildscript` section, configure your\n deployment by specifying your project ID and version:\n\n appengine {\n deploy {\n version = 'v1'\n project = \"your GCP project ID\"\n }\n }\n\n The new tooling ignores the application and version elements in your\n `appengine-web.xml` file.\n5. At the root of your service, run the following command to verify that you can\n deploy your application:\n\n gradle appengineDeploy\n\nMigrating EAR based multi-service configurations\n------------------------------------------------\n\nThe new plugin does not support EAR packaging. Instead, it supports running\nmultiple services locally without any special packaging steps.\n\nTo migrate your EAR-based Gradle project:\n\n1. Pick a primary service that will be responsible for running the rest of the\n services. You should select your default service, but it can be any of the\n services that are run together.\n\n2. In your `appengine` configuration, modify the `run.services` entry to include\n all the services that should be run by the local development server.\n\n An example project structure: \n\n ../{projectRoot}/\n build.gradle\n settings.gradle (includes default-service & secondary-service)\n {your-default-service}/build.gradle {includes appengine-gradle-plugin}\n ....\n {your-default-service}/src/main/webapp/WEB-INF/appengine-web.xml\n {your-secondary-service}build.gradle {includes appengine-gradle-plugin}\n ....\n {your-secondary-service}/src/main/webapp/WEB-INF/appengine-web.xml\n\n An example `build.gradle` buildscript: \n\n appengine {\n run {\n // configure the app to point to the right service directories\n services = [\n projectAsService(project),\n projectAsService(\":another-module\")\n ]\n }\n }\n\n // helper method to obtain correct directory and set up dependencies\n def getExplodedAppDir(Project serverProject) {\n // if not 'this' module, then do some setup.\n if (serverProject != project) {\n // make sure we evaluate other modules first so we get the right value\n evaluationDependsOn(serverProject.path)\n // make sure we build \"run\" depends on the other modules exploding wars\n project.tasks.appengineRun.dependsOn serverProject.tasks.explodeWar\n }\n return serverProject.tasks.explodeWar.explodedAppDirectory\n }\n\nApp Engine SDK-based vs gcloud CLI-based Gradle commands\n--------------------------------------------------------\n\nThe following table shows the different ways you invoke the Gradle plugin,\ndepending on whether you use the App Engine SDK-based Gradle plugin or\nthe [gcloud CLI-based Gradle](/appengine/docs/legacy/standard/java/using-gradle)\nplugin.\n\nWhat's next\n-----------\n\n- Now that you have migrated to the new plugin successfully, you can [test](/appengine/docs/legacy/standard/java/using-gradle#testing_gradle_app) and [deploy](/appengine/docs/legacy/standard/java/using-gradle#deploying_gradle_app) your application."]]