0

We got a requirement to call a static method inside a Java class via perl script and capture the return value of the method as we have to remove the syso statements in the Java code.

Sample Java class

public class SampleClass
{
   public static void main (String [] args) throws Exception   
   {
       var_1 = func(arg1,arg2);       
       System.out.print(var_1);
    }
    private static String func(final String arg1, final String arg2)
    throws Exception
    { 

        <--- code -->

        return value;
     }

     public static String SampleMethod(final String arg1, final String arg2)
     throws Exception
     {     
         var_2 = func(arg1,arg2);
         return var_2;
     }
}

Intially in perl we are calling the actual class like below

command = SampleClass Arg_1  Arg 2 
`$command`

Now the requirement is to call the SampleMethod and capture the return value to avoid reading the o/p from console.

Tried the below

command = SampleClass.SampleMethod Arg_1  Arg 2 
`$command`

But it failed saying unable to load main class in SampleMethod

Please advise.

Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • 2
    *"in perl we are calling the actual class like below: command = SampleClass Arg_1 Arg 2 "* : This is not valid Perl syntax. Please clarify – Håkon Hægland Aug 10 '21 at 21:13
  • 2
    *"We got a requirement to call a static method inside a Java class via perl script.."* : Please show the Perl script you use. – Håkon Hægland Aug 10 '21 at 21:16
  • 1
    See also [Calling a static jar class method from command line](https://stackoverflow.com/q/25061695/2173773) – Håkon Hægland Aug 10 '21 at 21:26
  • 1
    I think you need to wrap the static method inside another class with a static main() that calls the original static method. See [this](https://stackoverflow.com/a/58168922/2173773) answer – Håkon Hægland Aug 10 '21 at 21:31
  • 1
    [Inline::Java](https://metacpan.org/pod/Inline::Java) – ikegami Aug 11 '21 at 03:30

1 Answers1

2

You cannot call other static methods than main() in a Java class from Perl. A workaround is to wrap the static method inside another class with a static main() that calls the original static method, see also this answer. For example:

SampleClass.java:

public class SampleClass
{
    public static void main(String [] args) throws Exception
    {
       String result = SampleMethod("string1", "string2");
       System.out.println("Result: " + result);
    }

    public static String SampleMethod(final String arg1, final String arg2)
        throws Exception
     {
         return arg1 + " " + arg2;
     }
}

p.pl:

use feature qw(say);
use strict;
use warnings;

my $wrap_name = 'Wrapper';
my $source = <<"END_JAVA";
class $wrap_name {
    public static void main(String[] args) throws Exception {
        String result = SampleClass.SampleMethod("string1", "string2");
        System.out.print("Result: " + result);
    }
}
END_JAVA

my $fn = $wrap_name . '.java';
open ( my $fh, '>', $fn ) or die "Could not open file '$fn': $!";
print $fh $source;
close $fh;
system 'javac', $fn;
my $output = `java ${wrap_name}`;
say "Got output: '$output'";

You can then run:

$ javac SampleClass.java
$ perl p.pl
Got output: 'Result: string1 string2'
Håkon Hægland
  • 39,012
  • 21
  • 81
  • 174
  • Thanks for the reply, In the similar way can we call static SampleMethod which is outside main method in SampleClass.java which calls "func" as the requirement is to remove the Syso statements in main method. – Shyam Koyyana Aug 11 '21 at 21:17
  • I am not sure what you mean. The current script is calling `SampleMethod()` in `SampleClass`. Please clarify – Håkon Hægland Aug 11 '21 at 21:19
  • my SampleClass.java is like public class SampleClass { public static void main (String [] args) throws Exception { var_1 = func(arg1,arg2); System.out.print(var_1); } private static String func(final String arg1, final String arg2) throws Exception { <--- code --> return value; } public static String SampleMethod(final String arg1, final String arg2) throws Exception { var_2 = func(arg1,arg2); return var_2; } } – Shyam Koyyana Aug 11 '21 at 21:38
  • Can I also be able to call SampleMethod through wrapper though it is not in main method ? – Shyam Koyyana Aug 11 '21 at 21:41
  • Yes the wrapper is calling `SampleMethod()`. See line #9 in the perl script above – Håkon Hægland Aug 11 '21 at 21:43
  • I have applied the changes but found SampleClass is in jar file so I m getting Unable to load SampleClass error. Tried using Java::Import but getting Can't locate java.pm in @INC errror. Please advise. – Shyam Koyyana Aug 12 '21 at 11:30
  • *"Can't locate java.pm in @INC errror."* Can you upload the perl script you used somewhere? Then I will have a look at it. Alternatively you can send it to me by email. – Håkon Hægland Aug 12 '21 at 11:53
  • Can we import the jar which has SampleClass.java to the program snippet suggested ? – Shyam Koyyana Aug 12 '21 at 11:58
  • *"but found SampleClass is in jar file.. "* What is the name of the jar file? Is it loacted in the same directory as the perl script? – Håkon Hægland Aug 12 '21 at 11:58
  • *"Can we import the jar which has SampleClass.java to the program snippet suggested?"* : Yes, please provide information about the name of the .jar file, its location relative to the perl script, and which package `SampleClass` belongs to – Håkon Hægland Aug 12 '21 at 12:21
  • Perl script Location : /opt/apps/batch/scripts/perl/ Jar location : /opt/apps/batch/utilities/Utilities.jar Package : com.utilties.SampleClass Perl Version : v5.16.3 – Shyam Koyyana Aug 12 '21 at 14:08
  • Thanks, can you try this Perl script: https://pastebin.com/YfTSyzE9 – Håkon Hægland Aug 12 '21 at 14:12
  • Hi , one qq in the line 21 is it $fn or ${wrap_name} and after trying both i am getting com.utilties does not exist error. – Shyam Koyyana Aug 12 '21 at 16:04
  • *"i am getting com.utilties does not exist error"* Try adding a `-cp` option to `java` also, see line 21 in the updated version: https://pastebin.com/YfTSyzE9 – Håkon Hægland Aug 12 '21 at 16:10
  • Hi , I have replaced import with package in line 7 and now i am seeing "Could not find or load main class wrapper" error. Please advise. – Shyam Koyyana Aug 12 '21 at 16:11
  • *"I have replaced import with package in line 7"* Can you first try the change in my previous comment? – Håkon Hægland Aug 12 '21 at 16:13
  • "Could not find or load main class Wrapper" this is error after replacing. – Shyam Koyyana Aug 12 '21 at 16:20
  • *"Could not find or load main class Wrapper*" : Did it compile the Wrapper.java file at line 20? Is there a file Wrapper.class in the current directory ? – Håkon Hægland Aug 12 '21 at 16:23
  • yes , I can see Wrapper.class in the directory where i executed the script. – Shyam Koyyana Aug 12 '21 at 16:30
  • Ok..Maybe we should first try delete it in case it was an earlier version. Then run the perl script and see if it generates a new one or not – Håkon Hægland Aug 12 '21 at 16:32
  • Yeah i ran again , it created wrapper.class and wrapper.java but getting same error. – Shyam Koyyana Aug 12 '21 at 16:54
  • Good. Can you run the command on line 21 manually? Try run `java -cp .:/opt/apps/batch/utilities/Utilities.jar Wrapper` from the terminal window – Håkon Hægland Aug 12 '21 at 16:55
  • Manual check is also giving the same error. Executed manually by removing the Wrapper* in the path. – Shyam Koyyana Aug 12 '21 at 19:38
  • When you execute manually you should not remove `Wrapper.class`. Please try again – Håkon Hægland Aug 12 '21 at 19:42
  • Tried that too .. but still getting same error. – Shyam Koyyana Aug 12 '21 at 19:47
  • What is the content of the current directory? Type `ls` for example. There should be a file there called `Wrapper.class` ? – Håkon Hægland Aug 12 '21 at 20:00
  • Yeah it's there which got generated while running the perl script after that i ran the command manually and Wrapper.class is there . – Shyam Koyyana Aug 12 '21 at 20:05
  • Do we need to use import statement or package statement in the $source file. – Shyam Koyyana Aug 12 '21 at 20:05
  • yes there is an `import com.utilties;` statement at line 7, see https://pastebin.com/YfTSyzE9 – Håkon Hægland Aug 12 '21 at 20:07
  • Can you try run java without the `-cp` option: Try run just `java Wrapper`. It should give you an import error – Håkon Hægland Aug 12 '21 at 20:07
  • I have removed the older Wrapper.class and Wrapper.java and ran java Wrapper by removing the -cp option . This time got the compilation error package com.utilties does not exist. – Shyam Koyyana Aug 12 '21 at 20:17
  • Good, and if you add the `-cp` option what error do you then get? This command: `java -cp .:/opt/apps/batch/utilities/Utilities.jar Wrapper` – Håkon Hægland Aug 12 '21 at 20:18
  • Using import statement in line 7 is giving package com.utilties does not exist with both java Wrapper and java -cp. If i replace import keyword with package in line 7 then it is getting compiled and saying "Could not find or load Wrapper" – Shyam Koyyana Aug 12 '21 at 20:28
  • So it cannot find `com.utilties` package inside `Utilities.jar` ? Maybe you need to import the class instead of the package? See [this](https://stackoverflow.com/a/460375/2173773) answer. Can you try replace `import com.utilties` with `import com.utilties.SampleClass;` ? – Håkon Hægland Aug 12 '21 at 20:33
  • See my updated source: https://pastebin.com/YfTSyzE9 – Håkon Hægland Aug 12 '21 at 20:34
  • 1
    It Worked this time. Thank you very much for all the support provided. – Shyam Koyyana Aug 12 '21 at 22:09