You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by mr...@apache.org on 2026/10/24 09:23:06 UTC

(ofbiz-framework) branch trunk updated: java.util.logging output bypasses Log4j 2

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

mridulpathak pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 01bcc0b559 java.util.logging output bypasses Log4j 2
01bcc0b559 is described below

commit 01bcc0b559263cf41083df0eaa40d93c47c5af13
Author: Mridul Pathak <mr...@gmail.com>
AuthorDate: Sat Oct 24 14:53:00 2026 +0530

    java.util.logging output bypasses Log4j 2
    
    - Route java.util.logging to Log4j 2: log4j-jul was on the runtime classpath but nothing activated it, so libraries logging through java.util.logging (Tomcat, Jersey, Geronimo and others) wrote to stdout in the JDK format, never reached ofbiz.log and ignored the levels set in log4j2.xml. Start now installs Log4j's Log4jBridgeHandler for the start command, before the startup configuration is read; it works even when java.util.logging was started before main() (for example by a JMX agen [...]
    - In verbose mode, the REST request logging writes only the headers, redacting Authorization, Proxy-Authorization, Cookie, Set-Cookie and Refresh-Token: now that java.util.logging reaches the log files, the bodies and these headers, which can hold credentials and tokens, would otherwise have been written there.
    
    Thanks: Jacopo Cappellato for the review and feedback
---
 .../apache/ofbiz/ws/rs/core/OFBizApiConfig.java    |  9 ++++--
 .../java/org/apache/ofbiz/base/start/Start.java    | 35 ++++++++++++++++++++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java b/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
index 4a07488133..a58796253f 100644
--- a/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
+++ b/framework/rest-api/src/main/java/org/apache/ofbiz/ws/rs/core/OFBizApiConfig.java
@@ -74,8 +74,13 @@ public class OFBizApiConfig extends ResourceConfig {
         register(ServiceContextCleanupFilter.class);
         //property(ServerProperties.TRACING, "ALL");
         if (Debug.verboseOn()) {
-            register(new LoggingFeature(Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME), Level.INFO,
-                    LoggingFeature.Verbosity.PAYLOAD_ANY, 10000));
+            // headers only, the ones carrying credentials or tokens being redacted: bodies can hold credentials and tokens
+            register(LoggingFeature.builder()
+                    .withLogger(Logger.getLogger(LoggingFeature.DEFAULT_LOGGER_NAME))
+                    .level(Level.INFO)
+                    .verbosity(LoggingFeature.Verbosity.HEADERS_ONLY)
+                    .redactHeaders(List.of("Authorization", "Proxy-Authorization", "Cookie", "Set-Cookie", "Refresh-Token"))
+                    .build());
         }
         registerDSLResources();
         EncodingFilter.enableFor(this, GZipEncoder.class);
diff --git a/framework/start/src/main/java/org/apache/ofbiz/base/start/Start.java b/framework/start/src/main/java/org/apache/ofbiz/base/start/Start.java
index 33ed1dfb26..a8c2ef4ecd 100644
--- a/framework/start/src/main/java/org/apache/ofbiz/base/start/Start.java
+++ b/framework/start/src/main/java/org/apache/ofbiz/base/start/Start.java
@@ -22,6 +22,9 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
+import java.util.logging.Logger;
 import java.util.stream.Collectors;
 
 import org.apache.ofbiz.base.container.ContainerLoader;
@@ -71,6 +74,10 @@ public final class Start {
         }
 
         CommandType commandType = CommandType.valueOf(ofbizCommands);
+        if (commandType.equals(CommandType.START)) {
+            // not for the status and shutdown clients: they would open, and roll over, the log files of the running server
+            routeJavaUtilLoggingToLog4j();
+        }
         if (!commandType.equals(CommandType.HELP)) {
             INSTANCE.config = StartupControlPanel.init(ofbizCommands);
         }
@@ -96,6 +103,34 @@ public final class Start {
         }
     }
 
+    /**
+     * Routes java.util.logging (used by Tomcat, Jersey, Geronimo and other libraries) to Log4j 2,
+     * so that it reaches the OFBiz log files and follows the levels of log4j2.xml.
+     * The bridge handler also works when java.util.logging was started before main() (e.g. by a JMX agent),
+     * and it only forwards the records java.util.logging itself lets through (INFO and above by default).
+     * Only the default console handler of the JDK is removed, and only when java.util.logging has not been
+     * configured on purpose, so that handlers set up by an operator or an agent are kept.
+     */
+    private static void routeJavaUtilLoggingToLog4j() {
+        try {
+            Class.forName("org.apache.logging.log4j.jul.Log4jBridgeHandler")
+                    .getMethod("install", boolean.class, String.class, boolean.class)
+                    .invoke(null, false, null, false);
+        } catch (ReflectiveOperationException | LinkageError e) {
+            System.err.println("java.util.logging is not routed to Log4j 2 (log4j-jul missing?): " + e);
+            return;
+        }
+        if (System.getProperty("java.util.logging.config.file") == null
+                && System.getProperty("java.util.logging.config.class") == null) {
+            Logger rootLogger = Logger.getLogger("");
+            for (Handler handler : rootLogger.getHandlers()) {
+                if (handler.getClass() == ConsoleHandler.class) {
+                    rootLogger.removeHandler(handler);
+                }
+            }
+        }
+    }
+
     /**
      * Returns the <code>Start</code> instance.
      */