- 2201.12.10 (Swan Lake Update 12)
- 2201.12.9 (Swan Lake Update 12)
- 2201.12.8 (Swan Lake Update 12)
- 2201.12.7 (Swan Lake Update 12)
- 2201.12.6 (Swan Lake Update 12)
- 2201.12.5 (Swan Lake Update 12)
- 2201.12.4 (Swan Lake Update 12)
- 2201.12.3 (Swan Lake Update 12)
- 2201.12.2 (Swan Lake Update 12)
- 2201.12.1 (Swan Lake Update 12)
- 2201.12.0 (Swan Lake Update 12)
- 2201.8.10 (Swan Lake Update 8)
- 2201.8.9 (Swan Lake Update 8)
- 2201.8.8 (Swan Lake Update 8)
- 2201.8.7 (Swan Lake Update 8)
- 2201.8.6 (Swan Lake Update 8)
- 2201.8.5 (Swan Lake Update 8)
- 2201.8.4 (Swan Lake Update 8)
- 2201.8.3 (Swan Lake Update 8)
- 2201.8.2 (Swan Lake Update 8)
- 2201.8.1 (Swan Lake Update 8)
- 2201.8.0 (Swan Lake Update 8)
- 1.2.62
- 1.2.61
- 1.2.60
- 1.2.59
- 1.2.58
- 1.2.57
- 1.2.56
- 1.2.55
- 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 Alpha2
This Alpha2 release includes the language features planned for the Ballerina Swan Lake release. Moreover, this release includes improvements and bug fixes to the compiler, runtime, standard library, and developer tooling. This release note lists only the features and updates added after the Alpha1 release of Ballerina Swan Lake.
- Updating Ballerina
- Highlights
- What is new in Ballerina Swan Lake Alpha2
Updating Ballerina
You can use the update tool to update to Ballerina Swan Lake Alpha2 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.
bal update
If you are using an update tool version below 0.8.14, execute the ballerina update command to update it. Next, execute the command below to update to Swan Lake Alpha2.
bal dist pull slalpha2
For new users
If you have not installed Ballerina, then download the installers to install.
Highlights
- Support for mapping and error binding patterns in the
matchstatement - Support for configurable variables of
recordandtabletypes - Support for decrypting string values using the new
lang.configlang library - Improvements to the HTTP, MIME, WebSocket, GraphQL, WebSub, WebSubHub, IO, email, UDP, crypto, and JWT standard library modules
- The extension of the Ballerina package distribution file has been changed from
.baloto.bala - Improvements to developer tools such as the Language Server and debugger
What is new in Ballerina Swan Lake Alpha2
Language
Support for mapping and error binding patterns in the match statement
Mapping binding pattern
The match statement now supports mapping and error binding patterns with var.
match v { var {a, b} => { // Matches mappings that contain at least the fields `a` and `b`. // The values of these fields can be accessed via the variables // `a` and `b` within this block. io:println(a); } var {c: {x: a1, y: a2}, ...rest} => { // Matches mappings that have a field `c` where its value is // another mapping that contains at least the fields `x` and `y`. // All of the remaining fields (if any) can be accessed via // the new variable `rest`. int length = rest.length(); } }
Error binding pattern
match v { var error(message, error(causeMessage)) => { // Matches errors that have a cause. // The messages of the matched error and the cause error // can be accessed via the variables `message` and // `causeMessage` within this block. io:println(causeMessage); } var error(a, code = matchedCode) => { // Matches errors that have a detail entry with the key `code`. // The `code` can be accessed using the `matchedCode` variable // within this block. io:println(matchedCode); } }
Runtime
Support for configurable variables of record and table types
Record type
Record fields with simple types like int, string, boolean, float, decimal, and arrays of the respective types are now supported.
For example, if the Config.toml file contains the following TOML table,
[Pkg.testUserOne] username = "john" password = "abcd" scopes = ["write"] [Pkg.testUserTwo] username = "mary" password = "test123"
it can be loaded as configurable variables of a record type as follows.
type AuthInfo record { readonly string username; string password; string[] scopes?; }; configurable AuthInfo & readonly testUserOne = ?; configurable AuthInfo & readonly testUserTwo = ?;
Table type
Ballerina now supports configurable variables of type table through TOML arrays of tables.
For example, if the Config.toml file contains the following TOML table array,
[[Pkg.users]] username = "alice" password = "password1" scopes = ["scope1"] [[Pkg.users]] username = "bob" password = "password2" scopes = ["scope1", "scope2"] [[Pkg.users]] username = "jack" password = "password3"
it can be loaded as a configurable variable of a table type as follows.
configurable table<AuthInfo> key(username) & readonly users = ?;
Support for decrypting string values using the new config lang library
The bal encrypt command can be used to encrypt plain text values and specify those in the Config.toml file. Then, the config:decryptString() function can be used to decrypt the configurable value.
For example, if the Config.toml file contains the following encrypted string value,
password = "@encrypted:{ODYUoKSw0xW31eoxa/s2ESdBNgk1gX77txBIgpLC6NQ=}"
it can be decrypted in the Ballerina code as follows.
import ballerina/lang.config; configurable string password = ?; public function main() { string decryptedPassword = config:decryptString(password); }
Standard library
HTTP module improvements
Introduced byte stream manipulation functions to the request and response
This introduction enables manipulating the payload as a stream of byte[]. The setByteStream() and getByteStream() methods use the Ballerina stream feature.
http:Request request = new; io:ReadableByteChannel byteChannel = check io:openReadableFile("path/to/file.tmp"); stream<io:Block, io:Error> byteStream = check byteChannel.blockStream(8196); request.setByteStream(byteStream); http:Response response = new; stream<byte[], io:Error>|error str = response.getByteStream();
Introduced the http:Header annotation to bind headers in an inbound request
With the introduction of the @http:Header annotation, inbound request headers can be retrieved by binding them to a resource method parameter. Individual headers can be accessed as string or string[] types while a parameter of type http:Headers can be used to access all headers.
service on helloEP { resource function get hello(@http:Header {name: "Accept"} string? acceptHeader, http:Headers allHeaders) { //... } }
MIME module improvements
Introduced byte stream manipulation methods to the mime:Entity class
This introduction enables manipulating the entity body as a stream of byte[].
function setByteStream(stream<byte[], io:Error> byteStream, string contentType = "application/octet-stream") function getByteStream(int arraySize = 8196) returns stream<byte[], io:Error>|mime:ParserError function getBodyPartsAsStream(int arraySize = 8196) returns stream<byte[], io:Error>|mime:ParserError
WebSocket module improvements
Introduced the Sync client. This is the primary client of the WebSocket module. This client is capable of reading and writing messages synchronously.
Reading and writing text messages
websocket:Client wsClient = check new ("ws://echo.websocket.org"); var err = wsClient->writeTextMessage("Text message"); string textResp = check wsClient->readTextMessage();
Reading and writing binary messages
websocket:Client wsClient = check new ("ws://echo.websocket.org"); var err = wsClient->writeBinaryMessage("Binary message".toBytes()); byte[] byteResp = check wsClient->readBinaryMessage();
GraphQL module improvements
Ballerina GraphQL listeners can now be configured using the same configurations as the listener configurations in http:Listener. Additionally, a GraphQL service can be secured by defining a maxQueryDepth as an annotation to restrict the depth of a query before execution.
import ballerina/graphql; graphql:ListenerConfiguration configs = { // http listener configurations }; listener graphql:Listener graphqlListener = new (9090, configs); @graphql:ServiceConfiguration {maxQueryDepth: 3} service /graphql on graphqlListener { // Service definition }
WebSub module improvements
Included functionality to the websub:SubscriberService to respond with user-defined custom payloads/header parameters in error scenarios.
import ballerina/websub; listener websub:Listener subscriberListener = new (9001); service /subscriber on subscriberListener { remote function onSubscriptionValidationDenied(websub:SubscriptionDeniedError msg) returns websub:Acknowledgement? { websub:Acknowledgement ack = { headers: { "Content-Encoding": "gzip" }, body: { "message": "Successfully processed request" } }; return ack; } remote function onSubscriptionVerification(websub:SubscriptionVerification msg) returns websub:SubscriptionVerificationSuccess|websub:SubscriptionVerificationError { if (msg.hubTopic == "https://www.sample.topic") { return error websub:SubscriptionVerificationError("Hub topic not supported", headers = {"Content-Encoding": "gzip"}, body = {"message": "Hub topic not supported"}); } else { return {}; } } remote function onEventNotification(websub:ContentDistributionMessage event) returns websub:Acknowledgement| websub:SubscriptionDeletedError? { return error websub:SubscriptionDeletedError("Subscriber wants to unsubscribe", headers = {"Content-Encoding": "gzip"}, body = {"message": "Unsubscribing from the topic"}); } }
WebSubHub module improvements
Included functionality to the websubhub:Service to respond with user-defined custom payloads/header parameters in error scenarios.
import ballerina/websubhub; service /websubhub on new websubhub:Listener(9091) { remote function onRegisterTopic(websubhub:TopicRegistration message) returns websubhub:TopicRegistrationSuccess|websubhub:TopicRegistrationError { if (message.topic == "https://sub.topic.com") { websubhub:TopicRegistrationSuccess successResult = {body: <map<string>>{isSuccess: "true"}}; return successResult; } else { return error websubhub:TopicRegistrationError("Topic registration failed!", headers = {"Content-Encoding": "gzip"}, body = {"hub.additional.details": "Feature is not supported in the hub"}); } } // Other remote methods... }
IO module improvements
Introduce a parameter of type XmlWriteOptions to specify the entity type and the document type declaration.
public function fileWriteXml(@untainted string path, xml content, *XmlWriteOptions xmlOptions, FileWriteOption fileWriteOption = OVERWRITE) returns Error? { }
Example
import ballerina/io; public function main() returns error? { xml content = xml `<note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note>`; string publicId = "-//W3C//DTD HTML 4.01 Transitional//EN"; string systemId = "http://www.w3.org/TR/html4/loose.dtd"; var writeResult = io:fileWriteXml("./xmlFileWithDoc.xml", content, doctype = { system: systemId, 'public: publicId }); }
Output
<!DOCTYPE note PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <note> <to>Tove</to> <from>Jani</from> <heading>Reminder</heading> <body>Don't forget me this weekend!</body> </note>
Email module improvements
-
Make the
bodyfield of theemail:Messagerecord optional. This enables sending an email with only thehtmlBodyfield set without a text-typedbodyfield. -
Add
mime:Entitytype to the union type of theattachmentsfield in theemail:Messagerecord. That enables attaching a single MIME Entity as an attachment. Thisemail:Messagerecord change would appear as follows.
public type Message record {| // ... other fields mime:Entity|Attachment|(mime:Entity|Attachment)[] attachments?; |};
- The above-mentioned changes related to the
bodyandattachmentsfields are updated in theemail:Optionsrecord as given below in order to facilitate the same in thesendEmailmethod in theemail:SmtpClient.
public type Options record {| // ... other fields string body?; mime:Entity|Attachment|(mime:Entity|Attachment)[] attachments?; |};
-
Remove the
propertiesfield representing custom properties from all Email module related configuration records:email:SmtpConfig,email:PopConfig,email:ImapConfig,email:PopListenerConfig, andemail:ImapListenerConfig. -
The
mail.smtp.ssl.checkserveridentitycustom property was passed as an entry in thepropertiesto enable/disable the server certificate’s hostname verification. As thepropertiesfield is removed from the API, from this release onwards, theverifyHostNameboolean field is introduced to thesecureSocketrecord for all the configurations related to the Email module.
This email:SecureSocket record change would appear as follows.
public type SecureSocket record {| // ... other fields boolean verifyHostname = true; |};
UDP module improvements
-
The
sendDatagrammethod will now send multiple datagrams if the size of thebyte[]value provided as thedatafield of the datagram exceeds 8KB. -
Returning
Datagramfrom theonDatagramoronBytesremote methods also sends multiple datagrams if the size of thebyte[]value provided (as thedatafield of the datagram) exceeds 8KB.
Crypto module improvements
Added support to decode private keys from .key files and public keys from .cert files and updated the APIs for decoding private/public keys. This enables reading private/public keys from PEM files.
JWT module improvements
Extended the private key support for JWT signature generation and public cert support for JWT signature validation.
Log module improvements
Introduced a configuration in the log module to set the output format to JSON. You need to add the entry below in the Config.toml file to set the output format to JSON.
[ballerina.log] format = "json"
Code to Cloud
- The
Kubernetes.tomlfile is renamed toCloud.toml. - The
--cloud=dockerbuild option is implemented. This will build the Dockerfile and Docker image without generating the Kubernetes artifacts.
Developer tools
Language Server
Implemented renaming support in the Language Server. Now, VSCode users are able to select a symbol and rename all occurrences within the same module as well as across modules.
Debugger
Added variable paging support. With this feature, the Ballerina variables, which contain a large number of child variables will be shown in a paged view in the debug variable presentation.
Ballerina Shell REPL [EXPERIMENTAL]
- Fixed the REPL expression output to output the
toBalString()result. - Improved the REPL parser to support some partial snippets such as the example cases below.
- Template strings will allow continuing on new lines.
- The CLI will wait for more input if the last character was an operator.
- The CLI will not wait for unclosed double quotes.
- Enabled REPL to exit on
Ctrl+D.
Breaking changes
- Member access on a value of type
tablenow returns()if thetabledoes not contain a member with the specified key. Otherwise, the result is the member in thetablevalue with the given key.
import ballerina/io; type Employee record { readonly string name; int id; }; public function main() { table<Employee> key(name) employeeTable = table [ {name: "Mike", id: 1234}, {name: "John", id: 4567} ]; Employee? emp1 = employeeTable["John"]; io:println(emp1); // {"name":"John","id":4567} Employee? emp2 = employeeTable["Kate"]; io:println(emp2 is ()); // true }
- Iterating over
xmlin afromclause in query expressions now returnsxmland iterating overxml<T>returnsT.
import ballerina/io; public function main() { xml authorList = xml `<authorList> <author> <name>Sir Arthur Conan Doyle</name> <country>UK</country> </author> <author> <name>Dan Brown</name> <country>US</country> </author> </authorList>`; xml authors = from xml y in authorList/<author>/<name> select y; io:println(authors); //<name>Sir Arthur Conan Doyle</name><name>Dan Brown</name> }
- Variables of types
readonlyandvalue:Cloneablecannot be assigned toanysince they may contain values of typeerror.