Ballerina, which is developed and supported by WSO2, is billed as “a statically typed, open-source, cloud-native programming language.” What is a cloud-native programming language? In the case of Ballerina, it is one that supports networking and common internet data structures and that includes interfaces to a large number of databases and internet services. Ballerina was designed to simplify the development of distributed microservices by making it easier to integrate APIs, and to do so in a way that will feel familiar to C, C++, C#, and Java programmers.
Essentially, Ballerina is a C-like compiled language that has features for JSON, XML, and tabular data with SQL-like language-integrated queries, concurrency with sequence diagrams and language-managed threads, live sequence diagrams synched to the source code, flexible types for use both inside programs and in service interfaces, explicit error handling and concurrency safety, and network primitives built into the language.
There are two implementations of Ballerina. The currently available version, jBallerina, has a toolchain implemented in Java, compiles to Java bytecode, runs on a Java virtual machine, and interoperates with Java programs. A newer, unreleased (and incomplete) version, nBallerina, cross-compiles to native binaries using LLVM and provides a C foreign function interface. jBallerina can currently generate GraalVM native images on an experimental basis from its CLI, and can also generate cloud artifacts for Docker and Kubernetes. Ballerina has interface modules for PostgreSQL, MySQL, Microsoft SQL Server, Redis, DynamoDB, Azure Cosmos DB, MongoDB, Snowflake, Oracle Database, and JDBC databases.
For development, Ballerina offers a Visual Studio Code plug-in for source and graphical editing and debugging; a command-line utility with several useful features; a web-based sandbox; and a REPL (read-evaluate-print loop) shell. Ballerina can work with OpenAPI, GraphQL schemas, and gRPC schemas. It has a module-sharing platform called Ballerina Central, and a large library of examples. The command-line utility provides a build system and a package manager, along with code generators and the interactive REPL shell.
Finally, Ballerina offers integration with Choreo, WSO2’s cloud-hosted API management and integration solution, for observability, CI/CD, and devops, for a small fee. Ballerina itself is free open source.
Ballerina Language
The Ballerina Language combines familiar elements from C-like languages with unique features. For an example using familiar elements, here’s a “Hello, World” program with variables:
import ballerina/io; string greeting = "Hello"; public function main() { string name = "Ballerina"; io:println(greeting, " ", name); }
Both int
and float
types are signed 64-bit in Ballerina. Strings and identifiers are Unicode, so they can accommodate many languages. Strings are immutable. The language supports methods as well as functions, for example:
// You can have Unicode identifiers. function พิมพ์ชื่อ(string ชื่อ) { // Use \u{H} to specify character using Unicode code point in hex. io:println(ชื่\u{E2D}); } string s = "abc".substring(1, 2); int n = s.length();
In Ballerina, nil
is the name for what is normally called null
. A question mark after the type makes it nullable, as in C#. An empty pair of parentheses means nil
.
int? v = ();
Arrays in Ballerina use square brackets:
int[] v = [1, 2, 3];
Ballerina maps are associative key-value structures, similar to Python dictionaries:
map<int> m = { "x": 1, "y": 2 };
Ballerina records are similar to C structs:
record { int x; int y; } r = { x: 1, y: 2 };
You can define named types and records in Ballerina, similar to C typedefs:
type MapArray map<string>[]; MapArray arr = [ {"x": "foo"}, {"y": "bar"} ]; type Coord record { int x; int y; };
You can create a union of multiple types using the |
character:
type flexType string|int; flexType a = 1; flexType b = "Hello";
Ballerina doesn’t support exceptions, but it does support errors. The check
keyword is a shorthand for returning if the type is error
:
function intFromBytes(byte[] bytes) returns int|error { string|error ret = string:fromBytes(bytes); if ret is error { return ret; } else { return int:fromString(ret); } }
This is the same function using check
instead of if ret is error { return ret
:
function intFromBytes(byte[] bytes) returns int|error { string str = check string:fromBytes(bytes); return int:fromString(str); }
You can handle abnormal errors and make them fatal with the panic
keyword. You can ignore return values and errors using the Python-like underscore _
character.
Ballerina has an any
type, classes, and objects. Object creation uses the new
keyword, like Java. Ballerina’s enum
types are shortcuts for unions of string
constants, unlike C. The match
statement is like the switch case
statement in C, only more flexible. Ballerina allows type inference to a var
keyword. Functions in Ballerina are first-class types, so Ballerina can be used as a functional programming language. Ballerina supports asynchronous programming with the start
, future
, wait
, and cancel
keywords; these run in strands, which are logical threads.
Ballerina provides distinctive network services, tables and XML types, concurrency and transactions, and various advanced features. These are all worth exploring carefully; there’s too much for me to summarize here. The program in the image below should give you a feel for some of them.
Ballerina standard libraries and extensions
There are more than a thousand packages in the Ballerina Central repository. They include the Ballerina Standard Library (ballerina/*), Ballerina-written extensions (ballerinax/*), and a few third-party demos and extensions.
The standard library is documented here. The Ballerina-written extensions tend to be connectors to third-party products such as databases, observability systems, event streams, and common web APIs, for example GitHub, Slack, and Salesforce.
Anyone can create an organization and publish (push) a package to Ballerina Central. Note that all packages in this repository are public. You can of course commit your code to GitHub or another source code repository, and control access to that.
Installing Ballerina
You can install Ballerina by downloading the appropriate package for your Windows, Linux, or macOS system and then running the installer. There are additional installation options, including building it from the source code. Then run bal version
from the command line to verify a successful installation.
In addition, you should install the Ballerina extension for Visual Studio Code. You can double-check that the extension installed correctly in VS Code by running View -> Command Palette -> Ballerina. You should see about 20 commands.
The bal command line
The bal command-line is a tool for managing Ballerina source code that helps you to manage Ballerina packages and modules, test, build, and run programs. It also enables you to easily install, update, and switch among Ballerina distributions. See the screen shot below, which shows part of the output from bal help
, or refer to the documentation.
Ballerina Examples
Ballerina has, well, a lot of examples. You can find them in the Ballerina by Example learning page, and also in VS Code by running the Ballerina: Show Examples
command. Going through the examples is an alternate way to learn Ballerina programming; it’s a good supplement to the tutorials and documentation, and supports unstructured discovery as well as deliberate searches.
One caution about the examples: Not all of them are self-explanatory, as though an intern who knew the product wrote them without thinking about learners or having any review by naive users. On the other hand, many are self-explanatory and/or include links to the relevant documentation and source code.
For instance, in browsing the examples I discovered that Ballerina has a testing framework, Testarina, which is defined in the module ballerina/test
. The test
module defines the necessary annotations to construct a test suite, such as @test:Config {}
, and the assertions you might expect if you’re familiar with JUnit, Rails unit tests, or any similar testing frameworks, for example the assertion test:assertEquals()
. The test
module also defines ways to specify setup and teardown functions, specify mock functions, and establish test dependencies.
Overall, Ballerina is a useful and feature-rich programming language for its intended purpose, which is cloud-oriented programming, and it is free open source. It doesn’t produce the speediest runtime modules I’ve ever used, but that problem is being addressed, both by experimental GraalVM native images and the planned nBallerina project, which will compile to native code.
At this point, Ballerina might be worth adopting for internal projects that integrate internet services and don’t need to run fast or be beautiful. Certainly, the price is right.
Cost: Ballerina Platform and Ballerina Language: Free open source under the Apache License 2.0. Choreo hosting: $150 per component per month after five free components, plus infrastructure costs.
Platform: Windows, Linux, macOS; Visual Studio Code.
Copyright © 2023 IDG Communications, Inc.