# Standalone Nexus Operations - Java SDK

> Execute Nexus Operations independently without a Workflow using the Temporal Java SDK.

> **Pre-release**
> Requires Java SDK `v1.36.1` or above. 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)
- [Run Standalone Nexus Operations with Temporal Cloud](#run-standalone-nexus-operations-temporal-cloud)

> **📝 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).
>

## Prerequisites 

Standalone Nexus Operations are at Pre-release and require a special Temporal CLI build.

### 1. Install and verify the Pre-release Temporal CLI 

The `temporal nexus operation` commands require a Pre-release build of the Temporal CLI. See
[Temporal CLI support](/standalone-nexus-operation#temporal-cli-support) for the platform downloads,
then verify:

```bash
./temporal --version
# temporal version 1.7.4-standalone-nexus-operations
```

Run it as `./temporal` from the directory where you extracted it. The standard `brew install temporal`
build does not include Standalone Nexus Operation support during Pre-release.

### 2. Start a local dev server 

The Pre-release dev server enables Standalone Nexus Operations by default — no dynamic config is
required. Start it with the caller and handler Namespaces pre-created:

```bash
./temporal server start-dev \
  --namespace my-caller-namespace \
  --namespace my-handler-namespace
```

The starter and Worker connect to two different Namespaces (a caller Namespace and a handler
Namespace), mirroring how Nexus crosses Namespace boundaries.

To run the examples on this page against the [Java sample](https://github.com/temporalio/samples-java/tree/main/core/src/main/java/io/temporal/samples/nexusstandalone),
create a Nexus Endpoint that routes to the handler Namespace and the Worker's Task Queue:

```bash
./temporal operator nexus endpoint create \
  --name my-nexus-endpoint \
  --target-namespace my-handler-namespace \
  --target-task-queue nexus-handler-queue
```

Start the sample handler Worker in the handler Namespace:

```bash
TEMPORAL_NAMESPACE=my-handler-namespace \
  ./gradlew -q :core:execute -PmainClass=io.temporal.samples.nexusstandalone.handler.HandlerWorker
```

Run the starter in the caller Namespace (from a separate terminal):

```bash
TEMPORAL_NAMESPACE=my-caller-namespace \
  ./gradlew -q :core:execute -PmainClass=io.temporal.samples.nexusstandalone.StandaloneClientStarter
```

## Execute a Standalone Nexus 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<GreetingNexusService> greetingClient =
    nexusClient.newNexusServiceClient(GreetingNexusService.class, ENDPOINT_NAME);

// Block until the operation completes and return its result.
GreetingOutput greeting =
    greetingClient.execute(
        GreetingNexusService::greet,
        StartNexusOperationOptions.newBuilder()
            .setId("greet-" + UUID.randomUUID())
            .setScheduleToCloseTimeout(Duration.ofSeconds(10))
            .build(),
        new GreetingInput("World"));
```

`executeAsync()` is the same but returns a `CompletableFuture` instead of blocking.

```java
CompletableFuture<GreetingOutput> future =
    greetingClient.executeAsync(
        GreetingNexusService::greet, options, new GreetingInput("World"));
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.

Or use the Temporal CLI to execute a Standalone Nexus Operation:

```bash
./temporal nexus operation execute \
  --namespace my-caller-namespace \
  --endpoint my-nexus-endpoint \
  --service GreetingNexusService \
  --operation greet \
  --operation-id my-greet-op \
  --input '{"name":"World"}'
```

## Start a Standalone Nexus Operation and Wait for the 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<GreetingOutput> handle =
    greetingClient.start(
        GreetingNexusService::startGreeting, options, new GreetingInput("World"));

// 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.

Or use the Temporal CLI to wait for a result by Operation ID:

```bash
./temporal nexus operation result --namespace my-caller-namespace --operation-id my-greet-op
```

## List Standalone Nexus 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'"`.

Or use the Temporal CLI:

```bash
./temporal nexus operation list --namespace my-caller-namespace --query 'Endpoint = "my-nexus-endpoint"'
```

## Count Standalone Nexus 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()`.

Or use the Temporal CLI:

```bash
./temporal nexus operation count --namespace my-caller-namespace --query 'Endpoint = "my-nexus-endpoint"'
```

## Run Standalone Nexus Operations with 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).
