From ca20c6559124076ae1bb8086fd379d4c001ed8db Mon Sep 17 00:00:00 2001 From: Evan Reynolds Date: Mon, 8 Jun 2026 15:24:32 -0700 Subject: [PATCH 1/2] Adding Nexus Java standalone operations --- docs/develop/java/index.mdx | 1 + docs/develop/java/nexus/index.mdx | 1 + .../java/nexus/standalone-operations.mdx | 168 ++++++++++++++++++ sidebars.js | 1 + 4 files changed, 171 insertions(+) create mode 100644 docs/develop/java/nexus/standalone-operations.mdx diff --git a/docs/develop/java/index.mdx b/docs/develop/java/index.mdx index 46f73981be..f71a645be4 100644 --- a/docs/develop/java/index.mdx +++ b/docs/develop/java/index.mdx @@ -66,6 +66,7 @@ From there, you can dive deeper into any of the Temporal primitives to start bui - [Quickstart](/develop/java/nexus/quickstart) - [Feature guide](/develop/java/nexus/feature-guide) +- [Standalone Operations](/develop/java/nexus/standalone-operations) ## [Platform](/develop/java/platform) diff --git a/docs/develop/java/nexus/index.mdx b/docs/develop/java/nexus/index.mdx index 2246063f16..4b68df76fc 100644 --- a/docs/develop/java/nexus/index.mdx +++ b/docs/develop/java/nexus/index.mdx @@ -25,4 +25,5 @@ Temporal Java SDK support for Nexus is [Generally Available](/evaluate/developme - [Quickstart](/develop/java/nexus/quickstart) - [Feature guide](/develop/java/nexus/feature-guide) +- [Standalone Operations](/develop/java/nexus/standalone-operations) - [Nexus sync tutorial](https://learn.temporal.io/tutorials/nexus/nexus-sync-tutorial/) diff --git a/docs/develop/java/nexus/standalone-operations.mdx b/docs/develop/java/nexus/standalone-operations.mdx new file mode 100644 index 0000000000..def425e49f --- /dev/null +++ b/docs/develop/java/nexus/standalone-operations.mdx @@ -0,0 +1,168 @@ +--- +id: standalone-operations +title: Standalone Nexus Operations - Java SDK +sidebar_label: Standalone Operations +toc_max_heading_level: 4 +keywords: + - standalone nexus operation + - nexus operation execution + - execute nexus operation + - nexus operation handle + - list nexus operations + - count nexus operations + - java sdk +tags: + - Nexus + - Temporal Client + - Java SDK + - Temporal SDKs +description: Execute Nexus Operations independently without a Workflow using the Temporal Java SDK. +--- + +:::tip SUPPORT, STABILITY, and DEPENDENCY INFO + +Temporal Java SDK support for Standalone Nexus Operations is at +[Pre-release](/evaluate/development-production-features/release-stages#pre-release). + +All APIs are experimental and may be subject to backwards-incompatible changes. + +::: + +[Standalone Nexus Operations](/standalone-nexus-operation) let you run Nexus Operation Executions independently, without +being orchestrated by a Workflow. Instead of calling a Nexus Operation from within a Workflow Definition using +`Workflow.newNexusServiceStub()`, you execute a Standalone Nexus Operation directly from a Nexus service client created +from a `NexusClient` using `NexusClient.newNexusServiceClient()`. + +Standalone Nexus Operations use the same Nexus Service contract, Operation handlers, and Worker setup as +Workflow-driven Operations — only the execution path differs. See the [Nexus feature guide](/develop/java/nexus/feature-guide) for details on +[defining a Service contract](/develop/java/nexus/feature-guide#define-nexus-service-contract), +[developing Operation handlers](/develop/java/nexus/feature-guide#develop-nexus-service-operation-handlers), and +[registering a Service in a Worker](/develop/java/nexus/feature-guide#register-a-nexus-service-in-a-worker). + +This page focuses on the client-side APIs that are unique to Standalone Nexus Operations: + +- [Execute a Standalone Nexus Operation](#execute-operation) +- [Start a Standalone Nexus Operation and Wait for the Result](#get-operation-result) +- [List Standalone Nexus Operations](#list-operations) +- [Count Standalone Nexus Operations](#count-operations) + +:::note +This documentation uses source code from the +[Java Nexus Standalone sample](https://github.com/temporalio/samples-java/tree/main/core/src/main/java/io/temporal/samples/nexusstandalone). + +::: + +## Execute a Standalone Nexus Operation {/* #execute-operation */} + +To execute a Standalone Nexus Operation, first create a +[`NexusClient`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/NexusClient.html), then +derive a typed +[`NexusServiceClient`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/NexusServiceClient.html) +from it with `newNexusServiceClient()`, bound to a specific Nexus Endpoint and Service. The endpoint must be +pre-created on the server. Then call `start()` or `execute()` from application code (for example, a starter program), +not from inside a Workflow Definition. + +`execute()` waits for the Operation to complete and returns the result. +Both methods take a [`StartNexusOperationOptions`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/StartNexusOperationOptions.html) +whose `id` is required — the SDK never generates one for you. `scheduleToCloseTimeout` is optional and defaults to the +maximum allowed by the Temporal server. + +```java +NexusClient nexusClient = NexusClient.newInstance(stubs, options); +NexusServiceClient greetingClient = + nexusClient.newNexusServiceClient(GreetingNexusService.class, ENDPOINT_NAME); + +// Block until the operation completes and return its result. +GreetingOutput greeting = + greetingClient.execute( + GreetingNexusService::greet, + new GreetingInput("World"), + StartNexusOperationOptions.newBuilder() + .setId("greet-" + UUID.randomUUID()) + .setScheduleToCloseTimeout(Duration.ofSeconds(10)) + .build()); +``` + +`executeAsync()` is the same but returns a `CompletableFuture` instead of blocking. + +```java +CompletableFuture future = + greetingClient.executeAsync( + GreetingNexusService::greet, new GreetingInput("World"), options); +GreetingOutput greeting = future.get(); +``` + +See the full +[starter sample](https://github.com/temporalio/samples-java/blob/main/core/src/main/java/io/temporal/samples/nexusstandalone/StandaloneClientStarter.java) +for a complete example that executes both synchronous and asynchronous Operations, gets their results, and lists and +counts Operations. + +## Start a Standalone Nexus Operation and Wait for the Result {/* #get-operation-result */} + +`start()` returns a +[`NexusOperationHandle`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/NexusOperationHandle.html). +Use `NexusOperationHandle.getResult()` to wait until the Operation completes and retrieve its result. This works for +both synchronous and asynchronous Operations. + +```java +// Start an operation and get a NexusOperationHandle. +NexusOperationHandle handle = + greetingClient.start( + GreetingNexusService::startGreeting, new GreetingInput("World"), options); + +// Block until the operation completes and retrieve its result. +GreetingOutput greeting = handle.getResult(); +``` + +If the Operation completed successfully, the result is returned. If the Operation failed, the failure is thrown as a +`NexusOperationException`. Use `getResultAsync()` for a non-blocking `CompletableFuture`, or +`getResult(long timeout, TimeUnit unit)` to bound the wait. + +## List Standalone Nexus Operations {/* #list-operations */} + +Use [`NexusClient.listNexusOperationExecutions()`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/NexusClient.html) +to list Standalone Nexus Operation Executions that match a [List Filter](/list-filter) query. The result is a `Stream` +of operation metadata entries. + +Note that `listNexusOperationExecutions()` is called on a `NexusClient`, not on the typed `NexusServiceClient`. + +```java +String query = "Endpoint = \"" + ENDPOINT_NAME + "\""; +nexusClient + .listNexusOperationExecutions(query) + .forEach( + op -> + System.out.printf( + "OperationId: %s, Operation: %s, Status: %s%n", + op.getOperationId(), op.getOperation(), op.getStatus())); +``` + +The `query` parameter accepts [List Filter](/list-filter) syntax. For example, +`"Endpoint = 'my-endpoint' AND ExecutionStatus = 'Running'"`. + +## Count Standalone Nexus Operations {/* #count-operations */} + +Use [`NexusClient.countNexusOperationExecutions()`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/NexusClient.html) +to count Standalone Nexus Operation Executions that match a [List Filter](/list-filter) query. + +Note that `countNexusOperationExecutions()` is called on a `NexusClient`, not on the typed `NexusServiceClient`. + +```java +String query = "Endpoint = \"" + ENDPOINT_NAME + "\""; +NexusOperationExecutionCount count = nexusClient.countNexusOperationExecutions(query); +System.out.println("Total Nexus operations: " + count.getCount()); +``` + +Passing a `GROUP BY` query (for example, `"GROUP BY ExecutionStatus"`) returns a count per group, available through +`NexusOperationExecutionCount.getGroups()`. + +## Run Standalone Nexus Operations with Temporal Cloud {/* #run-standalone-nexus-operations-temporal-cloud */} + +The code samples referenced on this page build their client from a `ClientConfigProfile` loaded from a TOML profile, so +the same code works against Temporal Cloud — just point the profile at your Cloud Namespace (or override the connection +via `TEMPORAL_*` environment variables). No code changes are needed. + +For full details on connecting to Temporal Cloud, including Namespace creation, Nexus Endpoint setup, certificate +generation, and authentication options, see +[Make Nexus calls across Namespaces in Temporal Cloud](/develop/java/nexus/feature-guide#nexus-calls-across-namespaces-temporal-cloud) +and [Connect to Temporal Cloud](/develop/java/client/temporal-client#connect-to-temporal-cloud). diff --git a/sidebars.js b/sidebars.js index f2db99d5ed..927ac98d59 100644 --- a/sidebars.js +++ b/sidebars.js @@ -327,6 +327,7 @@ module.exports = { items: [ 'develop/java/nexus/quickstart', 'develop/java/nexus/feature-guide', + 'develop/java/nexus/standalone-operations', ], }, { From dce89cf6818f45578415d8c40d6de21e963054c9 Mon Sep 17 00:00:00 2001 From: Evan Reynolds Date: Tue, 9 Jun 2026 10:31:14 -0700 Subject: [PATCH 2/2] Updated to match SDK changes --- docs/develop/java/nexus/standalone-operations.mdx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/develop/java/nexus/standalone-operations.mdx b/docs/develop/java/nexus/standalone-operations.mdx index def425e49f..fb65c6d866 100644 --- a/docs/develop/java/nexus/standalone-operations.mdx +++ b/docs/develop/java/nexus/standalone-operations.mdx @@ -76,11 +76,11 @@ NexusServiceClient greetingClient = GreetingOutput greeting = greetingClient.execute( GreetingNexusService::greet, - new GreetingInput("World"), StartNexusOperationOptions.newBuilder() .setId("greet-" + UUID.randomUUID()) .setScheduleToCloseTimeout(Duration.ofSeconds(10)) - .build()); + .build(), + new GreetingInput("World")); ``` `executeAsync()` is the same but returns a `CompletableFuture` instead of blocking. @@ -88,7 +88,7 @@ GreetingOutput greeting = ```java CompletableFuture future = greetingClient.executeAsync( - GreetingNexusService::greet, new GreetingInput("World"), options); + GreetingNexusService::greet, options, new GreetingInput("World")); GreetingOutput greeting = future.get(); ``` @@ -108,7 +108,7 @@ both synchronous and asynchronous Operations. // Start an operation and get a NexusOperationHandle. NexusOperationHandle handle = greetingClient.start( - GreetingNexusService::startGreeting, new GreetingInput("World"), options); + GreetingNexusService::startGreeting, options, new GreetingInput("World")); // Block until the operation completes and retrieve its result. GreetingOutput greeting = handle.getResult();