Bug 10528

Summary: MDC: %X conversion pattern can cause NullPointerException
Product: Log4j - Now in Jira Reporter: Mark Womack <mwomack>
Component: OtherAssignee: log4j-dev <log4j-dev>
Status: RESOLVED FIXED    
Severity: major    
Priority: P3    
Version: 1.2   
Target Milestone: ---   
Hardware: All   
OS: other   

Description Mark Womack 2002-07-07 06:41:43 UTC
1) Set the following MDC conversion pattern in a PatternLayout for an appender:

%X

(note that no MDC key is specified)

2) Set some MDC key/value pairs.
3) Call a log message that will invoke the PatternLayout configured with the 
conversion pattern.

Result: NullPointerException in MDC class.

Bug found by Eric Thors (etoelz@yahoo.com).  Data from original email:

OS: Win2000
Java:1.3.1
Log4j: 1.2.4

---- TestError.java----------
public class TestError {
   static Logger log = Logger.getLogger("foo");

   public static void main (String[] args) {
      PropertyConfigurator.configure(args[0]);

      System.out.println("start");
      MDC.put("test", "foo");
      log.warn("Warn me");
      log.error("Warn me");
      System.out.println("done");

   }
}
-------------------
------ log4j.properties --------------
log4j.rootCategory=warn, A2, RR, dest2

# A2 is set to be a LF5Appender
log4j.appender.A2=org.apache.log4j.lf5.LF5Appender
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=[slf5s.start]%d{DATE}[slf5s.DATE]%n\
 
%p[slf5s.PRIORITY]%n%x[slf5s.NDC]%n%t[slf5s.THREAD]%n\
 
%c[slf5s.CATEGORY]%n%l[slf5s.LOCATION]%n%m[slf5s.MESSAGE]%n%n

log4j.appender.dest2.ImmediateFlush=true
log4j.appender.dest2.layout=org.apache.log4j.PatternLayout
log4j.appender.dest2.layout.ConversionPattern=%-4r
[%t] %-5p %c (%X) - %m ~%l%n

! WRITE LOG TO A FILE, ROLL THE FILE AFTER SOME SIZE
log4j.appender.dest2=org.apache.log4j.DailyRollingFileAppender
! This appender will only log messages with priority
equal to or higher than
! the one specified here
log4j.appender.dest2.Threshold=WARN
! Specify the file name (${property_key} gets
substituted with its value)
log4j.appender.dest2.File=log4j.log

# RR is the RollingFileAppender that outputs to a
rolling log
# file called sample.log.

log4j.appender.RR=org.apache.log4j.RollingFileAppender
log4j.appender.RR.File=sample.log

log4j.appender.RR.layout=org.apache.log4j.PatternLayout
log4j.appender.RR.layout.ConversionPattern=[slf5s.start]%d{DATE}[slf5s.DATE]%n\
 
%p[slf5s.PRIORITY]%n%x[slf5s.NDC]%n%t[slf5s.THREAD]%n\
 
%c[slf5s.CATEGORY]%n%l[slf5s.LOCATION]%n%m[slf5s.MESSAGE]%n%n

# Set the max size of the file
log4j.appender.RR.MaxFileSize=500KB
------------------------

-------Error ----------------

java TestError log4j.properties
start
java.lang.NullPointerException
        at java.util.Hashtable.get(Hashtable.java:320)
        at org.apache.log4j.MDC.get0(MDC.java:121)
        at org.apache.log4j.MDC.get(MDC.java:75)
        at
org.apache.log4j.spi.LoggingEvent.getMDC(LoggingEvent.java:228)
        at
org.apache.log4j.helpers.PatternParser$MDCPatternConverter.convert
(PatternParser.java:455)
        at
org.apache.log4j.helpers.PatternConverter.format(PatternConverter.java:56)
        at
org.apache.log4j.PatternLayout.format(PatternLayout.java:495)
        at
org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:292)
        at
org.apache.log4j.RollingFileAppender.subAppend(RollingFileAppender.java:225)
        at
org.apache.log4j.WriterAppender.append(WriterAppender.java:150)
        at
org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:221)
        at
org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders
(AppenderAttachableImpl.java:57)
        at
org.apache.log4j.Category.callAppenders(Category.java:190)
        at
org.apache.log4j.Category.forcedLog(Category.java:375)
        at
org.apache.log4j.Category.warn(Category.java:1024)
        at TestError.main(TestError.java:11)

If it were to exit gracefully, you should see "done".

----- Patch -------------
--- MDC.java    2002-07-03 12:09:01.000000000 -0400
+++ c:/MDC.java 2002-07-03 08:40:54.000000000 -0400
@@ -117,7 +117,7 @@
       return null;
     } else {
       Hashtable ht = (Hashtable)
((ThreadLocalMap)tlm).get();
-      if(ht != null) {
+      if(ht != null && key != null) {
        return ht.get(key);
       } else {
        return null;
Comment 1 Mark Womack 2002-07-07 06:51:03 UTC
Confirmed bug, applied Eric's patch to MDC.java, created new 
PatternParserTestCase to test fix.  Bug resolved.