Quickstart (Core Engine)
Get up and running with OxMQ in a Java 17+ / Java 21+ application in less than 5 minutes.
📋 Prerequisites
- Java 17 or newer (OpenJDK, Temurin, Corretto, GraalVM) — automatic Project Loom Virtual Threads on Java 21+
- Redis 6.2+, Redis 7.x, or Valkey running locally or in Docker
bash
# Start a clean Redis instance via Docker
docker run -d --name oxmq-redis -p 6379:6379 redis:7-alpine📦 1. Add Dependency
xml
<dependencies>
<dependency>
<groupId>io.github.gaurav10610</groupId>
<artifactId>oxmq-core</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>kotlin
dependencies {
implementation("io.github.gaurav10610:oxmq-core:1.8.0")
}xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.github.gaurav10610.oxmq</groupId>
<artifactId>oxmq-core</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>kotlin
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
dependencies {
implementation("com.github.gaurav10610.oxmq:oxmq-core:1.8.0")
}xml
<!-- In your pom.xml -->
<repositories>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/gaurav10610/oxmq</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.github.gaurav10610</groupId>
<artifactId>oxmq-core</artifactId>
<version>1.8.0</version>
</dependency>
</dependencies>
<!-- Requires GitHub PAT with read:packages in ~/.m2/settings.xml -->kotlin
repositories {
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/gaurav10610/oxmq")
credentials {
username = project.findProperty("gpr.user") as String? ?: System.getenv("GITHUB_ACTOR")
password = project.findProperty("gpr.key") as String? ?: System.getenv("GITHUB_TOKEN")
}
}
}
dependencies {
implementation("io.github.gaurav10610:oxmq-core:1.8.0")
}💡 Standalone JARs: You can also download pre-built binaries directly from GitHub Releases v1.8.0.
📝 2. Define Your Payload
OxMQ works natively with Java 17/21 records and standard POJOs via Jackson:
java
package com.example.model;
public record OrderInvoice(
String orderId,
String customerEmail,
double amount
) {}📤 3. Produce Jobs
Initialize a connection pool and enqueue jobs using OxmqQueue:
java
package com.example;
import com.example.model.OrderInvoice;
import io.oxmq.OxmqQueue;
import io.oxmq.model.Job;
import io.oxmq.model.JobOptions;
import java.time.Duration;
public class OrderProducer {
public static void main(String[] args) {
// Build the Queue
OxmqQueue<OrderInvoice> queue = OxmqQueue.<OrderInvoice>builder()
.name("order-invoices")
.redisUri("redis://localhost:6379")
.payloadClass(OrderInvoice.class)
.build();
// Enqueue with 5s delay, 3 retry attempts, exponential backoff, and KeepJobs memory pruning
Job<OrderInvoice> job = queue.add(
"generate-pdf",
new OrderInvoice("ord_101", "alice@example.com", 149.50),
JobOptions.builder()
.delay(Duration.ofSeconds(5))
.attempts(3)
.exponentialBackoff(Duration.ofSeconds(1), Duration.ofSeconds(30))
.removeOnComplete(KeepJobs.of(1000, Duration.ofHours(2)))
.build()
);
System.out.println("Enqueued job ID: " + job.getId());
}
}📥 4. Consume Jobs with Virtual Threads (Java 21+) / Platform Threads (Java 17)
Create an OxmqWorker to execute tasks concurrently using Java 21 Virtual Threads (with automatic platform thread pool fallback on Java 17):
java
package com.example;
import com.example.model.OrderInvoice;
import io.oxmq.OxmqWorker;
import java.time.Duration;
public class OrderWorker {
public static void main(String[] args) throws InterruptedException {
OxmqWorker<OrderInvoice> worker = OxmqWorker.<OrderInvoice>builder()
.queueName("order-invoices")
.redisUri("redis://localhost:6379")
.payloadClass(OrderInvoice.class)
.concurrency(50) // 50 concurrent Virtual Threads (or platform threads on Java 17)
.lockDuration(Duration.ofSeconds(30))
.processor(job -> {
OrderInvoice invoice = job.getData();
System.out.printf("[%s] Processing order %s ($%.2f) on thread %s%n",
job.getId(), invoice.orderId(), invoice.amount(), Thread.currentThread());
// Virtual threads unmount during blocking I/O (DB, HTTP, Disk)
Thread.sleep(500);
// Return any serializable result or null
return "Invoice PDF generated: /invoices/" + invoice.orderId() + ".pdf";
})
.build();
worker.start();
System.out.println("Worker started. Listening for jobs...");
// Graceful shutdown on JVM exit
Runtime.getRuntime().addShutdownHook(new Thread(worker::close));
}
}⚡ What Happens Under the Hood?
- Atomic Ingestion: The producer invokes BullMQ's
addDelayedJob-6.luascript, pushing the job into Redis with delayed maturity. - Auto-Promotion: BullMQ Lua scripts check the Redis sorted set
bull:order-invoices:delayedand atomically move matured jobs tobull:order-invoices:wait. - Virtual Thread Worker: The
OxmqWorkerpulls ready jobs viamoveToActive-11.luaand dispatches each job to an unpinned Virtual Thread (or platform thread pool on Java 17). - Heartbeat Lock Watchdog: An automated background timer extends the job lock via
extendLock-2.luauntil task completion. - Completion & Cleanup:
moveToFinished-14.luamarks the job completed and persists the return value.