Service Orchestration¶
Overview¶
In this tutorial, you’ll create a service to process appointment requests for hospitals. The service will call multiple backend services sequentially, using data from each call to inform the next. This approach integrates several services into one, known as service orchestration. To implement this, you’ll build a REST service with a single resource in Ballerina Integrator extension and then run the service. The resource will receive user requests, make the necessary backend calls, and respond with the appointment details.
The flow is as follows.
- The user sends an appointment request to the service.
{ "patient": { "name": "John Doe", "dob": "1940-03-19", "ssn": "234-23-525", "address": "California", "phone": "8770586755", "email": "[email protected]", "cardNo": "7844481124110331" }, "doctor": "thomas collins", "hospital_id": "grandoaks", "hospital": "grand oak community hospital", "appointment_date": "2024-11-06" }
- Extract necessary details from the request (e.g., hospital, patient, doctor, etc.) and make a call to the hospital backend service to request an appointment. A response similar to the following will be returned from the hospital backend service on success.
{ "appointmentNumber": 1, "doctor": { "name": "thomas collins", "hospital": "grand oak community hospital", "category": "surgery", "availability": "9.00 a.m - 11.00 a.m", "fee": 7000 }, "patient": { "name": "John Doe", "dob": "1940-03-19", "ssn": "234-23-525", "address": "California", "phone": "8770586755", "email": "[email protected]" }, "hospital": "grand oak community hospital", "confirmed": false, "appointmentDate": "2023-10-02" }
- Use the hospital ID and the appointment number and call the hospital backend service to retrieve the fee for the appointment. The response will be similar to the following.
{ "patientName": "John Doe", "doctorName": "thomas collins", "actualFee": "7000" }
- Finally, call the payment backend service to make the payment and retrieve the reservation status.
{ "appointmentNo": 2, "doctorName": "thomas collins", "patient": "John Doe", "actualFee": 7000, "discount": 20, "discounted": 5600.0, "paymentID": "f130e2ed-a34e-4434-9b40-6a0a8054ee6b", "status": "settled" }
Prerequisites¶
- Docker installed on the machine.
Step 1: Create a new integration project¶
- Click on the Ballerina Integrator icon on the sidebar.
- Click on the Create New Integration button.
- Enter the project name as
ServiceOrchestration
. - Select project directory location by clicking on the Select Location button.
- Click on the Create New Integration button to create the integration project.
Step 2: Create an HTTP service¶
- In the design view, click on the Add Artifact button.
- Select HTTP Service under the Integration as API category.
- Select the + Listeners option from the Listeners dropdown to add a new listener.
- Enter the listener name as
healthListener
,8290
as the port and click on the Save button. - Add the service base path as
/healthcare
and select the Design from Scratch option as the The contract of the service. -
Click on the Create button to create the new service with the specified configurations.
Step 3: Define types¶
-
Click on the Add Artifacts button and select Type in the Other Artifacts section.
-
Click on + Add Type to add a new type Generate record types corresponding to the response from the hospital backend service by providing a sample of the expected JSON payload. The values are given below.
Type Name Sample JSON value Make Separate Record Definition Record ReservationRequest {"patient":{"name":"John Doe","dob":"1940-03-19","ssn":"234-23-525","address":"California","phone":"8770586755","email":"[email protected]","cardNo":"7844481124110331"},"doctor":"thomas collins","hospital_id":"grandoaks","hospital":"grand oak community hospital","appointment_date":"2024-11-06"}
☑️ Record ReservationStatus {"appointmentNo":1, "doctorName":"thomas collins", "patient":"John Doe", "actualFee":7000.0, "discount":20, "discounted":5600.0, "paymentID":"e560ea82-1c42-4972-a471-af5c1ad4995f", "status":"settled"}
☑️ Record Appointment {"appointmentNumber":12345,"doctor":{"name":"Dr. Alice Carter","hospital":"Green Valley Hospital","category":"Cardiology","availability":"Mon-Fri, 9 AM - 5 PM","fee":200},"patientName":"Emma Johnson","hospital":"Green Valley Hospital","confirmed":true,"appointmentDate":"2024-11-20T10:00:00"}
☑️ Record Fee {"patientName":"Emma Johnson","doctorName":"Dr. Alice Carter","actualFee":"150.00"}
-
The final types will look like the following.
Step 4: Add connections¶
- Navigate to design view and click on the Add Artifacts button and select Connection in the Other Artifacts section.
- Search and select the HTTP Client connector.
-
Enter the connector name as
hospitalEp
, URL ashttp://localhost:9090
and click on the Save button. -
Add another connector for the payment backend service with the URL
http://localhost:9090/healthcare/payments
and the namepaymentEp
.
HTTP Connector
To learn more about HTTP client, see Ballerina HTTP Client. See supported client configurations in the HTTP Client Configurations.
Step 5: Design the resource¶
- The service will have a default resource named
greeting
with the GET method. Click on three dots appear in front of the/healthCare
service resource and select Edit from menu. - Change the resource HTTP method to POST.
- Change the resource name as
categories/[string category]/reserve
. - Add a payload parameter named
reservation
to the resource of typeReservationRequest
. - Change the 201 response return type to
ReservationStatus
. -
Add a new response of type HttpNotFound under the responses.
-
Click on the Save button to save the resource.
Step 6: Make the appointment request¶
- Click on the
categories/[string category]/reserve
resource to navigate to the resource implementation designer view. - Delete the default
Return
action from the resource. - Hover to the arrow after start and click the ➕ button to add a new action to the resource.
- Select Declare Variable from the node panel on the left. This variable will be used to store the request payload for the hospital service.
- Change the variable name to
hospitalRequest
, type asjson
and expression as below.{ patient:{ name: reservation.patient.name, dob: reservation.patient.dob, ssn: reservation.patient.ssn, address: reservation.patient.address, phone: reservation.patient.phone, email: reservation.patient.email }, doctor: reservation.doctor, hospital: reservation.hospital, appointment_date: reservation.appointment_date }
-
Click on the Save button to add the variable.
-
Click ➕ sign and select hospitalServicesEp connector from the node panel and select post from the dropdown. Then, fill in the required fields with the values given below and click Save.
Field Value Variable Name appointment
Variable Type Appointment
Resource Path string `/${reservation.hospital_id}/categories/${category}/reserve`
message hospitalRequest
-
The connector action will look like the following.
Step 7: Get the fee¶
-
Declare an int variable named
appointmentNumber
with expressionappointment.appointmentNumber
after the hospital service request. -
Let's add another connector invocation to get the fee for the appointment. Click on the ➕ sign and select hospitalServicesEp connector from the node panel.
-
Select get from the dropdown. Then, fill in the required fields with the values given below and click Save.
Field Value Variable Name fee
Variable Type Fee
Resource Path string `/${reservation.hospital_id}/categories/appointments/${appointmentNumber}/fee`
Step 8: Make the payment¶
- Declare a decimal type variable named
actualFee
with expressioncheck decimal:fromString(fee.actualFee)
after the fee request. -
Create another new to prepare the payment request. Click on the ➕ sign and select Declare Variable from the node panel. Add a variable named
paymentRequest
with the type json and expression as below.{ appointmentNumber: appointmentNumber, doctor: appointment.doctor.toJson(), patient: check hospitalRequest.patient, fee: actualFee, confirmed: false, card_number: reservation.patient.cardNo }
-
Let's add another connector action to make the payment. Click on the ➕ sign and select paymentEP connector from the node panel. Select post from the dropdown.
-
Then, fill in the required fields with the values given below and click Save.
Field Value Variable Name status
Variable Type ReservationStatus
Resource Path "/"
message paymentRequest
-
Click on the ➕ sign and select Return from the node panel. Add the
status
variable to the return node. -
The final integration will look like the following.
Step 9: Run the service¶
- Click on the Run button to start the service.
- Start the backend service by executing the following command in a terminal.
docker run --name hospital-backend -p 9090:9090 -d anuruddhal/kola-hospital-backend
- Click on the Run on the run button (▶️) in the top right corner to run the service.
- The service will start and the service will be available at
http://localhost:8290/healthcare/categories/[category]/reserve
. - Click on the Try it button to open the embedded HTTP client.
- Replace the {category} with
surgery
in the resource path and enter the following JSON payload in the request body and click on the ▶️ button to send the request.{ "patient": { "name": "John Doe", "dob": "1940-03-19", "ssn": "234-23-525", "address": "California", "phone": "8770586755", "email": "[email protected]", "cardNo": "7844481124110331" }, "doctor": "thomas collins", "hospital_id": "grandoak", "hospital": "grand oak community hospital", "appointment_date": "2023-10-02" }
-
The response will be similar to the following.
{ "appointmentNo": 1, "doctorName": "thomas collins", "patient": "John Doe", "actualFee": 7000, "discount": 20, "discounted": 5600, "paymentID": "b219c4ad-5365-4a22-ae35-048bb8e570e7", "status": "settled" }
-
You can also test the service using the curl command.
curl -X POST "http://localhost:8290/healthcare/categories/surgery/reserve" \ -H "Content-Type: application/json" \ -d '{ "patient": { "name": "John Doe", "dob": "1940-03-19", "ssn": "234-23-525", "address": "California", "phone": "8770586755", "email": "[email protected]", "cardNo": "7844481124110331" }, "doctor": "thomas collins", "hospital_id": "grandoak", "hospital": "grand oak community hospital", "appointment_date": "2023-10-02" }'
Step 10: Stop the integration¶
- Click on the Stop button to stop the integration or press
Shift
+F5
. - Stop the hospital backend server by running the following command:
docker stop hospital-backend