Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Calling Perl with arguments From Java

by rgwest61 (Initiate)
on May 18, 2016 at 17:52 UTC ( [id://1163360]=perlquestion: print w/replies, xml ) Need Help??

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

I have written a Java application that allows a database admin user the ability to provide a unique application ID, and associated driver, url, username, and password for the corresponding java application to connect to a oracle database. Such attributes are stored encrypted in a configuration file for security reasons. A java application retrieves the associated unencrypted connection attributes based on its unique application id. The indicated Java application works great for java Oracle related connection attributes. I have been tasked to provide the same functionality to provide Perl database connection attributes like driver dbi:driver:; url (in my case) //misrac/codb and allow a Perl application to retrieve its unencrypted attributes to connect to an Oracle database. I have written a Java Database Utility Class that handles all required Oracle database actions such as: database connection, create new account, etc. The problem is this class works for a Java Oracle database connection with provided java Oracle connection attributes. I want to write the Perl equivalent of this Java Database Utility Class such that I can call the appropriate subroutines passing the required connection arguments (Perl driver, Perl URL, username, password and in same cases other arguments) from the Java application. Issues are: 1) I do not understand from other/earlier posts how to call Perl subroutines from Java, and 2) how to provide/pass the required arguments to such Perl subroutines. As always thanks for your time and assistance.

Replies are listed 'Best First'.
Re: Calling Perl with arguments From Java
by haukex (Archbishop) on May 18, 2016 at 18:22 UTC

    Hi rgwest61,

    I'm not sure I fully understand your description. So you want to write a Perl-only version of a Java tool you have? (In that case, DBD::Oracle is probably helpful.) And you then want to call this Perl tool from Java?

    I believe the standard method for running an external process from Java is java.lang.ProcessBuilder.

    Earlier you wrote about Inline::Java, so if that's what you're talking about, then perhaps Inline::Java::Callback is what you're looking for (calling Perl from Java code within Inline::Java).

    Hope this helps,
    -- Hauke D

      Hauke D I have tried the following two ways of calling a simple Perl script that currently just prints out the fact that it has been reached from a Java Application. Both attempts were found from an internet search and have not been successful - the expected output is not observed in the Linux window that starts the Java application. Just a little background - the Java code and simple Perl script were developed using the Eclipse IDE and the Perl script resides within one of the previously existing Java packages (Utils)

      // First Method List<String> cmds = new ArrayList<String>(); cmds.add("perl"); cmds.add("/home/rwest/workspace/src/AppMaint/Utils/PerlUtil.pl"); ProcessBuilder pb = new ProcessBuilder(cmds); pb.start(); // Second method Process p = RunTime.getRuntime().exec("perl /home/rwest/workspace/src/ +AppMaint/Utils/PerlUtil.pl"); p.waitFor();

      Other things I have done in an attempt to get either method to work: 1) Changed the group (chgrp) and access rights (chmod) so that the Perl script exists in the same group as the Java application and has read and execute permission. 2)Added /home/rwest/workspace/src/AppMaint/Utils/PerlUtil.pl to the Eclipse manifest file classpath line. 3) Executed the Perl script from Eclipse IDE with success. 4) Stepped through Eclipse debugger to make sure the applicable Java application lines of code to execute the Perl script are executed.

        Hi rgwest61,

        the expected output is not observed in the Linux window that starts the Java application

        That's normal; I suggest you study the documentation of ProcessBuilder:

        By default, the subprocess writes standard output and standard error to pipes.

        You'll either have to read these pipes yourself, which is the normal approach if your Perl script is generating output that your Java process is interested in, or you can have them inherit the Java process's streams by calling the methods such as pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); for each stream you want to inherit, or simply pb.inheritIO(); to inherit all three stdin/out/err streams. You should also inspect the Process's exitValue() to see if it's zero (normal exit) or not.

        Hope this helps,
        -- Hauke D

Re: Calling Perl with arguments From Java
by afoken (Chancellor) on May 19, 2016 at 06:32 UTC
    I want to write the Perl equivalent of this Java Database Utility Class such that I can call the appropriate subroutines passing the required connection arguments (Perl driver, Perl URL, username, password and in same cases other arguments) from the Java application. Issues are: 1) I do not understand from other/earlier posts how to call Perl subroutines from Java, and 2) how to provide/pass the required arguments to such Perl subroutines. As always thanks for your time and assistance.

    So you want to start a Perl script from Java.

    I guess you know how to start any executable with a list of parameters from Java, or at least you should know how to get that information.

    Depending on your platform (Win32 / Unix), you may need to call the Perl interpreter with the name of the perl script (Win32), or you can directly call the perl script (Unix). Calling the Perl interpreter with the name of the perl script also works on Unix.

    You can pass a lot of arguments to the script, Linux allows something like 4 kBytes, ancient DOS would allow only 126 Bytes, Windows should be somewhere in between, maybe even more that 4 kBytes.

    Perl has Getopt::Long to parse that arguments into variables.

    So, using all of these parts, you end with Java doing the equivalent of

    /usr/bin/perl yourscript.pl --datasource=dbi:Pg:dbname=MyDatabase --db +user=Me --dbpass=T0pS3cr3t --action=frobnicate --frobnicate-foo=42 -- +frobnicate-bar=lalala

    In yourscript.pl, you would call a Getopt::Long function (RTFM) to parse the arguments, create a DBI connection using the datasource, dbuser, dbpass arguments, then look at the action parameter, and call a function for the given argument (using if-then-else, switch-case, or a hash mapping actions to function references).

    You can also use the action as first argument to the script, then call a function that calls Getopt to parse the remaining arguments depending on the current action. Your command line would look like this:

    /usr/bin/perl yourscript.pl frobnicate --datasource=dbi:Pg:dbname=MyDa +tabase --dbuser=Me --dbpass=T0pS3cr3t --frobnicate-foo=42 --frobnicat +e-bar=lalala

    In yourscript.pl, you would start with my $action=shift @ARGV;, then decide which funtion to call, depending on $action. In the called function, you would call Getopt.

    More options: You can pass data from Java to Perl using STDIN or files written by Java. You can pass data from Perl to Java using STDOUT or files written by Perl.

    Both Java and Perl can easily use JSON to transfer structured data, so you may want to use JSON for communication using files, STDIN, STOUT.

    Update: Passing passwords on the command line is not the best idea, as any user can use tools like ps to read the command line arguments of any running program. So you may want to pass at least the password via STDIN to perl, and - if required - use a separate file instead of STDIN to pass large amounts of data from Java to Perl.

    Update: You could also omit all command line parameters and pass the entire "job" as JSON via STDIN: action, action parameters, database connection information. Action parameters can be an arbitary large data block, structured or not, both is possible with JSON.

    Update: To avoid encoding trouble, you may want to make sure that the generated JSON uses only ASCII characters, i.e. all non-ASCII characters are expressed using escape sequences. JSON::XS offers the ascii() method for that. I assume that one of the Java encoders has a similar feature.


    I've explained a different approach in Re: Dazed/Confused from previous posts on how to call Java method from Perl.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: Calling Perl with arguments From Java
by afoken (Chancellor) on May 19, 2016 at 06:13 UTC

      Alexander, actually this post is the opposite of my post titled Dazed/Confused from previous posts.... I am trying to call Perl Script with parameters from Java and receive a return value/response versus calling a Java class from Perl and receiving a return value/response. I figured out how to call the Java class from Perl using a Perl handle and the Java code performing System.out.println() calls.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1163360]
Approved by Marshall
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (5)
As of 2024-04-25 13:07 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found