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
| Element | Default | Meaning |
|---|---|---|
name | class FQN | The job type — the routing key matched against enqueued jobs. |
queue | "default" | The queue this job is served on. |
maxAttempts | 3 | Attempts before Flare dead-letters the job. |
timeoutSeconds | 1800 | Per-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.