abramia has asked for the wisdom of the Perl Monks concerning the following question:

Greetings all, I want to execute perl code from within a java application. For example I pass the following command to my java application:

perl somescript.pl args...

This works fine and I am able to capture the script's output in my java code. However if I use the "-e" command-line option, the perl program is successfully executed but my java program shows that no output is produced. For example:

perl -e "print \"Hello World\""

My guess is that the perl interpreter works differently with the "-e" option than it does when reading and executing a perl script. I would like someone to tell me how to run a perl program using the "-e" option and capture its output in my java code. I am running perl 5.8.6 for MSwin32-x86-multi-thread on Microsoft Windows 2000 Version 5.00.2195 and Sun Microsystems java version 1.6.0_21

Thanks, Avi.

Replies are listed 'Best First'.
Re: Running perl from java
by ELISHEVA (Prior) on Jan 06, 2011 at 08:11 UTC

    You haven't stated how you are running this command, but I'll presume you are running the command via one of the Runtime class methods, most likely exec(String).

    exec(String) will parse your single string using StringTokenizer, which simply splits on whitespace. perl somescript.pl args worked because in this particular case splitting on whitespace does the right thing.

    However with your second command, perl -e "print \"Hello World\"", what Perl is getting is not the Perl code print "Hello World", but rather a Perl string containing "print \"Hello World\"". No print command is ever called. Hence nothing is sent to STDOUT.

    If you want to pass a Perl snippet, you need instead to use the exec(String[] args) or exec(String[] args, String[] envp) version of exec. Both of these let you pass the individual arguments without making Java guess at how you want to break up a long line into arguments. It would look something like this.

    (Note: the code in the readmore tags was too hastily posted and a corrected, more reliable, and tested version is in my reply below. The original code is preserved here so that abramia's initial reply makes sense.)

    Update: placed code in readme tags, added disclaimer.

      Elisheva,

      Your code snippet is precisely how I am doing it.

      Except for the call to "getOutputStream()" because, according to the javadoc for class Process, method "getInputStream()" obtains data piped from the standard output stream of the process.

      Did you try it out yourself?

      Did it work for you?

      Cheers, Avi.

        The javadoc is right of course and my too quickly typed code is wrong on that point - input vs. output (another item on the list of things I often confuse). However, I promise you, if you've done it right, passing code snippets does work.

        You are using exec(String[]), the one with the array? I'm not at all sure why you are having problems. Are you flushing the output stream before you exit? Throwing away and silencing exceptions? Waiting for the process to finish before querying the output stream? As you know sometimes these problems are in the details or in a small type - an extra quote, a space in the wrong place that the eye doesn't see. Guessing why you are having problems with something that should work is hard without seeing the code.

        Here is a working example of code, that did indeed execute a Perl snippet via the -e option. This was run on Debian Linux (Etch), Perl 5.8.8.

        import java.io.InputStream; import java.io.InputStreamReader; import java.io.BufferedReader; import java.io.IOException; class RunPerl { public static void main(String[] args) throws IOException { String[] aCmdArgs = { "perl", "-e" , "print \"Hello World, Hello Avi\"" }; Runtime oRuntime = Runtime.getRuntime(); Process oProcess = null; try { oProcess = oRuntime.exec(aCmdArgs); oProcess.waitFor(); } catch (Exception e) { System.out.println("error executing " + aCmdArgs[0]); } /* dump output stream */ BufferedReader is = new BufferedReader ( new InputStreamReader(oProcess.getInputStream())); String sLine; while ((sLine = is.readLine()) != null) { System.out.println(sLine); } System.out.flush(); /* print final result of process */ System.err.println("Exit status=" + oProcess.exitValue()); return; } }

        Update: added demo platform.

        Your code snippet is precisely how I am doing it.

        Well then, what is the error message?

Re: Running perl from java
by Marshall (Canon) on Jan 06, 2011 at 07:22 UTC
    The kind of "quotes" that are needed for various shells vary.

    I personally stay away from this "perl -e" syntax for a couple of reasons:
    1)if the program that the -e does is "significant", I want to give it a name, make it a "real Perl" file and put it my personal library and maybe even alias it in my shell.
    2) The resulting program file is executable on multi-platforms (I work on Linux and MS Windows).

    So maybe my question sounds dumb, but why do you want to do that? I haven't found a good reason yet.

    I am sure that we will hear how to make it work, and I also would find it interesting. In general this shell syntax problem also boggles my mind and is platform specific. I just avoid it by making a Perl executable file.

    You are correct in that perl -e "print \"Hello World\"" works from the Windows command line. But a file with: print "Hello World"; works also and is a lot more clear.

      Hi Marshall, Yes, I have committed the cardinal sin of asking: "how do I implement my solution" and not: "how do I solve my problem".

      So here is my problem:

      I have a Web application that uses JSF (JavaServer Faces). The Web application needs to display data that is located in a "ClearQuest" database. My version of ClearQuest supports only a perl API, hence the requirement to execute perl from java.

      Because it's a Web application, I would like to have all the application files bundled in the one WAR file.

      So my problem is how to display the data, obtained from "ClearQuest" using perl, in a Web application?

      Cheers, Avi.

        Because it's a Web application, I would like to have all the application files bundled in the one WAR file.

        Options:

        • Place the perl script inside the WAR file, unpack it on demand, pass the filename of the unpacked script to the perl interpreter.
        • Store the perl script as a string constant inside the Java code, write that string constant into a temp file, pass the filename of the temp file to the perl interpreter.
        • Like before, but use a pipe instead of writing to a physical file, and make the perl interpreter read either stdin or some special file representing perl's end of the pipe (e.g. /dev/fd/4).

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Running perl from java
by Anonymous Monk on Jan 06, 2011 at 07:38 UTC
    You need to read up carefully on the java equivalents of system/exec

    What is happening, is you think you're invoking the shell, when you're probably not (or its a different shell, with different quoting rules)

    $ perl -V:sh sh='cmd /x /c'; $ perl -e die(1) 1 at -e line 1. $ perl -e " die(1) " 1 at -e line 1. $ perl -e ' die(1) ' Can't find string terminator "'" anywhere before EOF at -e line 1. $ perl -MO=Deparse,-p -e 'die(1)' '???'; -e syntax OK $ perl -MO=Deparse,-p -e "die(1)" die(1); -e syntax OK $ perl -MO=Deparse,-p -e " system qw! perl -e warn(@ARGV) a r g v !" system('perl', '-e', 'warn(@ARGV)', 'a', 'r', 'g', 'v'); -e syntax OK $ perl -e " system qw! perl -e warn(@ARGV) a r g v !" argv at -e line 1.
    Also, you should have gotten error messages when you were error checking :)
      Anonymous Monk,

      Thank you for your reply, which was helpful to me.

      Nonetheless I would be grateful for a clarification. (And please pardon my ignorance.)

      How do I perform this "error checking" you mention?

      Thank you, Avi.
        How do I perform this "error checking" you mention?

        In java they call them exceptions -- you shouldn't ignore them

Re: Running perl from java
by JavaFan (Canon) on Jan 06, 2011 at 15:54 UTC
    I suggest going to a Python forum, ask how to call Python from a Java program, and in their answer, replace "python" with "perl".

    You run the chance the Python people tell you to ask the question in a Ruby forum, and then to replace "ruby" by "python" in the answer you got.

    Now, the good people at the Ruby forum will probably suggest you ask the question in a Dylan forum, ....

    Or you could just go to a Java forum, and ask how to call external programs.

    A reply falls below the community's threshold of quality. You may see it by logging in.