1 2 Previous Next 17 Replies Latest reply on Jul 31, 2009 4:35 PM by Jim.Marion-Oracle

    AE with java

    Axoliien
      Our shop has a lot of apps written in java and ruby, and I'm trying to integrate with these apps to perform standard operations without rewriting a ton of code. One problem I have with java is that stdout or console does not show up from our PS environments. I have tried using java object method calls or using log4j as found in Jim's blog. I just can't get anything that the java application outputs to stdout or to console to show up in the view log / trace. Any suggestions?
        • 1. Re: AE with java
          Jim.Marion-Oracle
          @Axoliien,

          This is Jim, the author of those posts. I'm glad you found them. I am sorry they aren't as useful as they should be. If I understand correctly, you are calling Java from an AppEngine and would like to see output in stdout, but you aren't. Can you post an example AE PeopleCode step that should write to stdout? Make it simple please, just a "Hello World" example would be fine.

          If you already have Java classes that use System.out.println and you call those Java classes from AE, the output should go in the AE's stdout file.

          Are you getting a stdout file in View log/trace but it doesn't have the print statements, or you don't even get a stdout file?

          For log4j, are you using log4j.xml or PeopleCode to configure your loggers? The first PeopleCode snippet in this post should print to stdout: [http://jjmpsj.blogspot.com/2006/11/log4j-and-peoplecode-part-ii.html|http://jjmpsj.blogspot.com/2006/11/log4j-and-peoplecode-part-ii.html].

          Let me know what you find.
          • 2. Re: AE with java
            Axoliien
            Thanks for your reply! After trying to get a simple java hello world app to write from AE, I just used your snippet from your blog that performs the configuration within PC. I had also tried using the XML file, or the delivered properties file but to no avail. I do get a stdout file, but the print statements don't show up - just the stdout you would get if you ran an empty AE.

            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.");
            • 3. Re: AE with java
              Jim.Marion-Oracle
              So, just to confirm, the PeopleCode snippet with logger configuration in PeopleCode printed output to stdout, correct? But when you use log4j.xml, you don't get output, correct?

              I've seen this before. log4j uses a static block in one of the classes to load log4j.xml from the class path. Make sure you have your log4j.xml file in your classpath and restart your app server. A PeopleCode trace on an AppEngine will print your classpath when the first Java object is created, so that is helpful. Normally you put the log4j.xml in your $PS_HOME/class directory. I believe log4j searches for log4j.xml prior to log4j.properties. If your PT install has a log4j.properties, then you will need to merge the two files or the log4j.properties won't be used. I haven't worked with the log4j classpath issue for a few years, so these are just some notes I'm digging out of my memory, but hopefully it helps.
              • 4. Re: AE with java
                Axoliien
                Sorry, I was totally unclear! Neither one outputs anything to the stdout. For the simplest test, let me show what I received with the code snippet.

                [AE code]
                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.");

                [AE stdout]
                PSAESRV started service request at 11.39.39 2009-07-30

                Application Engine program LX_JAVA_TEST ended normally

                PSAESRV completed service request at 11.39.39 2009-07-30
                • 5. Re: AE with java
                  Jim.Marion-Oracle
                  Oh wow! I have no idea. I have never seen that before. I have seen where I've redirected stdout using Java and then any Java executed thereafter sends stdout to a different file (has no affect on the PeopleSoft C++ AE code, just the Java executed within it).

                  I hate to send you on a wild goose chase, but try this: Go here: [http://jjmpsj.blogspot.com/2008/05/appengine-output-tricks-reporting.html|http://jjmpsj.blogspot.com/2008/05/appengine-output-tricks-reporting.html] and use the redirect_stdout function to redirect stdout to a different file. This will only affect the JVM output. It won't impact the PS AE output. Then execute the log4j PC from the previous post as well as the println_to_stdout function. if you can get it to print into /tmp/ae_output.txt or c:\temp\output.txt, then you can later replace the hard coded path with SQL that selects the process output directory (same blog post). In fact, perhaps a stdout and a java-stdout isn't such a bad idea?

                  By the way, did you try running your AE's through app designer or just online?
                  • 6. Re: AE with java
                    Axoliien
                    Good call on trying it from AppDesigner directly on the server - I received the following when I run the AE from AppDesigner and create an output log:

                    log4j:ERROR setFile(null,true) call failed.
                    java.io.FileNotFoundException: .\LOGS\PSJChart.log (The system cannot find the path specified)
                         at java.io.FileOutputStream.openAppend(Native Method)
                         at java.io.FileOutputStream.<init>(Unknown Source)
                         at java.io.FileOutputStream.<init>(Unknown Source)
                         at org.apache.log4j.FileAppender.setFile(FileAppender.java:272)
                         at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:151)
                         at org.apache.log4j.DailyRollingFileAppender.activateOptions(DailyRollingFileAppender.java:206)
                         at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:247)
                         at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:123)
                         at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:87)
                         at org.apache.log4j.PropertyConfigurator.parseAppender(PropertyConfigurator.java:645)
                         at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:603)
                         at org.apache.log4j.PropertyConfigurator.parseCatsAndRenderers(PropertyConfigurator.java:524)
                         at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:408)
                         at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:432)
                         at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:460)
                         at org.apache.log4j.LogManager.<clinit>(LogManager.java:113)
                         at org.apache.log4j.Logger.getLogger(Logger.java:85)
                    log4j:ERROR Either File or DatePattern options are not set for appender [A1].

                    I remember seeing these in the delivered log4j properties file, but I didn't want to change it since it was delivered. This had a heading marking it as Oracle confidential but I am guessing I can post the delivered properties file here?

                    Delivered log4j.properties file in class directory:
                    # Set root logger priority to INFO and its only appender to A1.
                    ##log4j.rootLogger=WARN, A1

                    # A1 is set to be a ConsoleAppender which outputs to System.out.
                    log4j.appender.A1=org.apache.log4j.DailyRollingFileAppender
                    log4j.appender.A1.File=./LOGS/PSJChart.log

                    # A1 uses PatternLayout.
                    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
                    log4j.appender.A1.DatePattern=.yyyy-MM-dd
                    log4j.appender.A1.layout.ConversionPattern=%d{DATE} [%t] %-5p %c %x - %m%n

                    log4j.category.com.peoplesoft.pt.charting=WARN, A1
                    • 7. Re: AE with java
                      Jim.Marion-Oracle
                      Oh, yes, I get that all the time when running locally. I just ignore it. One thing it does show, though is that your log4j.xml is NOT getting picked up in the class path. The good news is that the error you see is from Java and is written to the AE's stdout (log fie). That is data written to stdout or stderr (can't remember which).

                      Hmmm... there is an idea. What happens when you change the examples to use stderr?
                      • 8. Re: AE with java
                        Axoliien
                        I added your functions and tried with an AE defined as follows:

                        redirect_stdout("C:\temp\stdout.txt");
                        redirect_stderr("C:\temp\stderr.txt");

                        println_to_stdout("println_to_stdout begin");
                        println_to_stderr("println_to_stderr begin");

                        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").WARN);
                        &logger.warn("WARN Hello from a PeopleCode configured logger.");

                        println_to_stdout("println_to_stdout end");
                        println_to_stderr("println_to_stderr end");


                        When run from the PIA via the process scheduler, I receive the following:
                        PIA stdout
                        PSAESRV started service request at 15.27.13 2009-07-30

                        Application Engine program LX_JAVA_TEST ended normally

                        PSAESRV completed service request at 15.27.13 2009-07-30

                        file stdout.txt
                        println_to_stdout begin
                        94 2009-07-30 15:27:12,360 [Thread-0] WARN my.custom.logger [] - WARN Hello from a PeopleCode configured logger.
                        println_to_stdout end

                        file stderr.txt
                        println_to_stderr begin
                        println_to_stderr end


                        Now I just can't seem to figure out why the messages are showing up when stdout is redirected, but not when stdout is just left alone! This at least gives me an option of creating a separate output file within the current run directory... but my curiosity keeps me going...

                        Edited by: Axoliien on Jul 30, 2009 3:32 PM
                        • 9. Re: AE with java
                          Jim.Marion-Oracle
                          It looks like something is redirecting your stdout when the AE starts. I haven't experienced this before. I have no idea why.
                          • 10. Re: AE with java
                            Axoliien
                            That's what it seems like to me... I'll keep up the testing and hopefully find something. I guess my next step is to figure out why the xml file isn't being found although it's in the class directory, and the class directory is defined explicitly in the path. Would it hurt for me to define the full path including file name in this case and try that way?
                            • 11. Re: AE with java
                              Jim.Marion-Oracle
                              It won't hurt to explicitly include it. Besides that, there are a couple of things you can try. You can print the classpath or turn on PeopleCode tracing and look at the classpath in the trace file. Another thing you can do is Class.getResource to see if the class loader is able to find your log4j.xml. It has been a while since I've dug through the log4j source, but I thought there was a static initializer in there that loads log4j.properties or log4j.xml from the classpath. It tries one, and if it doesn't find it, then it tries the other. Perhaps it is trying log4j.properties first? If you look at the source, make sure you look at the right version. The version included with PeopleSoft is older than the latest on logging.apache.org.
                              • 12. Re: AE with java
                                Axoliien
                                Thanks, I'll take it from here for a bit and try your suggestions. I did have a bit of trouble understanding the initialization so I'll look into that first and move on from there. I'll keep the thread updated on what I find out.
                                • 13. Re: AE with java
                                  Jim.Marion-Oracle
                                  Thanks. You're doing a great job!
                                  • 14. Re: AE with java
                                    PSFT_PP
                                    Thanks!! to Jim,

                                    This is what I use

                                    class MY_BATCH_LOG
                                    method MY_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 MY_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 = "MY_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 = "MY_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 = "MY_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 = "MY_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;

                                    and to use this I use the following code. *** Always safe to redirect both stdout and stderr as PS does not support all extensions***

                                    import MY_BATCH_LOG:*;

                                    Local MY_BATCH_LOG:MY_BATCH_LOG &msgLog_ = create MY_BATCH_LOG:MY_BATCH_LOG();

                                    SQLExec("SELECT PRCSOUTPUTDIR FROM PSPRCSPARMS WHERE PRCSINSTANCE = :1", &PrcsInstance_, &FileDir_);
                                    &ANZErrSub_ = "AE_BAL_FTP_" | &PrcsInstance_ | ".txt";
                                    /* 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 stdout */
                                    &msgLog_.redirect_stdout(&ErrFile_);
                                    /* Generate Batch Log Report */
                                    &msgLog_.println_to_stdout("******************************************************************");
                                    &msgLog_.println_to_stdout("* *");
                                    &msgLog_.println_to_stdout("* PeopleSoft JAVA Logging *");
                                    &msgLog_.println_to_stdout("* Sample Report *");
                                    &msgLog_.println_to_stdout(" Generated On : " | %Datetime);
                                    &msgLog_.println_to_stdout("******************************************************************");

                                    and to use this any where in your AE just import the class and create an Object and use the methods...

                                    Hope this helps!!

                                    Thanks Jim!!

                                    Cheerz!!
                                    Prashant
                                    1 2 Previous Next