[logback-dev] svn commit: r1897 - in logback/trunk/logback-classic/src: main/java/ch/qos/logback/classic test/java/ch/qos/logback/classic

noreply.ceki at qos.ch noreply.ceki at qos.ch
Tue Oct 28 19:07:19 CET 2008


Author: ceki
Date: Tue Oct 28 19:07:19 2008
New Revision: 1897

Added:
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/Foo.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java
Modified:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java

Log:
fixes LBCLASSIC-74

Make ch.qos.logback.classic.Logger instances deserialize with a valid LoggerContext reference.
This is accomplished by the readResolve() method which returns a Logger
generated by org.slf4j.LoggerFactory which may or not be using the correct LoggerContext. However,
that is probably the best we can do at that stage.

Associated test case.

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java	Tue Oct 28 19:07:19 2008
@@ -10,12 +10,14 @@
 
 package ch.qos.logback.classic;
 
+import java.io.ObjectStreamException;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
+import org.slf4j.LoggerFactory;
 import org.slf4j.Marker;
 import org.slf4j.spi.LocationAwareLogger;
 
@@ -73,18 +75,12 @@
    * synchronized on 'this' (Logger) protecting against simultaneous
    * re-configuration of this logger (a very unlikely scenario).
    * 
-   * <p>
-   * It is further assumed that the AppenderAttachableImpl is responsible for
-   * its internal synchronization and thread safety. Thus, we can get away with
-   * *not* synchronizing on the 'aai' (check null/ read) because
-   * <p>
-   * 1) the 'aai' variable is immutable once set to non-null
-   * <p>
-   * 2) 'aai' is getAndSet only within addAppender which is synchronized
-   * <p>
-   * 3) all the other methods check whether 'aai' is null
-   * <p>
-   * 4) AppenderAttachableImpl is thread safe
+   * <p> It is further assumed that the AppenderAttachableImpl is responsible
+   * for its internal synchronization and thread safety. Thus, we can get away
+   * with *not* synchronizing on the 'aai' (check null/ read) because <p> 1) the
+   * 'aai' variable is immutable once set to non-null <p> 2) 'aai' is getAndSet
+   * only within addAppender which is synchronized <p> 3) all the other methods
+   * check whether 'aai' is null <p> 4) AppenderAttachableImpl is thread safe
    */
   private transient AppenderAttachableImpl<LoggingEvent> aai;
   /**
@@ -134,9 +130,8 @@
   /**
    * Get a child by its suffix.
    * 
-   * <p>
-   * IMPORTANT: Calls to this method must be within a synchronized block on this
-   * logger!
+   * <p> IMPORTANT: Calls to this method must be within a synchronized block on
+   * this logger!
    * 
    * @param suffix
    * @return
@@ -315,9 +310,8 @@
    * extending this logger. For example, if this logger is named "x.y" and the
    * lastPart is "z", then the created child logger will be named "x.y.z".
    * 
-   * <p>
-   * IMPORTANT: Calls to this method must be within a syncronized block on this
-   * logger.
+   * <p> IMPORTANT: Calls to this method must be within a syncronized block on
+   * this logger.
    * 
    * @param lastPart
    *                the suffix (i.e. last part) of the child logger name. This
@@ -833,4 +827,16 @@
     }
     filterAndLog(fqcn, marker, level, message, null, t);
   }
+
+  /**
+   * After serialization, the logger instance does not know its LoggerContext.
+   * The best we can do here, is to return a logger with the same name as
+   * generated by LoggerFactory.
+   * 
+   * @return Logger instance with the same name
+   * @throws ObjectStreamException
+   */
+  protected Object readResolve() throws ObjectStreamException {
+    return LoggerFactory.getLogger(getName());
+  }
 }

Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/Foo.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/Foo.java	Tue Oct 28 19:07:19 2008
@@ -0,0 +1,17 @@
+package ch.qos.logback.classic;
+
+import java.io.Serializable;
+
+class Foo implements Serializable {
+  private static final long serialVersionUID = 1L;
+  final Logger logger;
+  
+  Foo(Logger logger) {
+    this.logger = logger;
+  }
+  
+  void doFoo() {
+    logger.debug("hello");
+  }
+}
+

Added: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerSerializationTest.java	Tue Oct 28 19:07:19 2008
@@ -0,0 +1,55 @@
+package ch.qos.logback.classic;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class LoggerSerializationTest {
+
+  LoggerContext lc;
+  Logger logger;
+
+  ByteArrayOutputStream bos;
+  ObjectOutputStream oos;
+  ObjectInputStream inputStream;
+
+  @Before
+  public void setUp() throws Exception {
+    lc = new LoggerContext();
+    lc.setName("testContext");
+    logger = lc.getLogger(LoggerSerializationTest.class);
+    // create the byte output stream
+    bos = new ByteArrayOutputStream();
+    oos = new ObjectOutputStream(bos);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    lc = null;
+    logger = null;
+    oos.close();
+  }
+  
+  @Test
+  public void serialization() throws IOException, ClassNotFoundException {
+    Foo foo = new Foo(logger);
+    foo.doFoo();
+    Foo fooBack = writeAndRead(foo);
+    fooBack.doFoo();
+  }
+
+  private Foo writeAndRead(Foo foo) throws IOException,
+      ClassNotFoundException {
+    oos.writeObject(foo);
+    ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+    inputStream = new ObjectInputStream(bis);
+
+    return (Foo) inputStream.readObject();
+  }
+}

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerTestHelper.java	Tue Oct 28 19:07:19 2008
@@ -19,7 +19,4 @@
     }
     assertEquals(effectiveLevel, logger.getEffectiveLevel());
   }
-
-
-
 }
\ No newline at end of file

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/PackageTest.java	Tue Oct 28 19:07:19 2008
@@ -20,6 +20,7 @@
     suite.addTest(new JUnit4TestAdapter(DynamicLoggerContextTest.class));
     suite.addTest(new JUnit4TestAdapter(PatternLayoutTest.class));
     suite.addTestSuite(BasicLoggerTest.class);
+    suite.addTest(new JUnit4TestAdapter(LoggerSerializationTest.class));
     suite.addTestSuite(MessageFormattingTest.class);
     suite.addTestSuite(MDCTest.class);
     suite.addTestSuite(TurboFilteringInLoggerTest.class);


More information about the logback-dev mailing list