Friday, September 7, 2007

Log4j in PeopleCode

Jim's PeopleSoft Journal had a good entry on using Log4j in PeopleCode. This first article assumed that you would have control over the log4j.properties file in your environment. Jim also posted a follow-up on Log4j and Peoplecode Part II where he discussed how to programmatically configure the logging. This is nice for those, like me, that do not have access to modify the $PS_HOME/appserv/classes/log4j.properties file.

The programmatic approach works well, but I didn't want to hardcode all that information in each event I want to log information in. You can point log4j to an alternative logging file using the code below, that way you can keep control of the logging level and setup of the appenders in a file that is easy to modify. Of course, this assumes that in your environment you have some access to a directory where you can store the file and grant write access to it for the daemon that runs the application server.


Local JavaObject &log4jConfig = GetJavaClass("org.apache.log4j.PropertyConfigurator");

&log4jConfig.configure("/some/directory/log4j.properties");

Local JavaObject &log = GetJavaClass("org.apache.log4j.Logger").getLogger("edu.csufresno.cis.HRS_CE_RESUME.PageActivate");

&log.info("hi from peoplecode");


Note: I got tripped up initially because I didn't read Jim's code closely enough and tried using CreateJavaObject out of habit instead of GetJavaClass. Since both methods are static (i.e., can't create an instance of a Logger) it blew up with an error.

5 comments:

Jim Marion said...

Excellent idea John. This builds well off my previous post. This post got me thinking about another idea. As you noted, both approaches require the developer to have access to a file that can be accessed from the app or process scheduler server. What about storing the configuration properties in a table, using the PropertyConfiguratorconfigure(java.util.Properties) and loading a Properties object from the table?

John Wagenleitner said...

I like the idea of storing the log4 properties in the database. Is this what you were thinking (message cat in place of table, but same concept I think)?

Local string &props = MsgGetExplainText(31000,1,"");

Local JavaObject &string_props = CreateJavaObject("java.lang.String", &props);

Local JavaObject &inputstream = CreateJavaObject("java.io.ByteArrayInputStream", &string_props.getBytes());

Local JavaObject &log4jprops = CreateJavaObject("java.util.Properties");

&log4jprops.load(&inputstream);

PropertyConfiguration.configure(&log4jprops);

Jim Marion said...

Hmmm... that would work too. That would be the unstructured approach. What I was actually thinking was a table with fields like LOGGER_NAME, KEY, VALUE and it would be keyed on LOGGER_NAME, KEY. Then, some PeopleCode would loop through the rowset and populate the properties object using the setProperty method. Your suggestion would result in much less code and would be much easier to implement.

John Wagenleitner said...

I see now what you were talking about. This actually reminds me of a recent customization we made creating a table similar to the one you suggested but one that is not specific to logging.

Basically we needed a table to store misc properties that we need to reference in our customizations, sort of a xlat table for settings. We designed our table with just 2 fields, PROP_KEY and PROP_VALUE. We wrote an Application Class modeled after the java.util.Properties class for accessing the table via PeopleCode.

Jim Marion said...

Exactly.