Hi Guys,

Due to a requirement for a project I am working on, we recently made a small 
change to the log4j source file spi/LoggingEvent.java.  We needed to pass in 
custom message objects when creating a log event, log those events over the 
SocketAppender, and write custom Appenders to deal with our objects on the 
other end of that socket.  Currently, because the LoggingEvent object can't 
guarantee that message objects are Serializable, it renders them as Strings 
upon Serialization.  In order to keep our custom objects intact, we added code 
to check, during Serialization, to see if a message object is Serializable.  If 
it is, a reference to that object is stored in a non-transient field during 
serialization, and restored to it's original field upon deserialization.

So, in the interest of giving back, would the log4j team be open to 
incorporating this idea in the official distribution?  This change could 
benefit anyone using SocketAppenders (or anyone serializing LoggingEvent 
objects for that matter) who doesn't want to render their logs as Strings 
prematurely.  As far as I can tell, there is no down side to this solution, 
since non-serializable objects are still treated in the same way as before.  I 
am using log4j version 1.2.14, but if there is interest, I can make a similar 
change to the latest development code base.  Below is a patch for 
spi/LoggingEvent.java version 1.2.14.

Thanks,
Peter


--- LoggingEvent.java.orig      2007-03-21 18:58:50.000000000 -0400
+++ LoggingEvent.java   2007-03-21 12:18:28.000000000 -0400
@@ -23,6 +23,7 @@
 import java.lang.reflect.Method;
 import java.io.ObjectOutputStream;
 import java.io.ObjectInputStream;
+import java.io.Serializable;
 import java.util.Hashtable;
 
 // Contributors:   Nelson Minar <[EMAIL PROTECTED]>
@@ -106,6 +107,9 @@
   /** The application supplied message of logging event. */
   transient private Object message;
 
+  /** A non-transient place holder for the message Object for serialization. */
+  private Serializable serializableMessage;
+
   /** The application supplied message rendered through the log4j
       objet rendering mechanism.*/
   private String renderedMessage;
@@ -377,6 +381,9 @@
   private void readObject(ObjectInputStream ois)
                         throws java.io.IOException, ClassNotFoundException {
     ois.defaultReadObject();
+    if(serializableMessage != null) {
+      message = serializableMessage;
+    }
     readLevel(ois);
 
     // Make sure that no location info is available to Layouts
@@ -390,8 +397,13 @@
     // method sets the threadName variable.
     this.getThreadName();
 
-    // This sets the renders the message in case it wasn't up to now.
-    this.getRenderedMessage();
+    // If the message can be serialized, save it off in a non-transient field.
+    // If not, this renders the message in case it wasn't up to now.
+    if(message instanceof Serializable) {
+      serializableMessage = (Serializable)message;
+    } else {
+      this.getRenderedMessage();
+    }
 
     // This call has a side effect of setting this.ndc and
     // setting ndcLookupRequired to false if not already false.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to