- 1.2.54
- 1.2.53
- 1.2.52
- 1.2.51
- 1.2.50
- 1.2.49
- 1.2.48
- 1.2.47
- 1.2.46
- 1.2.45
- 1.2.44
- 1.2.43
- 1.2.42
- 1.2.41
- 1.2.40
- 1.2.39
- 1.2.38
- 1.2.37
- 1.2.36
- 1.2.35
- 1.2.34
- 1.2.33
- 1.2.32
- 1.2.31
- 1.2.30
- 1.2.29
- 1.2.28
- 1.2.27
- 1.2.26
- 1.2.25
- 1.2.24
- 1.2.23
- 1.2.22
- 1.2.21
- 1.2.20
- 1.2.19
- 1.2.18
- 1.2.17
- 1.2.16
- 1.2.15
- 1.2.14
- 1.2.13
- 1.2.12
- 1.2.11
- 1.2.10
- 1.2.9
- 1.2.8
- 1.2.7
- 1.2.6
- 1.2.5
- 1.2.4
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
Overview of Ballerina Swan Lake Preview 8
This release is the eighth preview version of Ballerina Swan Lake. It includes a new set of language features along with improvements and bug fixes to the compiler, runtime, standard library, and developer tooling.
Updating Ballerina
You can use the update tool to update to Ballerina Swan Lake Preview 8 as follows.
For existing users
If you are already using Ballerina, you can directly update your distribution to the Swan Lake channel using the Ballerina update tool. To do this, first, execute the command below to get the update tool updated to its latest version.
ballerina update
Next, execute the command below to update to Swan Lake Preview 8.
ballerina dist pull slp8
However, if you are using a Ballerina version below 1.1.0, install via the installers.
For new users
If you have not installed Ballerina, then download the installers to install.
Highlights
- Ability to use
\
to escape the special characters in an identifier without specifying the initial quote - Introduction of included record parameters
- Introduction of service typing changes basing services on objects
- Extension of Ballerina transaction capabilities to define transactional resource functions and transactional remote functions
- Improvements to the HTTP, Log, Email, and WebSub Standard Library modules
- Introduction of the new GraphQL, NATS Streaming (STAN), UUID, and WebSocket Standard Library modules
What is new in Ballerina Swan Lake Preview 8
Language
Support identifier escapes without an initial quote
Now, \
can simply be used to escape the special characters in an identifier without specifying the initial quote. For example, both the formats below are supported now.
int a\-b; int 'a\-b;
Included record parameters
Included record parameters can be specified as *T P
in which T
denotes a record type descriptor and P
denotes the name of the parameter.
An included record parameter is similar to a required parameter, but it also allows the caller of the function to specify the value for a field of the record type as a named argument using the field's name, as if it had been declared as a parameter.
The names of the fields in the record type of an included record parameter must be distinct from each other and also from the names of the other parameters, unless it is an optional field of type never
.
A named argument in a function call can correspond to the fields of an included record parameter in two different ways.
-
Being relevant to a field of the included recorded parameter, which is not of the
never
type.mport ballerina/io; ype Student record { string firstName; string lastName?; ; unction printStudentDetails(int admissionNo, *Student student) { string name = student.firstName; string? lastName = student?.lastName; if lastName is string { name += string ` ${lastName}`; } io:println("Admission No: ", admissionNo, ", Student Name: ", name); ublic function main() { printStudentDetails(1001, firstName = "Peter"); printStudentDetails(1002, firstName = "Anne", lastName = "Doe");
-
Being relevant to a record rest descriptor of an included record parameter that is of an open record type. The following conditions should be satisfied for this.
- In the parameter list, there should be only one included record parameter that is of an open record type.
- The open record type must disallow fields of the same names as the other parameters and individual field descriptors of the other included record parameters, by including optional individual field descriptors of the type
never
. In addition to these optional individual field descriptors, there should not be any other field descriptors in this record type.
import ballerina/io; type Grades record {| never math?; never physics?; int...; |}; function printAverage(int math, int physics, *Grades grades) { int totalMarks = math + physics; int count = grades.length() + 2; foreach int grade in grades { totalMarks += grade; } io:println("Average: ", totalMarks/count); } public function main() { printAverage(90, 85); printAverage(85, 85, chemistry = 75); printAverage(75, 85, chemistry = 90, zoology = 80); }
Service typing changes
Services are now based on objects. The service declaration syntax below is mere syntactic sugar for creating a new instance of a service class and then attaching it to a listener. With this change, the path that the service should serve on can be provided in the service-declaration syntax. This was previously provided using an annotation.
Previous syntax
import ballerina/http; service hello on new http:Listener(9090) { resource function sayHello() returns error? { } }
New syntax
import ballerina/http; service [/optional_base_path] on new http:Listener(9090) { resource function get sayHello() returns string { } }
Note: There is no longer a service variable name as
hello
in the first example. Since services are objects, they can contain fields and regular methods. In addition to that, services can contain remote methods and resource methods.
Resource methods are defined as follows:
resource function
resource-method-name
resource-path
() { }
- Resource methods do not have a method name similar to a regular method.
- The
resource-method-name
informs the listener of the operations this resource allows. For example, in the HTTP listener, theresource-method-name
maps to the HTTP methods such asGET
orPUT
. - The
resource-path
is the path in which this resource resides within the service. You can use.
as theresource-path
to indicate the path/
.
A service declared using the service-declaration syntax cannot be referred to using an identifier anymore. Instead, you need to use an object constructor prepended by the service
keyword to declare a service object or create a new instance of a service class.
service object { } hello = service object { string message = "Hello"; resource function get sayHello() returns string { } } listener http:Listener l = new (7000); string[] basePath = ["/"]; // service base path: / l.attach(hello, basePath);
service class HelloService { string message; resource function get sayHello() returns string { } function init(string message) { self.message = message; } } var hello = new HelloService("Hello"); listener http:Listener l = new(7000); string[] basePath = ["hello", "path"]; // service on "/hello/path" l.attach(hello, basePath);
Listener object
Listener is no longer defined in ballerina/lang.object
lang-library, now it is a compiler known internal type.
A type is a listener object type if it is a subtype of the object type Listener<T,A>, for some type T
that is a subtype of service object {}
and some type A
that is a subtype of string[]|string|()
.
The object type Listener<T,A>
, is described by the following object type descriptor:
object { public function attach(T svc, A attachPoint) returns error?; public function detach(T svc) returns error?; public function start() returns error?; public function gracefulStop() returns error?; public function immediateStop() returns error?; }
Transactional services
Ballerina transaction capabilities have been extended to services. Now, you can define transactional resource methods and transactional remote methods. These methods will be participants of global distributed transactions. Infection and agreement protocols are implemented based on the Ballerina distributed transaction protocol.
By defining services as participants, all services work as a single unit of work. If any of the services fail, the whole transaction will be reverted and if all the services are successfully called, the transaction will be completed and committed successfully.
Defining transactional resource methods in a service
transactional resource function get message(http:Caller caller, http:Request req) { http:Response res = new; callSomeService(res); callAnotherService(res); checkpanic caller->respond(res); }
Defining transactional remote methods in a client object
transactional remote function callMyFirstService() returns @tainted any|error { return self.httpClient1->get("/echo/message"); } transactional remote function callMySecondService() returns @tainted any|error { return self.httpClient2->get("/user/history"); }
Calling the service
transaction { var res1 = client->callMyFirstService(); var res2 = client ->callMySecondService(); var x = commit; if (x is error) { // error code } else { // success code } }
Standard library
http
module changes
Service declaration
- Basepath field has been removed from the
ServiceConfig
annotation. Use theabsolute resource path
that begins with/
as the basePath which is optional and defaults to/
when not specified. - The service type can be added as
http:Service
, which is optional after theservice
keyword.
Previous syntax
@http:ServiceConfig { basePath: “hello” } service myService on new http:Listener(9090) { }
New syntax
service http:Service /hello on new http:Listener(9090) { }
Resource method declaration
- Use the resource method name to specify the HTTP method to support instead of the
methods
field of theResourceConfig
annotation (e.g.,get
). - Use
default
as the resource method name when the resource has to support all methods including standard HTTP methods and custom methods (e.g., the passthrough/proxy use case). - The resource path segment represents the
path
as thepath
field of theResourceConfig
has been removed. - Use
.
to specify the resource path segment if the path needs to be set as/
. - Path params are specified in the resource path segment within square brackets along with the type. The supported types are string, int, float, boolean (e.g.,
path/[string foo]
). - Resource signature parameters are optional. Even the
Caller
andRequest
are optional and not ordered. - Query param binding support is added. The supported types are string, int, float, boolean, decimal, and the array types of the aforementioned types. The
Query
param type can be nilable (e.g.,(string? bar)
). - Rest param support is added. It can be used as a wildcard path segment to accept requests to multiple different paths. Earlier it was used as
/*
and now it can be specified as[string… s]
in whichs
is accessible within the resource. - Use the
@http:Payload {}
annotation to denote the data binding param in the resource signature as thebody
field of theResourceConfig
has been removed.
service http:Service /mytest on new http:Listener(9090) { resource function post foo/[int id]/bar/[string... extra](string? bar, http:Caller caller, @http:Payload {} json p) { // [int id] is a path param // [string... extra] is a rest param // string? bar is a query param // json p is the request payload } }
log
module changes
-
Log levels are reduced to
INFO
andERROR
. There will be no user configuration to control the log level. All the logs will be printed to the standard error stream. -
There are only two APIs to log messages as follows.
- Log
INFO
messages
log:print("something went wrong", id = 845315); Output: time = 2019-08-09 11:47:07,342 module = "myorg/hello" message = "something went wrong" id = 845315
- Log
ERROR
messages
log:printError("something went wrong", err = e, id = 845315); Output: time = 2019-08-09 11:47:07,342 module = "myorg/hello" message = "something went wrong" error = "invaild operation" id = 845315
- Log
-
The API supports passing any number of key/value pairs along with the message.
-
Log messages are printed following the
LogFMT
standards.
email
module changes
The methods related to sending and receiving emails were renamed. The Listener API was divided into the POP and IMAP protocols.
Client changes
- The
email:Email
definition is changed toemail:Message
. - The
read
method of theemail:ImapClient
,email:PopClient
, andemail:Listener
(i.e., the newemail:PopListener
andemail:ImapListener
) are changed toreceiveEmailMessage
.
Service declaration
- The
email:Listener
is split into theemail:PopListener
andemail:ImapListener
. Therefore, theprotocol
field is removed from the new protocol-specific listeners. Theemail:PopConfig
oremail:ImapConfig
that was used as a field for theemail:Listener
is not required for new the API implementation. The protocol configuration-related fields are made parts of the new listeners. - The resource methods are changed to remote methods in the new listener APIs.
- The service name is given as a string with the new Ballerina language changes.
- The
onMessage
method of theemail:Listener
(i.e., the newemail:PopListener
andemail:ImapListener
) is changed toonEmailMessage
. - The
pollingInterval
field of theemail:Listener
is changed topollingIntervalInMillis
in new listener APIs. That makes it consistent with other Ballerina modules, which have time durations configured in milliseconds.
A sample POP3 listener is given below.
Previous syntax
email:PopConfig popConfig = { port: 995, enableSsl: true }; listener email:Listener emailListener = new ({ host: "pop.email.com", username: "reader@email.com", password: "pass456", protocol: "POP", protocolConfig: popConfig, pollingInterval: 2000 }); service emailObserver on emailListener { resource function onMessage(email:Email emailMessage) { } resource function onError(email:Error emailError) { } }
New syntax
listener email:PopListener emailListener = new ({ host: "pop.email.com", username: "reader@email.com", password: "pass456", pollingIntervalInMillis: 2000, port: 995, enableSsl: true }); service "emailObserver" on emailListener { remote function onEmailMessage(email:Message emailMessage) { } remote function onError(email:Error emailError) { } }
websub
module changes
- The base path is removed from the
SubscriberServiceConfig
annotation. - The
onNotification
andonIntentVerification
resources are converted to remote methods.
Previous syntax
@websub:SubscriberServiceConfig { path: "/websub", target: ["http://localhost:9191/websub/hub", "http://websubpubtopic.com"] } service websubSubscriber on new websub:Listener(8181) { resource function onIntentVerification(websub:Caller caller, websub:IntentVerificationRequest request) {} resource function onNotification(websub:Notification notification) {} }
New syntax
@websub:SubscriberServiceConfig { target: ["http://localhost:23191/websub/hub", "http://one.websub.topic.com"] } service websub:SubscriberService /websub on new websub:Listener(8181) { remote function onIntentVerification(websub:Caller caller, websub:IntentVerificationRequest request) {} remote function onNotification (websub:Notification notification) {} }
Introduced new modules
GraphQL
The Ballerina GraphQL module is introduced with this release. This module provides the support to define GraphQL services and handle simple GraphQL queries. Currently, this supports GraphQL service endpoints with the resource methods, which return graphql:Scalar
values (int
, string
, boolean
, and float
) and record types only.
NATS Streaming (STAN)
With this release, a new module is introduced for NATS Streaming. Previously, the Ballerina NATS module included the support for streaming as well. Now, NATS and NATS Streaming are separated into Ballerina NATS and Ballerina STAN modules.
UUID
The Ballerina UUID module is introduced with this release. This module provides functions related to UUID (Universally Unique Identifier) such as generating different types of UUIDs and validating and checking the versions of UUID strings.
WebSocket
- The WebSocket module has been moved out of the HTTP module. Therefore, you will have to change the import from
ballerina/http
toballerina/websocket
. - Introduced a new listener for the WebSocket module.
Previous syntax
listener http:Listener wsListener = new (9090);
New syntax
listener websocket:Listener wsListener = new (9090);
-
The base path is removed from the
WebSocketServiceConfig
. -
Has 2 types of services. In order to work with WebSockets, the two services below are mandatory.
websocket:UpgradeService
- This is to handle the WebSocket upgrade. This takes thehttp:Request
andhttp:Caller
parameters in. This service has a predefinedonUpgrade
remote method that returns awebsocket:Service
or an error. Earlier, this was handled by an HTTP upgrade resource.websocket:Service
- This is to handle events after the WebSocket upgrade. This service is still similar to the earlier WebSocket service, which had predefined resources likeonText
,onBinary
,onError
,onPing
, andonPong
. With the new syntax, all those resources are converted into remote methods.
Previous syntax
import ballerina/http; listener http:Listener socketListener = new (9000); @http:WebSocketServiceConfig { path: "/basic" } service echo on socketListener { resource function onText(http:WebSocketCaller caller, json text) {} resource function onBinary(http:WebSocketCaller caller, byte[] b) {} }
New syntax
import ballerina/http; import ballerina/websocket; service websocket:UpgradeService / basic on new websocket:Listener(9000) { remote isolated function onUpgrade(http:Caller caller, http:Request req) returns websocket:Service|websocket:WebSocketError { return new WsService(); } } service class WsService { *websocket:Service; remote isolated function onText(websocket:Caller caller, string data) { } remote isolated function onBinary(websocket:Caller caller, byte[] data) { } }