Skip to main content

Java SDK

The Java SDK for writing TaskDaemon handlers.

Installation

Maven

<dependency>
    <groupId>com.taskdaemon</groupId>
    <artifactId>handler</artifactId>
    <version>0.1.0</version>
</dependency>

Gradle

implementation 'com.taskdaemon:handler:0.1.0'

Basic Usage

import com.taskdaemon.Handler;
import com.taskdaemon.Handler.*;
import java.util.Map;

public class MyHandler {
    public static void main(String[] args) throws Exception {
        Handler.run(task -> {
            String name = (String) task.task_data().getOrDefault("name", "World");
            return new Success(Map.of("message", "Hello, " + name + "!"));
        });
    }
}

Task Record

public record Task(
    String task_id,
    String task_type,
    Map<String, Object> task_data,
    int attempt  // Current attempt (starts at 0)
) {}

Result Types

// Sealed interface for type safety
public sealed interface Result permits Success, Error {}

// Success with result
public record Success(Object result) implements Result {}

// Error with message and retryable flag
public record Error(String error, boolean retryable) implements Result {}
Usage:
// Success
return new Success(Map.of("processed", true));

// Non-retryable error
return new Error("Invalid input", false);

// Retryable error
return new Error("Service unavailable", true);

Complete Example

import com.taskdaemon.Handler;
import com.taskdaemon.Handler.*;
import java.util.Map;
import java.util.Arrays;

public class WordCountHandler {
    public static void main(String[] args) throws Exception {
        Handler.run(task -> {
            String text = (String) task.task_data().getOrDefault("text", "");
            
            // Count words
            long words = Arrays.stream(text.split("\\s+"))
                .filter(s -> !s.isEmpty())
                .count();
            
            // Count characters (excluding spaces)
            long chars = text.chars()
                .filter(c -> !Character.isWhitespace(c))
                .count();
            
            // Count lines
            long lines = text.lines().count();
            
            return new Success(Map.of(
                "words", words,
                "characters", chars,
                "lines", lines
            ));
        });
    }
}

Error Handling

Exceptions are automatically caught and converted to non-retryable errors:
Handler.run(task -> {
    // If this throws, it becomes Error(exception.getMessage(), false)
    String required = (String) task.task_data().get("required");
    return new Success(Map.of("value", required));
});
For explicit error handling:
Handler.run(task -> {
    if (!task.task_data().containsKey("required")) {
        return new Error("Missing required field", false);
    }
    
    try {
        var result = externalApiCall();
        return new Success(result);
    } catch (IOException e) {
        return new Error("API unavailable: " + e.getMessage(), true);
    }
});

Dockerfile

FROM eclipse-temurin:21-jdk AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN ./mvnw package -DskipTests

FROM eclipse-temurin:21-jre
COPY --from=builder /app/target/handler.jar /app/handler.jar
CMD ["java", "-jar", "/app/handler.jar"]
For GraalVM native image (faster startup):
FROM ghcr.io/graalvm/native-image:21 AS builder
WORKDIR /app
COPY . .
RUN ./mvnw package -Pnative -DskipTests

FROM debian:bookworm-slim
COPY --from=builder /app/target/handler /handler
CMD ["/handler"]

Handler Configuration

[handlers.wordcount]
image = "java-handler:latest"
instances = 4
timeout = 30

Requirements

  • Java 17+ (uses records and sealed interfaces)
  • Jackson for JSON serialization (included in SDK)