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

lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 7574d9b31a84db4f93b9eac9c593f45aa6ecadd5
Author: Lukasz Lenart <[email protected]>
AuthorDate: Fri Oct 23 13:16:25 2026 +0200

    WW-5791 docs: document bind address, logging and packaging in boot-hello
    
    README: struts.boot.address, error pages, the jar name, BOM usage, a
    logging backend note, and non-Spring packaging alternatives. Spec: fix
    the .method(name) row and state that registry config is never broader
    than the equivalent struts.xml.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 apps/boot-hello/README.md                          | 31 +++++++++++++++++++---
 .../specs/2026-10-23-WW-5791-struts-boot-design.md |  8 ++++--
 2 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/apps/boot-hello/README.md b/apps/boot-hello/README.md
index 2e36a61cc..c0e048a4c 100644
--- a/apps/boot-hello/README.md
+++ b/apps/boot-hello/README.md
@@ -4,7 +4,9 @@ The smallest Struts Boot application: one action, one 
FreeMarker template, no `w
 
 ## Three steps
 
-1. Depend on `org.apache.struts:struts2-boot-starter`.
+1. Depend on `org.apache.struts:struts2-boot-starter`, at the same version as 
the rest of Struts. Importing
+   `org.apache.struts:struts2-bom` in `<dependencyManagement>` keeps the 
versions aligned so the starter needs no
+   `<version>` of its own.
 2. Implement `StrutsBootApplication` and register actions:
 
    ```java
@@ -32,6 +34,9 @@ mvn package -pl apps/boot-hello -am -DskipAssembly -DskipTests
 java -jar apps/boot-hello/target/struts2-boot-hello-<version>.jar 
--struts.boot.port=9090
 ```
 
+`<version>` is the Struts version being built, for example 
`struts2-boot-hello-7.5.0-SNAPSHOT.jar`. The example is
+not deployed to Maven repositories; build it from source.
+
 ## Settings
 
 Settings are read from `struts.properties` on the classpath. A `--key=value` 
argument overrides the file.
@@ -40,10 +45,12 @@ Settings are read from `struts.properties` on the 
classpath. A `--key=value` arg
 
|----------------------------|---------|--------------------------------------------|
 | `struts.boot.port`         | `8080`  | HTTP port; `0` picks a free port      
     |
 | `struts.boot.context-path` | `""`    | Context path the application is 
served at  |
+| `struts.boot.address`      | all     | Interface to listen on, e.g. 
`127.0.0.1`   |
 
 ## Defaults worth knowing
 
-- Tomcat listens on all interfaces, not only on localhost.
+- Tomcat listens on all interfaces, not only on localhost; set 
`struts.boot.address` to restrict it.
+- Error pages show the status only, without stack traces or the Tomcat version.
 - `struts.devMode` stays off.
 - Each start uses a fresh temporary base directory (`struts-boot-<uuid>`) that 
is deleted on shutdown.
 - Views are FreeMarker only; a result path such as `hello.ftl` resolves to 
`/templates/hello.ftl` on the classpath.
@@ -52,5 +59,21 @@ Settings are read from `struts.properties` on the classpath. 
A `--key=value` arg
 
 The jar is built with `maven-shade-plugin`. Every Struts plugin ships its own 
`META-INF/struts-plugin.xml`, and shading
 keeps only one file with that name, so with two or more plugins on the 
classpath all but one would be silently lost.
-This example uses no plugins. If your application needs them, package it 
differently (for example with
-Spring Boot's repackager or a `lib/` directory next to a thin jar) instead of 
shading.
+This example uses no plugins. If your application needs them, package it 
differently instead of shading: a thin jar
+with its dependencies in a `lib/` directory (`maven-dependency-plugin` copies 
them, `maven-jar-plugin` writes the
+`Class-Path` manifest entry), or a distribution built with 
`maven-assembly-plugin`.
+
+## Logging
+
+Struts logs through the Log4j 2 API, and the starter ships no logging backend, 
so warnings and errors from Struts are
+not printed. Add one to your application, for example (version managed by 
`org.apache.logging.log4j:log4j-bom`):
+
+```xml
+<dependency>
+    <groupId>org.apache.logging.log4j</groupId>
+    <artifactId>log4j-core</artifactId>
+    <scope>runtime</scope>
+</dependency>
+```
+
+with a `log4j2.xml` on the classpath, or `log4j-slf4j2-impl` to route to an 
SLF4J backend.
diff --git a/docs/superpowers/specs/2026-10-23-WW-5791-struts-boot-design.md 
b/docs/superpowers/specs/2026-10-23-WW-5791-struts-boot-design.md
index ea379b8e5..7cac1e787 100644
--- a/docs/superpowers/specs/2026-10-23-WW-5791-struts-boot-design.md
+++ b/docs/superpowers/specs/2026-10-23-WW-5791-struts-boot-design.md
@@ -44,7 +44,11 @@ self-contained jar is a later step.
   `ResultConfig` objects that `struts.xml` produces. Whatever a registered 
action does must match
   what the equivalent XML would do, including security defaults: strict method 
invocation,
   `@StrutsParameter` enforcement and the allowlist. If Boot quietly relaxes 
any of these to make
-  the first page easier, it has failed, even if it works.
+  the first page easier, it has failed, even if it works. The invariant: 
registry config is never
+  broader than the equivalent `struts.xml`. Where the two differ, the registry 
is narrower: a
+  registry action allows only its registered method, while an XML action also 
inherits the
+  package's global allowed methods 
(`execute,input,back,cancel,browse,save,delete,list,index` in
+  `struts-default`).
 - **A Spring Boot look-alike that pulls in Spring.**
 - **Core changes for Boot's convenience.** Boot uses only existing extension 
points (see
   "Wiring"). If something can't be done that way, stop and raise it. Don't 
patch `Dispatcher`.
@@ -89,7 +93,7 @@ The template lives at 
`src/main/resources/templates/hello.ftl`. Running `HelloAp
 | top-level `actions.action(...)` | an action in a Boot-owned package with 
namespace `""` |
 | `namespace(ns, consumer)` | one `PackageConfig` with that namespace, 
extending `struts-default` |
 | `action(name, Class)` | `ActionConfig` with `className`; method defaults to 
`execute` |
-| `.method(name)` | `methodName`, **and** adds it to the allowed methods. 
`struts-default` packages run with strict method invocation, so without this 
the call would be rejected |
+| `.method(name)` | `methodName`, and adds it to the allowed methods. 
`ActionConfig#isAllowedMethod` already accepts the configured method, so the 
explicit entry only makes it visible in `getAllowedMethods()`. No other method 
is added: a registry action does not inherit the package's global allowed 
methods |
 | `.success(path)` | shorthand for `.result("success", path)` |
 | `.result(name, path)` | a `freemarker` result whose location is 
`/templates/` + `path` |
 | `.redirectAction(name, actionName)` | a `redirectAction` result |

Reply via email to