Skip to main content

Java & Spring Boot

The Adjudon Java SDK is the integration path for Spring Boot backends, the dominant stack at the DACH banks Adjudon was built to serve. The package targets Java 17+ and Spring Boot 3.x and is shipped as com.adjudon:adjudon-java on Maven Central, with a adjudon-spring-boot-starter companion that auto-wires the client into a Spring application context. Runtime dependencies are limited to Jackson and the JDK's built-in HttpClient; no Apache HTTP, no Netty, no transitive surprises in a regulated build.

Status: Public roadmap

The Java SDK is on the published roadmap with a Maven Central release target of Q3 2026. Until then, Java integrations call the Traces API directly with Jackson + HttpClient; the wire contract is identical and a hand-rolled client ports cleanly to the SDK once it ships. This page documents the SDK shape as it will land.

Coordinates

Maven (target Q3 2026)
<dependency>
<groupId>com.adjudon</groupId>
<artifactId>adjudon-java</artifactId>
<version>0.1.0</version>
</dependency>
Gradle (Kotlin DSL)
implementation("com.adjudon:adjudon-java:0.1.0")

The Spring Boot starter:

Spring Boot starter
<dependency>
<groupId>com.adjudon</groupId>
<artifactId>adjudon-spring-boot-starter</artifactId>
<version>0.1.0</version>
</dependency>

First call

Plain Java
import com.adjudon.AdjudonClient;
import com.adjudon.TraceRequest;
import com.adjudon.TraceResponse;

AdjudonClient adjudon = AdjudonClient.builder()
.apiKey(System.getenv("ADJUDON_API_KEY")) // adj_agent_<48-hex>
.agentId("customer-support-bot")
.build();

TraceResponse trace = adjudon.trace(TraceRequest.builder()
.inputContext(Map.of("prompt", "Can I get a refund for order #1234?"))
.outputDecision(Map.of("action", "initiate_refund", "confidence", 0.91))
.build());

if ("blocked".equals(trace.getStatus())) {
return "Sorry, I can't process this request right now.";
}
Spring Boot — auto-wired
@RestController
public class RefundController {

private final AdjudonClient adjudon;

public RefundController(AdjudonClient adjudon) {
this.adjudon = adjudon;
}

@PostMapping("/refunds")
public ResponseEntity<?> refund(@RequestBody RefundRequest req) {
TraceResponse trace = adjudon.trace(TraceRequest.builder()
.inputContext(req.toInputContext())
.outputDecision(Map.of("action", "initiate_refund", "amount", req.getAmount()))
.build());

return switch (trace.getStatus()) {
case "blocked" -> ResponseEntity.status(403).body(trace);
case "flagged" -> ResponseEntity.status(202).body(trace);
default -> ResponseEntity.ok(trace);
};
}
}

The starter reads adjudon.api-key and adjudon.agent-id from application.yml or environment variables and registers the AdjudonClient as a singleton bean.

Versions

RuntimeSupported
Java 17✓ (minimum)
Java 21✓ (LTS, recommended)
Spring Boot 3.2
Spring Boot 3.3
Java 11— (out of upstream support)
Spring Boot 2.x— (Jakarta EE 9+ migration required)

Configuration

FieldDefaultDescription
apiKey(required)adj_agent_<48-hex>
agentId(required)Stable agent identifier
baseUrlhttps://api.adjudon.comOverride for self-hosted Adjudon
failModeOPENOPEN returns passthrough on failure; CLOSED raises
timeoutDuration.ofSeconds(10)HTTP timeout
maxRetries3Retry attempts on 429 / 5xx

Spring Boot configuration

The starter exposes the same fields as application.yml keys:

application.yml
adjudon:
api-key: ${ADJUDON_API_KEY}
agent-id: customer-support-bot
fail-mode: OPEN
timeout: PT10S
max-retries: 3

A @ConfigurationProperties("adjudon") binding picks each field up on startup; an unset api-key fails fast with AdjudonConfigException. Spring profiles work as expected for splitting test vs production credentials. Actuator-exposed health contributes adjudonReachable to /actuator/health so a Kubernetes liveness probe can read the same fail-open posture the SDK enforces internally.

Idempotency

adjudon.trace(req, idempotencyKey) accepts a string. If omitted, the SDK generates a UUID per call. Duplicate keys within the 24-hour window return the cached response, so retry storms during a transient network hiccup never inflate the org's metered trace count.

Errors

ExceptionCause
AdjudonAuthExceptionInvalid API key; never retried
AdjudonRateLimitExceptionRetries exhausted on 429 (only when failMode = CLOSED)
AdjudonTimeoutExceptionRetries exhausted on timeout (only when failMode = CLOSED)
AdjudonBlockedExceptionPolicy returned block; always propagated as a compliance signal
AdjudonConfigExceptionBuilder argument invalid

failMode = OPEN returns TraceResponse.passthrough() for every exception except AdjudonBlockedException and AdjudonAuthException — the first is a compliance signal you must not swallow, the second is a configuration bug.

Resources

  • Quickstart — first trace in 60 seconds
  • Authentication — API key formats and rotation
  • Traces API — the underlying HTTP surface this SDK calls (use this directly until the Maven Central release lands)
  • Error Codes — HTTP-level errors this SDK raises
  • GitHub: github.com/adjudon/adjudon-java (target repository for source, issues, and releases when the SDK ships)