[ 
https://issues.apache.org/jira/browse/WW-5791?focusedWorklogId=1049650&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1049650
 ]

ASF GitHub Bot logged work on WW-5791:
--------------------------------------

                Author: ASF GitHub Bot
            Created on: 23/Oct/26 11:44
            Start Date: 23/Oct/26 11:44
    Worklog Time Spent: 10m 
      Work Description: lukaszlenart opened a new pull request, #2053:
URL: https://github.com/apache/struts/pull/2053

   Fixes [WW-5791](https://issues.apache.org/jira/browse/WW-5791)
   
   ## What
   
   Struts Boot: run a Struts application from `main()` on embedded Tomcat, with 
actions registered in Java instead of `struts.xml`. Aimed at newcomers. 
Standalone, no Spring dependency, no changes under `core/`.
   
   ```java
   public class HelloApp implements StrutsBootApplication {
       public static void main(String[] args) {
           StrutsBoot.run(HelloApp.class, args);
       }
   
       @Override
       public void actions(ActionRegistry actions) {
           actions.action("hello", HelloAction.class).success("hello.ftl");
       }
   }
   ```
   
   - **`boot/` (`struts2-boot-starter`)** contains:
     - `StrutsBoot` / `StrutsBootServer`: embedded Tomcat that registers 
`StrutsPrepareAndExecuteFilter` in code.
     - The fluent `ActionRegistry` API.
     - `RegistryConfigurationProvider`, which turns the registry into ordinary 
`PackageConfig`s through the existing `configProviders` init param.
     - `BootSettings`, which reads `struts.boot.port`, `struts.boot.address` 
and `struts.boot.context-path` from `struts.properties` or `--key=value` 
arguments.
   - **Tomcat follows core's Jakarta line:** 10.1.59 by default, 11.0.27 under 
`-Pjakartaee11`. The version is managed in the parent POM, and the BOM lists 
the starter.
   - **`apps/boot-hello`** is an example app shaded into a runnable jar. It is 
not deployed (`maven.deploy.skip`), because shading merges the dependencies' 
LICENSE/NOTICE files.
   - **`THREAT_MODEL.md`** gets a Boot section. The starter's container 
defaults are now in the model, and §14 has a new question, Q-boot, for the PMC.
   
   ## Behaviour worth reviewing
   
   - **Registry config is never broader than the equivalent `struts.xml`.**
     - Packages extend `struts-default` and Strict Method Invocation stays on.
     - Action classes are added to the OGNL allowlist the same way the XML 
provider adds them.
     - Each action allows only its registered method. That is narrower than 
XML, which also inherits the package's global allowed methods.
   - **Configuration errors fail at startup** with a `ConfigurationException` 
for:
     - slashes in an action name (use namespaces instead);
     - non-`.ftl` views;
     - missing templates or unknown interceptor stacks;
     - non-public action classes, or classes without a no-arg constructor;
     - duplicate actions, within the registry or against `struts.xml`.
   - **Container defaults:**
     - listens on all interfaces, port 8080 (`struts.boot.address` restricts 
the interface);
     - error pages carry no stack trace or server version;
     - `DefaultServlet` serves an empty per-run docBase;
     - Tomcat's base directory is a UUID-named temp directory, deleted on 
shutdown;
     - `devMode` is never switched on;
     - a failed start stops Tomcat and removes the temp directory.
   - `jakarta.servlet.jsp-api` is a runtime dependency of the starter. 
FreeMarker's `TaglibFactory` needs it, and `tomcat-embed-core` doesn't ship it.
   
   ## Not in this PR (parked in WW-5791)
   
   Not covered here:
   - WAR-to-jar migration
   - JSP views
   - Gradle plugin
   - other containers
   - a fluent API for interceptor stacks
   - global results, global exception mappings and wildcards
   - a Convention bridge
   - dev-mode reload
   
   The struts-site documentation and the 7.5.0 Version Notes entry follow after 
merge.
   
   ## Testing
   
   - `./mvnw clean install -DskipAssembly`: BUILD SUCCESS, with and without 
`-Pjakartaee11`.
   - `boot` has 49 tests covering:
     - the registry, the provider and the settings;
     - end to end on embedded Tomcat:
       - FreeMarker rendering;
       - POST-only rejects GET;
       - `!method` and `method:` blocked with DMI on, with positive controls;
       - XML and the registry working side by side;
       - context path and redirects;
       - busy port and config-error cleanup;
       - error-page content;
       - bind address.
   - `java -jar` on the shaded `boot-hello` jar serves `/hello.action` with 200.
   
   Design and plan: 
`docs/superpowers/specs/2026-10-23-WW-5791-struts-boot-design.md`, 
`docs/superpowers/plans/2026-10-23-WW-5791-struts-boot.md`.
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   




Issue Time Tracking
-------------------

            Worklog Id:     (was: 1049650)
    Remaining Estimate: 0h
            Time Spent: 10m

> Struts Boot: run a Struts application from main() with an embedded container 
> and programmatic action registration
> -----------------------------------------------------------------------------------------------------------------
>
>                 Key: WW-5791
>                 URL: https://issues.apache.org/jira/browse/WW-5791
>             Project: Struts 2
>          Issue Type: New Feature
>          Components: Core
>            Reporter: Lukasz Lenart
>            Assignee: Lukasz Lenart
>            Priority: Major
>             Fix For: 7.5.0
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> h2. Goal
> Give newcomers a working Struts application with almost no setup: add one 
> dependency, write an action class, run {{main()}}, see the page. No 
> {{web.xml}}, no {{struts.xml}}, no external servlet container. Standalone — 
> no Spring dependency.
> h2. Minimal scope
> * New {{struts-boot-starter}} artifact pulling in core and an embedded 
> servlet container (Tomcat), registering {{StrutsPrepareAndExecuteFilter}} in 
> code.
> * {{StrutsBoot.run(App.class, args)}} entry point; the application class 
> implements {{StrutsBootApplication}}.
> * Fluent action registration, fed into the configuration through a single 
> {{ConfigurationProvider}} built on {{PackageConfig}} / {{ActionConfig}} / 
> {{ResultConfig}} builders. No Convention plugin, no classpath scanning.
> {code:java}public class HelloApp implements StrutsBootApplication {
>     public static void main(String[] args) {
>         StrutsBoot.run(HelloApp.class, args);
>     }
>     @Override
>     public void actions(ActionRegistry actions) {
>         actions.action("hello", HelloAction.class)
>                .success("hello.ftl");
>         actions.namespace("/admin", admin -> {
>             admin.action("users", UserAction.class)
>                  .method("list")
>                  .success("admin/users.ftl");
>             admin.action("saveUser", UserAction.class)
>                  .method("save")
>                  .httpMethods(POST)
>                  .result("input", "admin/userForm.ftl")
>                  .redirectAction("success", "users");
>         });
>     }
> }
> {code}
> * Defaults: each namespace is a package extending {{struts-default}}; top 
> level is namespace {{""}}; {{method}} defaults to {{execute}}; 
> {{success(path)}} is shorthand for {{result("success", path)}}; interceptors 
> default to {{defaultStack}}, overridable per action or namespace by stack 
> name; {{httpMethods(...)}} maps to the http-method restriction from WW-3717.
> * Views: FreeMarker only, chosen by {{.ftl}} extension, resolved from 
> {{classpath:/templates/}}.
> * Configuration: the existing {{struts.properties}}; Boot-only settings 
> (port, context path) under a {{struts.boot.*}} prefix. Not 
> {{application.properties}}, to avoid clashing with Spring Boot.
> * A {{struts.xml}} on the classpath is still loaded alongside the registry.
> * Runnable fat jar via a Maven plugin.
> h2. Parked for later
> * Running an existing Struts WAR as a self-contained jar (migration path).
> * JSP views in the embedded container.
> * Gradle plugin.
> * Alternative containers (Jetty, Undertow).
> * Fluent definition of custom interceptor stacks.
> * Global results, global exception mappings, wildcard actions in the registry.
> * Optional bridge to Convention plugin annotations.
> * Dev-mode reload of templates and registry.
> * Project generator / quick-start archetype.
> * Health and info endpoints.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to