diff --git a/docs/superpowers/plans/2026-07-23-helloworld-action-extension-404.md b/docs/superpowers/plans/2026-07-23-helloworld-action-extension-404.md new file mode 100644 index 00000000..6ccb4277 --- /dev/null +++ b/docs/superpowers/plans/2026-07-23-helloworld-action-extension-404.md @@ -0,0 +1,264 @@ +# WW-5416 action.extension 404 Fix — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Restore the framework-default `struts.action.extension` in the `helloworld`, `text-provider`, and `sitemesh3` example modules so documented `.action` URLs return 200 instead of 404. + +**Architecture:** Each affected module overrides `struts.action.extension` to a value that excludes the `.action` extension. Deleting that one `` line restores the framework default `action,,`, which accepts both `.action` and extensionless URLs. In-app navigation already routes through Struts URL/form tags, so widening the allowed extension set is strictly additive — no existing route breaks. + +**Tech Stack:** Struts 2 (XML config), Maven multi-module build, Jetty Maven plugin for local run. + +## Global Constraints + +- Do **not** modify `rest-angular` (`struts.action.extension=,,xml,json,action`) or `mailreader2` (`struts.action.extension=do`) — those overrides are intentional. +- No new automated/integration test is added (per spec scope decision). +- Commit messages use the repo convention: `WW-5416 fix(): ` (JIRA ticket prefix required). +- Work happens on branch `fix/WW-5416-action-extension-404` (already created). +- Each task must keep `mvn -pl clean package` green. + +--- + +### Task 1: Fix `helloworld` (the ticket) + +**Files:** +- Modify: `helloworld/src/main/resources/struts.xml:9` + +**Interfaces:** +- Consumes: nothing from other tasks. +- Produces: nothing other tasks depend on (each task is independent). + +- [ ] **Step 1: Confirm the bug exists (baseline)** + +Start the app in the background and confirm the documented URL 404s: + +```bash +cd /Users/lukaszlenart/Projects/Apache/struts-examples/helloworld +mvn -q jetty:run & +JETTY_PID=$! +# wait for startup +until curl -s -o /dev/null http://localhost:8080/helloworld/ ; do sleep 2; done +curl -s -o /dev/null -w "index.action -> %{http_code}\n" http://localhost:8080/helloworld/index.action +kill $JETTY_PID +``` + +Expected (before fix): `index.action -> 404` + +- [ ] **Step 2: Delete the extension override** + +In `helloworld/src/main/resources/struts.xml`, remove this line (line 9): + +```xml + +``` + +Leave `struts.devMode` and `struts.allowlist.packageNames` constants untouched. + +- [ ] **Step 3: Verify the build still passes** + +Run: `mvn -q -pl helloworld clean package` +Expected: `BUILD SUCCESS` + +- [ ] **Step 4: Verify the documented URL now returns 200** + +```bash +cd /Users/lukaszlenart/Projects/Apache/struts-examples/helloworld +mvn -q jetty:run & +JETTY_PID=$! +until curl -s -o /dev/null http://localhost:8080/helloworld/ ; do sleep 2; done +curl -s -o /dev/null -w "index.action -> %{http_code}\n" http://localhost:8080/helloworld/index.action +curl -s -o /dev/null -w "hello.action -> %{http_code}\n" http://localhost:8080/helloworld/hello.action +curl -s -o /dev/null -w "hello (no ext) -> %{http_code}\n" http://localhost:8080/helloworld/hello +kill $JETTY_PID +``` + +Expected (after fix): +``` +index.action -> 200 +hello.action -> 200 +hello (no ext) -> 200 +``` + +- [ ] **Step 5: Commit** + +```bash +git add helloworld/src/main/resources/struts.xml +git commit -m "WW-5416 fix(helloworld): restore default struts.action.extension + +Removing the ',' override restores the framework default 'action,,' so +the documented .action URLs return 200 instead of 404. + +Co-Authored-By: Claude Opus 4.8 " +``` + +--- + +### Task 2: Fix `text-provider` + +**Files:** +- Modify: `text-provider/src/main/resources/struts.xml:8` + +**Interfaces:** +- Consumes: nothing from other tasks. +- Produces: nothing other tasks depend on. + +- [ ] **Step 1: Confirm the bug exists (baseline)** + +```bash +cd /Users/lukaszlenart/Projects/Apache/struts-examples/text-provider +mvn -q jetty:run & +JETTY_PID=$! +until curl -s -o /dev/null http://localhost:8080/text-provider/ ; do sleep 2; done +curl -s -o /dev/null -w "index.action -> %{http_code}\n" http://localhost:8080/text-provider/index.action +kill $JETTY_PID +``` + +Expected (before fix): `index.action -> 404` + +- [ ] **Step 2: Delete the extension override** + +In `text-provider/src/main/resources/struts.xml`, remove this line (line 8): + +```xml + +``` + +Leave the `struts.convention.action.packages`, `struts.custom.i18n.resources`, and all `bean`/`TextProviderFactory` constants untouched. + +- [ ] **Step 3: Verify the build still passes** + +Run: `mvn -q -pl text-provider clean package` +Expected: `BUILD SUCCESS` + +- [ ] **Step 4: Verify the documented URL now returns 200** + +```bash +cd /Users/lukaszlenart/Projects/Apache/struts-examples/text-provider +mvn -q jetty:run & +JETTY_PID=$! +until curl -s -o /dev/null http://localhost:8080/text-provider/ ; do sleep 2; done +curl -s -o /dev/null -w "index.action -> %{http_code}\n" http://localhost:8080/text-provider/index.action +curl -s -o /dev/null -w "index (no ext) -> %{http_code}\n" http://localhost:8080/text-provider/index +kill $JETTY_PID +``` + +Expected (after fix): +``` +index.action -> 200 +index (no ext) -> 200 +``` + +- [ ] **Step 5: Commit** + +```bash +git add text-provider/src/main/resources/struts.xml +git commit -m "WW-5416 fix(text-provider): restore default struts.action.extension + +Removing the ',' override restores the framework default 'action,,' so +.action URLs no longer 404. + +Co-Authored-By: Claude Opus 4.8 " +``` + +--- + +### Task 3: Fix `sitemesh3` + +**Files:** +- Modify: `sitemesh3/src/main/resources/struts.xml:8` + +**Interfaces:** +- Consumes: nothing from other tasks. +- Produces: nothing other tasks depend on. + +- [ ] **Step 1: Confirm the bug exists (baseline)** + +```bash +cd /Users/lukaszlenart/Projects/Apache/struts-examples/sitemesh3 +mvn -q jetty:run & +JETTY_PID=$! +until curl -s -o /dev/null http://localhost:8080/sitemesh3/ ; do sleep 2; done +curl -s -o /dev/null -w "hello.action -> %{http_code}\n" http://localhost:8080/sitemesh3/hello.action +kill $JETTY_PID +``` + +Expected (before fix): `hello.action -> 404` + +- [ ] **Step 2: Delete the extension override** + +In `sitemesh3/src/main/resources/struts.xml`, remove this line (line 8): + +```xml + +``` + +Leave `struts.devMode`, `struts.ui.theme`, and `struts.custom.i18n.resources` constants untouched. + +- [ ] **Step 3: Verify the build still passes** + +Run: `mvn -q -pl sitemesh3 clean package` +Expected: `BUILD SUCCESS` + +- [ ] **Step 4: Verify the documented URL now returns 200 and SiteMesh decoration still applies** + +```bash +cd /Users/lukaszlenart/Projects/Apache/struts-examples/sitemesh3 +mvn -q jetty:run & +JETTY_PID=$! +until curl -s -o /dev/null http://localhost:8080/sitemesh3/ ; do sleep 2; done +curl -s -o /dev/null -w "hello.action -> %{http_code}\n" http://localhost:8080/sitemesh3/hello.action +curl -s -o /dev/null -w "hello (no ext) -> %{http_code}\n" http://localhost:8080/sitemesh3/hello +curl -s -o /dev/null -w "admin/hello.action -> %{http_code}\n" http://localhost:8080/sitemesh3/admin/hello.action +kill $JETTY_PID +``` + +Expected (after fix): +``` +hello.action -> 200 +hello (no ext) -> 200 +admin/hello.action -> 200 +``` + +- [ ] **Step 5: Commit** + +```bash +git add sitemesh3/src/main/resources/struts.xml +git commit -m "WW-5416 fix(sitemesh3): restore default struts.action.extension + +Removing the empty-string override restores the framework default +'action,,' so .action URLs no longer 404. + +Co-Authored-By: Claude Opus 4.8 " +``` + +--- + +### Task 4: Full multi-module build verification + +**Files:** +- None modified. Final gate across the whole repo. + +**Interfaces:** +- Consumes: the three fixes from Tasks 1–3. +- Produces: confirmation that the reactor build is green. + +- [ ] **Step 1: Build every module** + +Run: +```bash +cd /Users/lukaszlenart/Projects/Apache/struts-examples +mvn -q clean package +``` +Expected: `BUILD SUCCESS` with all modules reactored. + +- [ ] **Step 2: Confirm no unintended changes to out-of-scope modules** + +Run: `git diff main --stat` +Expected: only these three files changed (plus the docs added earlier): +``` +helloworld/src/main/resources/struts.xml +text-provider/src/main/resources/struts.xml +sitemesh3/src/main/resources/struts.xml +``` +Confirm `rest-angular` and `mailreader2` are NOT listed. + +- [ ] **Step 3: (No commit)** — this task only verifies; nothing new to commit. diff --git a/docs/superpowers/specs/2026-07-23-helloworld-action-extension-404-design.md b/docs/superpowers/specs/2026-07-23-helloworld-action-extension-404-design.md new file mode 100644 index 00000000..4e0013ef --- /dev/null +++ b/docs/superpowers/specs/2026-07-23-helloworld-action-extension-404-design.md @@ -0,0 +1,82 @@ +# WW-5416: Hello World example returns 404 — design + +- **JIRA:** [WW-5416](https://issues.apache.org/jira/browse/WW-5416) +- **Fix version:** 7.3.0 +- **Date:** 2026-07-23 + +## Problem + +Following the documented Hello World instructions produces a 404. The tutorial (and +`helloworld/README.txt`) tell users to visit `http://localhost:8080/helloworld/index.action`, +but the app returns 404 for any `.action` URL. + +### Root cause + +`helloworld/src/main/resources/struts.xml` sets: + +```xml + +``` + +The framework default is `action,,`, which maps **both** `.action` URLs and extensionless +URLs. Overriding it with `,` reduces the allowed set to the empty extension only, so +`.action` URLs no longer resolve and 404. + +The examples' own pages navigate via Struts URL/form tags (e.g. ``), +which emit URLs using whatever extension is configured — so in-app navigation "works" and +the bug is invisible until a user types the documented `.action` URL directly. + +### Same latent bug in other examples + +| Example | `struts.action.extension` | Verdict | +|---|---|---| +| `helloworld` | `","` | Bug — fix (the ticket) | +| `text-provider` | `","` | Same latent bug — fix | +| `sitemesh3` | `""` | Same latent bug — fix | +| `rest-angular` | `",,xml,json,action"` | Intentional (REST/JSON demo) — leave | +| `mailreader2` | `"do"` | Intentional (Struts1 `.do` migration) — leave | + +## Approach + +Delete the `struts.action.extension` override in the three affected modules, restoring the +framework default `action,,`. + +**Rejected alternative:** setting the value explicitly to `action,,`. Same runtime effect but +adds a config line that only restates the default — no teaching value for example apps. + +## Change set + +Three one-line deletions: + +- `helloworld/src/main/resources/struts.xml` — remove `` +- `text-provider/src/main/resources/struts.xml` — remove `` +- `sitemesh3/src/main/resources/struts.xml` — remove `` + +`rest-angular` and `mailreader2` are explicitly left unchanged. + +## Behavior after fix + +- `` tags emit `.action` URLs by default → in-app links match the tutorials. +- Directly-typed documented URLs (`/helloworld/index.action`, `/helloworld/hello.action`) return 200. +- Extensionless URLs (`/hello`) still resolve — the default is a superset, so nothing that + currently navigates breaks. + +## Risk + +Low / additive. No Java code in these modules inspects the URL extension; all navigation +routes through Struts tags that respect the configured extension. Widening the allowed +extension set cannot remove a previously working route. + +## Out of scope + +- The authoritative "Getting Started" tutorial text lives in the separate `struts-site` + repository; not edited here. `helloworld/README.txt` already references `.action` and + becomes correct once the override is removed. +- No new automated/integration test (per scope decision). Regression is guarded only by the + existing full build. + +## Verification + +- `mvn clean package` succeeds for all modules. +- For `helloworld`, `text-provider`, and `sitemesh3`: `mvn jetty:run`, then confirm the + documented `.action` URL returns 200 and the in-app links navigate correctly. diff --git a/helloworld/src/main/resources/struts.xml b/helloworld/src/main/resources/struts.xml index c7d9171c..45529a3b 100755 --- a/helloworld/src/main/resources/struts.xml +++ b/helloworld/src/main/resources/struts.xml @@ -6,7 +6,6 @@ - diff --git a/sitemesh3/src/main/resources/struts.xml b/sitemesh3/src/main/resources/struts.xml index 875a3dbb..97af6498 100644 --- a/sitemesh3/src/main/resources/struts.xml +++ b/sitemesh3/src/main/resources/struts.xml @@ -5,7 +5,6 @@ - diff --git a/text-provider/src/main/resources/struts.xml b/text-provider/src/main/resources/struts.xml index 7d1e2b40..00cdb31e 100644 --- a/text-provider/src/main/resources/struts.xml +++ b/text-provider/src/main/resources/struts.xml @@ -5,7 +5,6 @@ -