This is an example of how to decouple dependent micro-services by adding the Camunda Engine as part of the architecture. The project can be seen being demoed at this talk, which took place at Devoxx Belgium 2019.
There are 3 services a cashier
frontend where you can make orders to an order sorter
the order sorter will then request coffee from the barista
service if required.
There are two versions of the architecture
- Synchronous. All communication between services is completed in one transaction per request.
- Asynchronous. Each request is persisted and completed in a new transaction while waiting for the potential of additional requests.
To start the Synchronous version of this example open and build the following 3 Spring Boot projects
- Cashier - Which will start on http://localhost:8082
- Barista - Which will start on http://localhost:8081
- Sort Order Sync - Which will start on http://localhost:8080
Each of these can be started within your IDE as a Spring Boot project. You can also build them and start the jar file in the generated target folder.
Once each is started you can enter orders by going to the Cashier Homepage.
When the submit button is clicked it will send a REST call http://localhost:8080/order-up
to the Order-Sorter service with a payload that includes the order and the name of the person making the order.
If the order contains coffee
then it will call the barista service on http://localhost:8081/WorkIt/
. Once the coffee is ready it returns to the order sorter, which will return the result to the frontend, which will display Order of [orderMessage] Is Ready
This architecture only requires a change to the Order Sorter
the goal is to change this service so that instead of running synchronously for each request, it will actually hold the state of each request and return the result of the request with an asynchronous call.
To start this version of the project you need to start (if you haven't already):
- Cashier - Which will start on http://localhost:8082
- Barista - Which will start on http://localhost:8081
You will need to shut down Sort Order Sync and instead start up Sort Order aSync. Both use the same port (8080) so you can't run them at the same time.
Once an order is made the state will be kept by the Camunda Engine and you can view the current state by going to Cockpit on http://localhost:8080/
you can log in with:
username reb
password reb
Navigate to Cockpit or go directly through this link http://localhost:8080/app/cockpit/default/
There are a number of changes made to Sort Order project to give us the features we need.
- Camunda Engine is added to the project
- Callback service is created and called
- Process Model is created and added
- Camunda Engine is autowired in the service and a process is started
- The
application.yaml
has the Camunda configuration added to it.
The Camunda Engine and the Camunda webapps are added to the project by adding the following dependencies to the pom.xml
file.
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
<version>7.15.0</version>
</dependency>
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
<version>7.15.0</version>
</dependency>
A callback bean called tellCashierAboutOrder
is added to the project so that we can asynchronously contact the front end of the cashier service with the result of the request.
The process engine needs this BPMN model to describe how the process should proceed, what should be called and where to commit transactions. This is added to the resources
folder.
The Engine's RuntimeService is added to the ServiceController
class
@Autowired
private RuntimeService runtimeService;
and the process model is called directly when the REST request comes in.
runtimeService.startProcessInstanceByKey("ProcessOrder", businessKey, vars);
To log into the webapps a user needs to be defined. This is added to the application.yaml
file
camunda:
bpm:
admin-user:
id: reb
password: reb
firstName: Reb