Skip to main content

Java Customization

Keep business-model output generated and place application-owned behavior at the documented extension boundary:

ConcernGuide
Trusted identity, policy, routing, and runtime resourcesUserContext
Runtime composition and provider extensionsRuntime Extension Points
Entity and business identifier policiesInternal ID and Business ID
LocalizationInternationalization
SQL and diagnostic loggingLogging
Audit deliveryCustom Audit Trail
Cache, locks, and routingCache, Distributed Locks, and Read/Write Splitting

Framework and provider behavior must be verified independently. Continue with the current conformance snapshot; consult the Java Compatibility Archive only for its dated campaign.

Runtime infrastructure​

Java exposes process-local cache and keyed lease locks through UserContext. It also has remote cache/lock SPIs and Redis adapter classes, but the current default Redis cache provider does not construct an operational JedisPool, and the Redis lock release is not owner-token compare-and-delete. Supply and test a production provider instead of assuming the SPI is ready from class presence.

teaql-cloud supplies Nacos 1.x/2.x HTTP and Consul HTTP clients for service registration, deregistration, healthy discovery, and health; the Nacos adapter also retrieves configuration. Read the exact maturity and Nacos 3.x boundary in Cache, Lock, and Cloud Runtime Infrastructure.

Worked Example: Trusted Runtime and Context​

Create application-scoped infrastructure once, then derive a request context from authenticated server state. requestPolicy, tenant, and audit sink are never populated from request JSON.

public final class RuntimeFactory {
public static TeaQLRuntime runtime(
EntityMetaFactory metadata,
DataServiceExecutor provider,
RequestPolicy requestPolicy,
RuntimeLogSink logSink,
RuntimeTelemetry telemetry) {
return TeaQLRuntime.builder()
.metadata(metadata)
.dataService("default", provider)
.requestPolicy(requestPolicy)
.logSink(logSink)
.telemetry(telemetry)
.build();
}

public static DefaultUserContext requestContext(
TeaQLRuntime runtime,
String authenticatedTenant,
AppAuditEventSink appAuditSink) {
if (authenticatedTenant == null || authenticatedTenant.isBlank()) {
throw new IllegalArgumentException("trusted tenant is required");
}
DefaultUserContext context = new DefaultUserContext(runtime);
context.putAttribute("trustedTenant", authenticatedTenant);
context.putAttribute(AppAuditEventSink.class.getName(), appAuditSink);
return context;
}
}

Readiness must use the real runtime/provider path:

DefaultUserContext probe = RuntimeFactory.requestContext(runtime, "readiness", auditSink);
probe.ensureSchema();

ensureSchema() is an explicit startup/administrative action. Do not call it from ordinary liveness probes or per-request context creation.

Worked Example: Local Cache and Lock​

This example caches an immutable application projection and protects a process-local refresh. It does not claim cross-replica coordination.

String cacheKey = tenant + ":currency:" + currencyCode;
CurrencyView cached = context.getFromLocalCache(cacheKey, CurrencyView.class);
if (cached == null) {
String lockKey = tenant + ":currency-refresh:" + currencyCode;
if (!context.tryLocalLock(lockKey, 250, 5_000)) {
throw new IllegalStateException("currency refresh is busy");
}
try {
cached = context.getFromLocalCache(cacheKey, CurrencyView.class);
if (cached == null) {
cached = loadAuthorizedCurrencyView(context, currencyCode);
context.putToLocalCache(cacheKey, cached, 300);
}
} finally {
context.unlockLocal(lockKey);
}
}

After an audited currency update, call removeFromLocalCache(cacheKey). For multiple service replicas, install an owner-safe Remote Lock provider and make its presence part of readiness; the current built-in Redis lock implementation is not sufficient as the sole critical guard.