Skip to content

Commit

Permalink
Add Artemis JMS guide
Browse files Browse the repository at this point in the history
  • Loading branch information
middagj committed Sep 25, 2019
1 parent cf705dc commit 0e7a2b4
Show file tree
Hide file tree
Showing 2 changed files with 288 additions and 0 deletions.
287 changes: 287 additions & 0 deletions docs/src/main/asciidoc/artemis-jms-guide.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/master/docs/src/main/asciidoc
////
= Quarkus - Using Artemis JMS extension
include::./attributes.adoc[]

This guide demonstrates how your Quarkus application can use Artemis JMS messaging.

== Prerequisites

To complete this guide, you need:

* less than 15 minutes
* an IDE
* JDK 1.8+ installed with `JAVA_HOME` configured appropriately
* Apache Maven 3.5.3+
* A running Artemis server, or Docker Compose to start one
* GraalVM installed if you want to run in native mode.

== Architecture

In this guide, we are going to generate (random) prices in one component.
These prices are written in an JMS queue (`prices`).
Another component reads from the `prices` queue and stores the last price.
The data can be fetch from a browser using a fetch button from a JAX-RS resource.

== Solution

We recommend that you follow the instructions in the next sections and create the application step by step.
However, you can go right to the completed example.

Clone the Git repository: `git clone {quickstarts-clone-url}`, or download an {quickstarts-archive-url}[archive].

The solution is located in the `artemis-jms` {quickstarts-tree-url}/artemis-jms[directory].

== Creating the Maven Project

First, we need a new project. Create a new project with the following command:

[source, subs=attributes+]
----
mvn io.quarkus:quarkus-maven-plugin:{quarkus-version}:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=artemis-jms \
-Dextensions="artemis-jms"
----

This command generates a Maven project, importing the Artemis JMS extension.

== Starting an Artemis server

Then, we need an Artemis server.
You can follow the instructions from the https://activemq.apache.org/components/artemis/[Apache Artemis web site] or via docker:

[source]
----
docker run -it --rm -p 8161:8161 -p 61616:61616 -e ARTEMIS_USERNAME=quarkus -e ARTEMIS_PASSWORD=quarkus vromero/activemq-artemis:2.9.0-alpine
----

== The price producer

Create the `src/main/java/org/acme/quarkus/sample/PriceProducer.java` file, with the following content:

[source, java]
----
package org.acme.artemis;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.jms.ConnectionFactory;
import javax.jms.JMSContext;
import javax.jms.Session;
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
/**
* A bean producing random prices every 5 seconds and sending them to the prices JMS queue.
*/
@ApplicationScoped
public class PriceProducer implements Runnable {
@Inject
ConnectionFactory connectionFactory;
private final Random random = new Random();
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
void onStart(@Observes StartupEvent ev) {
scheduler.scheduleWithFixedDelay(this, 0L, 5L, TimeUnit.SECONDS);
}
void onStop(@Observes ShutdownEvent ev) {
scheduler.shutdown();
}
@Override
public void run() {
try (JMSContext context = connectionFactory.createContext(Session.AUTO_ACKNOWLEDGE)) {
context.createProducer().send(context.createQueue("prices"), Integer.toString(random.nextInt(100)));
}
}
}
----

== The price consumer

The price consumer reads the prices from JMS, and stores the last one.
Create the `src/main/java/org/acme/quarkus/sample/PriceConsumer.java` file with the following content:

[source, java]
----
package org.acme.artemis;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
import javax.jms.ConnectionFactory;
import javax.jms.JMSConsumer;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import io.quarkus.runtime.ShutdownEvent;
import io.quarkus.runtime.StartupEvent;
/**
* A bean consuming prices from the JMS queue.
*/
@ApplicationScoped
public class PriceConsumer implements Runnable {
@Inject
ConnectionFactory connectionFactory;
private final ExecutorService scheduler = Executors.newSingleThreadExecutor();
private volatile String lastPrice;
public String getLastPrice() {
return lastPrice;
}
void onStart(@Observes StartupEvent ev) {
scheduler.submit(this);
}
void onStop(@Observes ShutdownEvent ev) {
scheduler.shutdown();
}
@Override
public void run() {
try (JMSContext context = connectionFactory.createContext(Session.AUTO_ACKNOWLEDGE)) {
JMSConsumer consumer = context.createConsumer(context.createQueue("prices"));
while (true) {
Message message = consumer.receive();
if (message == null) return;
lastPrice = message.getBody(String.class);
}
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
}
----

== The price resource

Finally, let's create a simple JAX-RS resource to show the last price.
Creates the `src/main/java/org/acme/quarkus/sample/PriceResource.java` file with the following content:

[source, java]
----
package org.acme.artemis;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
* A simple resource showing the last price.
*/
@Path("/prices")
public class PriceResource {
@Inject
PriceConsumer consumer;
@GET
@Path("last")
@Produces(MediaType.TEXT_PLAIN)
public String last() {
return consumer.getLastPrice();
}
}
----

== Configuring the Artemis properties

We need to configure the Artemis connection properties.
This is done in the `application.properties` file.

[source]
----
# Configures the Artemis properties.
quarkus.artemis.url=tcp://localhost:61616
quarkus.artemis.username=quarkus
quarkus.artemis.password=quarkus
----

== The HTML page

Final touch, the HTML page reading the converted prices using SSE.

Create the `src/main/resources/META-INF/resources/prices.html` file, with the following content:

[source, html]
----
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Prices</title>
<link rel="stylesheet" type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.24.0/css/patternfly.min.css">
<link rel="stylesheet" type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/patternfly/3.24.0/css/patternfly-additions.min.css">
</head>
<body>
<div class="container">
<h2>Last price</h2>
<div class="row">
<p class="col-md-12"><button id="fetch">Fetch</button>The last price is <strong><span id="content">N/A</span>&nbsp;&euro;</strong>.</p>
</div>
</div>
</body>
<script>
document.getElementById("fetch").addEventListener("click", function() {
fetch("/prices/last").then(function (response) {
response.text().then(function (text) {
document.getElementById("content").textContent = text;
})
})
})
</script>
</html>
----

Nothing spectacular here. On each fetch, it updates the page.

== Get it running

If you followed the instructions, you should have the Artemis server running.
Then, you just need to run the application using:

[source, shell]
----
./mvnw compile quarkus:dev
----

Open `http://localhost:8080/prices.html` in your browser.

== Running Native

You can build the native executable with:

[source, shell]
----
./mvnw package -Pnative
----
1 change: 1 addition & 0 deletions docs/src/main/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ include::quarkus-intro.adoc[tag=intro]
* link:tika-guide.html[Using Apache Tika]
* link:mongo-guide.html[Using MongoDB]
* link:mongodb-panache-guide.html[Simplified MongoDB with Panache]
* link:artemis-jms-guide.html[Using Artemis JMS Client]

* link:faq.html[FAQs]

Expand Down

0 comments on commit 0e7a2b4

Please sign in to comment.