Ballerina Interop and all you need to know
Tags: ballerina, programming
Published: 2019-09-12 08:06:11

First of all, I'll give a brief introduction about **Ballerina** as this is my first post about ballerina in dev.to

**Ballerina** is a brand new statically typed programming language which was developed specifically targeting the integration space. There are some previous posts I have written in [Medium](https://medium.com/@lanka.vitharana) about ballerina language 

Let's come to the topic at hand, very often people were asking me about the interrelationship between java and ballerina and how to use existing Java libraries in Ballerina. I am not going to talk about the interrelationship in this post as that itself is a separate topic. This post is about how to properly use interop functionality to interact with java in Ballerina.

Earlier we used a different mechanism called _native binding_ to interact with java, however since the introduction of _interop_, we strongly recommend the usage of interop instead of the old mechanism, in fact, it is bit hard to do the old style binding anyway now(even though we have both of the mechanisms still there and most of the standard libraries are still using the old style)

If anyone is familiar with old-style binding, a major difference between two are how we keep binding details, wherein old-style we kept them at java side as an annotation and in interop, those details are kept at ballerina side as annotations.

First I'll explain the concept, say you need to invoke a java method inside ballerina, what you have to do is define a ballerina method which matches the java signature and specify the fully qualified Java class which has the java method in the annotation.


So let's dig into `howto` with a simple example

here we are going to invoke below java method from ballerina side as an interop function.

```java
package org.wso2.ballerina.math;

public class AddInt {

    public static long addInt(long a, long b) {
        return a + b;
    }
}

```
so, first of all, you'll have to write above java code and get that compiled into a jar. As you can see, above is a simple static java method which accepts two long parameters(I am using `long` type here because ballerina `int` is a `long` in java side which makes the sample simple one)

Next step is to create the ballerina function definition and provide necessary linking information. 

Below is the example ballerina function definition
```java 
public function addInt(int a, int b) returns int = @java:Method {
    class:"org/wso2/ballerina/math/AddInt"
} external;

```
That's simply it, you can use `addInit` as a normal function in ballerina side. Still, as I have said earlier, for the ballerina module to build properly, you'll have to provide the jar file which contains the above `AddInit` java class. That you can specify in the `Ballerina.toml` file itself. Below is how it's done.
```toml
[platform]
target = "java8"

    [[platform.libraries]]
    artifactId = "ballerina-math"
    version = "@project.version@"
    path = "../native-math/target/ballerina-math-1.0.0.jar"
    groupId = "org.wso2.ballerinalang"
    modules = ["math"]
```
You can find the complete example in the GitHub repo [ballerina-math](https://github.com/lankavitharana/ballerina-math) (check the tag relevant to the ballerina version)

The concept is pretty simple, even though we are invoking a java method, there should always be a ballerina side definition, so from ballerina perspective, it's very easy to do all the type checkings and validations. The only other validation we are doing with interop is validating the ballerina definition against the actual java implementation.

When it comes to invoking java, there comes the problem of how to map ballerina types to java types vice versa. And also what to do about actual java types that cannot be represented in ballerina side. For that, we have introduced a new type called **_handle_**. `Handle` is an opaque type as far as ballerina is concerned, so you can keep any kind of java value under `handle` type. Other than that, we tried to map all the possible types with java, because with `handle`s we cannot properly do type checking. So for example, `int` in ballerina side is a `long` value in java.

Ok now since we have the basics, let's dig into a bit complex example.

So how do we handle java method overloads?

For them, we can use annotations(`java:Method` annotation) to provide more details. Since ballerina doesn't allow overloading, you'll have to define separate ballerina functions with distinct names, however using annotations, you can specify the actual java method name you need to invoke. (Basically, you can use annotation to override the default behavior).

So how do we invoke instance methods and handle java constructors?
Fo constructor, you can use `java:Constructor` annotation. As you may have guessed, you can override parameter mapping in the annotation as well. And you can keep the created object reference in ballerina side as a `handle` then when invoking an instance method, you will have to pass that handle as the first argument of the method invocation. Ok let's take an example for more clarity

```java
package org.wso2.ballerina.math;

public class Substract {
    private long initialVal;

    public Substract(long initial) {
	this.initialVal = initial;
    }

    public long substractInt(long a) {
	return initialVal - a;
    }
}
```
Below is the ballerina side constructor mapping
```java
public function newSubstract(int initial) returns handle = @java:Constructor {
    class:"org/wso2/ballerina/math/Substract"
} external;
```
as you can see we have used `java:Constructor` annotation here, and we are returning a `handle` type value, which is the object instance. Here the name of the ballerina method doesn't matter(no need to match it with java constructor name or anything), we use parameters to distinguish between overloaded constructors.

Below is the ballerina method which matches to the instance method.
```java
public function substract(handle receiver, int b) returns int = @java:Method{
    class:"org/wso2/ballerina/math/Substract",
    name:"substractInt"
} external;
```
Note that I have used `name` field to specify the actual java method name(when the ballerina method name is different from actual java method name). 

So how do we use these constructors and instance methods?
Below is a sample code which creates and instance of java `Substract` class and invoke it's `substractInt` instance method.
```java
    // Creating instance
    handle sub = newSubstract(10);

    // Invoking a instance method
    int subRes = substract(sub, 5);
    io:println(subRes);
```
I have touched most of the parts related to java interop, however there are more complex scenarios than this, like how to handle errors in interop, how to do async invocations, how to access fields, how to use defaultable parameters and list goes on :) there are so many cool features in **Ballerina** :)

Yet I'm going to conclude the post here as it is already a bit long, I Will try to either extend this post or create a new one with rest of the details. (Maybe I have to update the post heading "..Part of what you need to know" instead of the current heading :) )