How to extend class and override method of log4j.Logger

1,110 views
Skip to first unread message

Tom Fischer

unread,
Mar 9, 2021, 5:36:52 AM3/9/21
to mozilla-rhino
  1. I want to test JS code automatically that runs in Rhino (fixed)
  2. The JS code uses log4j (v1) for logging
  3. I need to run the JS code and catch up the logged messages (add them to an array that I process after executing code)
My idea is to extend the Logger class of org.apache.log4j.Logger and override existing methods (prefer log() but debug/info/warn/error would also fit)

Problems where I stuck:
  • overriding debug method not working (ignored?)
  • some superclass methods are not accessible
Any idea?

Here's how it's done in Java:

Here's how I tried (sorry for the super stupid code, I hope it gives some details and highlights the problem):

org.apache.log4j.BasicConfigurator.configure();
var logger = org.apache.log4j.LogManager.getRootLogger();

var overrides = {
debug: function(message) {
java.lang.System.out.println("bingo!");
this.super$debug(message);
},
getLogger: function(name) {
logger.debug("super$debug: " + this.super$debug); // DEBUG root  - super$debug: function super$debug() { void super$debug(java.lang.Object,java.lang.Throwable) void super$debug(java.lang.Object) }
logger.debug("super$info: " + this.super$info); // DEBUG root  - super$info: undefined
logger.debug("super$warn: " + this.super$warn); // DEBUG root  - super$warn: undefined
logger.debug("super$error: " + this.super$error); // DEBUG root  - super$error: undefined
logger.debug("super$log: " + this.super$log); // DEBUG root  - super$log: undefined
logger.debug("super$getLogger: " + this.super$getLogger); // DEBUG root  - super$getLogger: undefined
return org.apache.log4j.Logger.getLogger(name); // works
// return this.super$getLogger(name); // does NOT work (undefined)
}
};

var loggerName = "transformer";

// example 1: using JavaAdapter to extend Logger class
var ja = new JavaAdapter(org.apache.log4j.Logger, overrides, loggerName);

logger.debug("ja.getClass(): " + ja.getClass()); // DEBUG root  - ja.getClass(): class adapter1
logger.debug("ja.getName(): " + ja.getName()); // DEBUG root  - ja.getName(): transformer

var logger_1 = ja.getLogger(loggerName);
logger.debug("logger_1: " + logger_1); // DEBUG root  - logger_1: org.apache.log4j.Logger@6895a785
logger.debug("logger_1.getClass(): " + logger_1.getClass()); // logger_1.getClass(): class org.apache.log4j.Logger
logger.debug("logger_1.getName(): " + logger_1.getName()); // logger_1.getName(): transformer
logger_1.debug("hello 1"); //* DEBUG transformer  - hello 1

// example 2: getLogger(Class clazz) where clazz = JavaAdapter object
var logger_2 = org.apache.log4j.LogManager.getLogger(ja);
logger.debug("logger_2: " + logger_2); // DEBUG root  - logger_2: org.apache.log4j.Logger@56aac163
logger_2.debug("hello 2"); //* DEBUG adapter1@184f6be2  - hello 2

// example 3: getLogger(Class clazz) clazz = Logger object from logger_1 via JavaAdapter
var logger_3 = org.apache.log4j.LogManager.getLogger(logger_1); // 
logger.debug("logger_3: " + logger_3); // DEBUG root  - logger_3: org.apache.log4j.Logger@1f7030a6
logger_3.debug("hello 3"); //* DEBUG org.apache.log4j.Logger@6895a785  - hello 3

//* should print "bingo!" first -> override NOT working

/* output:

0 [main] DEBUG root  - ja.getClass(): class adapter1
2 [main] DEBUG root  - ja.getName(): transformer
2 [main] DEBUG root  - super$debug: function super$debug() {
void super$debug(java.lang.Object,java.lang.Throwable)
void super$debug(java.lang.Object)
}

2 [main] DEBUG root  - super$info: undefined
3 [main] DEBUG root  - super$warn: undefined
3 [main] DEBUG root  - super$error: undefined
3 [main] DEBUG root  - super$log: undefined
3 [main] DEBUG root  - super$getLogger: undefined
3 [main] DEBUG root  - logger_1: org.apache.log4j.Logger@6895a785
3 [main] DEBUG root  - logger_1.getClass(): class org.apache.log4j.Logger
3 [main] DEBUG root  - logger_1.getName(): transformer
3 [main] DEBUG transformer  - hello 1
3 [main] DEBUG root  - logger_2: org.apache.log4j.Logger@56aac163
3 [main] DEBUG adapter1@184f6be2  - hello 2
4 [main] DEBUG root  - logger_3: org.apache.log4j.Logger@1f7030a6
5 [main] DEBUG org.apache.log4j.Logger@6895a785  - hello 3

*/

Tom Fischer

unread,
Mar 9, 2021, 7:02:27 AM3/9/21
to mozilla-rhino
If I minimize the code to this:

org.apache.log4j.BasicConfigurator.configure();
var logger = org.apache.log4j.LogManager.getRootLogger();

var overrides = {
getLogger: function(name) {
for(var i in this) {
try {
print(i + ": " + String(this[i]));
} catch(err) {
print(i + ": " + err.message);
}
}
return org.apache.log4j.Logger.getLogger(name);
}
};

var loggerName = "transformer";
var ja = new JavaAdapter(org.apache.log4j.Logger, overrides, loggerName);
var logger_1 = ja.getLogger(loggerName);

for(var i in logger_1) {
try {
print(i + ": " + String(logger_1[i]));
} catch(err) {
print(i + ": " + err.message);
}
}

And compare the output of the 2 for-loops: https://www.diffchecker.com/BhspSvf0

You see some important differences (e.g. logger, parent, NullPointerExceptions)... looks pretty strange like the JavaAdapter didn't properly extend the Logger class.

Any idea what I'm doing wrong?
Many thanks.
Reply all
Reply to author
Forward
0 new messages