From 64f2f15ef7899326589f385c1a44ae82091d1602 Mon Sep 17 00:00:00 2001 From: Ceki Gulcu Date: Tue, 3 Jul 2007 18:29:13 +0000 Subject: [PATCH] continued work on MDC support --- slf4j-api/src/main/java/org/slf4j/MDC.java | 27 +++++++- .../test/java/org/slf4j/NoBindingTest.java | 21 +++++-- .../java/org/slf4j/impl/StaticMDCBinder.java | 34 +++++++++++ .../test/java/org/slf4j/InvocationTest.java | 7 +++ .../java/org/slf4j/impl/StaticMDCBinder.java | 1 - .../test/java/org/slf4j/InvocationTest.java | 7 +++ .../java/org/slf4j/impl/StaticMDCBinder.java | 33 ++++++++++ .../java/org/slf4j/impl/StaticMDCBinder.java | 34 +++++++++++ .../test/java/org/slf4j/InvocationTest.java | 7 +++ .../org/slf4j/impl/StaticLoggerBinder.java | 43 ++++++------- .../java/org/slf4j/impl/StaticMDCBinder.java | 58 ++++++++++++++++++ .../org/slf4j/impl/StaticMarkerBinder.java | 44 ++++++------- .../test/java/org/slf4j/InvocationTest.java | 10 ++- slf4j-site/src/site/pages/codes.html | 61 +++++++++++++------ 14 files changed, 306 insertions(+), 81 deletions(-) create mode 100644 slf4j-jcl/src/main/java/org/slf4j/impl/StaticMDCBinder.java create mode 100644 slf4j-log4j12/src/main/java/org/slf4j/impl/StaticMDCBinder.java create mode 100644 slf4j-nop/src/main/java/org/slf4j/impl/StaticMDCBinder.java create mode 100644 slf4j-simple/src/main/java/org/slf4j/impl/StaticMDCBinder.java diff --git a/slf4j-api/src/main/java/org/slf4j/MDC.java b/slf4j-api/src/main/java/org/slf4j/MDC.java index fe20dbc6..e48fd35f 100644 --- a/slf4j-api/src/main/java/org/slf4j/MDC.java +++ b/slf4j-api/src/main/java/org/slf4j/MDC.java @@ -39,6 +39,9 @@ import org.slf4j.spi.MDCAdapter; * @author Ceki Gülcü */ public class MDC { + + static final String NULL_MDCA_URL = "http://www.slf4j.org/codes.html#null_MDCA"; + static final String NO_STATIC_MDC_BINDER_URL = "http://www.slf4j.org/codes.html#no_static_mdc_binder"; static MDCAdapter mdcAdapter; private MDC() { @@ -47,9 +50,17 @@ public class MDC { static { try { mdcAdapter = StaticMDCBinder.SINGLETON.getMDCA(); + } catch(NoClassDefFoundError ncde) { + String msg = ncde.getMessage(); + if(msg != null && msg.indexOf("org/slf4j/impl/StaticMDCBinder") != -1) { + Util.reportFailure("Failed to load class \"org.slf4j.impl.StaticMDCBinder\"."); + Util.reportFailure("See "+NO_STATIC_MDC_BINDER_URL+" for further details."); + + } + throw ncde; } catch (Exception e) { // we should never get here - Util.reportFailure("Could not instantiate instance of class [" + Util.reportFailure("Could not bind with an instance of class [" + StaticMDCBinder.SINGLETON.getMDCAdapterClassStr() + "]", e); } } @@ -61,6 +72,9 @@ public class MDC { * method delegates all work to the MDC of the underlying logging system. */ public static void put(String key, String val) { + if(mdcAdapter == null) { + throw new IllegalStateException("MDCAdapter cannot be null. See also "+NULL_MDCA_URL); + } mdcAdapter.put(key, val); } @@ -71,6 +85,9 @@ public class MDC { * @return the string value identified by the key parameter. */ public static String get(String key) { + if(mdcAdapter == null) { + throw new IllegalStateException("MDCAdapter cannot be null. See also "+NULL_MDCA_URL); + } return mdcAdapter.get(key); } @@ -79,13 +96,19 @@ public class MDC { * the underlying system's MDC implementation. */ public static void remove(String key) { + if(mdcAdapter == null) { + throw new IllegalStateException("MDCAdapter cannot be null. See also "+NULL_MDCA_URL); + } mdcAdapter.remove(key); } /** * Clear all entries in the MDC of the underlying implementation. */ - public void clear() { + public static void clear() { + if(mdcAdapter == null) { + throw new IllegalStateException("MDCAdapter cannot be null. See also "+NULL_MDCA_URL); + } mdcAdapter.clear(); } diff --git a/slf4j-api/src/test/java/org/slf4j/NoBindingTest.java b/slf4j-api/src/test/java/org/slf4j/NoBindingTest.java index 1815225e..b51f8833 100644 --- a/slf4j-api/src/test/java/org/slf4j/NoBindingTest.java +++ b/slf4j-api/src/test/java/org/slf4j/NoBindingTest.java @@ -4,13 +4,22 @@ import junit.framework.TestCase; public class NoBindingTest extends TestCase { - public void test() { + public void testLogger() { try { - Logger logger = LoggerFactory.getLogger(NoBindingTest.class); - logger.debug("hello"); - fail("slf4j-api does not ship with a binding"); - } catch(NoClassDefFoundError e) { - + Logger logger = LoggerFactory.getLogger(NoBindingTest.class); + logger.debug("hello"); + fail("slf4j-api does not ship with a binding"); + } catch (NoClassDefFoundError e) { + + } + } + + public void testMDC() { + try { + MDC.put("k", "v"); + fail("slf4j-api does not ship with a binding"); + } catch (NoClassDefFoundError e) { + } } } diff --git a/slf4j-jcl/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j-jcl/src/main/java/org/slf4j/impl/StaticMDCBinder.java new file mode 100644 index 00000000..62b9f865 --- /dev/null +++ b/slf4j-jcl/src/main/java/org/slf4j/impl/StaticMDCBinder.java @@ -0,0 +1,34 @@ +package org.slf4j.impl; + +import org.slf4j.helpers.NOPMakerAdapter; +import org.slf4j.spi.MDCAdapter; + + +/** + * This implementation is bound to {@link NOPMakerAdapter}. + * + * @author Ceki Gülcü + */ +public class StaticMDCBinder { + + + /** + * The unique instance of this class. + */ + public static final StaticMDCBinder SINGLETON = new StaticMDCBinder(); + + private StaticMDCBinder() { + } + + /** + * Currently this method always returns an instance of + * {@link StaticMDCBinder}. + */ + public MDCAdapter getMDCA() { + return new NOPMakerAdapter(); + } + + public String getMDCAdapterClassStr() { + return NOPMakerAdapter.class.getName(); + } +} diff --git a/slf4j-jcl/src/test/java/org/slf4j/InvocationTest.java b/slf4j-jcl/src/test/java/org/slf4j/InvocationTest.java index 4e055c78..3d208001 100644 --- a/slf4j-jcl/src/test/java/org/slf4j/InvocationTest.java +++ b/slf4j-jcl/src/test/java/org/slf4j/InvocationTest.java @@ -118,4 +118,11 @@ public class InvocationTest extends TestCase { logger.warn(blue, "hello {} and {} ", "world", "universe"); logger.error(blue, "hello {} and {} ", "world", "universe"); } + + public void testMDC() { + MDC.put("k", "v"); + MDC.remove("k"); + assertNull(MDC.get("k")); + MDC.clear(); + } } diff --git a/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticMDCBinder.java index 1c5414ce..62b9f865 100644 --- a/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticMDCBinder.java +++ b/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticMDCBinder.java @@ -18,7 +18,6 @@ public class StaticMDCBinder { public static final StaticMDCBinder SINGLETON = new StaticMDCBinder(); private StaticMDCBinder() { - throw new UnsupportedOperationException("This code should never make it into the jar"); } /** diff --git a/slf4j-jdk14/src/test/java/org/slf4j/InvocationTest.java b/slf4j-jdk14/src/test/java/org/slf4j/InvocationTest.java index 4e055c78..3d208001 100644 --- a/slf4j-jdk14/src/test/java/org/slf4j/InvocationTest.java +++ b/slf4j-jdk14/src/test/java/org/slf4j/InvocationTest.java @@ -118,4 +118,11 @@ public class InvocationTest extends TestCase { logger.warn(blue, "hello {} and {} ", "world", "universe"); logger.error(blue, "hello {} and {} ", "world", "universe"); } + + public void testMDC() { + MDC.put("k", "v"); + MDC.remove("k"); + assertNull(MDC.get("k")); + MDC.clear(); + } } diff --git a/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticMDCBinder.java new file mode 100644 index 00000000..897fda15 --- /dev/null +++ b/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticMDCBinder.java @@ -0,0 +1,33 @@ +package org.slf4j.impl; + +import org.slf4j.spi.MDCAdapter; + + +/** + * This implementation is bound to {@link Log4jMDCAdapter}. + * + * @author Ceki Gülcü + */ +public class StaticMDCBinder { + + + /** + * The unique instance of this class. + */ + public static final StaticMDCBinder SINGLETON = new StaticMDCBinder(); + + private StaticMDCBinder() { + } + + /** + * Currently this method always returns an instance of + * {@link StaticMDCBinder}. + */ + public MDCAdapter getMDCA() { + return new Log4jMDCAdapter(); + } + + public String getMDCAdapterClassStr() { + return Log4jMDCAdapter.class.getName(); + } +} diff --git a/slf4j-nop/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j-nop/src/main/java/org/slf4j/impl/StaticMDCBinder.java new file mode 100644 index 00000000..62b9f865 --- /dev/null +++ b/slf4j-nop/src/main/java/org/slf4j/impl/StaticMDCBinder.java @@ -0,0 +1,34 @@ +package org.slf4j.impl; + +import org.slf4j.helpers.NOPMakerAdapter; +import org.slf4j.spi.MDCAdapter; + + +/** + * This implementation is bound to {@link NOPMakerAdapter}. + * + * @author Ceki Gülcü + */ +public class StaticMDCBinder { + + + /** + * The unique instance of this class. + */ + public static final StaticMDCBinder SINGLETON = new StaticMDCBinder(); + + private StaticMDCBinder() { + } + + /** + * Currently this method always returns an instance of + * {@link StaticMDCBinder}. + */ + public MDCAdapter getMDCA() { + return new NOPMakerAdapter(); + } + + public String getMDCAdapterClassStr() { + return NOPMakerAdapter.class.getName(); + } +} diff --git a/slf4j-nop/src/test/java/org/slf4j/InvocationTest.java b/slf4j-nop/src/test/java/org/slf4j/InvocationTest.java index 4e055c78..3d208001 100644 --- a/slf4j-nop/src/test/java/org/slf4j/InvocationTest.java +++ b/slf4j-nop/src/test/java/org/slf4j/InvocationTest.java @@ -118,4 +118,11 @@ public class InvocationTest extends TestCase { logger.warn(blue, "hello {} and {} ", "world", "universe"); logger.error(blue, "hello {} and {} ", "world", "universe"); } + + public void testMDC() { + MDC.put("k", "v"); + MDC.remove("k"); + assertNull(MDC.get("k")); + MDC.clear(); + } } diff --git a/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index 0fea54ff..53955476 100644 --- a/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -1,34 +1,25 @@ -/* - * Copyright (c) 2004-2005 SLF4J.ORG - * Copyright (c) 2004-2005 QOS.ch - * +/* + * Copyright (c) 2004-2007 QOS.ch * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY - * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package org.slf4j.impl; diff --git a/slf4j-simple/src/main/java/org/slf4j/impl/StaticMDCBinder.java b/slf4j-simple/src/main/java/org/slf4j/impl/StaticMDCBinder.java new file mode 100644 index 00000000..a397bce7 --- /dev/null +++ b/slf4j-simple/src/main/java/org/slf4j/impl/StaticMDCBinder.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2004-2007 QOS.ch + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +package org.slf4j.impl; + +import org.slf4j.helpers.NOPMakerAdapter; +import org.slf4j.spi.MDCAdapter; + + +/** + * This implementation is bound to {@link NOPMakerAdapter}. + * + * @author Ceki Gülcü + */ +public class StaticMDCBinder { + + + /** + * The unique instance of this class. + */ + public static final StaticMDCBinder SINGLETON = new StaticMDCBinder(); + + private StaticMDCBinder() { + } + + /** + * Currently this method always returns an instance of + * {@link StaticMDCBinder}. + */ + public MDCAdapter getMDCA() { + return new NOPMakerAdapter(); + } + + public String getMDCAdapterClassStr() { + return NOPMakerAdapter.class.getName(); + } +} diff --git a/slf4j-simple/src/main/java/org/slf4j/impl/StaticMarkerBinder.java b/slf4j-simple/src/main/java/org/slf4j/impl/StaticMarkerBinder.java index b37c3640..6017ea9c 100644 --- a/slf4j-simple/src/main/java/org/slf4j/impl/StaticMarkerBinder.java +++ b/slf4j-simple/src/main/java/org/slf4j/impl/StaticMarkerBinder.java @@ -1,36 +1,28 @@ -/* - * Copyright (c) 2004-2005 SLF4J.ORG - * Copyright (c) 2004-2005 QOS.ch - * +/* + * Copyright (c) 2004-2007 QOS.ch * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, - * distribute, and/or sell copies of the Software, and to permit persons - * to whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR - * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY - * SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER - * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, use - * or other dealings in this Software without prior written authorization - * of the copyright holder. - * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + package org.slf4j.impl; import org.slf4j.IMarkerFactory; diff --git a/slf4j-simple/src/test/java/org/slf4j/InvocationTest.java b/slf4j-simple/src/test/java/org/slf4j/InvocationTest.java index 4e055c78..78254b9d 100644 --- a/slf4j-simple/src/test/java/org/slf4j/InvocationTest.java +++ b/slf4j-simple/src/test/java/org/slf4j/InvocationTest.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 2004-2005 SLF4J.ORG - * Copyright (c) 2004-2005 QOS.CH + * Copyright (c) 2004-2007 QOS.CH * * All rights reserved. * @@ -118,4 +117,11 @@ public class InvocationTest extends TestCase { logger.warn(blue, "hello {} and {} ", "world", "universe"); logger.error(blue, "hello {} and {} ", "world", "universe"); } + + public void testMDC() { + MDC.put("k", "v"); + MDC.remove("k"); + assertNull(MDC.get("k")); + MDC.clear(); + } } diff --git a/slf4j-site/src/site/pages/codes.html b/slf4j-site/src/site/pages/codes.html index 2c023616..f0df061b 100644 --- a/slf4j-site/src/site/pages/codes.html +++ b/slf4j-site/src/site/pages/codes.html @@ -20,9 +20,8 @@ prefix='';
-

SLF4J warning or error messages and their meanings

-

Ceki Gülcü
- created May 2006, last updated on May 2006

+

SLF4J warning or error messages and their meanings

+
@@ -47,7 +46,7 @@ prefix='';

This is a relatively common occurrence with recent versions of Tomcat, especially if you place jcl104-over-slf4j.jar in WEB-INF/lib directory of your web-application instead of - $TOMCAT_HOME/common/lib where $TOMCAT_HOME stands for the + $TOMCAT_HOME/common/lib, where $TOMCAT_HOME stands for the directory where Tomcat is installed. In order to fully benefit from the stability offered by jcl104-over-slf4j.jar, we recommend that you place jcl104-over-slf4j.jar in @@ -59,19 +58,7 @@ prefix=''; href="http://bugzilla.slf4j.org/show_bug.cgi?id=22">bug #22.

- - - -

Logging factory implementation cannot be null

- -

This error is reported when the LoggerFactory - class could not find an appropriate binding, indicating that no - appropriate SLF4J binding could be found. Placing one of - slf4j-nop.jar, slf4j-simple.jar, - slf4j-log4j12.jar, slf4j-jdk14.jar or - logback-classic.jar on the class path should prove to be - an effective remedy. -

+ @@ -82,13 +69,51 @@ prefix='';

This error is reported when the org.slf4j.impl.StaticLoggerBinder class could not be loaded into memory. This happens when no appropriate SLF4J - binding could be found on the class path. Placing one of + binding could be found on the class path. Placing one (and only + one) of slf4j-nop.jar, slf4j-simple.jar, + slf4j-log4j12.jar, slf4j-jdk14.jar or + logback-classic.jar on the class path should solve the + problem. +

+ + + + +

Logging factory implementation cannot be null

+ +

This error is reported when the LoggerFactory + class could not find an appropriate binding. Placing one (and only + one) of slf4j-nop.jar, slf4j-simple.jar, + slf4j-log4j12.jar, slf4j-jdk14.jar or + logback-classic.jar on the class path should prove to be + an effective remedy. +

+ + + + +

Failed to load class "org.slf4j.impl.StaticMDCBinder".

+ +

This error indicates that appropriate SLF4J binding could be + found on the class path. Placing one (and only one) of slf4j-nop.jar, slf4j-simple.jar, slf4j-log4j12.jar, slf4j-jdk14.jar or logback-classic.jar on the class path should solve the problem.

+ + + +

MDCAdapter cannot be null

+ +

This error is reported when org.slf4j.MDC class + has not been initialized correctly. Same cause and remedy as the + previously listed item. +

+ + +