In
preview
, backward compatibility and presence in the ecosystem is not guaranteed.
Specific improvements might require changing configuration or APIs, and plans to become
stable
are under way.
Feedback is welcome on our
mailing list
or as issues in our
GitHub issue tracker
.
For a full list of possible statuses, check our
FAQ entry
.
Optionally Mandrel or GraalVM installed and
configured appropriately
if you want to build a native executable (or Docker if you use a native container build)
A working Docker environment
In this guide, we are going to expose a simple Rest API to increment numbers by using the
INCRBY
command.
Along the way, we’ll see how to use other Redis commands like
GET
,
SET
(from the string group),
DEL
and
KEYS
(from the key group).
We’ll be using the Quarkus Redis extension to connect to interact with Redis.
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
https://github.com/quarkusio/quarkus-quickstarts.git
, or download an
archive
.
The solution is located in the
redis-quickstart
directory
.
quarkus create app org.acme:redis-quickstart \
--extension='redis-client,rest-jackson' \
--no-code
cd redis-quickstart
To create a Gradle project, add the
--gradle
or
--gradle-kotlin-dsl
option.
For more information about how to install and use the Quarkus CLI, see the
Quarkus CLI
guide.
mvn io.quarkus.platform:quarkus-maven-plugin:3.12.0:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=redis-quickstart \
-Dextensions='redis-client,rest-jackson' \
-DnoCode
cd redis-quickstart
To create a Gradle project, add the
-DbuildTool=gradle
or
-DbuildTool=gradle-kotlin-dsl
option.
If you already have your Quarkus project configured, you can add the
redis-client
extension
to your project by running the following command in your project base directory:
quarkus extension add redis-client
Maven
./mvnw quarkus:add-extension -Dextensions='redis-client'
Gradle
./gradlew addExtension --extensions='redis-client'
This will add the following to your build file:
pom.xml
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-redis-client</artifactId>
</dependency>
build.gradle
implementation("io.quarkus:quarkus-redis-client")
We are going to create an
IncrementService
class which will play the role of a Redis client.
With this class, we’ll be able to perform the
SET
,
GET
,
DEL
,
KEYS
and
INCRBY
Redis commands.
Create the
src/main/java/org/acme/redis/IncrementService.java
file, with the following content:
package org.acme.redis;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import io.quarkus.redis.datasource.ReactiveRedisDataSource;
import io.quarkus.redis.datasource.RedisDataSource;
import io.quarkus.redis.datasource.keys.KeyCommands;
import io.quarkus.redis.datasource.keys.ReactiveKeyCommands;
import io.quarkus.redis.datasource.string.StringCommands;
import io.smallrye.mutiny.Uni;
@ApplicationScoped
public class IncrementService {
// This quickstart demonstrates both the imperative
// and reactive Redis data sources
// Regular applications will pick one of them.
private ReactiveKeyCommands<String> keyCommands; (1)
private ValueCommands<String, Long> countCommands; (2)
public IncrementService(RedisDataSource ds, ReactiveRedisDataSource reactive) { (3)
countCommands = ds.value(Long.class); (4)
keyCommands = reactive.key(); (5)
long get(String key) {
Long value = countCommands.get(key); (6)
if (value == null) {
return 0L;
return value;
void set(String key, Long value) {
countCommands.set(key, value); (7)
void increment(String key, Long incrementBy) {
countCommands.incrby(key, incrementBy); (8)
Uni<Void> del(String key) {
return keyCommands.del(key) (9)
.replaceWithVoid();
Uni<List<String>> keys() {
return keyCommands.keys("*"); (10)
@POST
public Increment create(Increment increment) {
service.set(increment.key, increment.value);
return increment;
@Path("/{key}")
public Increment get(String key) {
return new Increment(key, service.get(key));
@Path("/{key}")
public void increment(String key, long value) {
service.increment(key, value);
@DELETE
@Path("/{key}")
public Uni<Void> delete(String key) {
return service.del(key);
// create a first increment key with an initial value of 0
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.body("{\"key\":\"first-key\",\"value\":0}")
.when()
.post("/increments")
.then()
.statusCode(200)
.body("key", is("first-key"))
.body("value", is(0));
// create a second increment key with an initial value of 10
given()
.contentType(ContentType.JSON)
.accept(ContentType.JSON)
.body("{\"key\":\"second-key\",\"value\":10}")
.when()
.post("/increments")
.then()
.statusCode(200)
.body("key", is("second-key"))
.body("value", is(10));
// increment first key by 1
given()
.contentType(ContentType.JSON)
.body("1")
.when()
.put("/increments/first-key")
.then()
.statusCode(204);
// verify that key has been incremented
given()
.accept(ContentType.JSON)
.when()
.get("/increments/first-key")
.then()
.statusCode(200)
.body("key", is("first-key"))
.body("value", is(1));
// increment second key by 1000
given()
.contentType(ContentType.JSON)
.body("1000")
.when()
.put("/increments/second-key")
.then()
.statusCode(204);
// verify that key has been incremented
given()
.accept(ContentType.JSON)
.when()
.get("/increments/second-key")
.then()
.statusCode(200)
.body("key", is("second-key"))
.body("value", is(1010));
// verify that we have two keys in registered
given()
.accept(ContentType.JSON)
.when()
.get("/increments")
.then()
.statusCode(200)
.body("size()", is(2));
// delete first key
given()
.accept(ContentType.JSON)
.when()
.delete("/increments/first-key")
.then()
.statusCode(204);
// verify that we have one key left after deletion
given()
.accept(ContentType.JSON)
.when()
.get("/increments")
.then()
.statusCode(200)
.body("size()", is(1));
// delete second key
given()
.accept(ContentType.JSON)
.when()
.delete("/increments/second-key")
.then()
.statusCode(204);
// verify that there is no key left
given()
.accept(ContentType.JSON)
.when()
.get("/increments")
.then()
.statusCode(200)
.body("size()", is(0));
If you followed the instructions, you should have the Redis server running.
Then, you just need to run the application using:
quarkus dev
Maven
./mvnw quarkus:dev
Gradle
./gradlew --console=plain quarkusDev
Open another terminal and run the curl http://localhost:8080/increments
command.
As we have seen above, the API exposes five Rest endpoints.
In this section we are going to see how to initialise an increment, see the list of current increments,
incrementing a value given its key, retrieving the current value of an increment, and finally deleting
a key.
curl -X POST -H "Content-Type: application/json" -d '{"key":"first","value":10}' http://localhost:8080/increments (1)
At this point, Quarkus uses the Redis Dev Service to run a Redis server and configure the application.
However, in production, you will run your own Redis (or used a Cloud offering).
Let’s start a Redis server on the port 6379 using:
docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 --name redis_quarkus_test -p 6379:6379 redis:5.0.6
Then, open the src/main/resources/application.properties
file and add:
%prod.quarkus.redis.hosts=redis://localhost:6379
You can also create a native executable from this application without making any
source code changes. A native executable removes the dependency on the JVM:
everything needed to run the application on the target platform is included in
the executable, allowing the application to run with minimal resource overhead.
Compiling a native executable takes a bit longer, as GraalVM performs additional
steps to remove unnecessary codepaths. Use the native
profile to compile a
native executable:
quarkus build --native
Maven
./mvnw install -Dnative
Gradle
./gradlew build -Dquarkus.native.enabled=true
Once the build is finished, you can run the executable with:
./target/redis-quickstart-1.0.0-SNAPSHOT-runner