How to Write a Connector in Ballerina
Writing a Twitter client in Ballerina
NOTE: All the Ballerina codes in this article are tested and compatible with Ballerina Swan Lake Beta versions
TL; DR
We build a Twitter connector, which can be used to Tweet, Retweet etc. with the use of Ballerina programming language. Then we publish it to Ballerina Central using GitHub Actions and make our connector available to use by everyone.
GitHub Repository:
Connector in Ballerina Central:
Prerequisites
Before starting, you have to setup your machine with Ballerina. Please refer to Setting up Ballerina guide.
Once you have successfully installed Ballerina, execute bal -v
command to make sure it works. This should display the Ballerina version you installed.
Let’s Start
NOTE: To make this article simple and easy to understand, I will use Twitter as an example. So that, at the end of this article you will build a Twitter connector for Ballerina and you can Tweet with Ballerina!
Creating a Client
The client
is an object type of Ballerina, where it may have remote methods to send network messages to a remote process according to some protocol. So, this can be used to connect to external systems by handling security and everything which are required by external system. So that, end user does not need to worry about protocol complexities. Simply, this is a wrapper of external system.
Here we create a Twitter Client which is used to call Twitter REST API.
We implement the client
and related files in the src/
folder added when creating the module.
<project-name>/src/<module-name>/twitter_client.bal
The following code sample demonstrates a simple Twitter Client
followed by the explanation. To make this code sample, easy to understand, I have removed all the documentations.
When initializing the Twitter Client
object, we use a set of configurations as a record called Configuration
. This record will be initialized by the end user inputs and will get passed to the constructor of the Twitter Client
object. These configurations are used to call the actual REST API inside the remote function. This may have authn/authz configurations, proxy configurations etc. which are needed to connect the actual REST API.
The remote functions which calls the actual REST API are defined as follows:
public remote function foo() returns bar {
// Remote function implementation goes here.
}
The remote function implementation should do the followings:
- Build the HTTP Request with the authentication information required by the REST API.
- Call the REST API with Ballerina HTTP client.
- Get the result of the API invocation.
- If the API invocation is success return the success status/result, else, return a meaningful error.
Testing
Writing test cases is a best practice when developing a connector. For this, we use Testerina, which is the built-in test framework of Ballerina.
To test Twitter Client, first we must obtain API keys and tokens to from Twitter. If you have already obtained the values needed to initialize theConfiguration
record we created previously, please ignore this step.
- Create a Twitter account, if you don’t have any.
- Visit https://apps.twitter.com/app/new and sign in.
- Provide the required information about the application.
- Agree to the Developer Agreement and click “Create your Twitter application”.
- After creating your Twitter application, your “Consumer Key” and “Consumer Secret” will be displayed in the “Keys and tokens” tab of your app on Twitter.
- Click the “Keys and tokens” tab, and then enable your Twitter account to use this application by clicking the “Create my access token” button.
- Copy the Consumer key (API key), Consumer Secret (API secret key), Access Token, and Access Token Secret from the screen.
NOTE: For more information, refer to the Getting started guide.
We implement the test cases in the tests/
folder added when creating the module.
<project-name>/src/<module-name>/tests/twitter_client_test.bal
Now, you can initialize the Twitter Client
by passing the Configuration
record with obtained values and then you call the remote actions you have implemented.
The following code sample demonstrates a test case for the Twitter Client
.
Now, execute the following command from your <project-name>
folder
$ ballerina test <module-name>
If your credentials are valid, the program should print the test status/result. But if there are any compile errors, you need to fix them first.
This is a sample of the complete output for the above command. You should get something like this. It shows the status of your test cases as well.
Compiling source
ldclakmal/twitter:1.0.0Creating balos
target/balo/twitter-2020r1-any-1.0.0.baloRunning Tests
ldclakmal/twitter:1.0.0
createdAt=Fri May 01 14:23:54 +0000 2020 id=1256227851508101125 text=Welcome to Ballerina Twitter Connector! source=<a href="https://central.ballerina.io/ldclakmal/twitter" rel="nofollow">Ballerina Twitter Client</a> truncated=false favorited=false retweeted=false favoriteCount=0 retweetCount=0 lang=en [pass] testTweet 1 passing
0 failing
0 skipped
Congratulations! Now you have implemented a Ballerina connector and tested it successfully. It is simple as that.
Please, refer the following guide to learn how to test ballerina code further.
Please refer this GitHub Project for the full implementation of Twitter Connector for Ballerina.
Publish your connector to the World!
This is the next step you should do to make your connector available for everyone to use. All the Ballerina connectors are hosted in Ballerina Central. So that any interested developer can pull and use your connector. Hence it is important to write the Module.md
file properly. That is the guide, that you display on Ballerina Central, instructing the users, how to use it. Please refer the Module.md of sample connector as an example.
First, you need to create an account in Ballerina Central. You can sign up with you “Google account” or “GitHub account” as you wish. Then you must create an organization at User Dashboard.
Now, you can get your “Ballerina Central access token” from the dashboard. Before you push your module, you must enter your “Ballerina Central access token” in Settings.toml
file in your home repository (<USER_HOME>/.ballerina/
).
Finally, you should update the Ballerina.toml
file of your project. This file is automatically created when you create a new project.
<project-name>/Ballerina.toml
The content of the file will be as follows. Most importantly, the name of the organization you created at Ballerina Central, should matched to the org-name
given at Ballerina.toml
file.
[project]
org-name = "ldclakmal"
version = "1.0.0"
license = ["Apache-2.0"]
authors = ["Chanaka Lakmal"]
repository = "https://github.com/ldclakmal/ballerina-twitter-module"
keywords = ["ballerina", "twitter", "connector", "integration"]
NOTE: When you push a module to Ballerina Central, the runtime validates organizations for the user against the org-name defined in your module’s Ballerina.toml
file. Therefore, when you have more than one organization in Ballerina Central, be sure to pick the organization name that you intend to push the module into and set that as the org-name
in the Ballerina.toml
file inside the project directory.
Now, you can push your connector to Ballerina Central. For that, there are 2 options that you can follow.
- Ballerina CLI commands
- GitHub actions
1. Ballerina CLI commands
This is a straightforward method. You must go to the <project-name>
folder and execute the following commands in order.
The first command will build your module with all the test cases and generate executable.
$ ballerina build <module-name>
The second command will push your module to Ballerina Central.
$ ballerina push <module-name>
NOTE: If there are any errors when building your connector, which is because of the program errors you have. You need to fix this. But, if you have successfully tested in the previous step, there can’t be errors when building a module.
Congratulations! Now you have published your connector in Ballerina Central successfully. It is simple as that.
Now, it should be displayed in Ballerina Central.
2. GitHub actions
This is an automated process where you can use push your connector to Ballerina Central when you do a release on GitHub. If you are not familiar with GitHub releases, please refer to the following article.
For this, you have a create a configuration file (YAML file) in following path. Let’s name it release.yml
file.
<project-name>/.github/workflows/
When you configure a GitHub workflow, there are few things you need to know. For more information, please refer to following documentation.
For this sample, let’s create our release.yml
file with following configurations.
Here, you can see there are 2 stages.
- Ballerina Build
- Ballerina Push
At the first stage, we set 4 environmental variables which are used to test the connector while building the connector.
env:
CONSUMER_KEY: ${{ secrets.CONSUMER_KEY }}
CONSUMER_SECRET: ${{ secrets.CONSUMER_SECRET }}
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
ACCESS_TOKEN_SECRET: ${{ secrets.ACCESS_TOKEN_SECRET }}
At the second stage, we set another environmental variable which is used to push the connector to Ballerina Central.
env:
BALLERINA_CENTRAL_ACCESS_TOKEN: ${{ secrets.BALLERINA_CENTRAL_ACCESS_TOKEN }}
You already know what are the values that should be used to this. Since those are sensitive informations, it is recommended to store them as encrypted secretes in GitHub. You can do it via the UI of your GitHub repository.
NOTE: When you store the secrets, the key-name of the secret value should be matched to the key-name set at the release.yml
.
Please refer to following article for more information on how to store secrets.
Now, all the configurations are done. You can start a release from GitHub UI. Go to, “Actions” tab of the GitHub repository. You can see, the progress of the workflow. Here is an example of successful workflow of my connector. You can refer to it with link given.
Congratulations again! Now you have published your connector in Ballerina Central successfully. It is simple as that.
Now, it should be displayed in Ballerina Central.
How to use Ballerina connector
Now, it is time to see, how to use your connector as a developer who is interested to use the Twitter services without worrying about its REST API.
You can create a new Ballerina project and follow the steps below. But to make this easy to understand, let’s create a .bal
file called twitter-test.bal
and follow the steps.
First, import your connector with import <org-name>/<module-name>
pattern.
import ldclakmal/twitter;
Now initialize the Twitter Client
with the obtained tokens.
twitter:Configuration twitterConfig = {
consumerKey: "Twitter App Consumer Key",
consumerSecret: "Twitter App Consumer Secret",
accessToken: "Twitter App Access Token",
accessTokenSecret: "Twitter App Access Token Secret",
};
twitter:Client twitterClient = new(twitterConfig);
Now, in the main function, you have to call the connector functions implemented. For this example, let’s use tweet
API, which sends a Tweet message.
public function main() {
string status = "Welcome to Ballerina Twitter Connector!";
var tweetResponse = twitterClient->tweet(status);
if (tweetResponse is twitter:Status) {
io:println(tweetResponse);
} else {
log:printError("Failed to tweet: " + <string>tweetResponse.detail()["message"]);
}
}
Now, you must try and see. Execute the following commands to run your .bal
file. You should get the details of your Twitter response printed on your terminal. Also, you can view your tweet from Twitter app as well.
$ ballerina run twitter-test.bal
You are done! It is as simple as that.
Happy coding with Ballerina!