You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2026/07/20 08:22:05 UTC

(struts) branch WW-5620-log4j2-logging-standardization created (now 8dd64e175)

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

lukaszlenart pushed a change to branch WW-5620-log4j2-logging-standardization
in repository https://gitbox.apache.org/repos/asf/struts.git


      at 8dd64e175 WW-5620 Remove dead first-party SLF4J dependency declarations

This branch includes the following new commits:

     new 594c7e517 WW-5620 docs: add Log4j2 logging standardization design spec
     new 57f8edfa9 WW-5620 docs: add Log4j2 logging standardization implementation plan
     new 378b500e8 WW-5620 Migrate FinalizableReferenceQueue to Log4j2
     new 7627c903f WW-5620 Migrate AbstractDefaultToStringRenderable to Log4j2
     new c6b3f656d WW-5620 Remove unused injectable j.u.l.Logger DI factory from ContainerBuilder
     new 8dd64e175 WW-5620 Remove dead first-party SLF4J dependency declarations

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(struts) 01/06: WW-5620 docs: add Log4j2 logging standardization design spec

Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5620-log4j2-logging-standardization
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 594c7e517686acafcc753ca80f0ff6f57d20f4fb
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Mon Jul 20 09:42:15 2026 +0200

    WW-5620 docs: add Log4j2 logging standardization design spec
    
    Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
 ...W-5620-log4j2-logging-standardization-design.md | 135 +++++++++++++++++++++
 1 file changed, 135 insertions(+)

