diff --git a/runtime/failinitfilterwebapp/pom.xml b/runtime/failinitfilterwebapp/pom.xml
new file mode 100644
index 00000000..7f1600e2
--- /dev/null
+++ b/runtime/failinitfilterwebapp/pom.xml
@@ -0,0 +1,83 @@
+
+
+
+
+ 4.0.0
+ war
+ 1.0
+
+ com.google.appengine.demos
+ failinitfilterwebapp
+ AppEngine :: failinitfilterwebapp
+
+
+ 1
+ UTF-8
+
+
+
+
+ javax.servlet
+ servlet-api
+ 2.5
+ provided
+
+
+
+ target/${project.artifactId}-${project.version}/WEB-INF/classes
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 3.3.2
+
+ true
+
+
+
+ ${basedir}/src/main/webapp/WEB-INF
+ true
+ WEB-INF
+
+
+
+
+
+ maven-compiler-plugin
+ 3.10.1
+
+
+ 1.8
+
+
+
+ com.google.cloud.tools
+ appengine-maven-plugin
+ 2.4.1
+
+ ludo-in-in
+ failinitfilter
+ false
+ true
+
+
+
+
+
+
diff --git a/runtime/failinitfilterwebapp/src/main/java/FailInitializationFilter.java b/runtime/failinitfilterwebapp/src/main/java/FailInitializationFilter.java
new file mode 100644
index 00000000..ce845eb4
--- /dev/null
+++ b/runtime/failinitfilterwebapp/src/main/java/FailInitializationFilter.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+public class FailInitializationFilter implements Filter {
+ @Override
+ public void init(FilterConfig config) throws ServletException {
+ throw new ServletException("Intentionally failing to initialize.");
+ }
+
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
+ throws ServletException {
+ throw new ServletException("Unexpectedly got a request.");
+ }
+
+ @Override
+ public void destroy() {}
+}
diff --git a/runtime/failinitfilterwebapp/src/main/webapp/WEB-INF/appengine-generated/app.yaml b/runtime/failinitfilterwebapp/src/main/webapp/WEB-INF/appengine-generated/app.yaml
new file mode 100644
index 00000000..dc566fa0
--- /dev/null
+++ b/runtime/failinitfilterwebapp/src/main/webapp/WEB-INF/appengine-generated/app.yaml
@@ -0,0 +1,25 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+runtime: java8
+inbound_services:
+- warmup
+threadsafe: True
+auto_id_policy: default
+api_version: 'user_defined'
+handlers:
+- url: /.*
+ script: unused
+ login: optional
+ secure: optional
diff --git a/runtime/failinitfilterwebapp/src/main/webapp/WEB-INF/appengine-web.xml b/runtime/failinitfilterwebapp/src/main/webapp/WEB-INF/appengine-web.xml
new file mode 100644
index 00000000..dcfaa9c5
--- /dev/null
+++ b/runtime/failinitfilterwebapp/src/main/webapp/WEB-INF/appengine-web.xml
@@ -0,0 +1,20 @@
+
+
+
+ true
+ java8
+
diff --git a/runtime/failinitfilterwebapp/src/main/webapp/WEB-INF/web.xml b/runtime/failinitfilterwebapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000..281a06ae
--- /dev/null
+++ b/runtime/failinitfilterwebapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,30 @@
+
+
+
+
+ FailInitializationFilter
+ FailInitializationFilter
+
+
+ FailInitializationFilter
+ /*
+
+
diff --git a/runtime/nogaeapiswebapp/src/main/webapp/WEB-INF/web.xml b/runtime/nogaeapiswebapp/src/main/webapp/WEB-INF/web.xml
index 05029050..075dc57a 100644
--- a/runtime/nogaeapiswebapp/src/main/webapp/WEB-INF/web.xml
+++ b/runtime/nogaeapiswebapp/src/main/webapp/WEB-INF/web.xml
@@ -14,9 +14,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-
-
+
+ NoGaeApisServletNoGaeApisServlet
diff --git a/runtime/pom.xml b/runtime/pom.xml
index ee06cfa5..0c61fe45 100644
--- a/runtime/pom.xml
+++ b/runtime/pom.xml
@@ -35,6 +35,7 @@
deploymentlocalnogaeapiswebapp
+ failinitfilterwebapptesttestapps
diff --git a/runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/FailureFilterTest.java b/runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/FailureFilterTest.java
new file mode 100644
index 00000000..4292ef75
--- /dev/null
+++ b/runtime/test/src/test/java/com/google/apphosting/runtime/jetty9/FailureFilterTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.google.apphosting.runtime.jetty9;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class FailureFilterTest extends JavaRuntimeViaHttpBase {
+
+ private static File appRoot;
+
+ @BeforeClass
+ public static void beforeClass() throws IOException, InterruptedException {
+ File currentDirectory = new File("").getAbsoluteFile();
+ appRoot = new File(currentDirectory, "../failinitfilterwebapp/target/failinitfilterwebapp-1.0");
+ assertThat(appRoot.isDirectory()).isTrue();
+ }
+
+ private RuntimeContext runtimeContext() throws IOException, InterruptedException {
+ RuntimeContext.Config config =
+ RuntimeContext.Config.builder().setApplicationPath(appRoot.toString()).build();
+ return RuntimeContext.create(config);
+ }
+
+ @Test
+ public void testFilterInitFailed() throws Exception {
+ try (RuntimeContext runtime = runtimeContext()) {
+ assertThat(runtime.executeHttpGet("/", 500))
+ .contains("javax.servlet.ServletException: Intentionally failing to initialize.");
+ }
+ }
+}