Skip to content

ankitagrawa/guide-microprofile-reactive-messaging-rest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Trigger messages in reactive Java microservice by a RESTful endpoint

Note
This repository contains the guide documentation source. To view the guide in published form, view it on the Open Liberty website.

Learn how to trigger messages in reactive Java microservice by a RESTful endpoint.

What you’ll learn

You’ll learn how to use RESTful endpoints to trigger microservices to produce and send messages to other microservices using MicroProfile Reactive Messaging. Current implementation of MicroProfile Reactive Messaging operates on continuous streams of events. E.g. Producer produces events periodically, and Customer consumes those events. This guide helps you write microservices so that when a user hits the RESTful endpoint, producer events are generated. You’ll learn how to bridge the gap between reactive applications and the traditional RESTful ones. You’ll also learn how we can achieve code execution on demand in the reactive applications.

The reactive application in this guide sends and receives messages between services using an external message broker, Apache Kafka. Using an external message broker enables asynchronous communications between services so that requests are non-blocking and decoupled from responses. You can learn more about reactive Java services that use an external message broker to manage communications in the Creating reactive Java microservices guide. Before you go any further it is highly recommended to go through the basic guide.

The application in this guide consists of two microservices, system and inventory. Every 15 seconds, the system microservice calculates and publishes events that contains its current average system load. The inventory microservice subscribes to that information so that it can keep an updated list of all the systems and their current system loads. The invetory microservice also subscribes to a POST request response that queries a specific system property on the system microservice. The current inventory of systems can be accessed via the /systems REST endpoint. You’ll create the system and inventory microservices using MicroProfile Reactive Messaging.

Reactive system inventory

Additional prerequisites

You need to have Docker installed. For installation instructions, refer to the official Docker documentation. You will build and run the microservices in Docker containers. An installation of Apache Kafka is provided in another Docker container.

Creating the system microservice

Navigate to the start directory to begin.

The system microservice is the producer of the messages that are published to the Kafka messaging system as a stream of events. Every 15 seconds, the system microservice publishes events that contains its calculation of the average system load (its CPU usage) for the last minute. It also processes the specific system property request from the inventory microservice and publishes it to the Kafka messaging system.

Create the SystemService class.
system/src/main/java/io/openliberty/guides/system/SystemService.java

SystemService.java

link:finish/system/src/main/java/io/openliberty/guides/system/SystemService.java[role=include]

system/microprofile-config.properties

link:finish/system/src/main/resources/META-INF/microprofile-config.properties[role=include]

The SystemService class contains a Publisher method that is called sendSystemLoad(), which calculates and returns the average system load. The @Outgoing annotation on the sendSystemLoad() method indicates that the method publishes its calculation as a message on a topic in the Kafka messaging system. The Flowable.interval() method from rxJava is used to set the frequency of how often the system service publishes the calculation to the event stream.

The system microservice also contains a method named sendProperty that receives a system property name from the inventory microservice and calculates the requested property on the fly and publishes it back to the Kafka. The sendProperty method acts as a processor in this scenario.

The messages are transported between the service and the Kafka messaging system through the channels called systemLoad and setProperty.

Creating the inventory microservice

The inventory microservice records in its inventory the average system load information and the requested system property, that it received from potentially multiple instances of the system service.

Create the InventoryResource class.
inventory/src/main/java/io/openliberty/guides/inventory/InventoryResource.java

InventoryResource.java

link:finish/inventory/src/main/java/io/openliberty/guides/inventory/InventoryResource.java[role=include]

inventory/microprofile-config.properties

link:finish/inventory/src/main/resources/META-INF/microprofile-config.properties[role=include]

The inventory microservice receives the message from the system microservice over the @Incoming("systemLoad") and @Incoming("propertyMessage") channel. The properties of this channel are defined in the microprofile-config.properties file. The inventory microservice is also a RESTful service that is served at the /inventory endpoint.

The InventoryResource class contains a method called updateStatus(), which receives the messages that contains the average system load and updates its existing inventory of systems and their average system load. The @Incoming("systemLoad") annotations on the updateStatus() method indicates that the method retrieves the average system load information by connecting to the channel called systemLoad.

When accessed, there is a RESTful endpoint to the inventory microservice that triggers message creation. The inventory microservice creates a system property request when a property name is sent in a POST request to the /systems/property/{propertyName} endpoint. The getSystemProperty() method receives a system property name like os.name from the POST request and adds it to the FlowableEmitter. The Flowable.create() method from rxJava is used to create a Publisher and an associated emitter. The property name sent to the emitter will be sent to the Publisher. The Publisher is returned from the @Outgoing("propertyName") channel, which is configured in the microprofile-config.properties propertyName stream and MicroProfile Reactive Messaging takes care of assigning the publisher to the channel.

Configuring the MicroProfile Reactive Messaging connectors for Kafka

The system and inventory services exchange messages with the external messaging system through a channel. The MicroProfile Reactive Messaging Connector API makes it easy to connect each service to the channel. You just need to add configuration keys in a properties file for each of the services. These configuration keys define properties such as the name of the channel and the topic in the Kafka messaging system. Open Liberty includes the liberty-kafka connector for sending and receiving messages from Apache Kafka.