diff --git a/docs/superpowers/specs/2026-07-20-WW-5620-log4j2-logging-standardization-design.md b/docs/superpowers/specs/2026-07-20-WW-5620-log4j2-logging-standardization-design.md
new file mode 100644
index 000000000..db5b619ef
--- /dev/null
+++ b/docs/superpowers/specs/2026-07-20-WW-5620-log4j2-logging-standardization-design.md
@@ -0,0 +1,135 @@
+# WW-5620 — Standardize logging on Log4j2
+
+- **Jira:** [WW-5620](https://issues.apache.org/jira/browse/WW-5620)
+- **Type:** Improvement (refactor / dependency cleanup)
+- **Fix version:** 7.3.0
+- **Components:** Core, Plugin - Tiles
+- **Date:** 2026-07-20
+
+## Goal
+
+Log4j2 is the project's standard logging layer. Three source files still use
+legacy logging frameworks. Migrate them to Log4j2 and remove the now-dead
+first-party SLF4J dependency declarations that only existed to support them.
+
+This is a pure logging-standardization refactor: **no functional or security
+behavior changes.** All three files are vendored (files 1 and 3 from Google
+Guice, file 2 from Apache Tiles), so there is no upstream-sync concern.
+
+## Scope
+
+### In scope
+1. Migrate `FinalizableReferenceQueue.java` (core) off `java.util.logging`.
+2. Migrate `AbstractDefaultToStringRenderable.java` (tiles) off SLF4J.
+3. Remove the injectable `java.util.logging.Logger` DI factory from
+   `ContainerBuilder.java` (core).
+4. Remove the first-party SLF4J dependency declarations that become dead after
+   step 2, gated on a build/dependency-tree verification.
+
+### Out of scope
+- The commons-logging → Log4j2 and SLF4J → Log4j2 **runtime bridges**
+  (`log4j-jcl`, `log4j-slf4j-impl`, `commons-logging`). These route
+  *transitive third-party* library logging into Log4j2 and are unrelated to
+  first-party code. They stay.
+- Any broader logging refactor beyond these three files.
+
+## File-level changes
+
+### 1. `core/src/main/java/org/apache/struts2/inject/util/FinalizableReferenceQueue.java`
+
+Faithful class-own logger swap, adopting the codebase convention (`private
+static final Logger LOG = LogManager.getLogger(<Class>.class);` — see
+`ActionSupport`, `ObjectFactory`, `DefaultActionInvocation`).
+
+- Remove imports `java.util.logging.Level`, `java.util.logging.Logger`.
+- Add imports `org.apache.logging.log4j.LogManager`,
+  `org.apache.logging.log4j.Logger`.
+- Replace
+  `private static final Logger logger = Logger.getLogger(FinalizableReferenceQueue.class.getName());`
+  with
+  `private static final Logger LOG = LogManager.getLogger(FinalizableReferenceQueue.class);`
+- Replace
+  `logger.log(Level.SEVERE, "Error cleaning up after reference.", t);`
+  with
+  `LOG.error("Error cleaning up after reference.", t);`
+
+### 2. `plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java`
+
+Faithful SLF4J swap. The Log4j2 `Logger` error API is call-compatible, so only
+imports and the factory call change.
+
+- Remove imports `org.slf4j.Logger`, `org.slf4j.LoggerFactory`.
+- Add imports `org.apache.logging.log4j.LogManager`,
+  `org.apache.logging.log4j.Logger`.
+- Replace `private final Logger log = LoggerFactory.getLogger(getClass());`
+  with `private final Logger log = LogManager.getLogger(getClass());`
+- `log.error("Error when closing a StringWriter, the impossible happened!", e);`
+  is unchanged.
+- No new pom dependency: `log4j-api` reaches the tiles plugin transitively via
+  `struts2-core`. Confirm at build time.
+
+### 3. `core/src/main/java/org/apache/struts2/inject/ContainerBuilder.java`
+
+Here `java.util.logging.Logger` is **not** a class-own logger — it is
+registered as an injectable DI type (a legacy Guice feature: consumers could
+`@Inject` a `Logger` scoped to their declaring class). A repo-wide search found
+**no code that injects it**. Per decision, remove the dead feature rather than
+port it to Log4j2 (which has no `getAnonymousLogger()` equivalent for the
+`member == null` fallback and would change the DI contract).
+
+- Remove the `LOGGER_FACTORY` `InternalFactory<Logger>` constant.
+- Remove its registration:
+  `factories.put(Key.newInstance(Logger.class, Container.DEFAULT_NAME), LOGGER_FACTORY);`
+  and the preceding comment.
+- Remove now-unused imports `java.util.logging.Logger` and
+  `java.lang.reflect.Member` (`Member` is used only inside the removed factory).
+- Update the class Javadoc: drop the
+  "Injects the `{@link Logger}` for the injected member's declaring class"
+  bullet, leaving the `Container` bullet.
+
+### 4. Dependency cleanup (gated on verification)
+
+Evidence for removal:
+- The tiles file (step 2) is the only main-source SLF4J user in the repo.
+- No test source uses SLF4J; there is no `simplelogger.properties`.
+- core's `slf4j-api` is `optional` (never part of the transitive API contract)
+  and dates to the original xwork merge.
+
+Remove, after the verification gate below:
+- `core/pom.xml` — the optional `slf4j-api` dependency and the test-scoped
+  `slf4j-simple` dependency (the `<!-- SLF4J support -->` block).
+- `parent/pom.xml` — the `dependencyManagement` entries for `slf4j-api` and
+  `slf4j-simple`.
+- root `pom.xml` — the `<slf4j.version>` property.
+
+`java.util.logging` is JDK built-in — nothing to remove for the two core files.
+
+## Verification
+
+1. **Dependency-tree gate (do before deleting pom entries):**
+   run `mvn dependency:tree` for `core` and `plugins/tiles`. Confirm no
+   first-party module *requires* Struts to expose SLF4J. If something genuinely
+   needs it, keep that minimum and record the reason here.
+2. **Compile + test:**
+   - `mvn test -DskipAssembly -pl core` (core tests are JUnit 4 in this repo)
+   - `mvn test -DskipAssembly -pl plugins/tiles`
+3. **Grep confirmation:** no source references the injectable `Logger` type,
+   the removed `logger` field, or `org.slf4j` after the change.
+
+## Testing strategy
+
+No new tests are required:
+- Files 1 and 2 are behavior-preserving logger swaps.
+- File 3 removes dead, untested code.
+
+Existing core and tiles test suites must stay green.
+
+## Risks
+
+- **Low.** The only non-mechanical change is removing the injectable `Logger`
+  factory in `ContainerBuilder`, which is unused internally. A third-party
+  extension that injected `java.util.logging.Logger` from the Struts container
+  would lose that binding; this is acceptable for the 7.3.0 minor and called out
+  here.
+- The dependency-tree gate protects against an unexpected transitive reliance on
+  the SLF4J declarations.


(struts) 03/06: WW-5620 Migrate FinalizableReferenceQueue to Log4j2

Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5620-log4j2-logging-standardization
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 378b500e8d8a452d233e2dbf35273f04e9b4322c
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Mon Jul 20 10:02:52 2026 +0200

    WW-5620 Migrate FinalizableReferenceQueue to Log4j2
    
    Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
 .../apache/struts2/inject/util/FinalizableReferenceQueue.java    | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/core/src/main/java/org/apache/struts2/inject/util/FinalizableReferenceQueue.java b/core/src/main/java/org/apache/struts2/inject/util/FinalizableReferenceQueue.java
index 07b7ececa..47027392b 100644
--- a/core/src/main/java/org/apache/struts2/inject/util/FinalizableReferenceQueue.java
+++ b/core/src/main/java/org/apache/struts2/inject/util/FinalizableReferenceQueue.java
@@ -19,8 +19,8 @@ package org.apache.struts2.inject.util;
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.util.concurrent.atomic.AtomicReference;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 
 /**
  * Starts a background thread that cleans up after reclaimed referents.
@@ -29,8 +29,7 @@ import java.util.logging.Logger;
  */
 public class FinalizableReferenceQueue extends ReferenceQueue<Object> {
 
-  private static final Logger logger =
-      Logger.getLogger(FinalizableReferenceQueue.class.getName());
+  private static final Logger LOG = LogManager.getLogger(FinalizableReferenceQueue.class);
 
   private final AtomicReference<Thread> cleanupThread = new AtomicReference<>();
 
@@ -45,7 +44,7 @@ public class FinalizableReferenceQueue extends ReferenceQueue<Object> {
   }
 
   void deliverBadNews(Throwable t) {
-    logger.log(Level.SEVERE, "Error cleaning up after reference.", t);
+    LOG.error("Error cleaning up after reference.", t);
   }
 
   void start() {


(struts) 05/06: WW-5620 Remove unused injectable j.u.l.Logger DI factory from ContainerBuilder

Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5620-log4j2-logging-standardization
in repository https://gitbox.apache.org/repos/asf/struts.git

commit c6b3f656d4beb6abd500446db26b2bf128a6c02f
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Mon Jul 20 10:11:02 2026 +0200

    WW-5620 Remove unused injectable j.u.l.Logger DI factory from ContainerBuilder
    
    Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
 .../org/apache/struts2/inject/ContainerBuilder.java  | 20 --------------------
 1 file changed, 20 deletions(-)

diff --git a/core/src/main/java/org/apache/struts2/inject/ContainerBuilder.java b/core/src/main/java/org/apache/struts2/inject/ContainerBuilder.java
index 3d5f7f6b4..0d7bc6b4e 100644
--- a/core/src/main/java/org/apache/struts2/inject/ContainerBuilder.java
+++ b/core/src/main/java/org/apache/struts2/inject/ContainerBuilder.java
@@ -16,14 +16,12 @@
 
 package org.apache.struts2.inject;
 
-import java.lang.reflect.Member;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.logging.Logger;
 
 /**
  * Builds a dependency injection {@link Container}. The combination of
@@ -34,7 +32,6 @@ import java.util.logging.Logger;
  *
  * <ul>
  *   <li>Injects the current {@link Container}.
- *   <li>Injects the {@link Logger} for the injected member's declaring class.
  * </ul>
  *
  * @author crazybob@google.com (Bob Lee)
@@ -60,29 +57,12 @@ public final class ContainerBuilder {
                 }
             };
 
-    private static final InternalFactory<Logger> LOGGER_FACTORY =
-            new InternalFactory<>() {
-                public Logger create(InternalContext context) {
-                    Member member = context.getExternalContext().getMember();
-                    return member == null ? Logger.getAnonymousLogger()
-                            : Logger.getLogger(member.getDeclaringClass().getName());
-                }
-
-                @Override
-                public Class<? extends Logger> type() {
-                    return Logger.class;
-                }
-            };
-
     /**
      * Constructs a new builder.
      */
     public ContainerBuilder() {
         // In the current container as the default Container implementation.
         factories.put(Key.newInstance(Container.class, Container.DEFAULT_NAME), CONTAINER_FACTORY);
-
-        // Inject the logger for the injected member's declaring class.
-        factories.put(Key.newInstance(Logger.class, Container.DEFAULT_NAME), LOGGER_FACTORY);
     }
 
     /**


(struts) 02/06: WW-5620 docs: add Log4j2 logging standardization implementation plan

Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5620-log4j2-logging-standardization
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 57f8edfa9e1ffd483838a1867683286fd040898d
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Mon Jul 20 10:00:51 2026 +0200

    WW-5620 docs: add Log4j2 logging standardization implementation plan
    
    Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
 ...07-20-WW-5620-log4j2-logging-standardization.md | 345 +++++++++++++++++++++
 1 file changed, 345 insertions(+)

diff --git a/docs/superpowers/plans/2026-07-20-WW-5620-log4j2-logging-standardization.md b/docs/superpowers/plans/2026-07-20-WW-5620-log4j2-logging-standardization.md
new file mode 100644
index 000000000..87442e449
--- /dev/null
+++ b/docs/superpowers/plans/2026-07-20-WW-5620-log4j2-logging-standardization.md
@@ -0,0 +1,345 @@
+# WW-5620 Log4j2 Logging Standardization 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:** Migrate the three remaining legacy-logging source files to Log4j2 and remove the now-dead first-party SLF4J dependency declarations.
+
+**Architecture:** Three independent, mostly mechanical source edits (two class-own logger swaps, one dead-DI-feature removal), followed by a pom cleanup gated on a `mvn dependency:tree` check. No functional or security behavior changes.
+
+**Tech Stack:** Java, Log4j2 (`org.apache.logging.log4j`), Maven. Core tests are JUnit 4 + AssertJ + Mockito in this repo.
+
+## Global Constraints
+
+- Fix version: 7.3.0. Target ticket: WW-5620. Every commit message MUST be prefixed `WW-5620`.
+- Logger convention: `private static final Logger LOG = LogManager.getLogger(<Class>.class);` for static class loggers (see `ActionSupport`, `ObjectFactory`). Preserve the existing field style where a file already uses an instance logger.
+- No new pom dependency may be added. `log4j-api` is already available (directly in core, transitively in tiles via `struts2-core`).
+- Do NOT touch the runtime bridges `log4j-jcl`, `log4j-slf4j-impl`, or `commons-logging` — they route third-party logging and are out of scope.
+- Build/test commands: `mvn test -DskipAssembly -pl core` and `mvn test -DskipAssembly -pl plugins/tiles`.
+- Reference spec: `docs/superpowers/specs/2026-07-20-WW-5620-log4j2-logging-standardization-design.md`.
+
+---
+
+## File Structure
+
+- Modify: `core/src/main/java/org/apache/struts2/inject/util/FinalizableReferenceQueue.java` — swap `java.util.logging` → Log4j2.
+- Modify: `plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java` — swap SLF4J → Log4j2.
+- Modify: `core/src/main/java/org/apache/struts2/inject/ContainerBuilder.java` — remove the injectable `java.util.logging.Logger` DI factory.
+- Modify: `core/pom.xml`, `parent/pom.xml`, `pom.xml` — remove dead first-party SLF4J declarations.
+
+No test files are created: files 1–2 are behavior-preserving; file 3 removes dead, untested code. Verification is via existing suites, `dependency:tree`, and grep.
+
+---
+
+### Task 1: Migrate `FinalizableReferenceQueue` to Log4j2
+
+**Files:**
+- Modify: `core/src/main/java/org/apache/struts2/inject/util/FinalizableReferenceQueue.java`
+
+**Interfaces:**
+- Consumes: nothing from other tasks.
+- Produces: nothing consumed by other tasks (internal logger only).
+
+- [ ] **Step 1: Confirm current state**
+
+Run: `grep -n "logging\|logger\|Level" core/src/main/java/org/apache/struts2/inject/util/FinalizableReferenceQueue.java`
+Expected: lines showing `import java.util.logging.Level;`, `import java.util.logging.Logger;`, the `logger` field (`Logger.getLogger(...getName())`), and `logger.log(Level.SEVERE, "Error cleaning up after reference.", t);`.
+
+- [ ] **Step 2: Replace the imports**
+
+Replace:
+```java
+import java.util.logging.Level;
+import java.util.logging.Logger;
+```
+with:
+```java
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+```
+(Keep these in import-order position consistent with the file; the surrounding `java.lang.ref.*` / `java.util.concurrent.*` imports stay.)
+
+- [ ] **Step 3: Replace the logger field**
+
+Replace:
+```java
+  private static final Logger logger =
+      Logger.getLogger(FinalizableReferenceQueue.class.getName());
+```
+with:
+```java
+  private static final Logger LOG = LogManager.getLogger(FinalizableReferenceQueue.class);
+```
+
+- [ ] **Step 4: Replace the log call**
+
+Replace:
+```java
+    logger.log(Level.SEVERE, "Error cleaning up after reference.", t);
+```
+with:
+```java
+    LOG.error("Error cleaning up after reference.", t);
+```
+
+- [ ] **Step 5: Verify no leftover legacy references**
+
+Run: `grep -n "java.util.logging\|Level\.\|logger\b" core/src/main/java/org/apache/struts2/inject/util/FinalizableReferenceQueue.java`
+Expected: no matches.
+
+- [ ] **Step 6: Compile core**
+
+Run: `mvn -q -o compile -pl core -DskipAssembly` (drop `-o` if the local repo needs downloads)
+Expected: BUILD SUCCESS.
+
+- [ ] **Step 7: Commit**
+
+```bash
+git add core/src/main/java/org/apache/struts2/inject/util/FinalizableReferenceQueue.java
+git commit -m "WW-5620 Migrate FinalizableReferenceQueue to Log4j2
+
+Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>"
+```
+
+---
+
+### Task 2: Migrate `AbstractDefaultToStringRenderable` to Log4j2
+
+**Files:**
+- Modify: `plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java`
+
+**Interfaces:**
+- Consumes: nothing from other tasks.
+- Produces: nothing consumed by other tasks (internal instance logger only).
+
+- [ ] **Step 1: Confirm current state**
+
+Run: `grep -n "slf4j\|Logger\|log\." plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java`
+Expected: `import org.slf4j.Logger;`, `import org.slf4j.LoggerFactory;`, `private final Logger log = LoggerFactory.getLogger(getClass());`, and `log.error("Error when closing a StringWriter, the impossible happened!", e);`.
+
+- [ ] **Step 2: Replace the imports**
+
+Replace:
+```java
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+```
+with:
+```java
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+```
+(Keep import ordering consistent with the file; `org.apache.logging...` sorts near the other `org.apache.*` imports.)
+
+- [ ] **Step 3: Replace the logger field factory call**
+
+Replace:
+```java
+    private final Logger log = LoggerFactory.getLogger(getClass());
+```
+with:
+```java
+    private final Logger log = LogManager.getLogger(getClass());
+```
+(The `log.error(...)` call is unchanged — the Log4j2 `Logger.error(String, Throwable)` signature is call-compatible.)
+
+- [ ] **Step 4: Verify no leftover SLF4J references**
+
+Run: `grep -n "slf4j\|LoggerFactory" plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java`
+Expected: no matches.
+
+- [ ] **Step 5: Compile the tiles plugin (confirms log4j-api resolves transitively)**
+
+Run: `mvn -q -o compile -pl plugins/tiles -am -DskipAssembly` (drop `-o` if downloads are needed)
+Expected: BUILD SUCCESS. If it fails with `package org.apache.logging.log4j does not exist`, STOP — the transitive assumption is wrong; report back before adding any dependency.
+
+- [ ] **Step 6: Commit**
+
+```bash
+git add plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java
+git commit -m "WW-5620 Migrate AbstractDefaultToStringRenderable to Log4j2
+
+Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>"
+```
+
+---
+
+### Task 3: Remove the injectable Logger factory from `ContainerBuilder`
+
+**Files:**
+- Modify: `core/src/main/java/org/apache/struts2/inject/ContainerBuilder.java`
+
+**Interfaces:**
+- Consumes: nothing from other tasks.
+- Produces: removes the DI binding for `java.util.logging.Logger` (verified unused repo-wide).
+
+- [ ] **Step 1: Re-confirm the injectable Logger is unused**
+
+Run: `grep -rn --include="*.java" "java.util.logging.Logger" . | grep -v /target/ | grep -v "ContainerBuilder.java\|FinalizableReferenceQueue.java"`
+Expected: no matches (after Task 1, `FinalizableReferenceQueue` no longer appears either). If any consumer appears, STOP and report.
+
+- [ ] **Step 2: Remove the `LOGGER_FACTORY` constant**
+
+Delete this block:
+```java
+    private static final InternalFactory<Logger> LOGGER_FACTORY =
+            new InternalFactory<>() {
+                public Logger create(InternalContext context) {
+                    Member member = context.getExternalContext().getMember();
+                    return member == null ? Logger.getAnonymousLogger()
+                            : Logger.getLogger(member.getDeclaringClass().getName());
+                }
+
+                @Override
+                public Class<? extends Logger> type() {
+                    return Logger.class;
+                }
+            };
+```
+
+- [ ] **Step 3: Remove the factory registration in the constructor**
+
+Delete these lines (comment + registration):
+```java
+        // Inject the logger for the injected member's declaring class.
+        factories.put(Key.newInstance(Logger.class, Container.DEFAULT_NAME), LOGGER_FACTORY);
+```
+Leave the preceding `CONTAINER_FACTORY` registration intact.
+
+- [ ] **Step 4: Remove the now-unused imports**
+
+Delete:
+```java
+import java.lang.reflect.Member;
+```
+and
+```java
+import java.util.logging.Logger;
+```
+
+- [ ] **Step 5: Update the class Javadoc**
+
+In the class Javadoc `<ul>`, delete the line:
+```java
+ *   <li>Injects the {@link Logger} for the injected member's declaring class.
+```
+Leave the `<li>Injects the current {@link Container}.` bullet.
+
+- [ ] **Step 6: Verify no leftover references**
+
+Run: `grep -n "Logger\|Member\|LOGGER_FACTORY" core/src/main/java/org/apache/struts2/inject/ContainerBuilder.java`
+Expected: no matches.
+
+- [ ] **Step 7: Compile core**
+
+Run: `mvn -q -o compile -pl core -DskipAssembly` (drop `-o` if downloads are needed)
+Expected: BUILD SUCCESS.
+
+- [ ] **Step 8: Commit**
+
+```bash
+git add core/src/main/java/org/apache/struts2/inject/ContainerBuilder.java
+git commit -m "WW-5620 Remove unused injectable j.u.l.Logger DI factory from ContainerBuilder
+
+Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>"
+```
+
+---
+
+### Task 4: Remove dead first-party SLF4J dependency declarations
+
+**Files:**
+- Modify: `core/pom.xml`
+- Modify: `parent/pom.xml`
+- Modify: `pom.xml`
+
+**Interfaces:**
+- Consumes: Tasks 1–3 must be done first (no first-party source uses SLF4J anymore).
+- Produces: nothing consumed by other tasks.
+
+- [ ] **Step 1: Dependency-tree gate (before deleting anything)**
+
+Run: `grep -rln --include="*.java" "org.slf4j" . | grep -v /target/`
+Expected: no matches (Task 2 removed the last usage).
+
+Run: `mvn -q -o dependency:tree -pl core,plugins/tiles -Dincludes=org.slf4j 2>&1 | grep -i slf4j` (drop `-o` if downloads are needed)
+Expected: any `org.slf4j:*` shown is transitive (an indented child of another artifact), not a direct first-party declaration. If a first-party module *requires* Struts to expose SLF4J for compilation, STOP, keep the minimum needed, and note it in the spec's Verification section before continuing.
+
+- [ ] **Step 2: Remove the SLF4J block from `core/pom.xml`**
+
+Delete:
+```xml
+        <!-- SLF4J support -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>test</scope>
+        </dependency>
+```
+
+- [ ] **Step 3: Remove the SLF4J `dependencyManagement` entries from `parent/pom.xml`**
+
+Delete:
+```xml
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>${slf4j.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-simple</artifactId>
+                <version>${slf4j.version}</version>
+            </dependency>
+```
+
+- [ ] **Step 4: Remove the `slf4j.version` property from root `pom.xml`**
+
+Delete:
+```xml
+        <slf4j.version>2.0.18</slf4j.version>
+```
+
+- [ ] **Step 5: Verify no SLF4J declarations remain**
+
+Run: `grep -rn "slf4j" --include="pom.xml" . | grep -v /target/`
+Expected: only bridge artifacts remain — `apps/showcase` `log4j-slf4j-impl` (and its `<name>slf4j</name>` profile entry). No `org.slf4j:slf4j-api`, no `slf4j-simple`, no `slf4j.version`.
+
+- [ ] **Step 6: Build and test core + tiles**
+
+Run: `mvn -o test -DskipAssembly -pl core -am` (drop `-o` if downloads are needed)
+Expected: BUILD SUCCESS, tests green.
+
+Run: `mvn -o test -DskipAssembly -pl plugins/tiles -am`
+Expected: BUILD SUCCESS, tests green.
+
+If any test fails because it silently relied on `slf4j-simple` as a test logging backend, STOP and report — do not add unrelated logging config to force a pass.
+
+- [ ] **Step 7: Commit**
+
+```bash
+git add core/pom.xml parent/pom.xml pom.xml
+git commit -m "WW-5620 Remove dead first-party SLF4J dependency declarations
+
+Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>"
+```
+
+---
+
+## Self-Review
+
+**Spec coverage:**
+- Spec §1 FinalizableReferenceQueue → Task 1. ✓
+- Spec §2 AbstractDefaultToStringRenderable → Task 2. ✓
+- Spec §3 ContainerBuilder factory removal → Task 3. ✓
+- Spec §4 dependency cleanup (core/parent/root poms) → Task 4. ✓
+- Spec Verification (dependency-tree gate, compile+test, grep) → Task 4 Step 1, per-task compile steps, grep steps. ✓
+- Out-of-scope bridges left untouched → asserted in Global Constraints and Task 4 Step 5. ✓
+
+**Placeholder scan:** No TBD/TODO/"handle edge cases"/vague steps. Every code step shows exact before/after. ✓
+
+**Type consistency:** Logger field named `LOG` (static, Task 1) vs `log` (instance, Task 2) — intentional, matches each file's existing style and the codebase convention; no cross-task symbol sharing. ✓


(struts) 04/06: WW-5620 Migrate AbstractDefaultToStringRenderable to Log4j2

Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5620-log4j2-logging-standardization
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 7627c903f5cb1c1b40ce6b79c24372d1e5cf7071
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Mon Jul 20 10:05:55 2026 +0200

    WW-5620 Migrate AbstractDefaultToStringRenderable to Log4j2
    
    Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
 .../tiles/velocity/template/AbstractDefaultToStringRenderable.java  | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java
index 7498bb5d2..be211e0ef 100644
--- a/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java
+++ b/plugins/tiles/src/main/java/org/apache/tiles/velocity/template/AbstractDefaultToStringRenderable.java
@@ -26,14 +26,14 @@ import java.util.Map;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
 import org.apache.tiles.velocity.TilesVelocityException;
 import org.apache.velocity.context.Context;
 import org.apache.velocity.exception.MethodInvocationException;
 import org.apache.velocity.exception.ParseErrorException;
 import org.apache.velocity.exception.ResourceNotFoundException;
 import org.apache.velocity.runtime.Renderable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Renderable that provides a default implementation of Renderable#toString()
@@ -74,7 +74,7 @@ public abstract class AbstractDefaultToStringRenderable implements Renderable {
     /**
      * The logging object.
      */
-    private final Logger log = LoggerFactory.getLogger(getClass());
+    private final Logger log = LogManager.getLogger(getClass());
 
     /**
      * Constructor.


(struts) 06/06: WW-5620 Remove dead first-party SLF4J dependency declarations

Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch WW-5620-log4j2-logging-standardization
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 8dd64e1753712e189f54423550b76e5d3299a706
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Mon Jul 20 10:16:31 2026 +0200

    WW-5620 Remove dead first-party SLF4J dependency declarations
    
    Co-Authored-By: Claude Opus 4.8 <no...@anthropic.com>
---
 core/pom.xml   | 12 ------------
 parent/pom.xml | 11 -----------
 pom.xml        |  1 -
 3 files changed, 24 deletions(-)

diff --git a/core/pom.xml b/core/pom.xml
index b5303545f..6509b6a42 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -316,18 +316,6 @@
             <scope>test</scope>
         </dependency>
 
-        <!-- SLF4J support -->
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
-            <scope>test</scope>
-        </dependency>
-
         <dependency>
             <groupId>commons-validator</groupId>
             <artifactId>commons-validator</artifactId>
diff --git a/parent/pom.xml b/parent/pom.xml
index 063269182..59defe45a 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -274,17 +274,6 @@
                 <scope>test</scope>
             </dependency>
 
-            <dependency>
-                <groupId>org.slf4j</groupId>
-                <artifactId>slf4j-api</artifactId>
-                <version>${slf4j.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.slf4j</groupId>
-                <artifactId>slf4j-simple</artifactId>
-                <version>${slf4j.version}</version>
-            </dependency>
-
             <dependency>
                 <groupId>org.apache.logging.log4j</groupId>
                 <artifactId>log4j-bom</artifactId>
diff --git a/pom.xml b/pom.xml
index d9a188a54..d471e8e77 100644
--- a/pom.xml
+++ b/pom.xml
@@ -125,7 +125,6 @@
         <log4j2.version>2.26.1</log4j2.version>
         <mockito.version>5.23.0</mockito.version>
         <ognl.version>3.4.11</ognl.version>
-        <slf4j.version>2.0.18</slf4j.version>
         <spring.version>6.2.12</spring.version>
         <struts-annotations.version>2.0</struts-annotations.version>
         <velocity-tools.version>3.1</velocity-tools.version>