Nowadays everything is Cloud Native; everybody talks about CN tools, frameworks, solutions, and so on. On the
other
hand, those tools totally changed the way we design, develop, test and release modern applications. I think
the
number of issues that we solved with the new concepts is equal to the number of new challenges, so in short, we simply shoveled problems from one hole to the other. Many new tools appeared on the market to make
developers' life easier by
My first impression of it was this language is a creature of Dr Frankenstein because it is a mix of 4+ existing languages with a few unique and interesting features. But first, let's talk about what CN programming language means?
First of all, there is no clear definition however here is my personal opinion. Beginning with the most important quality, it has handy support to create and publish (micro)services easily. It must contain REST and RPC connectors with data representation/conversion to communicate with other services language-natively. Circuit breaker, client-side load balancer, fail-over and retry logic are also very convenient features. And finally, it has to support containers and orchestration platforms like Kubernetes. The same application has to run locally or in the public cloud.
The language itself is a compiled, transactional, statically, and strongly typed programming language with textual and graphical syntaxes. The compiler is written in Java. It generates an intermediate byte-code, which looks like Java but it isn't compatible with JVM. The byte-code runs on Ballerina Virtual Machine. The first version was in Java with GC, but later on, they re-implemented the VM and switched to a register-based technology (for more information please visit this page). The language has textual representation a.k.a. source code, and an editable flow diagram view (image from dzone.com).
If you are familiar with Java, Groovy, Go and Python you will be familiar with Ballerina. Similarities are:
First I would like to introduce the simplest exchange service, which contains only the basic language features.
As I mentioned earlier, the CLI tool talks with two services to figure out the best price for exchange. The previous version was the simplest one. In the next section I want to present an enterprise grade version of the same service.
I hope this introduction to the Ballerina language was interesting for all. The source code of the application is available on GitHub. Ballerina by Example is a beautiful collection to learn the language, so don't forget to visit it. For development I used Visual Studio Code plugin which worked well including syntax highlighting, auto-completing, jumping to the declaration, finding all references, and debugging (rename was broken). Intellij IDEA plugin is also available in the marketplace. There is one important thing to mention about IDE plugins. They require Java 8, so be sure you set the right version of Java.
There are some other nice features that make the language more powerful. Here are just a few of them:
- integrating software with the underlying infrastructure
- watching file changes and building containers automatically
- generating resource descriptors on the fly
- allowing debugging in a running container
- etc.
My first impression of it was this language is a creature of Dr Frankenstein because it is a mix of 4+ existing languages with a few unique and interesting features. But first, let's talk about what CN programming language means?
First of all, there is no clear definition however here is my personal opinion. Beginning with the most important quality, it has handy support to create and publish (micro)services easily. It must contain REST and RPC connectors with data representation/conversion to communicate with other services language-natively. Circuit breaker, client-side load balancer, fail-over and retry logic are also very convenient features. And finally, it has to support containers and orchestration platforms like Kubernetes. The same application has to run locally or in the public cloud.
The language itself is a compiled, transactional, statically, and strongly typed programming language with textual and graphical syntaxes. The compiler is written in Java. It generates an intermediate byte-code, which looks like Java but it isn't compatible with JVM. The byte-code runs on Ballerina Virtual Machine. The first version was in Java with GC, but later on, they re-implemented the VM and switched to a register-based technology (for more information please visit this page). The language has textual representation a.k.a. source code, and an editable flow diagram view (image from dzone.com).
If you are familiar with Java, Groovy, Go and Python you will be familiar with Ballerina. Similarities are:
- Java
- Object
- Generic
- Annotation
- JUnit
- JDBC
- JMS
- Groovy
- Fork join and async library
- Elvis operator
- Nil lifting
- String template literal
- Go
- Struct type, called record
- Functions are first-class citizens
- Function declaration
- Dynamic interface implementation
- Panic and error handling
- Multi return value
- Ignore variable "_"
- Channels
- Python
- self.
- __init()
First I would like to introduce the simplest exchange service, which contains only the basic language features.
- Line 3: Our service will listen on port 9091.
- Line 5: It has an endpoint called "getRate".
- Line 6: It generates the response message with a type json. Built in types are int, float, decimal, byte, string, boolean, anydata, any, nil, json, xml, array, map, tuples.
- Line 7-8: New http:Response initialization with JSON payload.
- Line 9:- Sends the response to the caller, "_" means the application ignores the return value.
- Line 1: @untained is a special annotation and is required because the compiler checks major security vulnerabilities including SQL injection, path manipulation, file manipulation, unauthorized file access, and unvalidated redirects (open redirects). @untained annotation marks return content as manually secured.
- Line 1: Input parameter "string|error payload" looks weird, it's called union type, and means the type of payload is either string or error. Union type is the most questionable language behavior. It looks like bad practice at first glance, but on the other hand, Ballerina has many features which make them easier to use (match, type guard) or at least make them make sense.
- Line 2: Type check, a type-guard check is a typing test construct that allows selective code execution based on the type of the expression that is being tested. That means in line 3, the payload is a string but an error in line 4.
- Line 3: Json is a built-in type, so it's really easy to declare and use it.
- Line 4: Power of string template literals.
- Line 8: "match" is a cleverer switch, with support of simple, tuple, and record types (I will explain later).
# ballerina run exchange-simle.bal Initiating service(s) in 'exchange-simple.bal' [ballerina/http] started HTTP/WS endpoint 0.0.0.0:9091 (press Ctrl+c after curl to exit)
# curl -d "EUR" http://localhost:9091/exchangeSimple/getRate {"currency":"EUR", "rate":35.5}
As I mentioned earlier, the CLI tool talks with two services to figure out the best price for exchange. The previous version was the simplest one. In the next section I want to present an enterprise grade version of the same service.
- Line 1: Define a custom error type.
- Line 3: Our first Ballerina object. The concept isn't powerful as in Java. There are only two types of them, abstract and regular (non-abstract) objects. An abstract object can only contain member declarations and/or method signatures - method body isn't allowed. An instance automatically implements an abstract class if members and methods match it - like Go interfaces.
- Line 4: Member definition: the visibility is limited to public or private and modifiers (transient, final, static) are not allowed.
- Line 6: Constructor of the object.
- Line 12: Built-in collections support immutability by freezing.
- Line 17-24: Iterable collections have high order functions such as map, filter, average, sum, max, min, etc. The only problem with them is, that they don't support closures as a function in the current version (0.990.0) so it's impossible to use the outside context during execution. The code above compiles but throws a runtime exception.
- Line 18: Split tuple into separated variables. The number of elements in the tuple isn't limited to two, so the well-known left() and right() don't exist in Ballerina. The only way to get access to the content of a tuple is to split it into new variables.
- Line 28: Create a custom error.
- Line 2: Member declaration. Services are special objects in the background. Constructors and members are allowed, but functions not?? (i hope they will fix it as soon as possible).
- Line 1: Records are Data Transfer Objects.
- Line 4: Optional field definition. By default, all fields are mandatory in a record. Be careful with optional fields, because they throw KeyNotFound error in runtime!
- Line 10: Member function declaration without a body?? GOTO 13
- Line 13: Go style function attach to on object.
- Line 14: "check" is a developer friendly error handling mechanism. In this case the return value of getTextPayload() is a union type string|error. The function return value is also a union type json|error. Because our function returns an error, check can replace manual error handling and returns the error of the line execution immediately as function return value.
- Line 17: Ballerina has built-in converters for json, xml, map, and record, so it's very easy to transform from one type to the other.
- Line 2: Custom type with a limited number of values.
- Line 9: There are two types of records, closed and open. By default, all records are open, which means any number of additional fields can be append during initialization. "!..." sign closes the record, so only the listed fields are allowed.
- Line 13: Nullable value definition. Null pointer error is one of the most common errors in runtime. In Ballerina, null assignment is accepted only for nullable values. Nullable types are separated types, so float and float? are different types!
- Line 33: JSON to record conversion.
- Line 34: Record to record conversion.
- Line 4: Global variable with a simple HTTP endpoint configuration.
- Line 5: HTTP endpoint configuration with retry and timeout. The configuration has built-in circuit breaker, client-side load balancer, and failover between multiple services.
- Line 19: "untaint" calls for Ballerina's built-in sanitizer.
- Line 19: Typecasting from int to float.
- Line 28: Error or nil lifting. Ballerina breaks line execution if the right side of "!" is an error or null and lifts the result.
- Line 31: Stop function execution and throw a panic.
- Line 35-43: Use fork-join to call services parallel.
- Line 37: Catch panic with "trap" and convert it to a regular error.
# minikube start # minikube addons enable ingress # eval $(minikube docker-env) # ballerina build Compiling source exchange-simle.bal exchange-enterprise.bal calculator.bal convert.bal Generating executables ./target/exchange-simle.balx @kubernetes:Service - complete 1/1 @kubernetes:Deployment - complete 1/1 @kubernetes:Docker - complete 3/3 @kubernetes:Helm - complete 1/1 Run the following command to deploy the Kubernetes artifacts: kubectl apply -f /Users/mhmxs/GitHub/ballerina-gold-exchanger/target/kubernetes/exchange-simle Run the following command to install the application using Helm: helm install --name exchange-simle-deployment /Users/mhmxs/GitHub/ballerina-gold-exchanger/target/kubernetes/exchange-simle/exchange-simle-deployment ./target/exchange-enterprise.balx @kubernetes:Service - complete 1/1 @kubernetes:Deployment - complete 1/1 @kubernetes:Docker - complete 3/3 @kubernetes:Helm - complete 1/1 Run the following command to deploy the Kubernetes artifacts: kubectl apply -f /Users/mhmxs/GitHub/ballerina-gold-exchanger/target/kubernetes/exchange-enterprise Run the following command to install the application using Helm: helm install --name exchange-enterprise-deployment /Users/mhmxs/GitHub/ballerina-gold-exchanger/target/kubernetes/exchange-enterprise/exchange-enterprise-deployment ./target/calculator.balx @kubernetes:Service - complete 1/1 @kubernetes:Deployment - complete 1/1 @kubernetes:Docker - complete 3/3 @kubernetes:Helm - complete 1/1 Run the following command to deploy the Kubernetes artifacts: kubectl apply -f /Users/mhmxs/GitHub/ballerina-gold-exchanger/target/kubernetes/calculator Run the following command to install the application using Helm: helm install --name calculator-deployment /Users/mhmxs/GitHub/ballerina-gold-exchanger/target/kubernetes/calculator/calculator-deployment ./target/convert.balx # make kube-apply # make expose # ballerina run convert.bal 3 USD Handling connection for 9091 (call simple exchange service) Handling connection for 9092 (call enterprise exchange service) Handling connection for 9092 (the service doesn't work as I mentioned) Handling connection for 9092 (CLI retries a few times) Handling connection for 9090 (call calculator service) 106.5 # make cleanup
I hope this introduction to the Ballerina language was interesting for all. The source code of the application is available on GitHub. Ballerina by Example is a beautiful collection to learn the language, so don't forget to visit it. For development I used Visual Studio Code plugin which worked well including syntax highlighting, auto-completing, jumping to the declaration, finding all references, and debugging (rename was broken). Intellij IDEA plugin is also available in the marketplace. There is one important thing to mention about IDE plugins. They require Java 8, so be sure you set the right version of Java.
There are some other nice features that make the language more powerful. Here are just a few of them:
- Swagger generator
- Distributed transaction
- XA transaction
- Channel
- Reactive streams
- 3rd party plugin library