Java SDK
The Java SDK for writing TaskDaemon handlers.Installation
Maven
Copy
<dependency>
<groupId>com.taskdaemon</groupId>
<artifactId>handler</artifactId>
<version>0.1.0</version>
</dependency>
Gradle
Copy
implementation 'com.taskdaemon:handler:0.1.0'
Basic Usage
Copy
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
Copy
public record Task(
String task_id,
String task_type,
Map<String, Object> task_data,
int attempt // Current attempt (starts at 0)
) {}
Result Types
Copy
// 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 {}
Copy
// 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
Copy
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:Copy
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));
});
Copy
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
Copy
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"]
Copy
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
Copy
[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)