Using the strangler pattern
- Introduction
- Refactor the Catalog service to Quarkus
- Analyze the Mono2Micro results
- The Quarkus Event Producer
- The Event Consumer
- Run this solution
- Summary
Introduction
In this phase the backend application was analyzed and the Catalog service was identified as a candidate to be extracted in to it’s own Micro Service. The code was strangled from the monolith and deployed using Quarkus allowing the service to be developed, deployed and scaled independently of the rest of the application code.
Refactor the Catalog service to Quarkus
The Mono2Micro tool was used to identify the Catalog
service as a good candidate to become it’s own service. In this scenario, the Catalog
service handles information about the items in the store such as prices, titles, ratings and descriptions. When this information changes the store front as well as the items in the users carts should be updated.
Analyze the Mono2Micro results
Running Mono2Micro is out of the scope of this article but detailed steps can be found here.
The purple rectangle is essentially the catalog service (except of the missing Category class).
The green classes make up the remaining monolith (except of Address).
The red classes need to be assigned to either the catalog service of the remaining monolith dependent of class dependencies. Most of them are exceptions which weren’t covered in the use cases.
The Quarkus Event Producer
In order to display the new price, the order service (the remaining monolith) could invoke a synchronous REST API of the catalog service. However, in order to minimize the coupling between the components, we will use events instead.
Here is the code of the ‘strangled’ catalog service which has been implemented with Quarkus. The application uses MicroProfile and Kafka to send events asynchronously.
@PUT@Consumes("application/json")@Produces("application/json")@Path("/CustomerOrderServicesWeb/jaxrs/Product/{id}")@Transactionalpublic Product update(@PathParam("id") Long id, Product updatedProduct) {Product existingProduct = entityManager.find(Product.class, id);if (existingProduct == null) {throw new WebApplicationException(Response.Status.BAD_REQUEST);
The Event Consumer
The remaining monolith runs on Open Liberty. In order to prevent synchronous invocations of the catalog service, it caches the changed prices in it’s own Db2 database in a new column.
Here is the code of the remaining monolith which also uses MicroProfile.
import org.eclipse.microprofile.reactive.messaging.Incoming;import javax.enterprise.context.ApplicationScoped;import org.pwte.example.service.CustomerOrderServicesImpl;import javax.inject.Inject;@ApplicationScopedpublic class ProductPriceChanged {@Inject
Run this solution
Use the following steps to run this solution locally on Docker
$ git clone https://github.com/IBM/application-modernization-javaee-quarkus.git && cd application-modernization-javaee-quarkus$ ROOT_FOLDER=$(pwd)$ sh ${ROOT_FOLDER}/scripts-docker/build-and-run-monolith-db2.sh$ sh ${ROOT_FOLDER}/scripts-docker/run-database-postgres-catalog.sh$ sh ${ROOT_FOLDER}/scripts-docker/run-kafka.sh$ sh ${ROOT_FOLDER}/scripts-docker/build-and-run-catalog.sh
Summary
This application has been refactored in a series of steps from the original WebSphere ND v8.5.5 version to run as Micro Services on Red Hat OpenShift.