Get hands-on experience with 20+ free Google Cloud products and $300 in free credit for new customers.

Unrecognized element <app-engine-apis> == can't access legacy bundle services on Java 11+ GAE server

I finally migrated a long-running Google App Engine Java 8 project to Java 11+ standard environment before loss of Java 8 support in Jan 2024.

But I need to use the legacy bundled services including Datastore, Blobstore and Task Queues.  I should do this by 'Installing the App Engine API Jar.'

I followed the following Google tutorial https://cloud.google.com/appengine/docs/standard/java-gen2/services/access

In particular I need to 'Install the App Engine API JAR' by adding the following to the app-engine.web.xml file:

<app-engine-apis>true</app-engine-apis>

But trying to build/deploy the project via the Gradle plugin in Android Studio gets the exception 'Unrecognized element <app-engine-apis>'. 

So alas - I can't deploy to the new Java 11 server environment while preserving the old bundled legacy functions.

Note: because I use the Gradle plugin with Android Studio to build and deploy the server, I don't have a pom.xml file used by Maven.

Any advice on how to build the gradle file using the necessary '<app-engine-apis>true' would be greatly appreciated!  Specs below:

Android Studio Giraffe 2022.3.1 Patch 4 with Gradle 7.4.2

Running server on GAE Standard Environment with Objectify 5

AppEngine Gradle file

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'com.google.cloud.tools.appengine'
apply plugin: 'com.google.cloud.tools.endpoints-framework-server'

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath 'com.google.cloud.tools:endpoints-framework-gradle-plugin:2.1.0'
        classpath 'com.google.cloud.tools:appengine-gradle-plugin:2.4.2'
    }
}

repositories {
    google()
    mavenCentral()
}

appengine {
    deploy {
        version = "GCLOUD_CONFIG"
        projectId = "GCLOUD_CONFIG"
    }
}

sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

dependencies {
    implementation (group: 'com.google.appengine', name: 'appengine-api-1.0-sdk', version: '2.0.0')
    implementation 'com.google.endpoints:endpoints-framework:2.2.2'
    implementation ('com.google.http-client:google-http-client-gson:1.40.1') {
        exclude (group: 'httpclient', module: 'httpclient')
    }
    implementation 'javax.inject:javax.inject:1'
    implementation 'javax.servlet:servlet-api:3.0-alpha-1'
    implementation 'javax.activation:javax.activation-api:1.2.0'
    implementation ('com.google.firebase:firebase-admin:8.1.0') {
        exclude (group: 'com.google.guava')
    }
    implementation 'com.google.guava:guava:31.0.1-jre'
    implementation (group: 'com.google.appengine.tools', name: 'appengine-gcs-client', version: '0.8.2')
    implementation 'com.googlecode.objectify:objectify:5.1.25'
    implementation "com.stripe:stripe-java:20.90.0"
}

app-engine.web.xml

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>my-fashion-project</application>
    <version>1</version>
    <runtime>java11</runtime>
    <app-engine-apis>true</app-engine-apis>   // THIS IS THE LINE THAT CAUSES EXCEPTION
    <threadsafe>true</threadsafe>
    <url-stream-handler>urlfetch</url-stream-handler>

    <system-properties>
        <property name="java.util.logging.config.file" value="WEB-INF/logging.properties" />
    </system-properties>

    <sessions-enabled>
        true
    </sessions-enabled>

    <resource-files>
        <include path="/**.json" />
    </resource-files>

    <automatic-scaling>
        <min-instances>1</min-instances>
    </automatic-scaling>

</appengine-web-app>

web.xml

<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
    <app-engine-apis>true</app-engine-apis>

    <filter>
        <filter-name>ObjectifyFilter</filter-name>
        <filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>ObjectifyFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>EndpointsServlet</servlet-name>
        <servlet-class>com.google.api.server.spi.EndpointsServlet</servlet-class>
        <init-param>
            <param-name>services</param-name>
            <param-value>
                com.myfashionserver.entities.MemberEndpoint,
                ............ (list of entity endpoints excluded) ............
            </param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
............ (list of servlets excluded) ............

<security-constraint>
        <web-resource-collection>
            <web-resource-name>queue</web-resource-name>
            <url-pattern>/queue/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>
    <welcome-file-list>
        <welcome-file>blog.html</welcome-file>
    </welcome-file-list>
</web-app>

Android Studio Gradle build exception log

