From 11c10ee8f9259240285369c6feaae1fe6c06fc0d Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 20 Jul 2026 13:41:45 +0200 Subject: [PATCH] WW-5620 Standardize logging on Log4j2 (#1794) * WW-5620 docs: add Log4j2 logging standardization design spec Co-Authored-By: Claude Opus 4.8 * WW-5620 docs: add Log4j2 logging standardization implementation plan Co-Authored-By: Claude Opus 4.8 * WW-5620 Migrate FinalizableReferenceQueue to Log4j2 Co-Authored-By: Claude Opus 4.8 * WW-5620 Migrate AbstractDefaultToStringRenderable to Log4j2 Co-Authored-By: Claude Opus 4.8 * WW-5620 Remove unused injectable j.u.l.Logger DI factory from ContainerBuilder Co-Authored-By: Claude Opus 4.8 * WW-5620 Remove dead first-party SLF4J dependency declarations Co-Authored-By: Claude Opus 4.8 --------- Co-authored-by: Claude Opus 4.8 --- core/pom.xml | 12 - .../struts2/inject/ContainerBuilder.java | 20 - .../util/FinalizableReferenceQueue.java | 9 +- ...-WW-5620-log4j2-logging-standardization.md | 345 ++++++++++++++++++ ...0-log4j2-logging-standardization-design.md | 135 +++++++ parent/pom.xml | 11 - .../AbstractDefaultToStringRenderable.java | 6 +- pom.xml | 1 - 8 files changed, 487 insertions(+), 52 deletions(-) create mode 100644 docs/superpowers/plans/2026-07-20-WW-5620-log4j2-logging-standardization.md create mode 100644 docs/superpowers/specs/2026-07-20-WW-5620-log4j2-logging-standardization-design.md 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 @@ test - - - org.slf4j - slf4j-api - true - - - org.slf4j - slf4j-simple - test - - commons-validator commons-validator 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; * *
    *
  • Injects the current {@link Container}. - *
  • Injects the {@link Logger} for the injected member's declaring class. *
* * @author crazybob@google.com (Bob Lee) @@ -60,29 +57,12 @@ public final class ContainerBuilder { } }; - private static final InternalFactory 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 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); } /** 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 { - private static final Logger logger = - Logger.getLogger(FinalizableReferenceQueue.class.getName()); + private static final Logger LOG = LogManager.getLogger(FinalizableReferenceQueue.class); private final AtomicReference cleanupThread = new AtomicReference<>(); @@ -45,7 +44,7 @@ public class FinalizableReferenceQueue extends ReferenceQueue { } void deliverBadNews(Throwable t) { - logger.log(Level.SEVERE, "Error cleaning up after reference.", t); + LOG.error("Error cleaning up after reference.", t); } void start() { 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);` 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 " +``` + +--- + +### 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 " +``` + +--- + +### 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_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 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 `
    `, delete the line: +```java + *
  • Injects the {@link Logger} for the injected member's declaring class. +``` +Leave the `
  • 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 " +``` + +--- + +### 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 + + + org.slf4j + slf4j-api + true + + + org.slf4j + slf4j-simple + test + +``` + +- [ ] **Step 3: Remove the SLF4J `dependencyManagement` entries from `parent/pom.xml`** + +Delete: +```xml + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + slf4j-simple + ${slf4j.version} + +``` + +- [ ] **Step 4: Remove the `slf4j.version` property from root `pom.xml`** + +Delete: +```xml + 2.0.18 +``` + +- [ ] **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 `slf4j` 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 " +``` + +--- + +## 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. ✓ 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);` — 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` 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 `` block). +- `parent/pom.xml` — the `dependencyManagement` entries for `slf4j-api` and + `slf4j-simple`. +- root `pom.xml` — the `` 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. 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 @@ test - - org.slf4j - slf4j-api - ${slf4j.version} - - - org.slf4j - slf4j-simple - ${slf4j.version} - - org.apache.logging.log4j log4j-bom 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. diff --git a/pom.xml b/pom.xml index d9a188a54..d471e8e77 100644 --- a/pom.xml +++ b/pom.xml @@ -125,7 +125,6 @@ 2.26.1 5.23.0 3.4.11 - 2.0.18 6.2.12 2.0 3.1