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]