This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5791-struts-boot
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 9363c37ed36adeb9153780da1987e67e72d9d093
Author: Lukasz Lenart <[email protected]>
AuthorDate: Fri Oct 23 12:54:45 2026 +0200

    WW-5791 fix(boot): serve an empty docBase and capture every filter init 
failure
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../org/apache/struts2/boot/StrutsBootServer.java  | 22 +++++++++++++++-------
 .../apache/struts2/boot/StrutsBootTomcatTest.java  |  8 ++++++++
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/boot/src/main/java/org/apache/struts2/boot/StrutsBootServer.java 
b/boot/src/main/java/org/apache/struts2/boot/StrutsBootServer.java
index 910dd5cc0..4b42a731e 100644
--- a/boot/src/main/java/org/apache/struts2/boot/StrutsBootServer.java
+++ b/boot/src/main/java/org/apache/struts2/boot/StrutsBootServer.java
@@ -63,7 +63,8 @@ public final class StrutsBootServer implements AutoCloseable {
         try {
             tomcat.setBaseDir(baseDir.toString());
             tomcat.setPort(settings.port());
-            Context context = tomcat.addContext(settings.contextPath(), 
baseDir.toString());
+            Path docBase = Files.createDirectory(baseDir.resolve("webapp"));
+            Context context = tomcat.addContext(settings.contextPath(), 
docBase.toString());
             context.addServletContainerInitializer(
                     (classes, servletContext) -> 
servletContext.setAttribute(ActionRegistry.SERVLET_CONTEXT_ATTRIBUTE, registry),
                     null);
@@ -77,12 +78,11 @@ public final class StrutsBootServer implements 
AutoCloseable {
             ConfigurationException failure = e instanceof 
ConfigurationException configurationException
                     ? configurationException
                     : new ConfigurationException("Struts Boot failed to start: 
" + e.getMessage(), e);
-            try {
-                server.close();
-            } catch (RuntimeException closeFailure) {
-                failure.addSuppressed(closeFailure);
-            }
+            server.closeAfterFailure(failure);
             throw failure;
+        } catch (Error e) {
+            server.closeAfterFailure(e);
+            throw e;
         }
         Runtime.getRuntime().addShutdownHook(server.shutdownHook);
         return server;
@@ -120,6 +120,14 @@ public final class StrutsBootServer implements 
AutoCloseable {
         }
     }
 
+    private void closeAfterFailure(Throwable failure) {
+        try {
+            close();
+        } catch (RuntimeException closeFailure) {
+            failure.addSuppressed(closeFailure);
+        }
+    }
+
     private void assertStarted(Context context, CapturingStrutsFilter filter) {
         Throwable initFailure = filter.failure.get();
         if (initFailure != null || context.getState() != 
LifecycleState.STARTED) {
@@ -197,7 +205,7 @@ public final class StrutsBootServer implements 
AutoCloseable {
         public void init(FilterConfig filterConfig) throws ServletException {
             try {
                 super.init(filterConfig);
-            } catch (RuntimeException | ServletException e) {
+            } catch (Throwable e) {
                 failure.set(e);
                 throw e;
             }
diff --git 
a/boot/src/test/java/org/apache/struts2/boot/StrutsBootTomcatTest.java 
b/boot/src/test/java/org/apache/struts2/boot/StrutsBootTomcatTest.java
index be3f6d829..19ede906f 100644
--- a/boot/src/test/java/org/apache/struts2/boot/StrutsBootTomcatTest.java
+++ b/boot/src/test/java/org/apache/struts2/boot/StrutsBootTomcatTest.java
@@ -86,6 +86,7 @@ public class StrutsBootTomcatTest {
     @Test
     public void testUnregisteredMethodNotInvokable() throws Exception {
         UserAction.deleteInvoked = false;
+        assertThat(get(server.baseUrl() + 
"/admin/users!list.action").statusCode()).isEqualTo(200);
 
         HttpResponse<String> response = get(server.baseUrl() + 
"/admin/users!delete.action");
 
@@ -99,6 +100,13 @@ public class StrutsBootTomcatTest {
         assertThat(get(server.baseUrl() + 
"/hello.action").statusCode()).isEqualTo(200);
     }
 
+    @Test
+    public void testBaseDirFilesAreNotServed() throws Exception {
+        Files.writeString(server.baseDir().resolve("base-dir-file.txt"), "not 
public");
+
+        assertThat(get(server.baseUrl() + 
"/base-dir-file.txt").statusCode()).isNotEqualTo(200);
+    }
+
     @Test
     public void testConfigurationErrorStopsTomcatAndCleansBaseDir() throws 
Exception {
         Set<Path> before = bootTempDirs();

Reply via email to