OK… so let’s see if I can help a little.
First, re: the observation on EE8 vs EE11 in the stack trace. Here is a little more of the stack trace in which you’ll see that the EE11 SessionHandler makes the call to IsAuthorized which in turn hits Jetty… and then the EE8 Authenticator is throwing the NoClassDefFoundError:
java.lang.NoClassDefFoundError: org/eclipse/jetty/ee8/security/Authenticator
at com.google.apphosting.runtime.jetty.AppEngineAuthentication$AppEngineUserIdentity.isUserInRole(AppEngineAuthentication.java:382)
at org.eclipse.jetty.security.SecurityHandler.isAuthorized(SecurityHandler.java:690)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:527)
at org.eclipse.jetty.ee11.servlet.SessionHandler.handle(SessionHandler.java:763)
So it looks like EE11 is using some EE8 bits… which seems consistent with other things I’ve read about EE11.
Now, let’s look at two variants of the appengine-web.xml, web.xml and pom.xml.
Firstly, let’s take a look at what produced this stack trace.
Both variants use the same body in the web.xml
<servlet>
<servlet-name>secure</servlet-name>
<jsp-file>/secure/secure.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>secure</servlet-name>
<url-pattern>/secure</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>secret</servlet-name>
<jsp-file>/secure/secret.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>secret</servlet-name>
<url-pattern>/secret</url-pattern>
</servlet-mapping>
<!-- Secure the non-public content -->
<security-constraint>
<web-resource-collection>
<web-resource-name>secure</web-resource-name>
<url-pattern>/secure/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<!-- Secure the sensitive content -->
<security-constraint>
<web-resource-collection>
<web-resource-name>secret</web-resource-name>
<url-pattern>/secret</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
The difference between the two is that for java25, the jakartaee schema changes to 6.1
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_1.xsd"
version="6.1">
The appengine-web.xml built for the latest release of AppEngine targets java25 is Plain Jane simple:
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java25</runtime>
<app-engine-apis>true</app-engine-apis>
</appengine-web-app>
And in the pom.xml, the jarkarta-servlet-api is 6.1.0
...
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
...
<build>
...
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.8.6</version>
<configuration>
<projectId>test-site</projectId>
<version>GCLOUD_CONFIG</version>
</configuration>
</plugin>
</plugins>
</build>
Now, in order to test using cloudSdkVersion 544.0.0 I switched everything to target java21, EE10 and the pinned cloudSdkVersion. So, starting the jakartaee schema back to 6.0
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
Then appengine-web.xml forces the use of EE10 with java21
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java21</runtime>
<system-properties>
<property name="appengine.use.EE10" value="true"/>
</system-properties>
<app-engine-apis>true</app-engine-apis>
</appengine-web-app>
And in the pom.xml, the jarkarta-servlet-api is 6.0.0 and some extra bits are needed for the appengine-maven-plugin
...
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
...
<build>
...
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.8.6</version>
<configuration>
<projectId>test-site</projectId>
<version>GCLOUD_CONFIG</version>
<cloudSdkVersion>544.0.0</cloudSdkVersion>
</configuration>
</plugin>
</plugins>
</build>
Let me know if I missed something you were looking for.