# Temporal Client

> For the complete documentation index, see [llms.txt](https://docs.temporal.io/llms.txt).
> Any documentation page is available as raw Markdown by appending `.md` to its URL.
> For related questions, query https://docs.temporal.io/api/retrieve?q=<question>&jtb=<job-to-be-done>&src=md-page&agent=<your-name> (no auth; returns JSON `{content, source_url, page_url}`, with `source_url` pointing to Markdown for docs pages). Don't include personal data or credentials.
> If this page is wrong or missing something you needed, or Temporal behaves differently from what it says, report it with https://docs.temporal.io/api/feedback?title=<summary>&message=<what-happened>&category=documentation&page_url=/develop/java/client/temporal-client&src=md-page&agent=<your-name> (use `category=product` when the product, not the page, is wrong). Report only a specific problem you hit, send it once, and don't include personal data or credentials.

A [Temporal Client](/encyclopedia/temporal-client) enables you to communicate with the
[Temporal Service](/temporal-service). Communication with a Temporal Service lets you perform actions such as starting
Workflow Executions, sending Signals to Workflow Executions, sending Queries to Workflow Executions, getting the results
of a Workflow Execution, and providing Activity Task Tokens.

For [Standalone Activities](/standalone-activity), a Temporal Client can also start and manage Standalone Activities directly, without involving a Workflow.

This page shows you how to do the following using the Java SDK with the Temporal Client:

- [Connect to a local development Temporal Service](#connect-to-development-service)
- [Connect to Temporal Cloud](#connect-to-temporal-cloud)
- [Start a Workflow Execution](#start-workflow-execution)
- [Get Workflow results](#get-workflow-results)

> **⚠️ Caution:**
>
> A Temporal Client cannot be initialized and used inside a Workflow. However, it is acceptable and common to use a
> Temporal Client inside an Activity to communicate with a Temporal Service.
>

## Connect to development Temporal Service 

Use the `newLocalServiceStubs` method to create a stub that points to the Temporal development service, and then use the
[`WorkflowClient.newInstance` method](https://javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowClient.html#newInstance(io.temporal.serviceclient.WorkflowServiceStubs))
to create a Temporal Client.

<!--SNIPSTART java-temporal-client-local-service {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java)
```java
// Create an instance that connects to a Temporal Service running on the local machine, using the default port 7233
WorkflowServiceStubs serviceStub = WorkflowServiceStubs.newLocalServiceStubs();

// Initialize the Client
WorkflowClient client = WorkflowClient.newInstance(serviceStub);
```
<!--SNIPEND-->

When you create a new Client with an instance of `newLocalServiceStubs`, the Client connects to the default local port
at port 7233. When you don't specify a custom Namespace, the Client connects to the `default` Namespace.

To connect to a custom Namespace, use the `WorkflowClientOptions.Builder.setNamespace` method to set the Namespace. Then
pass the `clientOptions` to the `WorkflowClient.newInstance` method.

**Configuration File**

You can use a TOML configuration file to set connection options for the Temporal Client. The configuration file lets you
configure multiple profiles, each with its own set of connection options. You can then specify which profile to use when
creating the Temporal Client. You can use the environment variable `TEMPORAL_CONFIG_FILE` to specify the location of the
TOML file or provide the path to the file directly in code. If you don't provide the configuration file path, the SDK
looks for it at the path `~/.config/temporalio/temporal.toml`. For a list of all available configuration options, refer
to [Environment Configuration](/references/client-environment-configuration)

> **ℹ️ Info:**
>
> The connection options set in configuration files have lower precedence than environment variables. This means that if
> you set the same option in both the configuration file and as an environment variable, the environment variable value
> overrides the option set in the configuration file.
>

For example, the following TOML configuration file defines two profiles: `default` and `prod`. Each profile has its own
set of connection options.

<!--SNIPSTART java-temporal-client-config-file-->
[java-sandbox/client/temporal-client/src/main/resources/config.toml](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/resources/config.toml)
```toml
# Default profile for local development
[profile.default]
address = "localhost:7233"
namespace = "default"

# Custom gRPC headers
[profile.default.grpc_meta]
my-custom-header = "development-value"
trace-id = "dev-trace-123"

# Production profile for Temporal Cloud
[profile.prod]
address = "your-namespace.a1b2c.tmprl.cloud:7233"
namespace = "your-namespace"
api_key = "your-api-key-here"

# TLS configuration for production
[profile.prod.tls]
# TLS is auto-enabled when this TLS config or API key is present, but you can configure it explicitly
# disabled = false
# Use certificate files for mTLS
client_cert_path = "/etc/temporal/certs/client.pem"
client_key_path = "/etc/temporal/certs/client.key"

# Custom headers for production
[profile.prod.grpc_meta]
environment = "production"
service-version = "v1.2.3"
```
<!--SNIPEND-->

You can create a Temporal Client using a specific profile from the configuration file as follows. First use
`ClientConfigProfile.load` to load the profile from the configuration file. Then use
`profile.toWorkflowServiceStubsOptions` and `profile.toWorkflowClientOptions` to convert the profile to
`WorkflowServiceStubsOptions` and `WorkflowClientOptions` respectively. Then use `WorkflowClient.newInstance` to create
a Temporal Client.

<!--SNIPSTART java-temporal-client-load-from-file {"highlightedLines": "21-25,32-34"}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/LoadFromFile.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/LoadFromFile.java)
```java {21-25,32-34}
import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowClientOptions;
import io.temporal.envconfig.ClientConfigProfile;
import io.temporal.envconfig.LoadClientConfigProfileOptions;
import io.temporal.serviceclient.WorkflowServiceStubs;
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
import java.nio.file.Paths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoadFromFile {

  private static final Logger logger = LoggerFactory.getLogger(LoadFromFile.class);

  public static void main(String[] args) {
    try {

      String configFilePath =
          Paths.get(LoadFromFile.class.getResource("/config.toml").toURI()).toString();

      ClientConfigProfile profile =
          ClientConfigProfile.load(
              LoadClientConfigProfileOptions.newBuilder()
                  .setConfigFilePath(configFilePath)
                  .build());

      WorkflowServiceStubsOptions serviceStubsOptions = profile.toWorkflowServiceStubsOptions();
      WorkflowClientOptions clientOptions = profile.toWorkflowClientOptions();

      try {
        // Create the workflow client using the loaded configuration
        WorkflowClient client =
            WorkflowClient.newInstance(
                WorkflowServiceStubs.newServiceStubs(serviceStubsOptions), clientOptions);

        // Test the connection by getting system info
        var systemInfo =
            client
                .getWorkflowServiceStubs()
                .blockingStub()
                .getSystemInfo(
                    io.temporal.api.workflowservice.v1.GetSystemInfoRequest.getDefaultInstance());

        logger.info("✅ Client connected successfully!");
        logger.info("   Server version: {}", systemInfo.getServerVersion());

      } catch (Exception e) {
        logger.error("❌ Failed to connect: {}", e.getMessage());
      }

    } catch (Exception e) {
      logger.error("Failed to load configuration: {}", e.getMessage(), e);
      System.exit(1);
    }
  }
}
```
<!--SNIPEND-->

**Environment Variables**

Use the `envconfig` package to set connection options for the Temporal Client using environment variables. For a list of
all available environment variables and their default values, refer to
[Environment Configuration](/references/client-environment-configuration).

For example, the following code snippet loads all environment variables and creates a Temporal Client with the options
specified in those variables. If you have defined a configuration file at either the default location
(`~/.config/temporalio/temporal.toml`) or a custom location specified by the `TEMPORAL_CONFIG_FILE` environment
variable, this will also load the default profile in the configuration file. However, any options set via environment
variables will take precedence.

<!--SNIPSTART java-temporal-client-load-from-env {"highlightedLines": "17-18,25-27"}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/LoadFromEnv.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/LoadFromEnv.java)
```java {17-18,25-27}
import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowClientOptions;
import io.temporal.envconfig.ClientConfigProfile;
import io.temporal.envconfig.LoadClientConfigProfileOptions;
import io.temporal.serviceclient.WorkflowServiceStubs;
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoadFromEnv {

  private static final Logger logger = LoggerFactory.getLogger(LoadFromEnv.class);

  public static void main(String[] args) {
    try {

      ClientConfigProfile profile =
          ClientConfigProfile.load(LoadClientConfigProfileOptions.newBuilder().build());

      WorkflowServiceStubsOptions serviceStubsOptions = profile.toWorkflowServiceStubsOptions();
      WorkflowClientOptions clientOptions = profile.toWorkflowClientOptions();

      try {
        // Create the workflow client using the loaded configuration
        WorkflowClient client =
            WorkflowClient.newInstance(
                WorkflowServiceStubs.newServiceStubs(serviceStubsOptions), clientOptions);

        // Test the connection by getting system info
        var systemInfo =
            client
                .getWorkflowServiceStubs()
                .blockingStub()
                .getSystemInfo(
                    io.temporal.api.workflowservice.v1.GetSystemInfoRequest.getDefaultInstance());

        logger.info("✅ Client connected successfully!");
        logger.info("   Server version: {}", systemInfo.getServerVersion());

      } catch (Exception e) {
        logger.error("❌ Failed to connect: {}", e.getMessage());
      }

    } catch (Exception e) {
      logger.error("Failed to load configuration: {}", e.getMessage(), e);
      System.exit(1);
    }
  }
}
```
<!--SNIPEND-->

**Code**

If you don't want to use environment variables or a configuration file, you can specify connection options directly in
code. This is convenient for local development and testing. You can also load a base configuration from environment
variables or a configuration file, and then override specific options in code.

<!--SNIPSTART java-temporal-client-custom-namespace {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java)
```java
// Add the Namespace as a Client Option
WorkflowClientOptions clientOptions =
    WorkflowClientOptions.newBuilder().setNamespace(namespace).build();

// Initialize the Client
WorkflowClient client = WorkflowClient.newInstance(service, clientOptions);
```
<!--SNIPEND-->

## Connect to Temporal Cloud 

You can connect to Temporal Cloud using either an [API key](/cloud/api-keys) or through [mTLS](/cloud/certificates).
Connection to Temporal Cloud or any secured Temporal Service requires additional connection options compared to
connecting to an unsecured local development instance:

- Your credentials for authentication.
  - If you are using an API key, provide the API key value.
  - If you are using mTLS, provide the mTLS CA certificate and mTLS private key.
- Your _Namespace and Account ID_ combination, which follows the format `<namespace_id>.<account_id>`.
- The recommended _endpoint_ is the gRPC Namespace endpoint: `<namespace>.<account>.tmprl.cloud:7233`.
  This endpoint works for all Namespaces and automatically directs traffic to the active region for Namespaces with [High Availability](/cloud/high-availability).
  See [accessing Namespaces](/cloud/namespaces#access-namespaces) for more information on endpoint options.

You can find the Namespace and Account ID, as well as the endpoint, on the Namespaces tab.

You can provide these connection options using environment variables, a configuration file, or directly in code.

**Configuration File**

You can use a TOML configuration file to set connection options for the Temporal Client. The configuration file lets you
configure multiple profiles, each with its own set of connection options. You can then specify which profile to use when
creating the Temporal Client. For a list of all available configuration options you can set in the TOML file, refer to
[Environment Configuration](/references/client-environment-configuration).

You can use the environment variable `TEMPORAL_CONFIG_FILE` to specify the location of the TOML file or provide the path
to the file directly in code. If you don't provide the path to the configuration file, the SDK looks for it at the
default path `~/.config/temporalio/temporal.toml`.

> **ℹ️ Info:**
>
> The connection options set in configuration files have lower precedence than environment variables. This means that if
> you set the same option in both the configuration file and as an environment variable, the environment variable value
> overrides the option set in the configuration file.
>

For example, the following TOML configuration file defines a `cloud` profile with the necessary connection options to
connect to Temporal Cloud via an API key:

<!--SNIPSTART java-temporal-client-cloud-api-key-profile-->
[java-sandbox/client/temporal-client/src/main/resources/config.toml](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/resources/config.toml)
```toml
# Cloud profile for Temporal Cloud
[profile.cloud]
address = "your-namespace.a1b2c.tmprl.cloud:7233"
namespace = "your-namespace"
api_key = "your-api-key-here"
```
<!--SNIPEND-->

If you want to use mTLS authentication instead of an API key, replace the `api_key` field with a `tls` table that points
to your mTLS certificate and private key:

<!--SNIPSTART java-temporal-client-cloud-mtls-profile-->
[java-sandbox/client/temporal-client/src/main/resources/cloud-mtls.toml](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/resources/cloud-mtls.toml)
```toml
# Cloud profile for Temporal Cloud
[profile.cloud]
address = "your-namespace.a1b2c.tmprl.cloud:7233"
namespace = "your-namespace"

[profile.cloud.tls]
client_cert_path = "/etc/temporal/certs/client.pem"
client_key_path = "/etc/temporal/certs/client.key"
```
<!--SNIPEND-->

With the connections options defined in the configuration file, use the `LoadClientOptions` function in the `envconfig`
package to create a Temporal Client using the `cloud` profile as follows. After loading the profile, you can also
programmatically override specific connection options before creating the client.

<!--SNIPSTART java-temporal-client-load-profile {"highlightedLines": "25-30,33-35,42-44"}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/LoadProfile.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/LoadProfile.java)
```java {25-30,33-35,42-44}
import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowClientOptions;
import io.temporal.envconfig.ClientConfigProfile;
import io.temporal.envconfig.LoadClientConfigProfileOptions;
import io.temporal.serviceclient.WorkflowServiceStubs;
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
import java.nio.file.Paths;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoadProfile {

  private static final Logger logger = LoggerFactory.getLogger(LoadProfile.class);

  public static void main(String[] args) {
    String profileName = "cloud";

    try {
      String configFilePath =
          Paths.get(LoadProfile.class.getResource("/config.toml").toURI()).toString();

      logger.info("--- Loading '{}' profile from {} ---", profileName, configFilePath);

      // Load specific profile from file with environment variable overrides
      ClientConfigProfile profile =
          ClientConfigProfile.load(
              LoadClientConfigProfileOptions.newBuilder()
                  .setConfigFilePath(configFilePath)
                  .setConfigFileProfile(profileName)
                  .build());

      // Demonstrate programmatic override - set the Namespace in code instead of the file
      ClientConfigProfile.Builder profileBuilder = profile.toBuilder();
      profileBuilder.setNamespace("your-namespace.a1b2c"); // Override the Namespace from the file
      profile = profileBuilder.build();

      WorkflowServiceStubsOptions serviceStubsOptions = profile.toWorkflowServiceStubsOptions();
      WorkflowClientOptions clientOptions = profile.toWorkflowClientOptions();

      try {
        // Create the workflow client using the loaded configuration
        WorkflowClient client =
            WorkflowClient.newInstance(
                WorkflowServiceStubs.newServiceStubs(serviceStubsOptions), clientOptions);

        // Test the connection by getting system info
        var systemInfo =
            client
                .getWorkflowServiceStubs()
                .blockingStub()
                .getSystemInfo(
                    io.temporal.api.workflowservice.v1.GetSystemInfoRequest.getDefaultInstance());

        logger.info("✅ Client connected successfully!");
        logger.info("   Server version: {}", systemInfo.getServerVersion());

      } catch (Exception e) {
        logger.error("❌ Failed to connect: {}", e.getMessage());
      }

    } catch (Exception e) {
      logger.error("Failed to load configuration: {}", e.getMessage(), e);
      System.exit(1);
    }
  }
}
```
<!--SNIPEND-->

**Environment Variables**

The following environment variables are required to connect to Temporal Cloud:

- `TEMPORAL_NAMESPACE`: Your Namespace and Account ID combination in the format `<namespace_id>.<account_id>`.
- `TEMPORAL_ADDRESS`: The gRPC endpoint for your Temporal Cloud Namespace.
- `TEMPORAL_API_KEY`: Your API key value. Required if you are using API key authentication.
- `TEMPORAL_TLS_CLIENT_CERT_DATA` or `TEMPORAL_TLS_CLIENT_CERT_PATH`: Your mTLS client certificate data or file path.
  Required if you are using mTLS authentication.
- `TEMPORAL_TLS_CLIENT_KEY_DATA` or `TEMPORAL_TLS_CLIENT_KEY_PATH`: Your mTLS client private key data or file path.
  Required if you are using mTLS authentication.

Ensure these environment variables exist in your environment before running your Java application.

Import the `io.temporal.envconfig` package to set connection options for the Temporal Client using environment variables. The `ClientConfigProfile.load` method will automatically load all environment variables. For a list of all available environment variables and their default values, refer to [Environment Configuration](/references/client-environment-configuration).

For example, the following code snippet loads all environment variables and creates a Temporal Client with the options specified in those variables. If you have defined a configuration file at either the default location (`~/.config/temporalio/temporal.toml`) or a custom location specified by the `TEMPORAL_CONFIG_FILE` environment variable, this will also load the default profile in the configuration file. However, any options set via environment variables will take precedence.

<!--SNIPSTART java-temporal-client-load-from-env {"highlightedLines": "17-18,25-27"}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/LoadFromEnv.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/LoadFromEnv.java)
```java {17-18,25-27}
import io.temporal.client.WorkflowClient;
import io.temporal.client.WorkflowClientOptions;
import io.temporal.envconfig.ClientConfigProfile;
import io.temporal.envconfig.LoadClientConfigProfileOptions;
import io.temporal.serviceclient.WorkflowServiceStubs;
import io.temporal.serviceclient.WorkflowServiceStubsOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LoadFromEnv {

  private static final Logger logger = LoggerFactory.getLogger(LoadFromEnv.class);

  public static void main(String[] args) {
    try {

      ClientConfigProfile profile =
          ClientConfigProfile.load(LoadClientConfigProfileOptions.newBuilder().build());

      WorkflowServiceStubsOptions serviceStubsOptions = profile.toWorkflowServiceStubsOptions();
      WorkflowClientOptions clientOptions = profile.toWorkflowClientOptions();

      try {
        // Create the workflow client using the loaded configuration
        WorkflowClient client =
            WorkflowClient.newInstance(
                WorkflowServiceStubs.newServiceStubs(serviceStubsOptions), clientOptions);

        // Test the connection by getting system info
        var systemInfo =
            client
                .getWorkflowServiceStubs()
                .blockingStub()
                .getSystemInfo(
                    io.temporal.api.workflowservice.v1.GetSystemInfoRequest.getDefaultInstance());

        logger.info("✅ Client connected successfully!");
        logger.info("   Server version: {}", systemInfo.getServerVersion());

      } catch (Exception e) {
        logger.error("❌ Failed to connect: {}", e.getMessage());
      }

    } catch (Exception e) {
      logger.error("Failed to load configuration: {}", e.getMessage(), e);
      System.exit(1);
    }
  }
}
```
<!--SNIPEND-->

**Code**

Now, when instantiating a Temporal `client` in your Temporal Java SDK code, provide the API key with
`WorkflowServiceStubsOptions` and the Namespace and Account ID in `WorkflowClient.newInstance`:

<!--SNIPSTART java-temporal-client-api-key {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java)
```java
WorkflowServiceStubs service =
    WorkflowServiceStubs.newServiceStubs(
        WorkflowServiceStubsOptions.newBuilder()
            .addApiKey(() -> apiKey)
            .setTarget(endpoint)
            .setEnableHttps(true)
            .build());

// namespace is your <namespace_id>.<account_id>
WorkflowClient client =
    WorkflowClient.newInstance(
        service, WorkflowClientOptions.newBuilder().setNamespace(namespace).build());
```
<!--SNIPEND-->

To rotate the API key without restarting, return the current key from the supplier. The SDK calls the supplier on each
request and adds the `Bearer ` prefix, so store only the key and replace it in a thread-safe way:

<!--SNIPSTART java-temporal-client-update-api-key {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java)
```java
AtomicReference<String> myKey = new AtomicReference<>(apiKey);
WorkflowServiceStubsOptions stubOptions =
    WorkflowServiceStubsOptions.newBuilder().addApiKey(myKey::get).build();
// The SDK calls the supplier on each request and adds the "Bearer " prefix.
// Replace the key atomically; later requests use the new value.
myKey.set(newApiKey);
```
<!--SNIPEND-->

To connect to Temporal Cloud using mTLS, you need to provide the mTLS CA certificate and mTLS private key. You can then
use the `SimpleSslContextBuilder` to build an SSL context. Then use the
`WorkflowServiceStubsOptions.Builder.setSslContext` method to set the SSL context.

When you use a remote service, you don't use the `newLocalServiceStubs` convenience method. Instead, set your
connection details as stub configuration options:

<!--SNIPSTART java-temporal-client-mtls-stubs {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java)
```java
// Set the Service Stub options (SSL context and gRPC endpoint)
WorkflowServiceStubsOptions stubsOptions =
    WorkflowServiceStubsOptions.newBuilder()
        .setSslContext(sslContext)
        .setTarget(gRPCEndpoint)
        .build();

// Create a stub that accesses a Temporal Service
WorkflowServiceStubs serviceStub = WorkflowServiceStubs.newServiceStubs(stubsOptions);
```
<!--SNIPEND-->

Each Temporal Cloud service Client has four prerequisites.

- The full Namespace Id from the [Cloud Namespace](https://cloud.temporal.io/namespaces) details page
- The gRPC endpoint from the [Cloud Namespace](https://cloud.temporal.io/namespaces) details page
- Your mTLS private key
- Your mTLS x509 Certificate

Retrieve these values before building your Client.

The following sample generates an SSL context from the mTLS .pem and .key files. Along with the gRPC endpoint, this
information configures a service stub for Temporal Cloud. Add the Namespace to your Client build options and initialize
the new Client:

<!--SNIPSTART java-temporal-client-mtls-client {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java)
```java
// Generate an SSL context
InputStream clientCertInputStream = new FileInputStream(clientCertPath);
InputStream clientKeyInputStream = new FileInputStream(clientKeyPath);
SslContext sslContext =
    SimpleSslContextBuilder.forPKCS8(clientCertInputStream, clientKeyInputStream).build();

// Set the Service Stub options (SSL context and gRPC endpoint)
WorkflowServiceStubsOptions stubsOptions =
    WorkflowServiceStubsOptions.newBuilder()
        .setSslContext(sslContext)
        .setTarget(gRPCEndpoint)
        .build();

// Create a stub that accesses a Temporal Service
WorkflowServiceStubs serviceStub = WorkflowServiceStubs.newServiceStubs(stubsOptions);

// Set the Client options
WorkflowClientOptions clientOptions =
    WorkflowClientOptions.newBuilder().setNamespace(namespace).build();

// Initialize the Client
WorkflowClient client = WorkflowClient.newInstance(serviceStub, clientOptions);
```
<!--SNIPEND-->

To rotate an mTLS client certificate without restarting your Worker, build the `SslContext` with gRPC's
[`AdvancedTlsX509KeyManager`](https://grpc.github.io/grpc-java/javadoc/io/grpc/util/AdvancedTlsX509KeyManager.html)
instead of `SimpleSslContextBuilder`. `updateIdentityCredentialsFromFile` schedules a periodic reread of the certificate
and key files, so the same `SslContext` keeps serving fresh credentials for the life of the process:

<!--SNIPSTART java-temporal-client-mtls-rotation {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/ConnectExamples.java)
```java
// tlsKeyPath must point to a PKCS8 key
// Reread the certificate and key files every 5 minutes.
AdvancedTlsX509KeyManager keyManager = new AdvancedTlsX509KeyManager();
keyManager.updateIdentityCredentialsFromFile(
    new File(tlsKeyPath),
    new File(tlsCertPath),
    5,
    TimeUnit.MINUTES,
    Executors.newSingleThreadScheduledExecutor());

SslContextBuilder sslContextBuilder = SslContextBuilder.forClient();
GrpcSslContexts.configure(sslContextBuilder);
SslContext sslContext = sslContextBuilder.keyManager(keyManager).build();

WorkflowServiceStubsOptions stubsOptions =
    WorkflowServiceStubsOptions.newBuilder()
        .setSslContext(sslContext)
        .setTarget(gRPCEndpoint)
        .build();
WorkflowServiceStubs serviceStub = WorkflowServiceStubs.newServiceStubs(stubsOptions);
```
<!--SNIPEND-->

Rotate the certificate by overwriting the files at `tlsCertPath` and `tlsKeyPath`; `keyManager` picks up the new files on
its next scheduled check, and the Worker keeps running against the same `client`/`serviceStub`. See this
[reference implementation](https://github.com/temporal-sa/temporal-worker-cert-rotation) (written for the Go SDK, but the
"What if I am not using the Go SDK?" section covers this Java approach) for a full walkthrough.

## Start a Workflow Execution 

[Workflow Execution](/workflow-execution) semantics rely on several parameters. To start a Workflow Execution, you must
supply a Task Queue that will be used for the Tasks (one that a Worker is polling), the Workflow Type, language-specific
contextual data, and Workflow Function parameters.

In the examples below, all Workflow Executions are started using a Temporal Client. To spawn Workflow Executions from
within another Workflow Execution, use either the [Child Workflow](/develop/java/workflows/child-workflows) or External Workflow
APIs.

See the [Customize Workflow Type](/develop/java/workflows/basics#workflow-type) section to see how to customize the name
of the Workflow Type.

A request to spawn a Workflow Execution causes the Temporal Service to create the first Event
([WorkflowExecutionStarted](/references/events#workflowexecutionstarted)) in the Workflow Execution Event History. The
Temporal Service then creates the first Workflow Task, resulting in the first
[WorkflowTaskScheduled](/references/events#workflowtaskscheduled) Event.

Use `WorkflowStub` to start a Workflow Execution from a Client. From inside a Workflow, start another Workflow
Execution as a [Child Workflow](/develop/java/workflows/child-workflows), or use `ExternalWorkflowStub` to Signal or
cancel one that is already running.

See [`SignalwithStart`](/develop/java/workflows/message-passing#signal-with-start) to start a Workflow Execution to receive a
Signal from within another Workflow.

### Use WorkflowStub

`WorkflowStub` is a proxy generated by the `WorkflowClient`. Each time a new Workflow Execution is started, an instance
of the Workflow implementation object is created. Then, one of the methods (depending on the Workflow Type of the
instance) annotated with `@WorkflowMethod` can be invoked. As soon as this method returns, the Workflow Execution is
considered to be complete.

You can use a typed or untyped `WorkflowStub` in the client code.

- Typed `WorkflowStub` are useful because they are type safe and allow you to invoke your Workflow methods such as
  `@WorkflowMethod`, `@QueryMethod`, and `@SignalMethod` directly.
- An untyped `WorkflowStub` does not use the Workflow interface, and is not type safe. It is more flexible because it
  has methods from the `WorkflowStub` interface, such as `start`, `signalWithStart`, `getResults` (sync and async),
  `query`, `signal`, `cancel` and `terminate`. Note that the Temporal Java SDK also provides typed `WorkflowStub`
  versions for these methods. When using untyped `WorkflowStub`, we rely on the Workflow Type, Activity Type, Child
  Workflow Type, as well as Query and Signal names. For details, see [Temporal Client](/encyclopedia/temporal-client).

A Workflow Execution can be started either synchronously or asynchronously.

Synchronous invocation starts a Workflow and then waits for its completion. If the process that started the Workflow
crashes or stops waiting, the Workflow continues executing. Because Workflows are potentially long-running, and Client
crashes happen, it is not very commonly found in production use. The following example is a type-safe approach for
starting a Workflow Execution synchronously.

<!--SNIPSTART java-temporal-client-start-sync {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
NotifyUserAccounts workflow =
    client.newWorkflowStub(
        NotifyUserAccounts.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("notifyAccounts")
            .setTaskQueue(taskQueue)
            .build());

// Start the Workflow and wait for a result.
// notify(String[] accountIds) is a Workflow method defined in the Workflow Definition.
workflow.notify(
    new String[] {
      "Account1", "Account2", "Account3", "Account4", "Account5",
      "Account6", "Account7", "Account8", "Account9", "Account10"
    });
```
<!--SNIPEND-->

Asynchronous start initiates a Workflow Execution and immediately returns to the caller. This is the most common way
to start Workflows in production code. The
[`WorkflowClient`](https://github.com/temporalio/sdk-java/blob/main/temporal-sdk/src/main/java/io/temporal/client/WorkflowClient.java)
provides some static methods, such as `start`, `execute`, and `signalWithStart`, that help with starting your
Workflows asynchronously.

The following examples show how to start Workflow Executions asynchronously, with either typed or untyped
`WorkflowStub`.

Typed `WorkflowStub` example:

<!--SNIPSTART java-temporal-client-start-typed {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a typed Workflow stub
FileProcessingWorkflow workflow =
    client.newWorkflowStub(
        FileProcessingWorkflow.class,
        WorkflowOptions.newBuilder()
            .setTaskQueue(taskQueue)
            .setWorkflowId(workflowId)
            .build());
// Use WorkflowClient.execute to return a future that contains the Workflow result or failure,
// or use WorkflowClient.start to return the Workflow ID and Run ID of the started Workflow.
WorkflowExecution execution = WorkflowClient.start(workflow::processFile, fileName);
```
<!--SNIPEND-->

Untyped `WorkflowStub` example:

<!--SNIPSTART java-temporal-client-start-untyped {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
WorkflowStub untyped =
    client.newUntypedWorkflowStub(
        "FileProcessingWorkflow",
        WorkflowOptions.newBuilder()
            .setWorkflowId(workflowId)
            .setTaskQueue(taskQueue)
            .build());

// Blocks until the Workflow Execution has been started (not until it completes)
untyped.start(argument);
```
<!--SNIPEND-->

You can call a Dynamic Workflow implementation using an untyped `WorkflowStub`. The following example shows how to call
the Dynamic Workflow implementation in the Client code.

<!--SNIPSTART java-temporal-client-dynamic-stub {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// The Worker must register the Dynamic Workflow implementation, for example:
// worker.registerWorkflowImplementationTypes(DynamicGreetingWorkflowImpl.class);

// Create the Workflow stub to call the Dynamic Workflow.
// The "DynamicWF" Workflow Type is not explicitly registered with the Worker.
WorkflowOptions workflowOptions =
    WorkflowOptions.newBuilder().setTaskQueue(TASK_QUEUE).setWorkflowId(workflowId).build();
WorkflowStub workflow = client.newUntypedWorkflowStub("DynamicWF", workflowOptions);
```
<!--SNIPEND-->

`DynamicWorkflow` can be used to invoke different Workflow Types. To check what type is running when your Dynamic
Workflow `execute` method runs, use `getWorkflowType()` in the implementation code.

<!--SNIPSTART java-temporal-client-dynamic-workflow-type {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/Workflows.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/Workflows.java)
```java
String type = Workflow.getInfo().getWorkflowType();
```
<!--SNIPEND-->

See [Workflow Execution Result](#get-workflow-results) for details on how to get the results of the Workflow Execution.

### Use ExternalWorkflowStub

Use `ExternalWorkflowStub` within a Workflow to send Signals to, or cancel, another Workflow Execution by its Workflow ID.
The target Workflow can be written in any language SDK, because the untyped stub refers to the Signal by name, as shown
in the following example.

<!--SNIPSTART java-temporal-client-external-workflow-stub {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/Workflows.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/Workflows.java)
```java
@Override
public String yourWFMethod(String name) {
  // Get a stub for a running Workflow Execution by its Workflow ID
  ExternalWorkflowStub otherWorkflow = Workflow.newUntypedExternalWorkflowStub("OtherWFId");
  // Send a Signal by name; the target Workflow can be written in any SDK
  otherWorkflow.signal("addItem", name);
  return "Signaled OtherWFId";
}
```
<!--SNIPEND-->

See the [Temporal Polyglot](https://github.com/tsurdilo/temporal-polyglot) code for examples of executing Workflows
written in other language SDKs.

### Start a Workflow on a schedule

You can start a Workflow Execution on a regular schedule by using
[`setCronSchedule`](/develop/java/workflows/schedules#cron-schedule) Workflow option in the Client code.

### Set a Workflow's Task Queue 

The only Workflow Option that you must set is the name of the [Task Queue](/task-queue).

For your code to execute, a Worker Process must be running. This process needs a Worker Entity that is polling the same
Task Queue name.

Set the Workflow Task Queue with the
[`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html)
instance in the Client code using
[`WorkflowOptions.Builder.setTaskQueue`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html).

- Type: `String`
- Default: none

<!--SNIPSTART java-temporal-client-task-queue {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("YourWF")
            // Set the Task Queue
            .setTaskQueue(TASK_QUEUE)
            .build());
```
<!--SNIPEND-->

### Set a Workflow Id 

Although it is not required, we recommend providing your own
[Workflow Id](/workflow-execution/workflowid-runid#workflow-id) that maps to a business process or business entity
identifier, such as an order identifier or customer identifier.

Set the Workflow Id with the
[`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html)
instance in the Client code using
[`WorkflowOptions.Builder.setWorkflowId`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html).

- Type: `String`
- Default: none

<!--SNIPSTART java-temporal-client-workflow-id {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            // Set the Workflow ID
            .setWorkflowId("YourWF")
            .setTaskQueue(TASK_QUEUE)
            .build());
```
<!--SNIPEND-->

### Java WorkflowOptions reference 

Create a
[`newWorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html) in
the Temporal Client code, call the instance of the Workflow, and set the Workflow options with the
[`WorkflowOptions.Builder`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html)
class.

The following fields are available:

| Option                                                  | Required             | Type                                                                                                                 |
| ------------------------------------------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------- |
| [`WorkflowId`](#workflowid)                             | No (but recommended) | String                                                                                                               |
| [`TaskQueue`](#taskqueue)                               | **Yes**              | String                                                                                                               |
| [`WorkflowExecutionTimeout`](#workflowexecutiontimeout) | No                   | `Duration`                                                                                                           |
| [`WorkflowRunTimeout`](#workflowruntimeout)             | No                   | `Duration`                                                                                                           |
| [`WorkflowTaskTimeout`](#workflowtasktimeout)           | No                   | `Duration`                                                                                                           |
| [`WorkflowIdReusePolicy`](#workflowidreusepolicy)       | No                   | `WorkflowIdReusePolicy`                                                                                              |
| [`RetryOptions`](#retryoptions)                         | No                   | [`RetryOptions`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/common/RetryOptions.html)    |
| [`CronSchedule`](#cronschedule)                         | No                   | String                                                                                                               |
| [`Memo`](#memo)                                         | No                   | `String`                                                                                                             |
| [`SearchAttributes`](#searchattributes)                 | No                   | `SearchAttributes`                                                                                                   |

#### WorkflowId

Set the Workflow Id with the
[`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html)
instance in the Client code using
[`WorkflowOptions.Builder.setWorkflowId`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html).

- Type: `String`
- Default: none

<!--SNIPSTART java-temporal-client-workflow-id {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            // Set the Workflow ID
            .setWorkflowId("YourWF")
            .setTaskQueue(TASK_QUEUE)
            .build());
```
<!--SNIPEND-->

#### TaskQueue

Set the Workflow Task Queue with the
[`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html)
instance in the Client code using
[`WorkflowOptions.Builder.setTaskQueue`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html).

- Type: `String`
- Default: none

<!--SNIPSTART java-temporal-client-task-queue {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("YourWF")
            // Set the Task Queue
            .setTaskQueue(TASK_QUEUE)
            .build());
```
<!--SNIPEND-->

#### WorkflowExecutionTimeout

Set the [Workflow Execution Timeout](/encyclopedia/detecting-workflow-failures#workflow-execution-timeout) with the
[`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html)
instance in the Client code using
[`WorkflowOptions.Builder.setWorkflowExecutionTimeout`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html).

- Type: `Duration`
- Default: Unlimited

<!--SNIPSTART java-temporal-client-execution-timeout {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("YourWF")
            .setTaskQueue(TASK_QUEUE)
            // Set Workflow Execution Timeout duration
            .setWorkflowExecutionTimeout(Duration.ofSeconds(10))
            .build());
```
<!--SNIPEND-->

#### WorkflowRunTimeout

Set the Workflow Run Timeout with the
[`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html)
instance in the Client code using
[`WorkflowOptions.Builder.setWorkflowRunTimeout`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html).

- Type: `Duration`
- Default: Same as [WorkflowExecutionTimeout](#workflowexecutiontimeout).

<!--SNIPSTART java-temporal-client-run-timeout {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("YourWF")
            .setTaskQueue(TASK_QUEUE)
            // Set Workflow Run Timeout duration
            .setWorkflowRunTimeout(Duration.ofSeconds(10))
            .build());
```
<!--SNIPEND-->

#### WorkflowTaskTimeout

Set the Workflow Task Timeout with the
[`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html)
instance in the Client code using
[`WorkflowOptions.Builder.setWorkflowTaskTimeout`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html).

- Type: `Duration`
- Default: 10 seconds.
- Values: Maximum accepted value is 60 seconds.

<!--SNIPSTART java-temporal-client-task-timeout {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("YourWF")
            .setTaskQueue(TASK_QUEUE)
            // Set Workflow Task Timeout duration
            .setWorkflowTaskTimeout(Duration.ofSeconds(10))
            .build());
```
<!--SNIPEND-->

#### WorkflowIDReusePolicy

- Type: `WorkflowIdReusePolicy`
- Default: `AllowDuplicate`
- Values:
  - `enums.AllowDuplicateFailedOnly`: The Workflow can start if the earlier Workflow Execution failed, Canceled, or
    Terminated.
  - `AllowDuplicate`: The Workflow can start regardless of the earlier Execution's closure status.
  - `RejectDuplicate`: The Workflow can not start if there is an earlier Run.

<!--SNIPSTART java-temporal-client-id-reuse-policy {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("YourWF")
            .setTaskQueue(TASK_QUEUE)
            // Set Workflow ID Reuse Policy
            .setWorkflowIdReusePolicy(
                WorkflowIdReusePolicy.WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE)
            .build());
```
<!--SNIPEND-->

#### RetryOptions

To set Workflow Retry Options in the [`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html) instance, use [`WorkflowOptions.Builder.setRetryOptions`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html#setRetryOptions(io.temporal.common.RetryOptions)).

- Type: `RetryOptions`
- Default: `Null` which means no retries will be attempted.

<!--SNIPSTART java-temporal-client-retry-options {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("YourWF")
            .setTaskQueue(TASK_QUEUE)
            // Set Workflow Retry Options
            .setRetryOptions(RetryOptions.newBuilder().setMaximumAttempts(3).build())
            .build());
```
<!--SNIPEND-->

#### CronSchedule

A [Temporal Cron Job](/cron-job) is the series of Workflow Executions that occur when a Cron Schedule is provided in the
call to spawn a Workflow Execution.

A Cron Schedule is provided as an option when the call to spawn a Workflow Execution is made.

Set the Cron Schedule with the
[`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html)
instance in the Client code using
[`WorkflowOptions.Builder.setCronSchedule`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html).

Setting `setCronSchedule` changes the Workflow Execution into a Temporal Cron Job. The default timezone for a Cron is
UTC.

- Type: `String`
- Default: None

<!--SNIPSTART java-schedules-cron {"enable_code_dedenting": true}-->
[java-sandbox/workflows/schedules/src/main/java/io/temporal/docs/workflows/schedules/CronAndStartDelayExample.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/workflows/schedules/src/main/java/io/temporal/docs/workflows/schedules/CronAndStartDelayExample.java)
```java
// Create a Workflow stub for GreetingWorkflow
GreetingWorkflow workflow1 =
    client.newWorkflowStub(
        GreetingWorkflow.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("YourWF")
            .setTaskQueue(TASK_QUEUE)
            // Set Cron Schedule
            .setCronSchedule("* * * * *")
            .build());
```
<!--SNIPEND-->

For more details, see the
[HelloCron Sample](https://github.com/temporalio/samples-java/blob/main/core/src/main/java/io/temporal/samples/hello/HelloCron.java).

#### Memo

- Type: `String`
- Default: None

<!--SNIPSTART java-temporal-client-memo {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("YourWF")
            .setTaskQueue(TASK_QUEUE)
            // Set Memo. You can set additional non-indexed info via Memo
            .setMemo(Map.of("memoKey", "memoValue"))
            .build());
```
<!--SNIPEND-->

#### SearchAttributes

Search Attributes are additional indexed information attributed to Workflow and used for search and visibility. These
can be used in a query of List/Scan/Count Workflow APIs. The key and its value type must be registered on Temporal
server side.

- Type: `SearchAttributes`
- Default: None

<!--SNIPSTART java-temporal-client-search-attributes {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a Workflow stub for YourWorkflowInterface
YourWorkflowInterface workflow1 =
    client.newWorkflowStub(
        YourWorkflowInterface.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId("YourWF")
            .setTaskQueue(TASK_QUEUE)
            // Set Search Attributes
            .setTypedSearchAttributes(
                SearchAttributes.newBuilder()
                    .set(SearchAttributeKey.forKeyword("CustomKeywordField"), "value")
                    .build())
            .build());
```
<!--SNIPEND-->

Create each key with the `SearchAttributeKey` factory method that matches its type: `forKeyword`, `forText`,
`forLong`, `forDouble`, `forBoolean`, `forOffsetDateTime`, or `forKeywordList`.

## Get Workflow results 

If the call to start a Workflow Execution is successful, you will gain access to the Workflow Execution's Run Id.

The Workflow Id, Run Id, and Namespace may be used to uniquely identify a Workflow Execution in the system and get its
result.

It's possible to both block progress on the result (synchronous execution) or get the result at some other point in time
(asynchronous execution).

In the Temporal Platform, it's also acceptable to use Queries as the preferred method for accessing the state and
results of Workflow Executions.

A synchronous Workflow Execution blocks your client thread until the Workflow Execution completes (or fails) and get the
results (or error in case of failure).

The following example is a type-safe approach for getting the results of a synchronous Workflow Execution.

<!--SNIPSTART java-temporal-client-result-sync {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
FileProcessingWorkflow workflow =
    client.newWorkflowStub(
        FileProcessingWorkflow.class,
        WorkflowOptions.newBuilder()
            .setWorkflowId(workflowId)
            .setTaskQueue(taskQueue)
            .build());

// Start sync and wait for results (or failure)
String result = workflow.processFile(fileName);
```
<!--SNIPEND-->

An asynchronous Workflow Execution immediately returns a value to the caller.

The following examples show how to start a Workflow Execution asynchronously through typed and untyped `WorkflowStub`.

Typed `WorkflowStub` example:

<!--SNIPSTART java-temporal-client-start-typed {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
// Create a typed Workflow stub
FileProcessingWorkflow workflow =
    client.newWorkflowStub(
        FileProcessingWorkflow.class,
        WorkflowOptions.newBuilder()
            .setTaskQueue(taskQueue)
            .setWorkflowId(workflowId)
            .build());
// Use WorkflowClient.execute to return a future that contains the Workflow result or failure,
// or use WorkflowClient.start to return the Workflow ID and Run ID of the started Workflow.
WorkflowExecution execution = WorkflowClient.start(workflow::processFile, fileName);
```
<!--SNIPEND-->

Untyped `WorkflowStub` example:

<!--SNIPSTART java-temporal-client-start-untyped {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
WorkflowStub untyped =
    client.newUntypedWorkflowStub(
        "FileProcessingWorkflow",
        WorkflowOptions.newBuilder()
            .setWorkflowId(workflowId)
            .setTaskQueue(taskQueue)
            .build());

// Blocks until the Workflow Execution has been started (not until it completes)
untyped.start(argument);
```
<!--SNIPEND-->

If you need to wait for a Workflow Execution to complete after an asynchronous start, the most straightforward way is to
call the blocking Workflow instance again.

Note that if `WorkflowOptions.WorkflowIdReusePolicy` is not set to `AllowDuplicate`, then instead of throwing
`DuplicateWorkflowException`, it reconnects to an existing Workflow and waits for its completion.

The following example shows how to do this from a different process than the one that started the Workflow Execution.

<!--SNIPSTART java-temporal-client-result-by-id {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
FileProcessingWorkflow workflow = client.newWorkflowStub(FileProcessingWorkflow.class, workflowId);

// Returns the result after waiting for the Workflow to complete.
String result = workflow.processFile(null);
```
<!--SNIPEND-->

Another way to connect to an existing Workflow and wait for its completion from another process is to create an
untyped `WorkflowStub` from its Workflow ID. For example:

<!--SNIPSTART java-temporal-client-result-untyped {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/StartExamples.java)
```java
WorkflowStub workflowStub = client.newUntypedWorkflowStub(workflowId);

// Returns the result after waiting for the Workflow to complete.
String result = workflowStub.getResult(String.class);
```
<!--SNIPEND-->

### Get last completion result

For a Temporal Cron Job, get the result of previous successful runs using `GetLastCompletionResult()`. The method
returns `null` if there is no previous completion. The following example shows how to implement this in a Workflow.

<!--SNIPSTART java-temporal-client-last-completion-result {"enable_code_dedenting": true}-->
[java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/Workflows.java](https://github.com/temporalio/documentation-sdk-code-examples/blob/main/java-sandbox/client/temporal-client/src/main/java/io/temporal/docs/client/temporalclient/Workflows.java)
```java
@Override
public String cronWorkflow() {
  String lastProcessedFileName = Workflow.getLastCompletionResult(String.class);

  // Process work starting from the lastProcessedFileName.
  // Business logic implementation goes here.
  // Updates lastProcessedFileName to the new value.

  return lastProcessedFileName;
}
```
<!--SNIPEND-->

Note that this works even if one of the Cron schedule runs failed. The next schedule will still get the last successful
result if it ever successfully completed at least once. For example, for a daily cron Workflow, if the run succeeds on
the first day and fails on the second day, then the third day run will get the result from first day's run using these
APIs.
