Build a Microservice in 4 Steps: An Introduction to Jolie
A brief introduction to how the microservice-oriented Jolie programming language can be used to build microservices. We cover the four cardinal elements of service programming: APIs, Services, Access Points, and Behaviour.
Join the DZone community and get the full member experience.Join For Free
Jolie is a microservice-oriented language: it provides linguistic primitives (or abstractions) that address the common concerns of microservice design and implementation, in order to make their development more effective.
In this tutorial, we are going to get familiar with the basic aspects of the language, building a simple service that offers an operation for greeting people over HTTP+JSON. (The version of Jolie used in this article is 1.10.)
You can see a live coding demo in this video (it lasts about 3 minutes):
Step 1: APIs
Let's start from the API (Application Programming Interface) of our service.
First, we define a data type for the requests for greetings that we are going to get from clients, called
GreetingRequest. It contains a string called
name. (Jolie is not highlighted correctly on DZone yet, so we use TypeScript highlighting in this article.)
Then, we define a data type for the greetings that we are going to send back to clients in response, called
Greeting. It contains a string called
We can now use our data types to define an interface (Jolie for API), which specifies an operation,
greet, that our service is going to offer to clients.
RequestResponse means that operation
greet receives a request and always sends back a response to clients (Jolie also offers OneWay as an alternative, for simple communication/notifications). The
greet operation expects requests of type
GreetingRequest and sends back responses of type
That's it for the API!
Step 2: Services
Next up, we define our service. Jolie provides a native primitive for defining a service, called (unsurprisingly)
service. We call our service
Greeter. We use the
execution keyword to specify that we want
Greeter to handle clients concurrently.
The definition of service
Greeter needs to be filled with two essential components: at least one access point, which defines how the service can be accessed by clients, and its behavior, which defines the business logic that actually implements the API offered by the service. We write these components in the following (and last) two steps.
Step 3: Access Points
An access point is created by using the keyword
inputPort. To define an access point, we must state:
- The location at which clients can reach the service.
- The transport protocol that clients should use to communicate.
- The interfaces (that is, the APIs) that can be accessed.
Each one of these components has a corresponding primitive in Jolie. Below, we define an access point that:
- Accepts connections on TCP port 8080.
- Uses HTTP as a transport protocol, encoding data with the JSON format by default.
- Exposes the GreeterIface API.
Step 4: Behavior
We now define a behavior for our
Greeter service. We want it to:
- Receive a message for the
greetoperation from any client. In Jolie, this is done simply by writing the name of the operation.
- Store the received client request in a variable, say
- Compute a response containing a greeting, for example using a variable called
This corresponds to the following Jolie code.
Running Your Service
Let's review the code that we have so far:
Let's store this code in a file with the .ol suffix, say main.ol, and we are ready to go. Run this command:
Your service is now waiting for client requests. Let's give it one! Run the following curl command:
You'll see the output:
If you want to get in touch, we are active on our Discord server!
Bonus: A Reflection on Effectiveness and Technology Agnosticism
This simple example is already enough to showcase a couple of important aspects of Jolie.
The first aspect is that the coding of a service in Jolie is very similar to the usual conceptual models used for services: we have defined data types (for the data model), an interface, a service, an access point, and an implementation (the behavior). This helps in making us productive!
The second aspect is that Jolie is designed for integration. If you like, Jolie is a technology designed for technology agnosticism. Its data type language captures DTOs (Data Transfer Objects), assuming only native types that are available in most technologies (strings, booleans, etc.). The language for expressing behaviors abstracts from how data is encoded on the wire: for example, in the behavior that we wrote above, nothing says that the (data in the) variables
response are going to be de-/encoded in JSON. This is visible only in the access point, which we are thus free to change as we see fit. For example, say that we wanted to access our
Greeter service by sending requests encoded in XML instead of JSON. We just need to change the input port of
Greeter to use XML as follows:
Similarly, we could make
Greeter accessible over binary protocols or even different kinds of protocols at once.
These are just a few tastes of some of the design principles of Jolie. We'll explore more and delve deeper in the future!
Parts of this article previously appeared on https://fmontesi.github.io/2015/02/06/programming-microservices-with-jolie.html and https://fmontesi.github.io/2020/09/30/service-oriented-programming-languages.html.
Opinions expressed by DZone contributors are their own.