Skip to content

💥 Standalone Activities for Java#2858

Merged
GregoryTravis merged 91 commits intomasterfrom
gmt/java-standalone-activities
Apr 30, 2026
Merged

💥 Standalone Activities for Java#2858
GregoryTravis merged 91 commits intomasterfrom
gmt/java-standalone-activities

Conversation

@GregoryTravis
Copy link
Copy Markdown
Contributor

@GregoryTravis GregoryTravis commented Apr 22, 2026

Add standalone activity API (ActivityClient)

Introduces support for standalone activities — activities that execute independently of any workflow.

💥 Breaking Changes:

  • ActivityInfo.getWorkflowId, .getRunId, .getWorkflowNamespace can now return null, in the case of standalone activities
  • .getRunId now deprecated in favor of .getWorkflowRunId and .getActivityRunId.

New public API surface:

  • ActivityClient — top-level client for starting, describing,
    listing, counting, cancelling, and terminating standalone activities
  • ActivityHandle<R> / UntypedActivityHandle — typed and untyped
    handles returned by ActivityClient.start(); provide getResult(),
    getResult(long, TimeUnit), getResultAsync(), describe(),
    cancel(), and terminate()
  • StartActivityOptions — builder-based options for starting an
    activity (id, task queue, timeouts, retry, priority, etc.)
  • ActivityClientOptions — namespace / data converter / interceptor
    configuration for ActivityClient
  • ActivityExecutionDescription — rich descriptor returned by
    describe() and list*(); extends ActivityExecutionMetadata
  • ActivityExecutionMetadata — lightweight metadata used in list
    results
  • ActivityExecutionCount — result of countActivities()
  • ActivityAlreadyStartedException — thrown when a duplicate activity
    id is rejected by the server
  • ActivityFailedException — thrown from getResult() when the
    activity fails

New interceptor API:

  • ActivityClientCallsInterceptor — per-call interceptor for all
    ActivityClient operations
  • ActivityClientCallsInterceptorBase — pass-through base
    implementation (delegates every method to the next interceptor)
  • ActivityClientInterceptor — factory interceptor that wraps the
    client-level invoker
  • ActivityClientInterceptorBase — no-op base implementation

ActivityInfo additions:

  • getActivityRunId() — run-scoped id assigned by the server to each
    activity execution
  • isInWorkflow() — distinguishes workflow-dispatched activities
    from standalone ones

ActivityCompletionClient additions:

  • New overloads taking (String activityId, Optional<String> runId, …)
    for completing, failing, sending heartbeats, and cancelling standalone
    activities without a workflow id

ActivitySerializationContext fix:

  • workflowId and workflowType are now @Nullable; removed
    requireNonNull guards that caused NPEs for standalone activities

Functions.java:

  • Added Func and VFunc (zero-arg typed/void functional interfaces)
    needed by ActivityClient.start() method-reference overloads

CI:

  • Enable standalone-activity server feature flags in the Temporal CLI
    dev server used by unit tests:
    frontend.activityAPIsEnabled, activity.enableStandalone,
    history.enableChasm, history.enableTransitionHistory

Tests:

  • StandaloneActivityTest — integration tests against a real server
    covering the full activity lifecycle (start, poll, complete, cancel,
    terminate, describe, list, heartbeat, async completion)
  • ActivityClientCallsInterceptorBaseTest — delegation tests for the
    base interceptor
  • ActivityClientCallsInterceptorChainTest — chain ordering tests
    using a real server with two interceptors
  • ActivityHandleImplTest — unit tests for handle dispatch
  • ActivityCompletionClientImplTest — unit tests for completion client
  • ActivityInfoImplTest — unit tests for ActivityInfo in the
    standalone context
  • ActivitySerializationContextTest — confirms nullable workflow fields
  • StartActivityOptionsTest, ActivityClientOptionsTest,
    ActivityExecutionDescriptionTest, ActivityExecutionMetadataTest,
    ActivityAlreadyStartedExceptionTest — options and value-type tests

Remove isEmpty() check from isWorkflowActivity.
Comment thread temporal-sdk/src/main/java/io/temporal/client/ActivityHandle.java
Copy link
Copy Markdown
Contributor

@maciejdudko maciejdudko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but there are a couple things that need to be fixed before merging, most notably caching inside ActivityHandleImpl and how AsyncCompletionClient creates ManualActivityCompletionClient for standalone activities. See comments in code.

Comment thread temporal-sdk/src/main/java/io/temporal/client/ActivityExecutionDescription.java Outdated
Comment thread temporal-sdk/src/main/java/io/temporal/activity/ActivityInfo.java
@GregoryTravis GregoryTravis changed the title Standalone Activities for Java 💥 Standalone Activities for Java Apr 30, 2026
…cardsNonVoidResult.

Renames: ActivityInfoStandaloneTest -> ActivityInfoImplTest, testDescribeNoToken -> testDescribe in ActivityHandleImplTest.
Copy link
Copy Markdown
Contributor

@maciejdudko maciejdudko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@GregoryTravis GregoryTravis dismissed Quinn-With-Two-Ns’s stale review April 30, 2026 20:45

Finished with other reviewers.

@GregoryTravis GregoryTravis merged commit 3892394 into master Apr 30, 2026
26 of 29 checks passed
@GregoryTravis GregoryTravis deleted the gmt/java-standalone-activities branch April 30, 2026 20:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants