The Bindgen tool is a CLI tool that generates Ballerina bindings for Java classes.
The following sections explain how the Bindgen tool works.
|This optional parameter could be used to specify one or more comma-delimited classpaths for retrieving the Java libraries required for the generation of the Ballerina bindings. The classpath could be provided as comma-separated paths of JAR files or as comma-separated paths of directories containing all the relevant Java libraries. If the Ballerina bindings are to be generated from a standard Java library, from a library available inside the Ballerina SDK, or a platform library specified in the ||Optional|
|Specifies a Maven dependency required for the generation of the Ballerina bindings. Here, the specified library and its transitive dependencies get resolved into the ||Optional|
|Generates all the bindings inside a single directory instead of generating module-level mappings. This option could be used in instances where all the mappings are required inside a single module. The specified directory doesn't always have to be inside a Ballerina package.||Optional|
|Sets the visibility modifier of the generated binding classes to public. This flag is applicable only if the bindings are generated inside a single directory.||Mandatory|
|Generate the optional (i.e., nilable) types for the function parameter and return types to pass and retrieve Java null values to/from the underneath Java API.||Optional|
|Generate the optional (i.e., nilable) types for the function parameter types to pass Java null values to the underneath Java API.||Optional|
|Generate the optional (i.e., nilable) types for the function return types to retrieve Java null values from the underneath Java API.||Optional|
|One or more space-separated, fully-qualified Java class names for which the Ballerina bridge code is to be generated. These class names should be provided at the end of the command.||Mandatory|
Generated bridge code
When the tool is run, a
.bal file gets created to represent each Java class. This would contain the respective Ballerina binding class along with the required Java interoperability mappings. By default, these
.bal files are generated inside separate modules representing each Java package. If the
[(-o|--output) <output-path>] option is used, they are generated inside a single directory.
Apart from creating bindings for the specified Java classes, the command also generates empty Ballerina binding classes for dependent Java classes. A Java class would be considered dependent if it is used inside one of the generated Ballerina binding classes.
A set of additional
.bal files are generated to store the error types used within the Ballerina binding classes.
The generated bindings are inside the specified output directory as follows.
Java to Ballerina mapping
A Java class is mapped to a Ballerina class. This Ballerina class has the same name as the Java class.
E.g., the generated Ballerina class of the
java.util.ArrayDeque class is as follows.
If there are multiple classes with the same simple name, they need to be generated using a single execution. The tool then, applies a numerical identifier at the end of duplicated class names. This could be manually changed into something meaningful if required.
The format for specifying inner classes using the command is
<package-name>.ClassName$InnerClassName. The dollar sign might have to be escaped using the backslash key.
E.g., the command to generate bindings for
java.lang.Character.Subset class is as follows.
When referring to Java code to figure out the imported classes, you should be cautious about the Java classes from the
java.lang package since these are not visible as imports in the Java code. However, you need not generate bindings for the
java.lang.String class since it is mapped into the Ballerina
string type from within the generated Ballerina bindings.
Constructors of Java classes are mapped to functions outside the Ballerina class. These function names are comprised of the constructor name prefixed with the
new keyword. If there are multiple constructors, they are suffixed with an auto-incremented number.
E.g., generated constructors of the
java.util.ArrayDeque class is as follows.
All public methods are exposed through Ballerina bindings. Instance methods reside inside the Ballerina class and these would take the name of the Java method. However, if there are overloaded methods, a numeric suffix is appended at the end of the name.
E.g., some of the generated instance methods of the
java.util.ArrayDeque class is as follows.
Static methods would reside outside the Ballerina class as functions, which take the name of the Java method with the Java simple class name appended at the beginning as a prefix.
E.g., a generated static method
randomUUID() of the
java.util.UUID class is as follows. Here, the Ballerina equivalent of calling
UUID.randomUUID() in Java is
All public fields of a Java class are exposed through Ballerina bindings in the form of getters and setters. Instance fields have the respective getter and setter methods inside the Ballerina class, whereas, the static fields have getter and setter functions outside the Ballerina class.
The getter and setter functions of an instance field take the name of the field prefixed with a
set at the beginning.
For a static field, the getter and setter (if the field is not final) functions take the name of the field with a
set prefix along with the Java simple class name appended at the beginning.
When generating Ballerina bindings, Java exceptions are mapped onto Ballerina errors. They have identical names as that of the corresponding Java exceptions. Instead of returning a generic error from the Java side, the bindings return a more meaningful error representing the exact Java exception.
E.g., the following
IOException is returned from the
read() function in the
java.io.FileInputStream Ballerina binding class.
Note: If a Java exception class is explicitly generated as a Ballerina binding class, it would follow the naming convention
JError. For instance, the binding class's name for
When there are dependent Java classes present inside generated Ballerina bindings (as parameters or return types), the Bindgen tool generates an empty Ballerina binding class to represent each one of these classes. This represents a Java class mapping without the constructors, methods, or field bindings. If one of these classes is required later, the Bindgen tool could be re-run to generate the complete implementation of the Ballerina bindings.
E.g., the generated dependent class representing
java.util.List is as follows.
Generated Ballerina bindings support the following type mappings between Java and Ballerina.
- Ballerina primitive - Java primitive
- Ballerina string type - Java String class
- Ballerina binding class - Java class
The Ballerina binding classes store a handle reference of the Java object using its
The following table summarizes how Java primitive types are mapped to the corresponding Ballerina primitive types. This is applicable when mapping a return type of a Java method to a Ballerina type.
|Java type||Ballerina type|
|int, short, char, long||int|
Support for Java subtyping
Ballerina bindings provide support for Java subtyping with the aid of type inclusions in the language.
E.g., a Ballerina binding class mapping the
java.io.FileInputStream Java class could be assigned to a Ballerina binding class mapping the
java.io.InputStream as follows.
Support for handling Java null values
Ballerina bindings provide the flexibility for the user to handle Java
null values with the help of optional (i.e., nilable) types in the language.
However, the tool will not generate optional types by default (in order to reduce the complexity of handling nilable types) and the users can opt-in to generate optional types for the Ballerina function parameter and return types by passing the
In that way, users can populate null values to the underneath Java API by providing nil values to the generated Ballerina function and
the generated functions will return nil values in case the counterpart Java method returns null.
Support for Java casting
ballerina/jballerina.java package of the Ballerina library provides the
cast function to support Java casting. This could be used to cast Ballerina binding classes into their subtypes based on assignability.
E.g., a Ballerina binding class instance mapping the
java.io.InputStream Java class
inputStream could be cast onto a Ballerina binding class mapping the
java.io.FileInputStream Java class as follows.