Search code examples
interopballerinaballerina-java-interop

How to invoke user defined non-static Java method from Ballerina


The example[1] shows how to invoke a Java method. But in my case I need to invoke my own method from my own class. Something like this

Hello.java

public class Hello {
    public String sayHello() {
        return "Hello . . .";
    }
}

hello_java.bal

import ballerina/io;
import ballerina/java;

function sayHelloJava() returns handle = @java:Method {
    name: "sayHello",
    class: "Hello"
} external;


public function main() {
    var txt = sayHelloJava();
    io:println(txt);
}

When I run, I am getting the following exception

Compiling source
        hello_java.bal
error: .::hello_java.bal:4:1: {ballerina/java}CLASS_NOT_FOUND 'Hello'
Running executables

Error: Could not find or load main class ___init

both the .class and the .bal files are in the same directory

can anyone please tell me the correct syntax to invoke the sayHello java method in ballerina.

Also could you explain more about the handle keyword in ballerina

[1] https://ballerina.io/v1-2/learn/by-example/invoke-java-methods.html


Solution

  • You can refer to the interop guide for a detailed info regarding this.

    For your particular case, follow the following steps:

    • Create a Java project for your Hello class and get the built .jar file.
    • Create a new Ballerina project as well and add a module in it (let's say the module is called hello).
    • Create a directory named javalibs in your project root directory and copy the .jar file to it.
    • Your project directory look similar to the following:

      .
      ├── Ballerina.lock
      ├── Ballerina.toml
      ├── javalibs
      │   └── hello-1.0-SNAPSHOT.jar
      └── src
          └── hello
              └── main.bal
      
    • Add the following entries to your Ballerina.toml file:

      [platform]
      target = "java8"
      
         [[platform.libraries]]
         path = "./javalibs/hello-1.0-SNAPSHOT.jar"
         modules = ["hello"]
      
    • Your Ballerina code should look something like the following:

      import ballerina/io;
      import ballerina/java;
      
      public type Hello object {
          public function sayHello() returns string? {
              return java:toString(sayHelloExtern());
          }
      };
      
      function sayHelloExtern() returns handle = @java:Method {
          class: "xyz.pubudu.Hello",
          name: "sayHello",
          paramTypes: []
      } external;
      
      
      public function main() {
          Hello h = new;
          io:println(h.sayHello());
      
          string? s = java:toString(sayHelloExtern());
          io:println(s);
      }
      
    • Now you can run this using ballerina run hello and it should print Hello . . .

    With the 1.2.0 release, a new CLI tool called bindgen was introduced to easily generate the Ballerina bindings for Java APIs so the user doesn't have to manually write the bindings as we've done above. Checkout the interop guide I linked to above for more details on it.