Skip to main content

Handlers

A payload job is a class that implements Job<T> and is annotated with @FlareJob. The worker deserialises each polled job's JSON payload into T and calls execute.

import com.zeridion.flare.worker.FlareJob;
import com.zeridion.flare.worker.Job;
import com.zeridion.flare.worker.JobContext;

@FlareJob(name = "SendWelcomeEmail", queue = "default", maxAttempts = 5, timeoutSeconds = 60)
public final class SendWelcomeEmail implements Job<NewUserEvent> {
public void execute(NewUserEvent payload, JobContext ctx) throws Exception {
mailer.send(payload.email);
ctx.reportProgress(1.0);
}
}

The @FlareJob annotation

ElementDefaultMeaning
nameclass FQNThe job type — the routing key matched against enqueued jobs.
queue"default"The queue this job is served on.
maxAttempts3Attempts before Flare dead-letters the job.
timeoutSeconds1800Per-job timeout.
cron(none)Cron expression — set only for recurring jobs.
timezone(none)Timezone for the cron schedule.

Always set an explicit name

The name is the cross-language routing key. A job enqueued as "SendWelcomeEmail" reaches a worker only if a registered handler declares that exact name. Leaving name empty falls back to the fully-qualified class name, which only matches jobs enqueued by another JVM worker using the same class — so set an explicit name whenever jobs might be enqueued from a different language or service.

Registering a handler

Register each handler on the builder, supplying its class, payload type, and a factory that produces a fresh instance per execution:

FlareWorker.builder(client)
.register(SendWelcomeEmail.class, NewUserEvent.class, SendWelcomeEmail::new)
.register(ProcessPayment.class, PaymentRequest.class, () -> new ProcessPayment(gateway))
.build();

Registering the same job type twice fails fast at build time, so a routing collision is caught before the worker starts.

Payload binding

Payloads are bound with a snake_case JSON mapper that ignores unknown fields, so adding a field to the enqueued payload won't break an older worker. The sample SDK build does not enable parameter-name retention, so payload fields are bound by explicit JSON names:

import com.fasterxml.jackson.annotation.JsonProperty;

public final class NewUserEvent {
@JsonProperty("user_id") public String userId;
@JsonProperty("email") public String email;
}

A job enqueued with no payload binds to null — handle that case if your job can be enqueued without a body.

Reporting failure

Throw to fail a job. The worker acks it as failed and reports the exception's fully-qualified type and message; Flare then decides whether to retry (while attempts remain) or dead-letter it. You never decide retry-vs-give-up in the handler — that is server-governed.

public void execute(NewUserEvent payload, JobContext ctx) {
if (payload == null || payload.email == null) {
throw new IllegalArgumentException("missing email"); // acked failed
}
mailer.send(payload.email);
}

If the job type isn't registered, the worker acks it failed with a clear "no job type registered" message rather than silently dropping it.