Temporal Java SDK

repository·main·Indexed 19 days ago

https://github.com/temporalio/sdk-java

A framework for authoring resilient Workflows and Activities in Java using the Temporal Workflow-as-Code platform. Includes specialized modules for AWS Lambda workers, OpenTelemetry and OpenTracing integration for observability, and temporal-spring-ai for integrating Spring AI models as durable Temporal activities.

Tokens
21.9K
Snippets
57
Records
80
Agent score
65%

What's inside Temporal Java SDK

  1. Overview of the Temporal Remote Data Encoder (RDE) module

    main

    The Temporal Remote Data Encoder (RDE) module provides a mechanism to centralize complex encryption logic. Instead of having every developer workstation or service access encryption keys directly, you can use an RDE server to handle encoding and decoding of payloads.

    Key Benefits:

    • Language Agnostic: Reuse complex encryption logic across different programming languages.
    • Tooling Support: Enables the Temporal CLI to encode payloads for temporal workflow start and allows the Temporal WebUI to decode encrypted payloads.
    • Enhanced Security: Centralizes access to encryption keys within a dedicated service, reducing the surface area of key exposure.
  2. What is Temporal Workflow Check for Java

    main

    Temporal Workflow Check is a bytecode scanning utility designed to ensure Temporal workflows remain deterministic. It recursively analyzes Java bytecode to detect violations of workflow logic constraints, such as:

    • Invoking methods configured as invalid (e.g., threading, IO, random, system time).
    • Accessing invalid static fields (e.g., System.out).
    • Accessing non-final static fields.
    • Indirectly invoking methods that violate the above rules through transitive calls.

    Note: This tool is currently in BETA quality.

  3. What are Workflow Streams

    main

    Workflow Streams provide a durable publish/subscribe log hosted inside a Temporal Workflow. They allow external code (activities, starters, or other processes) to publish messages to named topics via signals, while subscribers long-poll for new items via updates. A query can be used to expose the current offset.

    Key characteristics:

    • Durability: Backed by Temporal's durable execution, providing ordered, durable, and exactly-once delivery.
    • Performance: Each poll round-trip has approximately 100ms of latency; it is not intended for ultra-low-latency streaming.
    • Scalability: Cost scales with durable batches rather than individual message counts.
    • Features: Supports client-side batching, publisher deduplication, continue-as-new survival, truncation, and ~1 MB response paging.

    Note: All APIs in this module are experimental and may change.

  4. How the RDE Server works

    main

    An RDE Server is an HTTP server that handles encoding and decoding requests via POST methods.

    Protocol Details:

    • Endpoints: The base URL is suffixed with /encode for encoding and /decode for decoding.
    • Content Type: Expects application/json for requests and returns application/json for responses.
    • Payload Format: It expects and emits io.temporal.api.common.v1.Payloads serialized to JSON using Proto3 JSON Mapping.

    Reference Implementations:

    • io.temporal.rde.httpserver.RDEHttpServer: A standalone, simple RDE HTTP Server.
    • io.temporal.rde.servlet.RDEServlet4: A Servlet compatible with Java Servlet Specification 3.0 and 4.0, suitable for deployment in standard application or servlet containers.
  5. Perform isolated testing of Activity implementations

    main
    If you want to test activity implementations in isolation without bootstrapping a Temporal server, an in-memory testing service, or triggering workflows, use io.temporal.testing.TestActivityEnvironment. This provides a lightweight way to verify activity logic independently.
  6. How Temporal Workflow Check for Java works

    main

    Temporal Workflow Check is a tool designed to ensure Temporal Workflows adhere to safety constraints by scanning the classpath and building a call graph.

    Core Mechanism

    1. Classpath Scanning: It scans all non-standard-library classes using OW2 ASM to collect method details, including workflow declarations (e.g., methods with @WorkflowMethod), method invocations, and field accesses.
    2. Workflow Identification: It identifies workflow implementations by checking if a method contains a body and overrides a super-interface workflow declaration.
    3. Invalidity Processing: For every workflow implementation, a recursive processor checks for invalidity by:
      • Identifying invalid field accesses.
      • Resolving static field accesses (non-final static fields are considered invalid).
      • Checking method calls against configured descriptor patterns. It uses advanced virtual resolution to find the most specific implementation in the class hierarchy to avoid false positives (e.g., if a superclass method is invalid but an overriding subclass method is valid).
    4. Call Graph Construction: It constructs a call graph of transitive, non-recursive invocations to ensure that even deeply nested calls to invalid code are detected.
    5. Reporting: The tool prints the detected invalid accesses.
  7. Security considerations for RDE encryption

    main

    Implementing an RDE introduces a new component with access to encryption keys and the ability to encode/decode any payload.

    Security Risks:

    • Endpoint Exposure: Anyone with access to the RDE HTTP endpoints can encode or decode any payload.
    • Access Control: You must protect the RDE HTTP endpoints with strict authorization, not just protect the encryption keys themselves.

    Security Benefits:

    • Reduced Key Exposure: It can significantly reduce the number of individual parties (developers, services, workstations) that require direct access to the raw encryption keys.
  8. How TaskScope execution model works

    main

    It is important to understand that TaskScope is an ownership boundary, not an executor.

    • It does not fork new threads.
    • It does not use executors under the hood.
    • It does not create virtual thread abstractions.

    Instead, it acts as a management wrapper over CompletableFuture to provide correctness guarantees regarding task lifetimes and cancellation propagation.

  9. Understand Lambda worker shutdown and deadlines

    main

    The Lambda worker manages its own lifecycle: it creates one worker per invocation, starts it, and shuts it down before the Lambda deadline.

    Shutdown Timing

    • shutdownDeadlineBuffer: The window reserved at the end of the invocation. The default is 7 seconds (5s for gracefulShutdownTimeout and 2s for hooks/service stubs).
    • Execution Window: The worker runs until remainingTime - shutdownDeadlineBuffer, then stops and awaits termination for the duration of gracefulShutdownTimeout.
    • Constraints: If you explicitly set shutdownDeadlineBuffer, it must be $\ge$ gracefulShutdownTimeout. If you change gracefulShutdownTimeout without setting the buffer, the buffer is automatically recomputed as gracefulShutdownTimeout + 2s.
  10. Use the Temporal Test Workflow Server for testing

    main

    The temporal-test-server provides an in-memory implementation of the Temporal server API for testing purposes.

    Important: Do not depend on this module directly in your projects. Instead, program against the TestWorkflowEnvironment interface provided in the temporal-testing module. This module is intended to be consumed as a library by JVM-based languages or built into a standalone executable.

  11. Understand Tool Types in temporal-spring-ai

    main

    When passing tools to defaultTools(), the plugin handles them based on their implementation type:

    1. Activity stubs: Interfaces annotated with @ActivityInterface and methods annotated with @Tool. These are executed as durable Temporal activities with retries and timeouts.
    2. @SideEffectTool: Classes annotated with @SideEffectTool. Each @Tool method is wrapped in Workflow.sideEffect(), making non-deterministic operations (like Instant.now()) deterministic by recording the result in history.
    3. Plain tools: Standard classes with @Tool methods. These execute directly in the workflow thread. Warning: You are responsible for ensuring determinism (e.g., by calling activities or Workflow.sideEffect() inside the tool).
    4. Nexus service stubs: Auto-detected and executed as Nexus operations.
    // Activity Stub Example
    @ActivityInterface
    public interface WeatherActivity {
        @Tool(description = "Get weather for a city") @ActivityMethod
        String getWeather(String city);
    }
    
    // @SideEffectTool Example
    @SideEffectTool
    public class TimestampTools {
        @Tool(description = "Get current time")
        public String now() { return Instant.now().toString(); }
    }
    
    // Plain Tool Example
    public class MyTools {
        @Tool(description = "Process data")
        public String process(String input) {
            SomeActivity act = Workflow.newActivityStub(SomeActivity.class, opts);
            return act.doWork(input);
        }
    }