Tuesday, November 14, 2006

log4j and PeopleCode Part II

Last month I wrote about using log4j to debug PeopleCode. This is a tool that I use quite often. Here are a couple more hints to help you use log4j from PeopleCode.

One of the main benefits of log4j is the ability to configure, and reconfigure, log4j without modifying your code. However, sometimes a configuration file is not practical. Here is an example of configuring log4j from PeopleCode:
Local JavaObject &logger = GetJavaClass("org.apache.log4j.Logger").getLogger("my.custom.logger");
Local JavaObject &layout = CreateJavaObject("org.apache.log4j.PatternLayout", "%-4r %d [%t] %-5p %c [%x] - %m%n");
Local JavaObject &appender = CreateJavaObject("org.apache.log4j.ConsoleAppender", &layout);

&appender.setLayout(&layout);

&logger.addAppender(&appender);
&logger.setLevel(GetJavaClass("org.apache.log4j.Level").DEBUG);
&logger.debug("Hello from a PeopleCode configured logger.");

Running this code on the AppServer will write log messages to the AppServer's stdout file. log4j has several other appenders that may be more practical if the AppServer's stdout file is not accessible. Here is a configuration example that uses the SMTPAppender to send log messages to an e-mail address (preferrably your e-mail address).
Local JavaObject &logger = GetJavaClass("org.apache.log4j.Logger").getLogger("jjm.email.debugger");
Local JavaObject &layout = CreateJavaObject("org.apache.log4j.HTMLLayout");
Local JavaObject &appender = CreateJavaObject("org.apache.log4j.net.SMTPAppender");

&appender.setSMTPHost("mail.yourserver.com");
&appender.setFrom("log4j@yourserver.com");
&appender.setTo("you@yourserver.com");
&appender.setSubject("PeopleCode debug log");
&appender.setBufferSize(1);
&appender.setLayout(&layout);
&appender.activateOptions();

&logger.addAppender(&appender);
&logger.setLevel(GetJavaClass("org.apache.log4j.Level").DEBUG);

&logger.fatal("Hello from PeopleCode!");

One thing to note about the SMTPAppender is that it only sends error and fatal log messages to the specified e-mail address.

About error messages... As you know, error is a key word in PeopleCode. Therefore, it is not possible to execute the error method of the Logger object directly. However, you may be able to get around this by using Java's reflection to execute the method.

13 comments:

kane81 said...

Hi,

I've implemented Log4J in PT844, but I have a problem when I use log4j.xml property file - (all works fine if I config by code)....

I have put my log4j.xml file in

C:\psoft\c3sb1\pt844\class\log4j.xml

I get a java exception

javax.xml.parsers.FactoryConfigurationError: Provider org.apache.xerces.jaxp.DocumentBuilderFactoryImpl not found during call org.apache.log4j.Logger.getLogger

any ideas why I get this error when using the xml file?

I checked the C:\psoft\c3sb1\pt844\class\xerces.jar file and it has the DocumentBuilder class

so I'm not sure what is wrong....

also anyone got any code that shows how to call Log.Error()?

Thanks so much!

Jim Marion said...

It sounds like Xerces is registering itself as the DOM implementation which confirms that xerces is in your classpath. Your xerces.jar file has a file called META-INF/services/javax.xml.parsers.DocumentBuilderFactory, doesn't it? Maybe your jar file is corrupt. It is possible that some of the classes in your jar are corrupt. Can you redeploy PeopleTools and grab a fresh copy of xerces? The jar's manifest file should have the Xerces implementation version number, so you could download a fresh copy from Apache as well.

If you can't get the log4j.xml file to work, you can use the log4j.properties file format instead.

Log.error is the same as log.debug and log.fatal, as demonstrated in the post. Just type:

&logger.error("this is the error message");

kane81 said...

thanks will try it...

"error" is a keyword in people code so you cant do

&logger.error("this is the error message");

Jim Marion said...

@kane81, you are right. I forgot about that. Now, I know that error is a function, but I'm not sure if it is a reserved/keyword. In otherwords, if you precede it with an object and a dot (&logger.) then I think PeopleCode will execute it as a method, not the error function. If you type the code and the PeopleCode validator points it out as an error or if it doesn't work, then you can use Java Reflection. I have a few examples of reflection labeled Java Reflection. Chris Heller has a nice Java Reflection post as well. If you write a reflection example, can you post it here? I'll do likewise. I'll see if I can get an example up here sometime before the end of the week.

Jim Marion said...

I should read my own posts... The last sentence of my post says, "As you know, error is a key word in PeopleCode..."

Jim Marion said...

@kane81, Calling logger.error from PeopleCode.

Ganesh said...

can someone explain me the real use of the Log4J in the peoplesoft. What is the need for Log4J ?
Example where this will be required and why not any peoplesoft delivered methods can be used to log error message.

Jim Marion said...

@Ganesh, Oracle delivers log4j with PeopleSoft. How do delivered PeopleSoft applications use log4j? I have no idea. Where can you use it? Any PeopleCode where you want targeted logging/tracing for debugging or application management. What delivered PeopleCode options exist? The PeopleCode MessageBox statement provides targeted logging/debugging information. The problem with MessageBox is that you have to modify your code when you want to print statements, and then modify it again when you want to stop printing statements. log4j offers a configurable alternative. You can litter your code with trace, debug, info, warn, error, and fatal statements and can figure whether or not those statements print. You don't have to delete them when you finish your debugging process. The only delivered configurable alternative is PeopleCode trace settings. The problem with trace settings is they log everything. They aren't targeted. You can't pick and choose what to log. Reviewing a PeopleCode trace file for errors is truly like sipping from a fire hose.

What is my need for log4j? Targeted and configurable logging/tracing. I can print what I want when I want. There are no PeopleCode/PeopleSoft options that provide this capability.

Sri Reddy said...

Hi Jim,
Last week, I read your PeopleSoft Peopletools tips & techniques and tried to implement log4j logging framework in the PeopleSoft.

Following things, I successfully implemented using log4J:
1.) logging framework for batch process (app engine)
2.) logging framework for debugging online pages

Issues encountered:
1.) Getting java errors when trying to implement log4j logging framework in the integration broker subscription peoplecode. (webservice consumption framework).

Do you know the reason why your log4j framework is failing for IB subscription peoplecode and is there any workaround for it?

Thanks
Sri

Jim Marion said...

@Sri, Off the top of my head, I can't think of any reason you would receive errors. What error messages are you receiving?

Sri Reddy said...

Hi Jim,
I figured out the issue. I am not able to instantiate the logger class in the constructor of the service handler class. But, I am able to instantiate in the OnRequest method.

I don't know the reason why I am getting the Java errors while instantiating from constructors.

Also, I faced one more issue while using log4j from an online application. Sytem is throwing ANNOTATION java errors because of the reflection used in the logmanager class.

I modified the code in initialize method of logmanager class to instantiate logger without using reflection. Then, It started working.

I really liked this log4j logging. We incorporated in our webservice consumption framework. It's very helpful for the developers to debug the service handlers.

Jim Marion said...

@Sri, Good to hear that you have it working and find it valuable. Are you using the version of log4j that ships with PeopleSoft or are you using a different version?

Sri Reddy said...

Hi Jim,

Yes, we are using the same version of log4j that shipped with Peopletools v8.52.
We didn't have any issues while instantiating log4j classes from application engine. We were having those issues only when calling from online peoplecode.