Log4j again – Asyn Log Appender to datasource

Hi, had some interesting use with the log4j. I think it should help some people, with similar situations with log4j. We need to do log4j with these needs:

(1) asynchronously (2) append to a database (3) use a datasource in a JNDI tree.

(1) is obviously advantageous, nobody wants to cost delay to processes that being logged.

(2) and (3) are common requirements – use dynamic connection pooling without having clear text password in log4j.xml or property files.

Here are the steps to do:

(a) Setup config in log4j.xml

<appender name=”DatabaseAppender”
class=”DatabaseAppender”>
<param name=”Threshold” value=”DEBUG” />
<layout>
<param name=”ConversionPattern” value=”%m” />
</layout>
</appender>

<appender name=”AsynAppenderToDatabaseAppender”
class=”org.apache.log4j.AsyncAppender”>
<appender-ref ref=”DatabaseAppender” />
</appender>

<root>
<appender-ref ref=”AsynAppenderToDatabaseAppender” />
</root>

DatabaseAppender is the custom appender which will eventually do the underhood logging.  The AsynAppenderToDatabaseAppender is simply a log4j AsyncAppender that will pipe the logger to the DatabaseAppender.  The root logger is my lazy mapping of all to the DatabaseAppender.  One can add many other loggers to it as desired.

(b) Implement the Custom DatabaseAppender.java

public class DatabaseAppender extends AppenderSkeleton {

public boolean requiresLayout(){
return true;
}

/**
* actual place to save to DB with LOG object for hibernate
*/
public synchronized void append( LoggingEvent event ) {

LogDatabaseDelegate del = new LogDatabaseDelegate();
LogTable log = new LogTable();
log.setLOGLEVEL_INT(event.getLevel().toInt());
log.setLOGLEVEL(event.getLevel().toString());
log.setLOGTIME(new Date(event.getTimeStamp()));
LocationInfo li = event.getLocationInformation();
log.setLOGGER(event.getLoggerName() + ” [” + li.getFileName() + “:” + li.getMethodName() + “:” + li.getLineNumber() + “]”);
log.setAPPID(SitePropertyConstants.getAPP_ID());
String msg = this.layout.format(event);
if (msg.length() > SitePropertyConstants.getMAX_CHAR_IN_LOG_MSG())
msg = msg.substring(0, SitePropertyConstants.getMAX_CHAR_IN_LOG_MSG());
log.setLOGMESSAGE(msg);
del.saveLog(log);

}

public synchronized void close(){

}
}

Here is pure java stuff with Hibernate.  The LogDatabaseDelegate will save LogTable object with information such as Log level, log time, logger name (class), log message, etc, etc. In the hibernate end, I simply mount the datasource to a JNDI tree using:

<property name=”connection.datasource”>myDataSource</property>

Definitely, hibernate is not relevant here, you can use any DAO layer to persist the log4j information to Database.

That’s all – Happy Logging4J to Database, asynchronously!

-T

NoClassDefFoundError, Xerces package in Weblogic Managed Server

I have spent 4-5 days including probably 10 hours this weekend to this tailspinning problem. We have this ear file deployed to WLS adminsevers w/o any problem. As soon as it is deployed to a managed server, we have this ClassDefNotFoundError each time we do an unmarshall from an XML soap msg to an object. This Object has a data type impl of Duration. To make long story short, the xerces always complained about unable to load this DurationImpl class in xerces. I use the latest xerces 2.9.1 and the class is obviously in APP-INF/lib. When all said and done, we semi-incidentally found by deploying to another instance of managed server. This worked on that instance. It turns out the problematic instance has this WILY management system in system classpath. So we think that must have some spoiler xerces packages which maybe of 2.6 or earlier for xerces. It is almost impossible to fix it by tuning CP config. in our ear file (with all those prefered CP options in weblogic or weblogic-application descriptors).

Not saying Wily is bad, but any package (JMX etc) that in the systm classpath is potentially a CP hell for us developers. WLS tends to include lots of open source packs or other 3rd party stuff, all could be sources of wasting precious times of ours.

<T/>

  1. java.lang.NoClassDefFoundError: Could not initialize class org.apache.xerces.jaxp.datatype.DurationImpl
  2. at org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl.newDuration(Unknown Source)
  3. at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$25.parse(RuntimeBuiltinLeafInfoImpl.java:787)
  4. at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$25.parse(RuntimeBuiltinLeafInfoImpl.java:780)
  5. at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.parse(TransducedAccessor.java:241)
  6. at com.sun.xml.bind.v2.runtime.unmarshaller.LeafPropertyLoader.text(LeafPropertyLoader.java:61)
  7. at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.text(UnmarshallingContext.java:462)
  8. at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.processText(SAXConnector.java:168)
  9. at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:141)
  10. at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
  11. at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
  12. at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
  13. at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
  14. at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
  15. at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
  16. at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
  17. at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
  18. at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
  19. at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:211)
  20. at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:184)
  21. at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
  22. at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:194)