com.google.apphosting.utils.config.AppEngineConfigException: Unrecognized element <app-engine-apis>
at com.google.apphosting.utils.config.AppEngineWebXmlProcessor.processSecondLevelNode(AppEngineWebXmlProcessor.java:243)
at com.google.apphosting.utils.config.AppEngineWebXmlProcessor.processXml(AppEngineWebXmlProcessor.java:64)
at com.google.apphosting.utils.config.AppEngineWebXmlReader.processXml(AppEngineWebXmlReader.java:132)
at com.google.apphosting.utils.config.AppEngineWebXmlReader.readAppEngineWebXml(AppEngineWebXmlReader.java:76)
at com.google.api.server.spi.tools.AppEngineUtil.getAppProperty(AppEngineUtil.java:138)
at com.google.api.server.spi.tools.AppEngineUtil.getApplicationId(AppEngineUtil.java:57)
at com.google.api.server.spi.tools.AppEngineUtil.getApplicationDefaultHostname(AppEngineUtil.java:96)
at com.google.api.server.spi.tools.EndpointsToolAction.getHostname(EndpointsToolAction.java:233)
at com.google.api.server.spi.tools.GetDiscoveryDocAction.execute(GetDiscoveryDocAction.java:85)
at com.google.api.server.spi.tools.EndpointsTool.execute(EndpointsTool.java:84)
at com.google.cloud.tools.gradle.endpoints.framework.server.task.EndpointsArtifactTask.generateEndpointsArtifact(EndpointsArtifactTask.java:208)
at java.base@17.0.6/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base@17.0.6/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base@17.0.6/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base@17.0.6/java.lang.reflect.Method.invoke(Unknown Source)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:125
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:58)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:51)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:29)
at org.gradle.api.internal.tasks.execution.TaskExecution$3.run(TaskExecution.java:236)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:29)
at org.gradle.internal.operations.DefaultBuildOperationRunner$1.execute(DefaultBuildOperationRunner.java:26)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:66)
at org.gradle.internal.operations.DefaultBuildOperationRunner$2.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:157)
at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:59)
at org.gradle.internal.operations.DefaultBuildOperationRunner.run(DefaultBuildOperationRunner.java:47)
at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:68)
at org.gradle.api.internal.tasks.execution.TaskExecution.executeAction(TaskExecution.java:221)
at org.gradle.api.internal.tasks.execution.TaskExecution.executeActions(TaskExecution.java:204)
at org.gradle.api.internal.tasks.execution.TaskExecution.executeWithPreviousOutputFiles(TaskExecution.java:187)
at org.gradle.api.internal.tasks.execution.TaskExecution.execute(TaskExecution.java:165)
at org.gradle.internal.execution.steps.ExecuteStep.executeInternal(ExecuteStep.java:89)
at org.gradle.internal.execution.steps.ExecuteStep.access$000(ExecuteStep.java:40)
at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:53)
at org.gradle.internal.execution.steps.ExecuteStep$1.call(ExecuteStep.java:50)

App Engine server exception log when trying to call API methods that use Datastore with Objectify 5.  Error occurs when deployed the project in the Java 11+ environment without the <app-engine-apis>true<app-engine-apis> line in app-engine.web.xml.

exception occurred while calling backend method
com.google.apphosting.api.ApiProxy$FeatureNotEnabledException: datastore_v3.RunQuery
at com.google.apphosting.utils.runtime.ApiProxyUtils.convertApiError(ApiProxyUtils.java:81)
at com.google.apphosting.utils.runtime.ApiProxyUtils.getApiError(ApiProxyUtils.java:198)
at com.google.apphosting.runtime.ApiProxyImpl$AsyncApiFuture.success(ApiProxyImpl.java:684)
at com.google.apphosting.runtime.ApiProxyImpl$AsyncApiFuture.success(ApiProxyImpl.java:581)
at com.google.apphosting.runtime.http.HttpApiHostClient.receivedResponse(HttpApiHostClient.java:296)
at com.google.apphosting.runtime.http.JettyHttpApiHostClient$Listener.onComplete(JettyHttpApiHostClient.java:206)
at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:218)
at org.eclipse.jetty.client.ResponseNotifier.notifyComplete(ResponseNotifier.java:210)
at org.eclipse.jetty.client.HttpReceiver.terminateResponse(HttpReceiver.java:481)
at org.eclipse.jetty.client.HttpReceiver.terminateResponse(HttpReceiver.java:461)
at org.eclipse.jetty.client.HttpReceiver.responseSuccess(HttpReceiver.java:424)
at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.messageComplete(HttpReceiverOverHTTP.java:374)
at org.eclipse.jetty.http.HttpParser.handleContentMessage(HttpParser.java:596)
at org.eclipse.jetty.http.HttpParser.parseContent(HttpParser.java:1723)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:1552)
at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.parse(HttpReceiverOverHTTP.java:208)
at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.process(HttpReceiverOverHTTP.java:148)
at org.eclipse.jetty.client.http.HttpReceiverOverHTTP.receive(HttpReceiverOverHTTP.java:80)
at org.eclipse.jetty.client.http.HttpChannelOverHTTP.receive(HttpChannelOverHTTP.java:131)
at org.eclipse.jetty.client.http.HttpConnectionOverHTTP.onFillable(HttpConnectionOverHTTP.java:172)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)

I assume this GAE exception is thrown because the server can't access the legacy Datastore due to failure to 'Install the App Engine API JAR'.  The alternative explanation is that I am not using Objectify 6, but I have read that others are running Java 11+ GAE servers with Objectify 5.

2 3 481
3 REPLIES 3