Skip to content

Commit

Permalink
Merge pull request #163 from redhat-developer-demos/reactive
Browse files Browse the repository at this point in the history
Reactive
  • Loading branch information
kdubois authored Jul 2, 2024
2 parents b3d5cce + b658160 commit c231bd9
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 22 deletions.
28 changes: 28 additions & 0 deletions documentation/modules/ROOT/pages/14_reactive.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,32 @@ cd {project-name}
--
====

== Start the app in Dev Mode:

[tabs%sync]
====
Maven::
+
--
[.console-input]
[source,bash,subs="+macros,+attributes"]
----
./mvnw quarkus:dev
----
--
Quarkus CLI::
+
--
[.console-input]
[source,bash,subs="+macros,+attributes"]
----
quarkus dev
----
--
====


== Create Beer POJO

Create a new `Beer` Java class in `src/main/java` in the `com.redhat.developers` package with the following contents:
Expand Down Expand Up @@ -117,6 +143,8 @@ public interface BeerService {

== Configure REST Client properties

NOTE: The original punkapi.com service is not operational anymore. To reproduce the application, you can deploy the API on an Openshift Sandbox (developers.redhat.com/sandbox). Once you have logged in to the Sandbox, go to the "Developers" perspective in the top left corner, click on +Add in the left menu, and then in the "Git Repository" section click on the "Import from Git". Paste in the Git Repo URL field: "https://github.com/kdubois/punkapi-server.git", scroll down and set "Target port" to `3333`. Wait for the build to complete (this may take a few minutes) and the app to be deployed. Now click on the deployed app circle in the Topology view and copy the URL from the "Routes" section which should be visible on the right side of your screen. Then paste this URL in the application.properties below:

Add the following properties to your `application.properties` in `src/main/resources`:

[.console-input]
Expand Down
27 changes: 13 additions & 14 deletions documentation/modules/ROOT/pages/15_reactive-messaging.adoc
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
= Reactive Messaging

As a Java developer you are aware that the JMS is the standard when comes to working with messages.
JMS is a blocking API which blocks us from implementing the reactive principles.
As a Java developer you're likely familiar with JMS, which is considered to be the standard when it comes to working with messages.
JMS however is a blocking API, which prevents us from implementing the reactive principles.

Quarkus has SmallRye Reactive Messaging which is an implementation of the Eclipse MicroProfile Reactive Messaging specification.
Quarkus implements version 2.x of this specification but also provides many other extensions.
Quarkus has a "SmallRye Reactive Messaging" extension which is an implementation of the Eclipse MicroProfile Reactive Messaging specification. Reactive Messaging allows us to implement messaging in a non-blocking, reactive way.

In this chapter we're going to use SmallRye Reactive Messaging to generate beers having a price but using messages instead of synchronous calls.
In this chapter we're going to use SmallRye Reactive Messaging to generate beers once again. This time we're going to add a (random) price to the beers. We're going to be using messages instead of synchronous calls to do this.

At this point, we're going to use an inmemory channel which means that messages are sent through the same application using the memory as transport channel of the messages.
To do so, we're going to use an in-memory channel. This means that messages are sent through the application using memory as transport channel of the messages.

In the following section, we'll see what we need to change to start using an external broker for sending messages.

== Add the Reactive Messaging extension

Just open a new terminal window, and make sure you’re at the root of your `{project-name}` project, then run:
Open a new terminal window, and make sure you’re at the root of your `{project-name}` project, then run:

[tabs]
====
Expand All @@ -41,9 +40,9 @@ quarkus extension add messaging

== Modify BeerResource

Let's create a new endpoint that finds a beer and sends/emits a message to `beers` channel with the beer.
Let's create a new endpoint that finds a beer and sends/emits a message to a `beers` channel.

Open `BeerResource` class and add the following code.
Open the `BeerResource` class and add the following code.

In the imports section:

Expand Down Expand Up @@ -79,9 +78,9 @@ public Response emitBeer(@PathParam("beer") int beerId) {
<4> Sends an ack to caller

The previous code sends the beer as a `JsonObject` to `beers` channel.
Since we are using a memory channel, let's create a new Java class in the same project capturing the messages sent to the channel.
Since we are using an in-memory channel, let's create a new Java class in the same project capturing the messages sent to the channel.

Moreover this new class, will send another event to a different channel which will be captured by another method.
This new class will send another event to a different channel which will be captured by yet another method.

== Create BeerProcessor

Expand All @@ -90,7 +89,7 @@ Create a new `BeerProcessor` Java class in `src/main/java` in the `org.acme` pac
[.console-input]
[source,java]
----
package org.acme;
package com.redhat.developers;
import java.util.concurrent.ThreadLocalRandom;
Expand All @@ -109,7 +108,7 @@ public class BeerProcessor {
@Incoming("beers") // <1>
@Outgoing("messages") // <2>
public JsonObject processPrize(JsonObject beer) { // <3>
public JsonObject processPrice(JsonObject beer) { // <3>
JsonObjectBuilder beerWithPrice = Json.createObjectBuilder(beer).add("price", getPrice());
return beerWithPrice.build(); // <4>
}
Expand All @@ -124,7 +123,7 @@ public class BeerProcessor {
}
}
----
<1> Listen events from `beers` channel
<1> Listen to events from `beers` channel
<2> Sends/Emits the result of the method call to the `messages` channel
<3> Argument is the message of the `beers` channel
<4> Return object is sent to the `messages` channel
Expand Down
14 changes: 6 additions & 8 deletions documentation/modules/ROOT/pages/16_kafka-and-streams.adoc
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
= Apache Kafka with Reactive Streams

Mutiny is just part of the Reactive story. To complement it, we need Reactive Streams too. And an important service that can serve as the underlying implementation for our stream is http://kafka.apache.org[Apache Kafka,window=_blank].
Mutiny is just one part of the Reactive story. To complement it, we could use Reactive Streams too. An important service that can serve as the underlying implementation for our stream is http://kafka.apache.org[Apache Kafka,window=_blank].

In this chapter, we'll do a small change, we send beers with a price to a Kafka broker instead of using a memory channel.
In this chapter, we'll make a small change: We will send beers with a price to a Kafka broker instead of using an in-memory channel.

== Add the Reactive Messaging Kafka extension

Just open a new terminal window, and make sure you’re at the root of your `{project-name}` project, then run:
Open a new terminal window, and make sure you’re at the root of your `{project-name}` project, then run:

[tabs]
====
Expand Down Expand Up @@ -65,13 +65,13 @@ TIP: If the channel name is the same as the topic, it's not necessary to set the

Because starting a Kafka broker can be long and you need to develop fast in your local environment, Dev Services for Kafka is here to help you!

Since `quarkus-smallrye-reactive-messaging-kafka` extension is present, Dev Services for Kafka automatically starts a Kafka broker in dev mode and when running tests.
Since we have added the `quarkus-messaging-kafka`, Quarkus Dev Services automatically starts a containerized Kafka broker in dev mode and when running tests.

TIP: You can disable Dev Services for Kafka by adding `quarkus.kafka.devservices.enabled=false` or configuring `kafka.bootstrap.servers` in `application.properties`.

== Invoke the endpoint

With all these changes done, having Docker/Podman running in your computer, and starting the service in dev mode, you can send the same request as in the previous chapter:
There's not really any code to add at this point. Just by having Docker/Podman running on our computer, and starting the service in dev mode, we can now send the same request as in the previous chapter, but it will be sent to a Kafka topic instead of an in-memory channel. Let's try it:

[.console-input]
[source,bash]
Expand All @@ -80,6 +80,4 @@ curl -w '\n' localhost:8080/beer/emit/1
----


Now, nothing is shown as return or in the Quarkus terminal, because the event is sent to a Kafka topic.

To check the content of the topic, we can use the Dev UI interfac by pointing your browser to http://localhost:8080/q/dev-ui/io.quarkus.quarkus-kafka-client/topics[window=_blank]
As you can see, nothing is shown in the return message, nor is there anything in the Quarkus terminal, because the event is simply sent to a Kafka topic. We could create some additional code to retrieve the message from Kafka, but in this case we're going to use the Dev UI interface where we can actually find the contents of the Kafka topic in the Kafka by pointing our browser to http://localhost:8080/q/dev-ui/io.quarkus.quarkus-kafka-client/topics[window=_blank]

0 comments on commit c231bd9

Please sign in to comment.