- Get link
- X
- Other Apps
- Get link
- X
- Other Apps
Well we all write a lot of custom batch programs, and since, a lot goes on behind the scene, we as developers need to ensure that sufficient logging takes place to help identify the problem.
For debugging, we normally make use of either a (Global or Component) file object or the famous but dreaded messagebox(). The problem with file object approach is that file handling adds an additional overhead of checking or making sure that we have opened it in the write mode and using the right charset.
Another approach most commonly used be developers is by adding numerous messageboxes to the PeopleCode, but most of them are unaware of the inherent danger, as in most of the PeopleTools versions, messagebox() fires and implicit COMMIT. This can create havoc if you have a restart enabled AE.
(Credits to the Original Uploader) Jim Marion - http://jjmpsj.blogspot.com/2008/05/appengine-output-tricks-reporting.html
came up with a wonderful solution of using the preloaded JVM on the Batch or App Server to serve as logging alternative. Please go through the above link for a detailed explanation.
The only modifications that I did to that piece of code was to paste in an Application Package and use that in all custom built Application Engines. This approach has loads of advantages on the ones discussed above (File Object or messagebox)
--The actual Application Package PeopleCode
class AE_BATCH_LOG
method AE_BATCH_LOG();
method println_to_stdout(&message As string);
method println_to_stderr(&message As string);
rem This method may be used at the discretion of the User;
method redirect_stdout(&fileName As string);
rem Use the Redirect for stderr as PS by default creates an stdout for each process;
method redirect_stderr(&fileName As string);
end-class;
/*
* The Constructor takes no arguments
*/
method AE_BATCH_LOG
end-method;
/**
* The println_to_stdout method is used to Print a line of text to Stdout.
*
* @param &message - Text to be written to Stdout.
*/
method println_to_stdout
/+ &message as String +/
try
Local string &sMethodName = "AE_BATCH_LOG:println_to_stdout";
Local JavaObject &jSystem = GetJavaClass("java.lang.System");
Local JavaObject &jOutStream = &jSystem.out;
Local JavaObject &jCls = GetJavaClass("java.lang.Class");
Local JavaObject &jStringClass = &jCls.forName("java.lang.String");
Local JavaObject &jPrintStreamCls = &jOutStream.getClass();
Local JavaObject &jPrintlnArgTypes = CreateJavaObject("java.lang.Class[]", &jStringClass);
Local JavaObject &jPrintlnMethod = &jPrintStreamCls.getDeclaredMethod("println", &jPrintlnArgTypes);
&jPrintlnMethod.invoke(&jOutStream, CreateJavaObject("java.lang.Object[]", &message));
rem ** I didn't find flushing necessary, but here is where you would flush the buffer if desired;
rem &jOutStream.flush();
catch Exception &ex
&ex.Output();
Error (MsgGetText(18130, 15001, "Unhandled exception occurred in %1.", &sMethodName));
end-try;
end-method;
/**
* The println_to_stderr method is used to Print a line of text to Stderr.
* This method should be used with a combination of redirect_stderr as PS
* maintains a single Stderr file for all processes.
* @param &message - Text to be written to Stdout.
*/
method println_to_stderr
/+ &message as String +/
try
Local string &sMethodName = "AE_BATCH_LOG:println_to_stderr";
Local JavaObject &jSystem = GetJavaClass("java.lang.System");
Local JavaObject &jOutStream = &jSystem.err;
Local JavaObject &jCls = GetJavaClass("java.lang.Class");
Local JavaObject &jStringClass = &jCls.forName("java.lang.String");
Local JavaObject &jPrintStreamCls = &jOutStream.getClass();
Local JavaObject &jPrintlnArgTypes = CreateJavaObject("java.lang.Class[]", &jStringClass);
Local JavaObject &jPrintlnMethod = &jPrintStreamCls.getDeclaredMethod("println", &jPrintlnArgTypes);
&jPrintlnMethod.invoke(&jOutStream, CreateJavaObject("java.lang.Object[]", &message));
rem ** I didn't find flushing necessary, but here is where you would flush the buffer if desired;
rem &jOutStream.flush();
catch Exception &ex
&ex.Output();
Error (MsgGetText(18130, 15001, "Unhandled exception occurred in %1.", &sMethodName));
end-try;
end-method;
/**
* The redirect_stdout method is used to redirect a line of text to a Custom file (Not a PS File Object) for general message logs.
* Use the this method prior to calling the println_to_stdout method.
*
* @param &fileName - File name of Redirected File.
*/
method redirect_stdout
/+ &fileName as String +/
try
Local string &sMethodName = "AE_BATCH_LOG:redirect_stdout";
Local JavaObject &jSystem = GetJavaClass("java.lang.System");
Local JavaObject &jfos_out = CreateJavaObject("java.io.FileOutputStream", &fileName, True);
Local JavaObject &jps_out = CreateJavaObject("java.io.PrintStream", &jfos_out, True);
&jSystem.setOut(&jps_out);
catch Exception &ex
&ex.Output();
Error (MsgGetText(18130, 15001, "Unhandled exception occurred in %1.", &sMethodName));
end-try;
end-method;
/**
* The redirect_stderr method is used to redirect a line of text to a Custom file (Not a PS File Object) for error logging.
* Use the this method prior to calling the println_to_stderr method.
*
* @param &fileName - File name of Redirected File.
*/
method redirect_stderr
/+ &fileName as String +/
try
Local string &sMethodName = "AE_BATCH_LOG:redirect_stderr";
Local JavaObject &jSystem = GetJavaClass("java.lang.System");
Local JavaObject &jfos_out = CreateJavaObject("java.io.FileOutputStream", &fileName, True);
Local JavaObject &jps_out = CreateJavaObject("java.io.PrintStream", &jfos_out, True);
&jSystem.setErr(&jps_out);
catch Exception &ex
&ex.Output();
Error (MsgGetText(18130, 15001, "Unhandled exception occurred in %1.", &sMethodName));
end-try;
end-method;
-----------------------------------
To use the logging feature all you need to do is to include the below lines in any PeopleCode action of yours in your Application Engine
-----------------------------------
import AE_BATCH_LOG:*;
/* Create Class Object for Logging */
Local AE_BATCH_LOG:AE_BATCH_LOG &AEmsgLog_
/* PeopleSoft prefers the Singleton apporach */
If None(&AEmsgLog_) Then
&AEmsgLog_ = create AE_BATCH_LOG:AE_BATCH_LOG();
------------------------------------
Once you have the class object, we need to redirect the stdout and stderr files. Its a good practice to redirect stdout, but you need to redirect the stderr always as the stderr is shared across processes.
------------------------------------
/* Create the error file in the following path */
rem Better to retrieve the path in an SQL action and store it in AET;
SQLExec("SELECT PRCSOUTPUTDIR FROM PSPRCSPARMS WHERE PRCSINSTANCE = :1", &YourPIValueFromAET, &FileDir_);
rem PS does not attach all extension types under view log trace. extension *.err being one of them. Hence using *.log;
&ErrSub_ = "AE_AENAME_" | &YourPIValuefromAET | ".log";
/* Determine the file path separator character. First check for backslash then forwardslash. */
&iTempPos = Find("\", &FileDir_);
If &iTempPos = 0 Then
&iTempPos = Find("/", &FileDir_);
&strSlash = "/";
Else
&strSlash = "\";
End-If;
&ErrFile_ = &FileDir_ | &strSlash | &ErrSub_;
/* redirect stderr */
&AEmsgLog_.redirect_stderr(&ErrFile_);
&AEmsgLog_.println_to_stderr("=============================================");
For debugging, we normally make use of either a (Global or Component) file object or the famous but dreaded messagebox(). The problem with file object approach is that file handling adds an additional overhead of checking or making sure that we have opened it in the write mode and using the right charset.
Another approach most commonly used be developers is by adding numerous messageboxes to the PeopleCode, but most of them are unaware of the inherent danger, as in most of the PeopleTools versions, messagebox() fires and implicit COMMIT. This can create havoc if you have a restart enabled AE.
(Credits to the Original Uploader) Jim Marion - http://jjmpsj.blogspot.com/2008/05/appengine-output-tricks-reporting.html
came up with a wonderful solution of using the preloaded JVM on the Batch or App Server to serve as logging alternative. Please go through the above link for a detailed explanation.
The only modifications that I did to that piece of code was to paste in an Application Package and use that in all custom built Application Engines. This approach has loads of advantages on the ones discussed above (File Object or messagebox)
--The actual Application Package PeopleCode
class AE_BATCH_LOG
method AE_BATCH_LOG();
method println_to_stdout(&message As string);
method println_to_stderr(&message As string);
rem This method may be used at the discretion of the User;
method redirect_stdout(&fileName As string);
rem Use the Redirect for stderr as PS by default creates an stdout for each process;
method redirect_stderr(&fileName As string);
end-class;
/*
* The Constructor takes no arguments
*/
method AE_BATCH_LOG
end-method;
/**
* The println_to_stdout method is used to Print a line of text to Stdout.
*
* @param &message - Text to be written to Stdout.
*/
method println_to_stdout
/+ &message as String +/
try
Local string &sMethodName = "AE_BATCH_LOG:println_to_stdout";
Local JavaObject &jSystem = GetJavaClass("java.lang.System");
Local JavaObject &jOutStream = &jSystem.out;
Local JavaObject &jCls = GetJavaClass("java.lang.Class");
Local JavaObject &jStringClass = &jCls.forName("java.lang.String");
Local JavaObject &jPrintStreamCls = &jOutStream.getClass();
Local JavaObject &jPrintlnArgTypes = CreateJavaObject("java.lang.Class[]", &jStringClass);
Local JavaObject &jPrintlnMethod = &jPrintStreamCls.getDeclaredMethod("println", &jPrintlnArgTypes);
&jPrintlnMethod.invoke(&jOutStream, CreateJavaObject("java.lang.Object[]", &message));
rem ** I didn't find flushing necessary, but here is where you would flush the buffer if desired;
rem &jOutStream.flush();
catch Exception &ex
&ex.Output();
Error (MsgGetText(18130, 15001, "Unhandled exception occurred in %1.", &sMethodName));
end-try;
end-method;
/**
* The println_to_stderr method is used to Print a line of text to Stderr.
* This method should be used with a combination of redirect_stderr as PS
* maintains a single Stderr file for all processes.
* @param &message - Text to be written to Stdout.
*/
method println_to_stderr
/+ &message as String +/
try
Local string &sMethodName = "AE_BATCH_LOG:println_to_stderr";
Local JavaObject &jSystem = GetJavaClass("java.lang.System");
Local JavaObject &jOutStream = &jSystem.err;
Local JavaObject &jCls = GetJavaClass("java.lang.Class");
Local JavaObject &jStringClass = &jCls.forName("java.lang.String");
Local JavaObject &jPrintStreamCls = &jOutStream.getClass();
Local JavaObject &jPrintlnArgTypes = CreateJavaObject("java.lang.Class[]", &jStringClass);
Local JavaObject &jPrintlnMethod = &jPrintStreamCls.getDeclaredMethod("println", &jPrintlnArgTypes);
&jPrintlnMethod.invoke(&jOutStream, CreateJavaObject("java.lang.Object[]", &message));
rem ** I didn't find flushing necessary, but here is where you would flush the buffer if desired;
rem &jOutStream.flush();
catch Exception &ex
&ex.Output();
Error (MsgGetText(18130, 15001, "Unhandled exception occurred in %1.", &sMethodName));
end-try;
end-method;
/**
* The redirect_stdout method is used to redirect a line of text to a Custom file (Not a PS File Object) for general message logs.
* Use the this method prior to calling the println_to_stdout method.
*
* @param &fileName - File name of Redirected File.
*/
method redirect_stdout
/+ &fileName as String +/
try
Local string &sMethodName = "AE_BATCH_LOG:redirect_stdout";
Local JavaObject &jSystem = GetJavaClass("java.lang.System");
Local JavaObject &jfos_out = CreateJavaObject("java.io.FileOutputStream", &fileName, True);
Local JavaObject &jps_out = CreateJavaObject("java.io.PrintStream", &jfos_out, True);
&jSystem.setOut(&jps_out);
catch Exception &ex
&ex.Output();
Error (MsgGetText(18130, 15001, "Unhandled exception occurred in %1.", &sMethodName));
end-try;
end-method;
/**
* The redirect_stderr method is used to redirect a line of text to a Custom file (Not a PS File Object) for error logging.
* Use the this method prior to calling the println_to_stderr method.
*
* @param &fileName - File name of Redirected File.
*/
method redirect_stderr
/+ &fileName as String +/
try
Local string &sMethodName = "AE_BATCH_LOG:redirect_stderr";
Local JavaObject &jSystem = GetJavaClass("java.lang.System");
Local JavaObject &jfos_out = CreateJavaObject("java.io.FileOutputStream", &fileName, True);
Local JavaObject &jps_out = CreateJavaObject("java.io.PrintStream", &jfos_out, True);
&jSystem.setErr(&jps_out);
catch Exception &ex
&ex.Output();
Error (MsgGetText(18130, 15001, "Unhandled exception occurred in %1.", &sMethodName));
end-try;
end-method;
-----------------------------------
To use the logging feature all you need to do is to include the below lines in any PeopleCode action of yours in your Application Engine
-----------------------------------
import AE_BATCH_LOG:*;
/* Create Class Object for Logging */
Local AE_BATCH_LOG:AE_BATCH_LOG &AEmsgLog_
/* PeopleSoft prefers the Singleton apporach */
If None(&AEmsgLog_) Then
&AEmsgLog_ = create AE_BATCH_LOG:AE_BATCH_LOG();
------------------------------------
Once you have the class object, we need to redirect the stdout and stderr files. Its a good practice to redirect stdout, but you need to redirect the stderr always as the stderr is shared across processes.
------------------------------------
/* Create the error file in the following path */
rem Better to retrieve the path in an SQL action and store it in AET;
SQLExec("SELECT PRCSOUTPUTDIR FROM PSPRCSPARMS WHERE PRCSINSTANCE = :1", &YourPIValueFromAET, &FileDir_);
rem PS does not attach all extension types under view log trace. extension *.err being one of them. Hence using *.log;
&ErrSub_ = "AE_AENAME_" | &YourPIValuefromAET | ".log";
/* Determine the file path separator character. First check for backslash then forwardslash. */
&iTempPos = Find("\", &FileDir_);
If &iTempPos = 0 Then
&iTempPos = Find("/", &FileDir_);
&strSlash = "/";
Else
&strSlash = "\";
End-If;
&ErrFile_ = &FileDir_ | &strSlash | &ErrSub_;
/* redirect stderr */
&AEmsgLog_.redirect_stderr(&ErrFile_);
&AEmsgLog_.println_to_stderr("=============================================");
Comments
Post a Comment