The system and inventory microservices each have a MicroProfile Config properties file to define the properties of their outgoing and incoming streams.

Create the system/microprofile-config.properties file.
system/src/main/resources/META-INF/microprofile-config.properties

system/microprofile-config.properties

link:finish/system/src/main/resources/META-INF/microprofile-config.properties[role=include]

inventory/microprofile-config.properties

link:finish/inventory/src/main/resources/META-INF/microprofile-config.properties[role=include]

The system microservice uses an outgoing connector to send messages through the systemLoad and setProperty channel to the systemLoadTopic and propertyMessageTopic topic respectively in the Kafka message broker so that the inventory microservices can consume the messages. The SystemLoadSerializer and PropertyMessageSerializer class implements the logic for turning a SystemLoad and PropertyMessage object into JSON and is configured as the value.serializer.

The inventory microservice uses a similar microprofile-config.properties configuration to define its required incoming stream.

Create the inventory/microprofile-config.properties file.
inventory/src/main/resources/META-INF/microprofile-config.properties

The inventory microservice uses an incoming connector to receive messages through the systemLoad and propertyMessage channel. The messages were published by the system microservice to the systemLoadTopic and propertyMessageTopic in the Kafka message broker. The SystemLoadDeserializer and PropertyMessageDeserializer class implements the logic for turning JSON into a SystemLoad and PropertyMessage object and is configured as the value.deserializer.

Configuring the server

To run the services, the Open Liberty server on which each service runs needs to be correctly configured. Relevant features, including the MicroProfile Reactive Messaging feature, must be enabled for the system and inventory services.

Create the system/server.xml configuration file.
system/src/main/liberty/config/server.xml

server.xml

link:finish/system/src/main/liberty/config/server.xml[role=include]

server.xml

link:finish/inventory/src/main/liberty/config/server.xml[role=include]

The server.xml file is already configured for the inventory microservice.

Building and running the application

Build the system and inventory microservices using Maven and then run them in Docker containers.

Create the Maven configuration file.
system/pom.xml

pom.xml

link:finish/system/pom.xml[role=include]

The pom.xml file lists the microprofile-reactive-messaging-api, kafka-clients, and rxjava dependencies.

The microprofile-reactive-messaging-api dependency is needed to enable the use of MicroProfile Reactive Messaging API. The kafka-clients dependency is added because the application needs a Kafka client to connect to the Kafka broker. The rxjava dependency is used for creating events at regular intervals.

Start your Docker environment. Dockerfiles are provided for you to use.

To build the application, run the Maven install and package goals from the command line in the start directory:

mvn -pl models install
mvn package

Run the following command to download or update to the latest open-liberty Docker image:

docker pull open-liberty

Run the following commands to containerize the microservices:

docker build -t system:1.0-SNAPSHOT system/.
docker build -t inventory:1.0-SNAPSHOT inventory/.

Next, use the provided script to start the application in Docker containers. The script creates a network for the containers to communicate with each other. It also creates containers for Kafka, Zookeeper, and the microservices in the project. For simplicity, the script starts one instance of the system service.

./scripts/startContainers.sh
.\scripts\startContainers.bat

Testing the application

After the application is up and running, you can access the application by making a GET request to the /systems endpoint of the inventory service.

Go to the http://localhost:9085/inventory/systems URL to access the inventory microservice. You see the CPU systemLoad property for all the systems:

{
   "hostname":"30bec2b63a96",
   "systemLoad":1.44
}

You can revisit the http://localhost:9085/inventory/systems URL after a while, and you will notice the CPU systemLoad property for the systems changed.

You can use the http://localhost:9085/inventory/systems/{hostname} URL to see the CPU systemLoad property for one particular system.

In the following example, the 30bec2b63a96 value is the hostname. If you go to the http://localhost:9085/inventory/systems/30bec2b63a96 URL, you can see the property only for the 30bec2b63a96 hostname:

{
   "hostname":"30bec2b63a96",
   "systemLoad":1.44
}

You can use the http://localhost:9085/inventory/systems/property/{propertyName} URL to see the value of a particular system property.

For example, : The http://localhost:9085/inventory/systems/property/os.name URL will give you the os.name value for your system.

Make a POST request to the service by using curl:

curl -X POST http://localhost:9085/inventory/systems/property/os.name

If the curl command is unavailable, then use Postman. Postman enables you to make requests using a graphical interface. To make a request with Postman, enter http://localhost:9085/inventory/systems/property/os.name into the URL bar and change the request from GET to POST. Click the blue Send button to make the request.

You will see the following output:

Request successful for the os.name property

Since the system service is available, the request to the service is successful and returns a 200 response code.

You can revisit the http://localhost:9085/inventory/systems URL and you would see the os.name system property value in addition to the previous values :

{
   "hostname":"30bec2b63a96",
   "os.name":"Linux",
   "systemLoad":1.44
}

Tearing down the environment

Run the following script to stop the application:

./scripts/stopContainers.sh
.\scripts\stopContainers.bat

Great work! You’re done!

You just developed a reactive Java application using MicroProfile Reactive Messaging, Open Liberty, and Kakfa.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published