diff --git a/docs/cloud/get-started/api-keys.mdx b/docs/cloud/get-started/api-keys.mdx index a86b25ff99..054f57d33d 100644 --- a/docs/cloud/get-started/api-keys.mdx +++ b/docs/cloud/get-started/api-keys.mdx @@ -409,7 +409,7 @@ To use your API key with a Temporal SDK, see the instructions in each SDK sectio [How to connect to Temporal Cloud using an API Key with the Go SDK](/develop/go/temporal-client#connect-to-temporal-cloud) -[How to connect to Temporal Cloud using an API Key with the Java SDK](/develop/java/temporal-client#connect-to-temporal-cloud) +[How to connect to Temporal Cloud using an API Key with the Java SDK](/develop/java/client/temporal-client#connect-to-temporal-cloud) [How to connect to Temporal Cloud using an API Key with the Python SDK](/develop/python/temporal-client#connect-to-temporal-cloud) diff --git a/docs/cloud/get-started/certificates.mdx b/docs/cloud/get-started/certificates.mdx index dce0cb246a..ee40bce5ea 100644 --- a/docs/cloud/get-started/certificates.mdx +++ b/docs/cloud/get-started/certificates.mdx @@ -482,7 +482,7 @@ To view the current certificate filters, use the ## Configure clients to use client certificates {#configure-clients-to-use-client-certificates} - [Go SDK](/develop/go/temporal-client#connect-to-temporal-cloud) -- [Java SDK](/develop/java/temporal-client#connect-to-temporal-cloud) +- [Java SDK](/develop/java/client/temporal-client#connect-to-temporal-cloud) - [PHP SDK](/develop/php/temporal-client#connect-to-a-dev-cluster) - [Python SDK](/develop/python/temporal-client#connect-to-temporal-cloud) - [TypeScript SDK](/develop/typescript/temporal-client#connect-to-temporal-cloud) diff --git a/docs/cloud/get-started/index.mdx b/docs/cloud/get-started/index.mdx index 382983e2c3..ac0562c958 100644 --- a/docs/cloud/get-started/index.mdx +++ b/docs/cloud/get-started/index.mdx @@ -53,7 +53,7 @@ cert management, then [mTLS](/cloud/certificates) is an excellent choice. See our guides for connecting each SDK to your Temporal Cloud Namespace: - [Connect to Temporal Cloud in Go](/develop/go/temporal-client#connect-to-temporal-cloud) -- [Connect to Temporal Cloud in Java](/develop/java/temporal-client#connect-to-temporal-cloud) +- [Connect to Temporal Cloud in Java](/develop/java/client/temporal-client#connect-to-temporal-cloud) - [Connect to Temporal Cloud in Python](/develop/python/temporal-client#connect-to-temporal-cloud) - [Connect to Temporal Cloud in TypeScript](/develop/typescript/core-application#connect-to-temporal-cloud) - [Connect to Temporal Cloud in .NET](/develop/dotnet/temporal-client#connect-to-temporal-cloud) @@ -65,7 +65,7 @@ See our guides for connecting each SDK to your Temporal Cloud Namespace: See our guides for starting a workflow using each SDK: - [Start a workflow in Go](/develop/go/temporal-client#start-workflow-execution) -- [Start a workflow in Java](/develop/java/temporal-client#start-workflow-execution) +- [Start a workflow in Java](/develop/java/client/temporal-client#start-workflow-execution) - [Start a workflow in Python](/develop/python/temporal-client#start-workflow-execution) - [Start a workflow in TypeScript](/develop/typescript/core-application#start-workflow-execution) - [Start a workflow in .NET](/develop/dotnet/temporal-client#start-workflow) diff --git a/docs/cloud/metrics/prometheus-grafana.mdx b/docs/cloud/metrics/prometheus-grafana.mdx index 71ffda59da..42a2214a8b 100644 --- a/docs/cloud/metrics/prometheus-grafana.mdx +++ b/docs/cloud/metrics/prometheus-grafana.mdx @@ -53,7 +53,7 @@ If you're following through with the examples provided here, ensure that you hav - Set up your connections to Temporal Cloud using an SDK of your choice and have some Workflows running on Temporal Cloud. See Connect to a Temporal Service for details. - [Go](/develop/go/temporal-client#connect-to-temporal-cloud) - - [Java](/develop/java/temporal-client#connect-to-temporal-cloud) + - [Java](/develop/java/client/temporal-client#connect-to-temporal-cloud) - [PHP](/develop/php/temporal-client#connect-to-a-dev-cluster) - [Python](/develop/python/temporal-client#connect-to-temporal-cloud) - [TypeScript](/develop/typescript/core-application#connect-to-temporal-cloud) @@ -93,7 +93,7 @@ You must configure a Prometheus scrape endpoint for Prometheus to collect and ag Each language development guide has details on how to set this up. - [Go SDK](/develop/go/observability#metrics) -- [Java SDK](/develop/java/observability#metrics) +- [Java SDK](/develop/java/workers/observability#metrics) - [TypeScript SDK](/develop/typescript/observability#metrics) - [Python](/develop/python/observability#metrics) - [.NET](/develop/dotnet/observability#metrics) diff --git a/docs/develop/java/asynchronous-activity-completion.mdx b/docs/develop/java/activities/asynchronous-activity-completion.mdx similarity index 100% rename from docs/develop/java/asynchronous-activity-completion.mdx rename to docs/develop/java/activities/asynchronous-activity-completion.mdx diff --git a/docs/develop/java/activities/basic-activity.mdx b/docs/develop/java/activities/basic-activity.mdx new file mode 100644 index 0000000000..38f038ce7e --- /dev/null +++ b/docs/develop/java/activities/basic-activity.mdx @@ -0,0 +1,205 @@ +--- +id: basic-activity +title: Basic Activity - Java SDK +sidebar_label: Basic Activity +description: This section explains how to implement Activities with the Java SDK +toc_max_heading_level: 4 +keywords: + - Java SDK +tags: + - Java SDK + - Temporal SDKs +--- + +## Develop a basic Activity + +One of the primary things that Workflows do is orchestrate the execution of Activities. +An Activity is a normal function or method execution that's intended to execute a single, well-defined action (either short or long-running), such as querying a database, calling a third-party API, or transcoding a media file. +An Activity can interact with world outside the Temporal Platform or use a Temporal Client to interact with a Temporal Service. +For the Workflow to be able to execute the Activity, we must define the [Activity Definition](/activity-definition). + +An [Activity Definition](/activities) is a combination of the Temporal Java SDK [Activity](https://www.javadoc.io/static/io.temporal/temporal-sdk/0.19.0/io/temporal/activity/Activity.html) Class implementing a specially annotated interface. + +An Activity interface is annotated with `@ActivityInterface` and an Activity implementation implements this Activity interface. +To handle Activity types that do not have an explicitly registered handler, you can directly implement a dynamic Activity. + +```java +@ActivityInterface +public interface GreetingActivities { + String composeGreeting(String greeting, String language); +} +``` + +Each method defined in the Activity interface defines a separate Activity method. +You can annotate each method in the Activity interface with the `@ActivityMethod` annotation, but this is completely optional. +The following example uses the `@ActivityMethod` annotation for the method defined in the previous example. + +```java +@ActivityInterface +public interface GreetingActivities { + @ActivityMethod + String composeGreeting(String greeting, String language); +} +``` + +An Activity implementation is a Java class that implements an Activity annotated interface. + +```java +// Implementation for the GreetingActivities interface example from in the previous section + static class GreetingActivitiesImpl implements GreetingActivities { + @Override + public String composeGreeting(String greeting, String name) { + return greeting + " " + name + "!"; + } + } +``` + +## Define Activity parameters {#activity-parameters} + +There is no explicit limit to the total number of parameters that an [Activity Definition](/activity-definition) may support. +However, there is a limit to the total size of the data that ends up encoded into a gRPC message Payload. + +A single argument is limited to a maximum size of 2 MB. +And the total size of a gRPC message, which includes all the arguments, is limited to a maximum of 4 MB. + +Also, keep in mind that all Payload data is recorded in the [Workflow Execution Event History](/workflow-execution/event#event-history) and large Event Histories can affect Worker performance. +This is because the entire Event History could be transferred to a Worker Process with a [Workflow Task](/tasks#workflow-task). + +{/* TODO link to gRPC limit section when available */} + +Some SDKs require that you pass context objects, others do not. +When it comes to your application data—that is, data that is serialized and encoded into a Payload—we recommend that you use a single object as an argument that wraps the application data passed to Activities. +This is so that you can change what data is passed to the Activity without breaking a function or method signature. + +An Activity interface can have any number of parameters. +All inputs should be serializable by the default Jackson JSON Payload Converter. + +When implementing Activities, be mindful of the amount of data that you transfer using the Activity invocation parameters or return values as these are recorded in the Workflow Execution Events History. +Large Events Histories can adversely impact performance. + +You can create a custom object, and pass it to the Activity interface, as shown in the following example. + +```java +@ActivityInterface +public interface YourActivities { + String getCustomObject(CustomObj customobj); + void sendCustomObject(CustomObj customobj, String abc); +} +``` + +The `execute` method in the dynamic Activity interface implementation takes in `EncodedValues` that are inputs to the Activity Execution, as shown in the following example. + +```java +// Dynamic Activity implementation + public static class DynamicActivityImpl implements DynamicActivity { + @Override + public Object execute(EncodedValues args) { + String activityType = Activity.getExecutionContext().getInfo().getActivityType(); + return activityType + + ": " + + args.get(0, String.class) + + " " + + args.get(1, String.class) + + " from: " + + args.get(2, String.class); + } + } +``` + +For more details, see [Dynamic Activity Reference](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/DynamicActivity.html). + +## Define Activity return values {#activity-return-values} + +All data returned from an Activity must be serializable. + +Activity return values are subject to payload size limits in Temporal. The default payload size limit is 2MB, and there is a hard limit of 4MB for any gRPC message size in the Event History transaction ([see Cloud limits here](https://docs.temporal.io/cloud/limits#per-message-grpc-limit)). Keep in mind that all return values are recorded in a [Workflow Execution Event History](/workflow-execution/event#event-history). + +Activity return values must be serializable and deserializable by the provided [`DataConverter`](https://www.javadoc.io/static/io.temporal/temporal-sdk/1.17.0/io/temporal/common/converter/DataConverter.html). + +The `execute` method for `DynamicActivity` can return type Object. +Ensure that your Workflow or Client can handle an Object type return or is able to convert the Object type response. + +- [Data Converter](/dataconversion) +- Java DataConverter reference: [https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/common/converter/DataConverter.html](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/common/converter/DataConverter.html) + +## Customize your Activity Type {#activity-type} + +Each Activity has a Type, which may also be referred to as the Activity 'name'. +This name appears in the Workflow Execution Event History in the Summary tab for each Activity Task. +The name lets you identify Activity Types called during the Execution. + +Custom Activity Type names prevent name collisions across interfaces and Workflows. +They offer descriptive Activity method names without concerns about re-using those names elsewhere in your project. +They also support code management, especially in larger projects with many Activities. +For example, you might use a prefix to group related activities together. +Custom names also distinguish keys for gathering metrics without name conflicts. + +The following examples show how to set custom names for your Activity Type. + +### Default behavior + +By default, an Activity Type is the method name with the first letter capitalized: + +```java +@ActivityInterface +public interface GreetingActivities { + String sendMessage(String input); + + @ActivityMethod + String composeGreeting(String greeting, String language); +} +``` + +- Method Name: `sendMessage` +- Activity Type: `SendMessage` +- Method Name: `composeGreeting` +- Activity Type: `ComposeGreeting` + +### Custom Prefix + +Using the `namePrefix` parameter in the `@ActivityInterface` annotation adds a prefix to each Activity Type name mentioned in the interface, unless the prefix is specifically overridden: + +```java +@ActivityInterface(namePrefix = "Messaging_") +public interface GreetingActivities { + String sendMessage(String input); + + @ActivityMethod + String composeGreeting(String greeting, String language); +} +``` + +- Method Name: `sendMessage` +- Activity Type: `Messaging_SendMessage` +- Method Name: `composeGreeting` +- Activity Type: `Messaging_ComposeGreeting` + +The Activity Type is capitalized, even when using a prefix. + +### Custom Name + +To override the default name and any inherited prefixes, use the `name` parameter in the `@ActivityMethod` annotation: + +```java +@ActivityInterface(namePrefix = "Messaging_") +public interface GreetingActivities { + String sendMessage(String input); + + @ActivityMethod + String composeGreeting(String greeting, String language); + @ActivityMethod(name = "farewell") + String composeFarewell(String farewell, String language); +} +``` + +Using the `name` parameter won't automatically capitalize the result: + +- Method Name: `sendMessage` +- Activity Type: `Messaging_SendMessage` +- Method Name: `composeGreeting` +- Activity Type: `Messaging_ComposeGreeting` +- Method Name: `composeFarewell` +- Activity Type: `farewell` + +Be cautious with names that contain special characters, as these can be used as metric tags. +Systems such as Prometheus may ignore metrics with tags using unsupported characters. \ No newline at end of file diff --git a/docs/develop/java/benign-exceptions.mdx b/docs/develop/java/activities/benign-exceptions.mdx similarity index 100% rename from docs/develop/java/benign-exceptions.mdx rename to docs/develop/java/activities/benign-exceptions.mdx diff --git a/docs/develop/java/activities/execution.mdx b/docs/develop/java/activities/execution.mdx new file mode 100644 index 0000000000..9af53244ff --- /dev/null +++ b/docs/develop/java/activities/execution.mdx @@ -0,0 +1,591 @@ +--- +id: execution +title: Activity execution - Java SDK +description: Shows how to perform Activity execution with the Java SDK +sidebar_label: Activity Execution +slug: /develop/java/activities/execution +toc_max_heading_level: 3 +tags: + - Java SDK + - Temporal SDKs + - Activity +--- + +## Start an Activity Execution {#activity-execution} + +Calls to spawn [Activity Executions](/activity-execution) are written within a [Workflow Definition](/workflow-definition). +The call to spawn an Activity Execution generates the [ScheduleActivityTask](/references/commands#scheduleactivitytask) Command. +This results in the set of three [Activity Task](/tasks#activity-task) related Events ([ActivityTaskScheduled](/references/events#activitytaskscheduled), [ActivityTaskStarted](/references/events#activitytaskstarted), and ActivityTask[Closed])in your Workflow Execution Event History. + +A single instance of the Activities implementation is shared across multiple simultaneous Activity invocations. +Activity implementation code should be _idempotent_. + +The values passed to Activities through invocation parameters or returned through a result value are recorded in the Execution history. +The entire Execution history is transferred from the Temporal service to Workflow Workers when a Workflow state needs to recover. +A large Execution history can thus adversely impact the performance of your Workflow. + +Therefore, be mindful of the amount of data you transfer through Activity invocation parameters or Return Values. +Otherwise, no additional limitations exist on Activity implementations. + +Activities are remote procedure calls that must be invoked from within a Workflow using `ActivityStub`. +Activities are not executable on their own. You cannot start an Activity Execution by itself. + +Note that before an Activity Execution is invoked: + +- Activity options (either [`setStartToCloseTimeout`](/encyclopedia/detecting-activity-failures#start-to-close-timeout) or [`ScheduleToCloseTimeout`](/encyclopedia/detecting-activity-failures#schedule-to-close-timeout) are required) must be set for the Activity. + For details, see [How to set Activity timeouts](/develop/java/activities/timeouts). +- The Activity must be registered with a Worker. + See [Worker Program](#run-a-dev-worker) +- Activity code must be thread-safe. + +Activities should only be instantiated using stubs from within a Workflow. +An `ActivityStub` returns a client-side stub that implements an Activity interface. +You can invoke Activities using `Workflow.newActivityStub`(type-safe) or `Workflow.newUntypedActivityStub` (untyped). + +Calling a method on the Activity interface schedules the Activity invocation with the Temporal service, and generates an [`ActivityTaskScheduled` Event](/references/events#activitytaskscheduled). + +Activities can be invoked synchronously or asynchronously. + +### Invoking Activities Synchronously + +In the following example, we use the type-safe `Workflow.newActivityStub` within the "FileProcessingWorkflow" Workflow implementation to create a client-side stub of the `FileProcessingActivities` class. We also define `ActivityOptions` and set `setStartToCloseTimeout` option to one hour. + +```java +public class FileProcessingWorkflowImpl implements FileProcessingWorkflow { + + private final FileProcessingActivities activities; + + public FileProcessingWorkflowImpl() { + this.activities = Workflow.newActivityStub( + FileProcessingActivities.class, + ActivityOptions.newBuilder() + .setStartToCloseTimeout(Duration.ofHours(1)) + .build()); + } + + @Override + public void processFile(Arguments args) { + String localName = null; + String processedName = null; + try { + localName = activities.download(args.getSourceBucketName(), args.getSourceFilename()); + processedName = activities.processFile(localName); + activities.upload(args.getTargetBucketName(), args.getTargetFilename(), processedName); + } finally { + if (localName != null) { + activities.deleteLocalFile(localName); + } + if (processedName != null) { + activities.deleteLocalFile(processedName); + } + } + } + // ... +} +``` + +A Workflow can have multiple Activity stubs. Each Activity stub can have its own `ActivityOptions` defined. +The following example shows a Workflow implementation with two typed Activity stubs. + +```java +public FileProcessingWorkflowImpl() { + ActivityOptions options1 = ActivityOptions.newBuilder() + .setTaskQueue("taskQueue1") + .setStartToCloseTimeout(Duration.ofMinutes(10)) + .build(); + this.store1 = Workflow.newActivityStub(FileProcessingActivities.class, options1); + + ActivityOptions options2 = ActivityOptions.newBuilder() + .setTaskQueue("taskQueue2") + .setStartToCloseTimeout(Duration.ofMinutes(5)) + .build(); + this.store2 = Workflow.newActivityStub(FileProcessingActivities.class, options2); +} +``` + +To invoke Activities inside Workflows without referencing the interface it implements, use an untyped Activity stub `Workflow.newUntypedActivityStub`. +This is useful when the Activity type is not known at compile time, or to invoke Activities implemented in different programming languages. + +```java + // Workflow code + ActivityOptions activityOptions = + ActivityOptions.newBuilder() + .setStartToCloseTimeout(Duration.ofSeconds(3)) + .setTaskQueue("simple-queue-node") + .build(); + + ActivityStub activity = Workflow.newUntypedActivityStub(activityOptions); + activity.execute("ComposeGreeting", String.class, "Hello World", "Spanish"); +``` + +### Invoking Activities Asynchronously + +Sometimes Workflows need to perform certain operations in parallel. +The Temporal Java SDK provides the `Async` class which includes static methods used to invoke any Activity asynchronously. +The calls return a result of type `Promise` which is similar to the Java `Future` and `CompletionStage`. +When invoking Activities, use `Async.function` for Activities that return a result, and `Async.procedure` for Activities that return void. + +In the following asynchronous Activity invocation, the method reference is passed to `Async.function` followed by Activity arguments. + +```java +Promise localNamePromise = Async.function(activities::download, sourceBucket, sourceFile); +``` + +The following example shows how to call two Activity methods, "download" and "upload", in parallel on multiple files. + +```java + public void processFile(Arguments args) { + List> localNamePromises = new ArrayList<>(); + List processedNames = null; + try { + // Download all files in parallel. + for (String sourceFilename : args.getSourceFilenames()) { + Promise localName = + Async.function(activities::download, args.getSourceBucketName(), sourceFilename); + localNamePromises.add(localName); + } + List localNames = new ArrayList<>(); + for (Promise localName : localNamePromises) { + localNames.add(localName.get()); + } + processedNames = activities.processFiles(localNames); + + // Upload all results in parallel. + List> uploadedList = new ArrayList<>(); + for (String processedName : processedNames) { + Promise uploaded = + Async.procedure( + activities::upload, + args.getTargetBucketName(), + args.getTargetFilename(), + processedName); + uploadedList.add(uploaded); + } + // Wait for all uploads to complete. + Promise.allOf(uploadedList).get(); + } finally { + for (Promise localNamePromise : localNamePromises) { + // Skip files that haven't completed downloading. + if (localNamePromise.isCompleted()) { + activities.deleteLocalFile(localNamePromise.get()); + } + } + if (processedNames != null) { + for (String processedName : processedNames) { + activities.deleteLocalFile(processedName); + } + } + } + } +``` + +### Activity Execution Context + +`ActivityExecutionContext` is a context object passed to each Activity implementation by default. +You can access it in your Activity implementations via `Activity.getExecutionContext()`. + +It provides getters to access information about the Workflow that invoked the Activity. +Note that the Activity context information is stored in a thread-local variable. +Therefore, calls to `getExecutionContext()` succeed only within the thread that invoked the Activity function. + +Following is an example of using the `ActivityExecutionContext`: + +```java +public class FileProcessingActivitiesImpl implements FileProcessingActivities { + + @Override + public String download(String bucketName, String remoteName, String localName) { + + ActivityExecutionContext ctx = Activity.getExecutionContext(); + ActivityInfo info = ctx.getInfo(); + + log.info("namespace=" + info.getActivityNamespace()); + log.info("workflowId=" + info.getWorkflowId()); + log.info("runId=" + info.getRunId()); + log.info("activityId=" + info.getActivityId()); + log.info("activityTimeout=" + info.getStartToCloseTimeout(); + + return downloadFileFromS3(bucketName, remoteName, localDirectory + localName); + } + ... +} +``` + +For details on getting the results of an Activity Execution, see [Activity Execution Result](#activity-execution-result). + +## Set required Activity Timeouts {#required-timeout} + +Activity Execution semantics rely on several parameters. +The only required value that needs to be set is either a [Schedule-To-Close Timeout](/encyclopedia/detecting-activity-failures#schedule-to-close-timeout) or a [Start-To-Close Timeout](/encyclopedia/detecting-activity-failures#start-to-close-timeout). +These values are set in the Activity Options. + +Set your Activity Timeout from the [`ActivityOptions.Builder`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html) class. + +Available timeouts are: + +- ScheduleToCloseTimeout() +- ScheduleToStartTimeout() +- StartToCloseTimeout() + +You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. + +The following uses `ActivityStub`. + +```java +GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, + ActivityOptions.newBuilder() + .setScheduleToCloseTimeout(Duration.ofSeconds(5)) + // .setStartToCloseTimeout(Duration.ofSeconds(2) + // .setScheduletoCloseTimeout(Duration.ofSeconds(20)) + .build()); +``` + +The following uses `WorkflowImplementationOptions`. + +```java +WorkflowImplementationOptions options = + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "GetCustomerGreeting", + // Set Activity Execution timeout + ActivityOptions.newBuilder() + .setScheduleToCloseTimeout(Duration.ofSeconds(5)) + // .setStartToCloseTimeout(Duration.ofSeconds(2)) + // .setScheduleToStartTimeout(Duration.ofSeconds(5)) + .build())) + .build(); +``` + +:::note + +If you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. + +::: + +## Java ActivityOptions reference {#activity-options-reference} + +Use [`ActivityOptions`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html) to configure how to invoke an Activity Execution. + +You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. +Note that if you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. + +The following table lists all `ActivityOptions` that can be configured for an Activity invocation. + +| Option | Required | Type | +| ------------------------------------------------------ | -------------------------------------------------- | ------------------------ | +| [`setScheduleToCloseTimeout`](#scheduletoclosetimeout) | Yes (if `StartToCloseTimeout` is not specified) | Duration | +| [`setScheduleToStartTimeout`](#scheduletostarttimeout) | No | Duration | +| [`setStartToCloseTimeout`](#starttoclosetimeout) | Yes (if `ScheduleToCloseTimeout` is not specified) | Duration | +| [`setHeartbeatTimeout`](#heartbeattimeout) | No | Duration | +| [`setTaskQueue`](#taskqueue) | No | String | +| [`setRetryOptions`](#retryoptions) | No | RetryOptions | +| [`setCancellationType`](#setcancellationtype) | No | ActivityCancellationType | + +### ScheduleToCloseTimeout + +To set a [Schedule-To-Close Timeout](/encyclopedia/detecting-activity-failures#schedule-to-close-timeout), use [`ActivityOptions.newBuilder.setScheduleToCloseTimeout​`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). + +This or `StartToCloseTimeout` must be set. + +- Type: `Duration` +- Default: Unlimited. + Note that if `WorkflowRunTimeout` and/or `WorkflowExecutionTimeout` are defined in the Workflow, all Activity retries will stop when either or both of these timeouts are reached. + +You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. +Note that if you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. + +- With `ActivityStub` + + ```java + GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, + ActivityOptions.newBuilder() + .setScheduleToCloseTimeout(Duration.ofSeconds(5)) + .build()); + ``` + +- With `WorkflowImplementationOptions` + + ```java + WorkflowImplementationOptions options = + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "GetCustomerGreeting", + ActivityOptions.newBuilder() + .setScheduleToCloseTimeout(Duration.ofSeconds(5)) + .build())) + .build(); + ``` + +### ScheduleToStartTimeout + +To set a [Schedule-To-Start Timeout](/encyclopedia/detecting-activity-failures#schedule-to-start-timeout), use [`ActivityOptions.newBuilder.setScheduleToStartTimeout​`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). + +- Type: `Duration` +- Default: Unlimited. This timeout is non-retryable. + +You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. +Note that if you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. + +- With `ActivityStub` + + ```java + GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, + ActivityOptions.newBuilder() + .setScheduleToStartTimeout(Duration.ofSeconds(5)) + // note that either StartToCloseTimeout or ScheduleToCloseTimeout are + // required when setting Activity options. + .setScheduletoCloseTimeout(Duration.ofSeconds(20)) + .build()); + ``` + +- With `WorkflowImplementationOptions` + + ```java + WorkflowImplementationOptions options = + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "GetCustomerGreeting", + ActivityOptions.newBuilder() + .setScheduleToStartTimeout(Duration.ofSeconds(5)) + .build())) + .build(); + ``` + +### StartToCloseTimeout + +To set a [Start-To-Close Timeout](/encyclopedia/detecting-activity-failures#start-to-close-timeout), use [`ActivityOptions.newBuilder.setStartToCloseTimeout​`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). + +This or `ScheduleToClose` must be set. + +- Type: `Duration` +- Default: Defaults to [`ScheduleToCloseTimeout`](#scheduletoclosetimeout) value + +You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. +Note that if you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. + +- With `ActivityStub` + + ```java + GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, + ActivityOptions.newBuilder() + .setStartToCloseTimeout(Duration.ofSeconds(2)) + .build()); + ``` + +- With `WorkflowImplementationOptions` + + ```java + WorkflowImplementationOptions options = + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "EmailCustomerGreeting", + ActivityOptions.newBuilder() + // Set Activity Execution timeout (single run) + .setStartToCloseTimeout(Duration.ofSeconds(2)) + .build())) + .build(); + ``` + +### HeartbeatTimeout + +To set a [Heartbeat Timeout](/encyclopedia/detecting-activity-failures#heartbeat-timeout), use [`ActivityOptions.newBuilder.setHeartbeatTimeout`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). + +- Type: `Duration` +- Default: None + +You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. +Note that if you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. + +- With `ActivityStub` + + ```java + private final GreetingActivities activities = + Workflow.newActivityStub( + GreetingActivities.class, + ActivityOptions.newBuilder() + // note that either StartToCloseTimeout or ScheduleToCloseTimeout are + // required when setting Activity options. + .setStartToCloseTimeout(Duration.ofSeconds(5)) + .setHeartbeatTimeout(Duration.ofSeconds(2)) + .build()); + ``` + +- With `WorkflowImplementationOptions` + + ```java + WorkflowImplementationOptions options = + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "EmailCustomerGreeting", + ActivityOptions.newBuilder() + // note that either StartToCloseTimeout or ScheduleToCloseTimeout are + // required when setting Activity options. + .setStartToCloseTimeout(Duration.ofSeconds(5)) + .setHeartbeatTimeout(Duration.ofSeconds(2)) + .build())) + .build(); + ``` + +### TaskQueue + +- Type: `String` +- Default: Defaults to the Task Queue that the Workflow was started with. + +- With `ActivityStub` + + ```java + GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, + ActivityOptions.newBuilder() + // note that either StartToCloseTimeout or ScheduleToCloseTimeout are required when + // setting Activity options. + .setStartToCloseTimeout(Duration.ofSeconds(5)) + .setTaskQueue("yourTaskQueue") + .build()); + ``` + +- With `WorkflowImplementationOptions` + + ```java + WorkflowImplementationOptions options = + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "EmailCustomerGreeting", + ActivityOptions.newBuilder() + // note that either StartToCloseTimeout or ScheduleToCloseTimeout are + // required when setting Activity options. + .setStartToCloseTimeout(Duration.ofSeconds(5)) + .setTaskQueue("yourTaskQueue") + .build())) + .build(); + ``` + +See [Task Queue](/task-queue) + +### RetryOptions + +To set a Retry Policy, known as the [Retry Options](/encyclopedia/retry-policies) in Java, use [`ActivityOptions.newBuilder.setRetryOptions()`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). + +- Type: `RetryOptions` +- Default: Server-defined Activity Retry policy. + +- With `ActivityStub` + + ```java + private final ActivityOptions options = + ActivityOptions.newBuilder() + // note that either StartToCloseTimeout or ScheduleToCloseTimeout are + // required when setting Activity options. + .setStartToCloseTimeout(Duration.ofSeconds(5)) + .setRetryOptions( + RetryOptions.newBuilder() + .setInitialInterval(Duration.ofSeconds(1)) + .setMaximumInterval(Duration.ofSeconds(10)) + .build()) + .build(); + ``` + +- With `WorkflowImplementationOptions` + + ```java + WorkflowImplementationOptions options = + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "EmailCustomerGreeting", + ActivityOptions.newBuilder() + // note that either StartToCloseTimeout or ScheduleToCloseTimeout are + // required when setting Activity options. + .setStartToCloseTimeout(Duration.ofSeconds(5)) + .setRetryOptions( + RetryOptions.newBuilder() + .setDoNotRetry(NullPointerException.class.getName()) + .build()) + .build())) + .build(); + ``` + +### setCancellationType + +- Type: `ActivityCancellationType` +- Default: `ActivityCancellationType.TRY_CANCEL` + +- With `ActivityStub` + + ```java + private final GreetingActivities activities = + Workflow.newActivityStub( + GreetingActivities.class, + ActivityOptions.newBuilder() + .setCancellationType(ActivityCancellationType.WAIT_CANCELLATION_COMPLETED) + .build()); + ``` + +- With `WorkflowImplementationOptions` + + ```java + WorkflowImplementationOptions options = + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "EmailCustomerGreeting", + ActivityOptions.newBuilder() + .setCancellationType(ActivityCancellationType.WAIT_CANCELLATION_COMPLETED) + .build())) + .build(); + ``` + +## Get the result of an Activity Execution {#activity-execution-result} + +The call to spawn an [Activity Execution](/activity-execution) generates the [ScheduleActivityTask](/references/commands#scheduleactivitytask) Command and provides the Workflow with an Awaitable. +Workflow Executions can either block progress until the result is available through the Awaitable or continue progressing, making use of the result when it becomes available. + +To get the results of an asynchronously invoked Activity method, use the `Promise` `get` method to block until the Activity method result is available. + +Sometimes an Activity Execution lifecycle goes beyond a synchronous method invocation. +For example, a request can be put in a queue and later a reply comes and is picked up by a different Worker process. +The whole request-reply interaction can be modeled as a single Activity. + +To indicate that an Activity should not be completed upon its method return, call `ActivityExecutionContext.doNotCompleteOnReturn()` from the original Activity thread. + +Then later, when replies come, complete the Activity using the `ActivityCompletionClient`. +To correlate Activity invocation with completion, use either a `TaskToken` or Workflow and Activity Ids. + +Following is an example of using `ActivityExecutionContext.doNotCompleteOnReturn()`: + +```java +public class FileProcessingActivitiesImpl implements FileProcessingActivities { + + public String download(String bucketName, String remoteName, String localName) { + + ActivityExecutionContext ctx = Activity.getExecutionContext(); + + // Used to correlate reply + byte[] taskToken = ctx.getInfo().getTaskToken(); + + asyncDownloadFileFromS3(taskToken, bucketName, remoteName, localDirectory + localName); + ctx.doNotCompleteOnReturn(); + + // Return value is ignored when doNotCompleteOnReturn was called. + return "ignored"; + } + ... +} +``` + +When the download is complete, the download service potentially can complete the Activity, or fail it from a different process, for example: + +```java + public void completeActivity(byte[] taskToken, R result) { + completionClient.complete(taskToken, result); + } + + public void failActivity(byte[] taskToken, Exception failure) { + completionClient.completeExceptionally(taskToken, failure); + } +``` \ No newline at end of file diff --git a/docs/develop/java/activities/index.mdx b/docs/develop/java/activities/index.mdx new file mode 100644 index 0000000000..2cb45ccb9d --- /dev/null +++ b/docs/develop/java/activities/index.mdx @@ -0,0 +1,24 @@ +--- +id: index +title: Activities - Java SDK +sidebar_label: Activities +description: This section explains how to implement Activities with the Java SDK +toc_max_heading_level: 4 +keywords: + - Java SDK +tags: + - Java SDK + - Temporal SDKs +--- + +import * as Components from '@site/src/components'; + +![Java SDK Banner](/img/assets/banner-java-temporal.png) + +## Activities + +- [Basic Activity](/develop/java/activities/basic-activity) +- [Activity Execution](/develop/java/activities/execution) +- [Timeouts](/develop/java/activities/timeouts) +- [Asynchronous Activity Completion](/develop/java/activities/asynchronous-activity-completion) +- [Benign exceptions](/develop/java/activities/benign-exceptions) \ No newline at end of file diff --git a/docs/develop/java/failure-detection.mdx b/docs/develop/java/activities/timeouts.mdx similarity index 50% rename from docs/develop/java/failure-detection.mdx rename to docs/develop/java/activities/timeouts.mdx index a7ee8b4a19..e5b6c2be45 100644 --- a/docs/develop/java/failure-detection.mdx +++ b/docs/develop/java/activities/timeouts.mdx @@ -1,99 +1,18 @@ --- -id: failure-detection -title: Failure detection - Java SDK -sidebar_label: Failure detection +id: timeouts +title: Activity Timeouts - Java SDK +sidebar_label: Timeouts +description: + This section explains how to implement Workers with the Java SDK toc_max_heading_level: 4 keywords: - - failure detection + - java tags: - - Activities - - Workflows - - Errors - - Failures - Java SDK - Temporal SDKs -description: Set Workflow and Activity timeouts, Retry Policies, and Heartbeat in Java using the Temporal Client and Worker for Workflow optimization and execution controls. --- -This page shows how to do the following: - -- [Set Workflow timeouts](#workflow-timeouts) -- [Set a Workflow Retry Policy](#workflow-retries) -- [Set Activity timeouts](#activity-timeouts) -- [Set a custom Activity Retry Policy](#activity-retries) -- [Heartbeat an Activity](#activity-heartbeats) -- [Set a Heartbeat Timeout](#heartbeat-timeout) - -## Workflow timeouts {#workflow-timeouts} - -**How to set Workflow timeouts using the Java SDK.** - -Each Workflow timeout controls the maximum duration of a different aspect of a Workflow Execution. - -Workflow timeouts are set when [starting the Workflow Execution](#workflow-timeouts). - -Before we continue, we want to note that we generally do not recommend setting Workflow Timeouts, because Workflows are designed to be long-running and resilient. -Instead, setting a Timeout can limit its ability to handle unexpected delays or long-running processes. -If you need to perform an action inside your Workflow after a specific period of time, we recommend using a Timer. - -- **[Workflow Execution Timeout](/encyclopedia/detecting-workflow-failures#workflow-execution-timeout)** - restricts the maximum amount of time that a single Workflow Execution can be executed. -- **[Workflow Run Timeout](/encyclopedia/detecting-workflow-failures#workflow-run-timeout):** restricts the maximum amount of time that a single Workflow Run can last. -- **[Workflow Task Timeout](/encyclopedia/detecting-workflow-failures#workflow-task-timeout):** restricts the maximum amount of time that a Worker can execute a Workflow Task. - -Create an instance of [`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html) in the Client code and set your timeout. - -Available timeouts are: - -- [setWorkflowExecutionTimeout()](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html#setWorkflowExecutionTimeout(java.time.Duration)) -- [setWorkflowRunTimeout()](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html#setWorkflowRunTimeout(java.time.Duration)) -- [setWorkflowTaskTimeout()](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html#setWorkflowTaskTimeout(java.time.Duration)) - -```java -//create Workflow stub for YourWorkflowInterface -YourWorkflowInterface workflow1 = - WorkerGreet.greetclient.newWorkflowStub( - GreetWorkflowInterface.class, - WorkflowOptions.newBuilder() - .setWorkflowId("YourWorkflow") - .setTaskQueue(WorkerGreet.TASK_QUEUE) - // Set Workflow Timeout duration - .setWorkflowExecutionTimeout(Duration.ofSeconds(10)) - // .setWorkflowRunTimeout(Duration.ofSeconds(10)) - // .setWorkflowTaskTimeout(Duration.ofSeconds(10)) - .build()); -``` - -### Workflow Retry Policy {#workflow-retries} - -**How to set a Workflow Retry Policy in Java.** - -A Retry Policy can work in cooperation with the timeouts to provide fine controls to optimize the execution experience. - -Use a [Retry Policy](/encyclopedia/retry-policies) to retry a Workflow Execution in the event of a failure. - -Workflow Executions do not retry by default, and Retry Policies should be used with Workflow Executions only in certain situations. - -To set a 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.setWorkflowRetryOptions`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html). - -- Type: `RetryOptions` -- Default: `Null` which means no retries will be attempted. - -```java -//create Workflow stub for GreetWorkflowInterface -GreetWorkflowInterface workflow1 = - WorkerGreet.greetclient.newWorkflowStub( - GreetWorkflowInterface.class, - WorkflowOptions.newBuilder() - .setWorkflowId("GreetWF") - .setTaskQueue(WorkerGreet.TASK_QUEUE) - // Set Workflow Retry Options - .setRetryOptions(RetryOptions.newBuilder() - .build()); -``` - -## Activity timeouts {#activity-timeouts} - -**How to set Activity timeouts using the Java SDK.** +## Activity timeouts Each Activity timeout controls the maximum duration of a different aspect of an Activity Execution. @@ -119,28 +38,28 @@ The following uses `ActivityStub`. ```java GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, - ActivityOptions.newBuilder() - .setScheduleToCloseTimeout(Duration.ofSeconds(5)) - // .setStartToCloseTimeout(Duration.ofSeconds(2) - // .setScheduletoCloseTimeout(Duration.ofSeconds(20)) - .build()); + ActivityOptions.newBuilder() + .setScheduleToCloseTimeout(Duration.ofSeconds(5)) + // .setStartToCloseTimeout(Duration.ofSeconds(2) + // .setScheduletoCloseTimeout(Duration.ofSeconds(20)) + .build()); ``` The following uses `WorkflowImplementationOptions`. ```java WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "GetCustomerGreeting", - // Set Activity Execution timeout - ActivityOptions.newBuilder() - .setScheduleToCloseTimeout(Duration.ofSeconds(5)) - // .setStartToCloseTimeout(Duration.ofSeconds(2)) - // .setScheduleToStartTimeout(Duration.ofSeconds(5)) - .build())) - .build(); + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "GetCustomerGreeting", + // Set Activity Execution timeout + ActivityOptions.newBuilder() + .setScheduleToCloseTimeout(Duration.ofSeconds(5)) + // .setStartToCloseTimeout(Duration.ofSeconds(2)) + // .setScheduleToStartTimeout(Duration.ofSeconds(5)) + .build())) + .build(); ``` :::note @@ -151,8 +70,6 @@ If you define options per-Activity Type options with `WorkflowImplementationOpti ### Custom Activity Retry Policy {#activity-retries} -**How to set a custom Activity Retry Policy in Java.** - A Retry Policy works in cooperation with the timeouts to provide fine controls to optimize the execution experience. Activity Executions are automatically associated with a default [Retry Policy](/encyclopedia/retry-policies) if a custom one is not provided. @@ -182,25 +99,23 @@ To set a Retry Policy, known as the [Retry Options](/encyclopedia/retry-policies ```java WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "EmailCustomerGreeting", - ActivityOptions.newBuilder() - // note that either StartToCloseTimeout or ScheduleToCloseTimeout are - // required when setting Activity options. - .setStartToCloseTimeout(Duration.ofSeconds(5)) - .setRetryOptions( - RetryOptions.newBuilder() - .setDoNotRetry(NullPointerException.class.getName()) - .build()) - .build())) - .build(); + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "EmailCustomerGreeting", + ActivityOptions.newBuilder() + // note that either StartToCloseTimeout or ScheduleToCloseTimeout are + // required when setting Activity options. + .setStartToCloseTimeout(Duration.ofSeconds(5)) + .setRetryOptions( + RetryOptions.newBuilder() + .setDoNotRetry(NullPointerException.class.getName()) + .build()) + .build())) + .build(); ``` -## Activity next Retry delay {#activity-next-retry-delay} - -**How to override the next Retry delay following an Activity failure using the Temporal Java SDK** +## Activity next retry delay {#activity-next-retry-delay} You may throw an [`ApplicationFailure`](/references/failures#application-failure) with the `NextRetryDelay` field set. This value will replace and override whatever the retry interval would be on the retry policy. @@ -218,8 +133,6 @@ throw ApplicationFailure.newFailureWithCauseAndDelay( ## Heartbeat an Activity {#activity-heartbeats} -**How to Heartbeat an Activity using the Java SDK.** - An [Activity Heartbeat](/encyclopedia/detecting-activity-failures#activity-heartbeat) is a ping from the [Worker Process](/workers#worker-process) that is executing the Activity to the [Temporal Service](/temporal-service). Each Heartbeat informs the Temporal Service that the [Activity Execution](/activity-execution) is making progress and the Worker has not crashed. If the Temporal Service does not receive a Heartbeat within a [Heartbeat Timeout](/encyclopedia/detecting-activity-failures#heartbeat-timeout) time period, the Activity will be considered failed and another [Activity Task Execution](/tasks#activity-task-execution) may be scheduled according to the Retry Policy. @@ -257,8 +170,6 @@ In the case of Activity retries, the last Heartbeat's `details` are available an ### Heartbeat Timeout {#heartbeat-timeout} -**How to set a Heartbeat Timeout using the Java SDK.** - A [Heartbeat Timeout](/encyclopedia/detecting-activity-failures#heartbeat-timeout) works in conjunction with [Activity Heartbeats](/encyclopedia/detecting-activity-failures#activity-heartbeat). To set a [Heartbeat Timeout](/encyclopedia/detecting-activity-failures#heartbeat-timeout), use [`ActivityOptions.newBuilder.setHeartbeatTimeout`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). @@ -287,15 +198,15 @@ Note that if you define options per-Activity Type options with `WorkflowImplemen ```java WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "EmailCustomerGreeting", - ActivityOptions.newBuilder() - // note that either StartToCloseTimeout or ScheduleToCloseTimeout are - // required when setting Activity options. - .setStartToCloseTimeout(Duration.ofSeconds(5)) - .setHeartbeatTimeout(Duration.ofSeconds(2)) - .build())) - .build(); + WorkflowImplementationOptions.newBuilder() + .setActivityOptions( + ImmutableMap.of( + "EmailCustomerGreeting", + ActivityOptions.newBuilder() + // note that either StartToCloseTimeout or ScheduleToCloseTimeout are + // required when setting Activity options. + .setStartToCloseTimeout(Duration.ofSeconds(5)) + .setHeartbeatTimeout(Duration.ofSeconds(2)) + .build())) + .build(); ``` diff --git a/docs/develop/java/converters-and-encryption.mdx b/docs/develop/java/best-practices/converters-and-encryption.mdx similarity index 100% rename from docs/develop/java/converters-and-encryption.mdx rename to docs/develop/java/best-practices/converters-and-encryption.mdx diff --git a/docs/develop/java/debugging.mdx b/docs/develop/java/best-practices/debugging.mdx similarity index 89% rename from docs/develop/java/debugging.mdx rename to docs/develop/java/best-practices/debugging.mdx index 19164777a6..5cddf6591f 100644 --- a/docs/develop/java/debugging.mdx +++ b/docs/develop/java/best-practices/debugging.mdx @@ -40,11 +40,11 @@ You can debug production Workflows using: - [Web UI](/web-ui) - [Temporal CLI](/cli) -- [Replay](/develop/java/testing-suite#replay) -- [Tracing](/develop/java/observability#tracing) -- [Logging](/develop/java/observability#logging) +- [Replay](/develop/java/best-practices/testing-suite#replay) +- [Tracing](/develop/java/workers/observability#tracing) +- [Logging](/develop/java/workers/observability#logging) You can debug and tune Worker performance with metrics and the [Worker performance guide](/develop/worker-performance). -For more information, see [Observability ▶️ Metrics](/develop/java/observability#metrics) for setting up SDK metrics. +For more information, see [Observability ▶️ Metrics](/develop/java/workers/observability#metrics) for setting up SDK metrics. Debug Server performance with [Cloud metrics](/cloud/metrics/) or [self-hosted Server metrics](/self-hosted-guide/production-checklist#scaling-and-metrics). diff --git a/docs/develop/java/best-practices/index.mdx b/docs/develop/java/best-practices/index.mdx new file mode 100644 index 0000000000..472ba2211c --- /dev/null +++ b/docs/develop/java/best-practices/index.mdx @@ -0,0 +1,22 @@ +--- +id: index +title: Best practices - Java SDK +sidebar_label: Best practices +description: This section explains how to implement best practices with the Java SDK +toc_max_heading_level: 4 +keywords: + - Java SDK +tags: + - Java SDK + - Temporal SDKs +--- + +import * as Components from '@site/src/components'; + +![Java SDK Banner](/img/assets/banner-java-temporal.png) + +## Best practices + +- [Testing](/develop/java/best-practices/testing-suite) +- [Debugging](/develop/java/best-practices/debugging) +- [Converters and encryption](/develop/java/best-practices/converters-and-encryption) \ No newline at end of file diff --git a/docs/develop/java/testing-suite.mdx b/docs/develop/java/best-practices/testing-suite.mdx similarity index 100% rename from docs/develop/java/testing-suite.mdx rename to docs/develop/java/best-practices/testing-suite.mdx diff --git a/docs/develop/java/client/index.mdx b/docs/develop/java/client/index.mdx new file mode 100644 index 0000000000..ef3cb4bb9a --- /dev/null +++ b/docs/develop/java/client/index.mdx @@ -0,0 +1,21 @@ +--- +id: index +title: Client - Java SDK +sidebar_label: Client +description: This section explains how to implement the Temporal Client with the Java SDK +toc_max_heading_level: 4 +keywords: + - Java SDK +tags: + - Java SDK + - Temporal SDKs +--- + +import * as Components from '@site/src/components'; + +![Java SDK Banner](/img/assets/banner-java-temporal.png) + +## Temporal Client + +- [Temporal Client](/develop/java/client/temporal-client) +- [Namespaces](/develop/java/client/namespaces) \ No newline at end of file diff --git a/docs/develop/java/namespaces.mdx b/docs/develop/java/client/namespaces.mdx similarity index 98% rename from docs/develop/java/namespaces.mdx rename to docs/develop/java/client/namespaces.mdx index 0293bb5657..74cef8086d 100644 --- a/docs/develop/java/namespaces.mdx +++ b/docs/develop/java/client/namespaces.mdx @@ -67,7 +67,7 @@ The Retention Period setting using `WorkflowExecutionRetentionPeriod` is mandato The minimum value you can set for this period is 1 day. Once registered, set Namespace using `WorkflowClientOptions` within a Workflow Client to run your Workflow Executions within that Namespace. -See [Connect to a Development Temporal Service](/develop/java/temporal-client#connect-to-development-service) for details. +See [Connect to a Development Temporal Service](/develop/java/client/temporal-client#connect-to-development-service) for details. Note that Namespace registration using this API takes up to 10 seconds to complete. Ensure that you wait for this registration to complete before starting the Workflow Execution against the Namespace. diff --git a/docs/develop/java/temporal-client.mdx b/docs/develop/java/client/temporal-client.mdx similarity index 99% rename from docs/develop/java/temporal-client.mdx rename to docs/develop/java/client/temporal-client.mdx index 1e7a4ed224..1f606542ea 100644 --- a/docs/develop/java/temporal-client.mdx +++ b/docs/develop/java/client/temporal-client.mdx @@ -449,7 +449,7 @@ Ensure these environment variables exist in your environment before running your Import the `envconfig` package to set connection options for the Temporal Client using environment variables. The `MustLoadDefaultClientOptions` function will automatically load all environment variables. For a list of all available -environment variables and their default values, refer to [Environment Configuration](../environment-configuration). +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 @@ -629,10 +629,10 @@ you must supply a Task Queue that will be used for the Tasks (one that a Worker 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/child-workflows) or External Workflow +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/core-application#workflow-type) section to see how to customize the name +See the [Customize Workflow Type](/develop/java/workflows/basic-workflow#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 @@ -643,7 +643,7 @@ Temporal Service then creates the first Workflow Task, resulting in the first Use `WorkflowStub` to start a Workflow Execution from within a Client, and `ExternalWorkflowStub` to start a different Workflow Execution from within a Workflow. -See [`SignalwithStart`](/develop/java/message-passing#signal-with-start) to start a Workflow Execution to receive a +See [`SignalwithStart`](/develop/java/workflows/message-passing#signal-with-start) to start a Workflow Execution to receive a Signal from within another Workflow. **Using `WorkflowStub`** @@ -767,7 +767,7 @@ written in other language SDKs. **Recurring start** You can start a Workflow Execution on a regular schedule by using -[`setCronSchedule`](/develop/java/schedules#cron-schedule) Workflow option in the Client code. +[`setCronSchedule`](/develop/java/workflows/schedules#cron-schedule) Workflow option in the Client code. ### How to set a Workflow's Task Queue {#set-task-queue} diff --git a/docs/develop/java/core-application.mdx b/docs/develop/java/core-application.mdx deleted file mode 100644 index 2f4f147333..0000000000 --- a/docs/develop/java/core-application.mdx +++ /dev/null @@ -1,1188 +0,0 @@ ---- -id: core-application -title: Core application - Java SDK -sidebar_label: Core application -description: Create a Workflow Definition, develop a basic Activity, initiate Activity Execution, and run a Development Worker using the Temporal Java SDK. Master essential concepts such as Workflow interface annotations, Activity definitions, custom Activity Types, and asynchronous Activity invocations to build robust and scalable Temporal applications. -toc_max_heading_level: 4 -keywords: - - Java - - api reference - - cli - - cli-feature - - code samples - - java - - options - - workers - - workflow -tags: - - Activities - - Temporal Client - - Task Queues - - Workers - - Workflows - - Java SDK - - Temporal SDKs ---- - -This page shows how to do the following: - -- [Develop a Workflow Definition](#develop-workflows) -- [Develop a basic Activity](#develop-activities) -- [Start an Activity Execution](#activity-execution) -- [Run a Development Worker](#run-a-dev-worker) - -## Develop a Workflow Definition {#develop-workflows} - -**How to develop a Workflow Definition using the Java SDK.** - -Workflows are the fundamental unit of a Temporal Application, and it all starts with the development of a [Workflow Definition](/workflow-definition). - -In the Temporal Java SDK programming model, a Workflow Definition comprises a Workflow interface annotated with `@WorkflowInterface` and a Workflow implementation that implements the Workflow interface. - -The Workflow interface is a Java interface and is annotated with `@WorkflowInterface`. -Each Workflow interface must have only one method annotated with `@WorkflowMethod`. - -```java -// Workflow interface -@WorkflowInterface -public interface YourWorkflow { - - @WorkflowMethod - String yourWFMethod(Arguments args); -} -``` - -However, when using dynamic Workflows, do not specify a `@WorkflowMethod`, and implement the `DynamicWorkflow` directly in the Workflow implementation code. - -The `@WorkflowMethod` identifies the method that is the starting point of the Workflow Execution. -The Workflow Execution completes when this method completes. - -You can create [interface inheritance hierarchies](#interface-inheritance) to reuse components across other Workflow interfaces. -The interface inheritance approach does not apply to `@WorkflowMethod` annotations. - -A Workflow implementation implements a Workflow interface. - -```java -// Define the Workflow implementation which implements our getGreeting Workflow method. - public static class GreetingWorkflowImpl implements GreetingWorkflow { - ... - } - } -``` - -To call Activities in your Workflow, call the Activity implementation. - -Use `ExternalWorkflowStub` to start or send Signals from within a Workflow to other running Workflow Executions. - -You can also invoke other Workflows as Child Workflows with `Workflow.newChildWorkflowStub()` or `Workflow.newUntypedChildWorkflowStub()` within a Workflow Definition. - -### Workflow interface inheritance {#interface-inheritance} - -Workflow interfaces can form inheritance hierarchies. -It may be useful for creating reusable components across multiple -Workflow interfaces. -For example imagine a UI or CLI button that allows a `retryNow` Signal on any Workflow. To implement this feature you can redesign an interface like the following: - -```java -public interface Retryable { - @SignalMethod - void retryNow(); -} - -@WorkflowInterface -public interface FileProcessingWorkflow extends Retryable { - - @WorkflowMethod - String processFile(Arguments args); - - @QueryMethod(name="history") - List getHistory(); - - @QueryMethod - String getStatus(); - - @SignalMethod - void abandon(); -} -``` - -Then some other Workflow interface can extend just `Retryable`, for example: - -```java -@WorkflowInterface -public interface MediaProcessingWorkflow extends Retryable { - - @WorkflowMethod - String processBlob(Arguments args); -} -``` - -Now if we have two running Workflows, one that implements the `FileProcessingWorkflow` interface and another that implements the `MediaProcessingWorkflow` interface, we can Signal to both using their common interface and knowing their WorkflowIds, for example: - -```java -Retryable r1 = client.newWorkflowStub(Retryable.class, firstWorkflowId); -Retryable r2 = client.newWorkflowStub(Retryable.class, secondWorkflowId); -r1.retryNow(); -r2.retryNow(); -``` - -The same technique can be used to query Workflows using a base Workflow interface. - -Note that this approach does not apply to `@WorkflowMethod` annotations, meaning that when using a base interface, it should not include any `@WorkflowMethod` methods. -To illustrate this, lets' say that we define the following **invalid** code: - -```java -// INVALID CODE! -public interface BaseWorkflow { - @WorkflowMethod - void retryNow(); -} - -@WorkflowInterface -public interface Workflow1 extends BaseWorkflow {} - -@WorkflowInterface -public interface Workflow2 extends BaseWorkflow {} -``` - -Any attempt to register both implementations with the Worker will fail. -Let's say that we have: - -```java -worker.registerWorkflowImplementationTypes( - Workflow1Impl.class, Workflow2Impl.class); -``` - -This registration will fail with: - -```text -java.lang.IllegalStateException: BaseWorkflow workflow type is already registered with the worker -``` - -### Define Workflow parameters {#workflow-parameters} - -**How to define Workflow parameters using the Java SDK.** - -Temporal Workflows may have any number of custom parameters. -However, we strongly recommend that objects are used as parameters, so that the object's individual fields may be altered without breaking the signature of the Workflow. -All Workflow Definition parameters must be serializable. - -A method annotated with `@WorkflowMethod` can have any number of parameters. - -We recommend passing a single parameter that contains all the input fields to allow for adding fields in a backward-compatible manner. - -Note that all inputs should be serializable by the default Jackson JSON Payload Converter. - -You can create a custom object and pass it to the Workflow method, as shown in the following example. - -```java -//... -@WorkflowInterface -public interface YourWorkflow { - @WorkflowMethod - String yourWFMethod(CustomObj customobj); -// ... -} -``` - -### Define Workflow return parameters {#workflow-return-values} - -**How to define Workflow return parameters using the Java SDK.** - -Workflow return values must also be serializable. -Returning results, returning errors, or throwing exceptions is fairly idiomatic in each language that is supported. -However, Temporal APIs that must be used to get the result of a Workflow Execution will only ever receive one of either the result or the error. - -Workflow method arguments and return values must be serializable and deserializable using the provided [`DataConverter`](https://www.javadoc.io/static/io.temporal/temporal-sdk/1.17.0/io/temporal/common/converter/DataConverter.html). - -The `execute` method for `DynamicWorkflow` can return type Object. -Ensure that your Client can handle an Object type return or is able to convert the Object type response. - -Related references: - -- [Data Converter](/dataconversion) -- Java DataConverter reference: [https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/common/converter/DataConverter.html](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/common/converter/DataConverter.html) - -### Customize your Workflow Type {#workflow-type} - -**How to customize your Workflow Type using the Java SDK.** - -Workflows have a Type that are referred to as the Workflow name. - -The following examples demonstrate how to set a custom name for your Workflow Type. - -The Workflow Type defaults to the short name of the Workflow interface. -In the following example, the Workflow Type defaults to `NotifyUserAccounts`. - -```java - @WorkflowInterface - - public interface NotifyUserAccounts { - @WorkflowMethod - void notify(String[] accountIds); -} -``` - -To overwrite this default naming and assign a custom Workflow Type, use the `@WorkflowMethod` annotation with the `name` parameter. -In the following example, the Workflow Type is set to `your-workflow`. - -```java -@WorkflowInterface - - public interface NotifyUserAccounts { - @WorkflowMethod(name = "your-workflow") - void notify(String[] accountIds); - } -``` - -When you set the Workflow Type this way, the value of the `name` parameter does not have to start with an uppercase letter. - -### Workflow logic requirements {#workflow-logic-requirements} - -Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints). -Therefore, each language is limited to the use of certain idiomatic techniques. -However, each Temporal SDK provides a set of APIs that can be used inside your Workflow to interact with external (to the Workflow) application code. - -When defining Workflows using the Temporal Java SDK, the Workflow code must be written to execute effectively once and to completion. - -The following constraints apply when writing Workflow Definitions: - -- Do not use mutable global variables in your Workflow implementations. - This will ensure that multiple Workflow instances are fully isolated. -- Your Workflow code must be deterministic. - Do not call non-deterministic functions (such as non-seeded random or `UUID.randomUUID()`) directly from the Workflow code. - The Temporal SDK provides specific API for calling non-deterministic code in your Workflows. -- Do not use programming language constructs that rely on system time. - For example, only use `Workflow.currentTimeMillis()` to get the current time inside a Workflow. -- Do not use native Java `Thread` or any other multi-threaded classes like `ThreadPoolExecutor`. - Use `Async.function` or `Async.procedure`, provided by the Temporal SDK, to execute code asynchronously. -- Do not use synchronization, locks, or other standard Java blocking concurrency-related classes besides those provided by the Workflow class. - There is no need for explicit synchronization because multi-threaded code inside a Workflow is executed one thread at a time and under a global lock. - - Call `Workflow.sleep` instead of `Thread.sleep`. - - Use `Promise` and `CompletablePromise` instead of `Future` and `CompletableFuture`. - - Use `WorkflowQueue` instead of `BlockingQueue`. -- Use `Workflow.getVersion` when making any changes to the Workflow code. - Without this, any deployment of updated Workflow code might break already running Workflows. -- Do not access configuration APIs directly from a Workflow because changes in the configuration might affect a Workflow Execution path. - Pass it as an argument to a Workflow function or use an Activity to load it. -- Use `DynamicWorkflow` when you need a default Workflow that can handle all Workflow Types that are not registered with a Worker. - A single implementation can implement a Workflow Type which by definition is dynamically loaded from some external source. - All standard `WorkflowOptions` and determinism rules apply to Dynamic Workflow implementations. - -Java Workflow reference: [https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/workflow/package-summary.html](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/workflow/package-summary.html) - -## Develop a basic Activity {#develop-activities} - -**How to develop a basic Activity using the Java SDK.** - -One of the primary things that Workflows do is orchestrate the execution of Activities. -An Activity is a normal function or method execution that's intended to execute a single, well-defined action (either short or long-running), such as querying a database, calling a third-party API, or transcoding a media file. -An Activity can interact with world outside the Temporal Platform or use a Temporal Client to interact with a Temporal Service. -For the Workflow to be able to execute the Activity, we must define the [Activity Definition](/activity-definition). - -An [Activity Definition](/activities) is a combination of the Temporal Java SDK [Activity](https://www.javadoc.io/static/io.temporal/temporal-sdk/0.19.0/io/temporal/activity/Activity.html) Class implementing a specially annotated interface. - -An Activity interface is annotated with `@ActivityInterface` and an Activity implementation implements this Activity interface. -To handle Activity types that do not have an explicitly registered handler, you can directly implement a dynamic Activity. - -```java -@ActivityInterface -public interface GreetingActivities { - String composeGreeting(String greeting, String language); -} -``` - -Each method defined in the Activity interface defines a separate Activity method. -You can annotate each method in the Activity interface with the `@ActivityMethod` annotation, but this is completely optional. -The following example uses the `@ActivityMethod` annotation for the method defined in the previous example. - -```java -@ActivityInterface -public interface GreetingActivities { - @ActivityMethod - String composeGreeting(String greeting, String language); -} -``` - -An Activity implementation is a Java class that implements an Activity annotated interface. - -```java -// Implementation for the GreetingActivities interface example from in the previous section - static class GreetingActivitiesImpl implements GreetingActivities { - @Override - public String composeGreeting(String greeting, String name) { - return greeting + " " + name + "!"; - } - } -``` - -### Define Activity parameters {#activity-parameters} - -**How to define Activity parameters using the Java SDK.** - -There is no explicit limit to the total number of parameters that an [Activity Definition](/activity-definition) may support. -However, there is a limit to the total size of the data that ends up encoded into a gRPC message Payload. - -A single argument is limited to a maximum size of 2 MB. -And the total size of a gRPC message, which includes all the arguments, is limited to a maximum of 4 MB. - -Also, keep in mind that all Payload data is recorded in the [Workflow Execution Event History](/workflow-execution/event#event-history) and large Event Histories can affect Worker performance. -This is because the entire Event History could be transferred to a Worker Process with a [Workflow Task](/tasks#workflow-task). - -{/* TODO link to gRPC limit section when available */} - -Some SDKs require that you pass context objects, others do not. -When it comes to your application data—that is, data that is serialized and encoded into a Payload—we recommend that you use a single object as an argument that wraps the application data passed to Activities. -This is so that you can change what data is passed to the Activity without breaking a function or method signature. - -An Activity interface can have any number of parameters. -All inputs should be serializable by the default Jackson JSON Payload Converter. - -When implementing Activities, be mindful of the amount of data that you transfer using the Activity invocation parameters or return values as these are recorded in the Workflow Execution Events History. -Large Events Histories can adversely impact performance. - -You can create a custom object, and pass it to the Activity interface, as shown in the following example. - -```java -@ActivityInterface -public interface YourActivities { - String getCustomObject(CustomObj customobj); - void sendCustomObject(CustomObj customobj, String abc); -} -``` - -The `execute` method in the dynamic Activity interface implementation takes in `EncodedValues` that are inputs to the Activity Execution, as shown in the following example. - -```java -// Dynamic Activity implementation - public static class DynamicActivityImpl implements DynamicActivity { - @Override - public Object execute(EncodedValues args) { - String activityType = Activity.getExecutionContext().getInfo().getActivityType(); - return activityType - + ": " - + args.get(0, String.class) - + " " - + args.get(1, String.class) - + " from: " - + args.get(2, String.class); - } - } -``` - -For more details, see [Dynamic Activity Reference](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/DynamicActivity.html). - -### Define Activity return values {#activity-return-values} - -**How to define Activity return values using the Java SDK.** - -All data returned from an Activity must be serializable. - -Activity return values are subject to payload size limits in Temporal. The default payload size limit is 2MB, and there is a hard limit of 4MB for any gRPC message size in the Event History transaction ([see Cloud limits here](https://docs.temporal.io/cloud/limits#per-message-grpc-limit)). Keep in mind that all return values are recorded in a [Workflow Execution Event History](/workflow-execution/event#event-history). - -Activity return values must be serializable and deserializable by the provided [`DataConverter`](https://www.javadoc.io/static/io.temporal/temporal-sdk/1.17.0/io/temporal/common/converter/DataConverter.html). - -The `execute` method for `DynamicActivity` can return type Object. -Ensure that your Workflow or Client can handle an Object type return or is able to convert the Object type response. - -- [Data Converter](/dataconversion) -- Java DataConverter reference: [https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/common/converter/DataConverter.html](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/common/converter/DataConverter.html) - -### Customize your Activity Type {#activity-type} - -**How to customize your Activity Type using the Java SDK.** - -Each Activity has a Type, which may also be referred to as the Activity 'name'. -This name appears in the Workflow Execution Event History in the Summary tab for each Activity Task. -The name lets you identify Activity Types called during the Execution. - -Custom Activity Type names prevent name collisions across interfaces and Workflows. -They offer descriptive Activity method names without concerns about re-using those names elsewhere in your project. -They also support code management, especially in larger projects with many Activities. -For example, you might use a prefix to group related activities together. -Custom names also distinguish keys for gathering metrics without name conflicts. - -The following examples show how to set custom names for your Activity Type. - -**Default behavior** - -By default, an Activity Type is the method name with the first letter capitalized: - -```java -@ActivityInterface -public interface GreetingActivities { - String sendMessage(String input); - - @ActivityMethod - String composeGreeting(String greeting, String language); -} -``` - -- Method Name: `sendMessage` -- Activity Type: `SendMessage` -- Method Name: `composeGreeting` -- Activity Type: `ComposeGreeting` - -**Custom Prefix** - -Using the `namePrefix` parameter in the `@ActivityInterface` annotation adds a prefix to each Activity Type name mentioned in the interface, unless the prefix is specifically overridden: - -```java -@ActivityInterface(namePrefix = "Messaging_") -public interface GreetingActivities { - String sendMessage(String input); - - @ActivityMethod - String composeGreeting(String greeting, String language); -} -``` - -- Method Name: `sendMessage` -- Activity Type: `Messaging_SendMessage` -- Method Name: `composeGreeting` -- Activity Type: `Messaging_ComposeGreeting` - -The Activity Type is capitalized, even when using a prefix. - -**Custom Name** - -To override the default name and any inherited prefixes, use the `name` parameter in the `@ActivityMethod` annotation: - -```java -@ActivityInterface(namePrefix = "Messaging_") -public interface GreetingActivities { - String sendMessage(String input); - - @ActivityMethod - String composeGreeting(String greeting, String language); - @ActivityMethod(name = "farewell") - String composeFarewell(String farewell, String language); -} -``` - -Using the `name` parameter won't automatically capitalize the result: - -- Method Name: `sendMessage` -- Activity Type: `Messaging_SendMessage` -- Method Name: `composeGreeting` -- Activity Type: `Messaging_ComposeGreeting` -- Method Name: `composeFarewell` -- Activity Type: `farewell` - -Be cautious with names that contain special characters, as these can be used as metric tags. -Systems such as Prometheus may ignore metrics with tags using unsupported characters. - -## Start an Activity Execution {#activity-execution} - -**How to start an Activity Execution using the Java SDK.** - -Calls to spawn [Activity Executions](/activity-execution) are written within a [Workflow Definition](/workflow-definition). -The call to spawn an Activity Execution generates the [ScheduleActivityTask](/references/commands#scheduleactivitytask) Command. -This results in the set of three [Activity Task](/tasks#activity-task) related Events ([ActivityTaskScheduled](/references/events#activitytaskscheduled), [ActivityTaskStarted](/references/events#activitytaskstarted), and ActivityTask[Closed])in your Workflow Execution Event History. - -A single instance of the Activities implementation is shared across multiple simultaneous Activity invocations. -Activity implementation code should be _idempotent_. - -The values passed to Activities through invocation parameters or returned through a result value are recorded in the Execution history. -The entire Execution history is transferred from the Temporal service to Workflow Workers when a Workflow state needs to recover. -A large Execution history can thus adversely impact the performance of your Workflow. - -Therefore, be mindful of the amount of data you transfer through Activity invocation parameters or Return Values. -Otherwise, no additional limitations exist on Activity implementations. - -Activities are remote procedure calls that must be invoked from within a Workflow using `ActivityStub`. -Activities are not executable on their own. You cannot start an Activity Execution by itself. - -Note that before an Activity Execution is invoked: - -- Activity options (either [`setStartToCloseTimeout`](/encyclopedia/detecting-activity-failures#start-to-close-timeout) or [`ScheduleToCloseTimeout`](/encyclopedia/detecting-activity-failures#schedule-to-close-timeout) are required) must be set for the Activity. - For details, see [How to set Activity timeouts](/develop/java/failure-detection#activity-timeouts). -- The Activity must be registered with a Worker. - See [Worker Program](#run-a-dev-worker) -- Activity code must be thread-safe. - -Activities should only be instantiated using stubs from within a Workflow. -An `ActivityStub` returns a client-side stub that implements an Activity interface. -You can invoke Activities using `Workflow.newActivityStub`(type-safe) or `Workflow.newUntypedActivityStub` (untyped). - -Calling a method on the Activity interface schedules the Activity invocation with the Temporal service, and generates an [`ActivityTaskScheduled` Event](/references/events#activitytaskscheduled). - -Activities can be invoked synchronously or asynchronously. - -**Invoking Activities Synchronously** - -In the following example, we use the type-safe `Workflow.newActivityStub` within the "FileProcessingWorkflow" Workflow implementation to create a client-side stub of the `FileProcessingActivities` class. We also define `ActivityOptions` and set `setStartToCloseTimeout` option to one hour. - -```java -public class FileProcessingWorkflowImpl implements FileProcessingWorkflow { - - private final FileProcessingActivities activities; - - public FileProcessingWorkflowImpl() { - this.activities = Workflow.newActivityStub( - FileProcessingActivities.class, - ActivityOptions.newBuilder() - .setStartToCloseTimeout(Duration.ofHours(1)) - .build()); - } - - @Override - public void processFile(Arguments args) { - String localName = null; - String processedName = null; - try { - localName = activities.download(args.getSourceBucketName(), args.getSourceFilename()); - processedName = activities.processFile(localName); - activities.upload(args.getTargetBucketName(), args.getTargetFilename(), processedName); - } finally { - if (localName != null) { - activities.deleteLocalFile(localName); - } - if (processedName != null) { - activities.deleteLocalFile(processedName); - } - } - } - // ... -} -``` - -A Workflow can have multiple Activity stubs. Each Activity stub can have its own `ActivityOptions` defined. -The following example shows a Workflow implementation with two typed Activity stubs. - -```java -public FileProcessingWorkflowImpl() { - ActivityOptions options1 = ActivityOptions.newBuilder() - .setTaskQueue("taskQueue1") - .setStartToCloseTimeout(Duration.ofMinutes(10)) - .build(); - this.store1 = Workflow.newActivityStub(FileProcessingActivities.class, options1); - - ActivityOptions options2 = ActivityOptions.newBuilder() - .setTaskQueue("taskQueue2") - .setStartToCloseTimeout(Duration.ofMinutes(5)) - .build(); - this.store2 = Workflow.newActivityStub(FileProcessingActivities.class, options2); -} -``` - -To invoke Activities inside Workflows without referencing the interface it implements, use an untyped Activity stub `Workflow.newUntypedActivityStub`. -This is useful when the Activity type is not known at compile time, or to invoke Activities implemented in different programming languages. - -```java - // Workflow code - ActivityOptions activityOptions = - ActivityOptions.newBuilder() - .setStartToCloseTimeout(Duration.ofSeconds(3)) - .setTaskQueue("simple-queue-node") - .build(); - - ActivityStub activity = Workflow.newUntypedActivityStub(activityOptions); - activity.execute("ComposeGreeting", String.class, "Hello World", "Spanish"); -``` - -**Invoking Activities Asynchronously** - -Sometimes Workflows need to perform certain operations in parallel. -The Temporal Java SDK provides the `Async` class which includes static methods used to invoke any Activity asynchronously. -The calls return a result of type `Promise` which is similar to the Java `Future` and `CompletionStage`. -When invoking Activities, use `Async.function` for Activities that return a result, and `Async.procedure` for Activities that return void. - -In the following asynchronous Activity invocation, the method reference is passed to `Async.function` followed by Activity arguments. - -```java -Promise localNamePromise = Async.function(activities::download, sourceBucket, sourceFile); -``` - -The following example shows how to call two Activity methods, "download" and "upload", in parallel on multiple files. - -```java - public void processFile(Arguments args) { - List> localNamePromises = new ArrayList<>(); - List processedNames = null; - try { - // Download all files in parallel. - for (String sourceFilename : args.getSourceFilenames()) { - Promise localName = - Async.function(activities::download, args.getSourceBucketName(), sourceFilename); - localNamePromises.add(localName); - } - List localNames = new ArrayList<>(); - for (Promise localName : localNamePromises) { - localNames.add(localName.get()); - } - processedNames = activities.processFiles(localNames); - - // Upload all results in parallel. - List> uploadedList = new ArrayList<>(); - for (String processedName : processedNames) { - Promise uploaded = - Async.procedure( - activities::upload, - args.getTargetBucketName(), - args.getTargetFilename(), - processedName); - uploadedList.add(uploaded); - } - // Wait for all uploads to complete. - Promise.allOf(uploadedList).get(); - } finally { - for (Promise localNamePromise : localNamePromises) { - // Skip files that haven't completed downloading. - if (localNamePromise.isCompleted()) { - activities.deleteLocalFile(localNamePromise.get()); - } - } - if (processedNames != null) { - for (String processedName : processedNames) { - activities.deleteLocalFile(processedName); - } - } - } - } -``` - -**Activity Execution Context** - -`ActivityExecutionContext` is a context object passed to each Activity implementation by default. -You can access it in your Activity implementations via `Activity.getExecutionContext()`. - -It provides getters to access information about the Workflow that invoked the Activity. -Note that the Activity context information is stored in a thread-local variable. -Therefore, calls to `getExecutionContext()` succeed only within the thread that invoked the Activity function. - -Following is an example of using the `ActivityExecutionContext`: - -```java -public class FileProcessingActivitiesImpl implements FileProcessingActivities { - - @Override - public String download(String bucketName, String remoteName, String localName) { - - ActivityExecutionContext ctx = Activity.getExecutionContext(); - ActivityInfo info = ctx.getInfo(); - - log.info("namespace=" + info.getActivityNamespace()); - log.info("workflowId=" + info.getWorkflowId()); - log.info("runId=" + info.getRunId()); - log.info("activityId=" + info.getActivityId()); - log.info("activityTimeout=" + info.getStartToCloseTimeout(); - - return downloadFileFromS3(bucketName, remoteName, localDirectory + localName); - } - ... -} -``` - -For details on getting the results of an Activity Execution, see [Activity Execution Result](#activity-execution-result). - -### Set required Activity Timeouts {#required-timeout} - -**How to set required Activity Timeouts using the Java SDK.** - -Activity Execution semantics rely on several parameters. -The only required value that needs to be set is either a [Schedule-To-Close Timeout](/encyclopedia/detecting-activity-failures#schedule-to-close-timeout) or a [Start-To-Close Timeout](/encyclopedia/detecting-activity-failures#start-to-close-timeout). -These values are set in the Activity Options. - -Set your Activity Timeout from the [`ActivityOptions.Builder`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html) class. - -Available timeouts are: - -- ScheduleToCloseTimeout() -- ScheduleToStartTimeout() -- StartToCloseTimeout() - -You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. - -The following uses `ActivityStub`. - -```java -GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, - ActivityOptions.newBuilder() - .setScheduleToCloseTimeout(Duration.ofSeconds(5)) - // .setStartToCloseTimeout(Duration.ofSeconds(2) - // .setScheduletoCloseTimeout(Duration.ofSeconds(20)) - .build()); -``` - -The following uses `WorkflowImplementationOptions`. - -```java -WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "GetCustomerGreeting", - // Set Activity Execution timeout - ActivityOptions.newBuilder() - .setScheduleToCloseTimeout(Duration.ofSeconds(5)) - // .setStartToCloseTimeout(Duration.ofSeconds(2)) - // .setScheduleToStartTimeout(Duration.ofSeconds(5)) - .build())) - .build(); -``` - -:::note - -If you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. - -::: - -### Java ActivityOptions reference {#activity-options-reference} - -Use [`ActivityOptions`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html) to configure how to invoke an Activity Execution. - -You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. -Note that if you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. - -The following table lists all `ActivityOptions` that can be configured for an Activity invocation. - -| Option | Required | Type | -| ------------------------------------------------------ | -------------------------------------------------- | ------------------------ | -| [`setScheduleToCloseTimeout`](#scheduletoclosetimeout) | Yes (if `StartToCloseTimeout` is not specified) | Duration | -| [`setScheduleToStartTimeout`](#scheduletostarttimeout) | No | Duration | -| [`setStartToCloseTimeout`](#starttoclosetimeout) | Yes (if `ScheduleToCloseTimeout` is not specified) | Duration | -| [`setHeartbeatTimeout`](#heartbeattimeout) | No | Duration | -| [`setTaskQueue`](#taskqueue) | No | String | -| [`setRetryOptions`](#retryoptions) | No | RetryOptions | -| [`setCancellationType`](#setcancellationtype) | No | ActivityCancellationType | - -#### ScheduleToCloseTimeout - -To set a [Schedule-To-Close Timeout](/encyclopedia/detecting-activity-failures#schedule-to-close-timeout), use [`ActivityOptions.newBuilder.setScheduleToCloseTimeout​`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). - -This or `StartToCloseTimeout` must be set. - -- Type: `Duration` -- Default: Unlimited. - Note that if `WorkflowRunTimeout` and/or `WorkflowExecutionTimeout` are defined in the Workflow, all Activity retries will stop when either or both of these timeouts are reached. - -You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. -Note that if you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. - -- With `ActivityStub` - - ```java - GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, - ActivityOptions.newBuilder() - .setScheduleToCloseTimeout(Duration.ofSeconds(5)) - .build()); - ``` - -- With `WorkflowImplementationOptions` - - ```java - WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "GetCustomerGreeting", - ActivityOptions.newBuilder() - .setScheduleToCloseTimeout(Duration.ofSeconds(5)) - .build())) - .build(); - ``` - -#### ScheduleToStartTimeout - -To set a [Schedule-To-Start Timeout](/encyclopedia/detecting-activity-failures#schedule-to-start-timeout), use [`ActivityOptions.newBuilder.setScheduleToStartTimeout​`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). - -- Type: `Duration` -- Default: Unlimited. This timeout is non-retryable. - -You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. -Note that if you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. - -- With `ActivityStub` - - ```java - GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, - ActivityOptions.newBuilder() - .setScheduleToStartTimeout(Duration.ofSeconds(5)) - // note that either StartToCloseTimeout or ScheduleToCloseTimeout are - // required when setting Activity options. - .setScheduletoCloseTimeout(Duration.ofSeconds(20)) - .build()); - ``` - -- With `WorkflowImplementationOptions` - - ```java - WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "GetCustomerGreeting", - ActivityOptions.newBuilder() - .setScheduleToStartTimeout(Duration.ofSeconds(5)) - .build())) - .build(); - ``` - -#### StartToCloseTimeout - -To set a [Start-To-Close Timeout](/encyclopedia/detecting-activity-failures#start-to-close-timeout), use [`ActivityOptions.newBuilder.setStartToCloseTimeout​`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). - -This or `ScheduleToClose` must be set. - -- Type: `Duration` -- Default: Defaults to [`ScheduleToCloseTimeout`](#scheduletoclosetimeout) value - -You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. -Note that if you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. - -- With `ActivityStub` - - ```java - GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, - ActivityOptions.newBuilder() - .setStartToCloseTimeout(Duration.ofSeconds(2)) - .build()); - ``` - -- With `WorkflowImplementationOptions` - - ```java - WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "EmailCustomerGreeting", - ActivityOptions.newBuilder() - // Set Activity Execution timeout (single run) - .setStartToCloseTimeout(Duration.ofSeconds(2)) - .build())) - .build(); - ``` - -#### HeartbeatTimeout - -To set a [Heartbeat Timeout](/encyclopedia/detecting-activity-failures#heartbeat-timeout), use [`ActivityOptions.newBuilder.setHeartbeatTimeout`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). - -- Type: `Duration` -- Default: None - -You can set Activity Options using an `ActivityStub` within a Workflow implementation, or per-Activity using `WorkflowImplementationOptions` within a Worker. -Note that if you define options per-Activity Type options with `WorkflowImplementationOptions.setActivityOptions()`, setting them again specifically with `ActivityStub` in a Workflow will override this setting. - -- With `ActivityStub` - - ```java - private final GreetingActivities activities = - Workflow.newActivityStub( - GreetingActivities.class, - ActivityOptions.newBuilder() - // note that either StartToCloseTimeout or ScheduleToCloseTimeout are - // required when setting Activity options. - .setStartToCloseTimeout(Duration.ofSeconds(5)) - .setHeartbeatTimeout(Duration.ofSeconds(2)) - .build()); - ``` - -- With `WorkflowImplementationOptions` - - ```java - WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "EmailCustomerGreeting", - ActivityOptions.newBuilder() - // note that either StartToCloseTimeout or ScheduleToCloseTimeout are - // required when setting Activity options. - .setStartToCloseTimeout(Duration.ofSeconds(5)) - .setHeartbeatTimeout(Duration.ofSeconds(2)) - .build())) - .build(); - ``` - -#### TaskQueue - -- Type: `String` -- Default: Defaults to the Task Queue that the Workflow was started with. - -- With `ActivityStub` - - ```java - GreetingActivities activities = Workflow.newActivityStub(GreetingActivities.class, - ActivityOptions.newBuilder() - // note that either StartToCloseTimeout or ScheduleToCloseTimeout are required when - // setting Activity options. - .setStartToCloseTimeout(Duration.ofSeconds(5)) - .setTaskQueue("yourTaskQueue") - .build()); - ``` - -- With `WorkflowImplementationOptions` - - ```java - WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "EmailCustomerGreeting", - ActivityOptions.newBuilder() - // note that either StartToCloseTimeout or ScheduleToCloseTimeout are - // required when setting Activity options. - .setStartToCloseTimeout(Duration.ofSeconds(5)) - .setTaskQueue("yourTaskQueue") - .build())) - .build(); - ``` - -See [Task Queue](/task-queue) - -#### RetryOptions - -To set a Retry Policy, known as the [Retry Options](/encyclopedia/retry-policies) in Java, use [`ActivityOptions.newBuilder.setRetryOptions()`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/activity/ActivityOptions.Builder.html). - -- Type: `RetryOptions` -- Default: Server-defined Activity Retry policy. - -- With `ActivityStub` - - ```java - private final ActivityOptions options = - ActivityOptions.newBuilder() - // note that either StartToCloseTimeout or ScheduleToCloseTimeout are - // required when setting Activity options. - .setStartToCloseTimeout(Duration.ofSeconds(5)) - .setRetryOptions( - RetryOptions.newBuilder() - .setInitialInterval(Duration.ofSeconds(1)) - .setMaximumInterval(Duration.ofSeconds(10)) - .build()) - .build(); - ``` - -- With `WorkflowImplementationOptions` - - ```java - WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "EmailCustomerGreeting", - ActivityOptions.newBuilder() - // note that either StartToCloseTimeout or ScheduleToCloseTimeout are - // required when setting Activity options. - .setStartToCloseTimeout(Duration.ofSeconds(5)) - .setRetryOptions( - RetryOptions.newBuilder() - .setDoNotRetry(NullPointerException.class.getName()) - .build()) - .build())) - .build(); - ``` - -#### setCancellationType - -- Type: `ActivityCancellationType` -- Default: `ActivityCancellationType.TRY_CANCEL` - -- With `ActivityStub` - - ```java - private final GreetingActivities activities = - Workflow.newActivityStub( - GreetingActivities.class, - ActivityOptions.newBuilder() - .setCancellationType(ActivityCancellationType.WAIT_CANCELLATION_COMPLETED) - .build()); - ``` - -- With `WorkflowImplementationOptions` - - ```java - WorkflowImplementationOptions options = - WorkflowImplementationOptions.newBuilder() - .setActivityOptions( - ImmutableMap.of( - "EmailCustomerGreeting", - ActivityOptions.newBuilder() - .setCancellationType(ActivityCancellationType.WAIT_CANCELLATION_COMPLETED) - .build())) - .build(); - ``` - -### Get the result of an Activity Execution {#activity-execution-result} - -**How to get the result of an Activity Execution using the Java SDK.** - -The call to spawn an [Activity Execution](/activity-execution) generates the [ScheduleActivityTask](/references/commands#scheduleactivitytask) Command and provides the Workflow with an Awaitable. -Workflow Executions can either block progress until the result is available through the Awaitable or continue progressing, making use of the result when it becomes available. - -To get the results of an asynchronously invoked Activity method, use the `Promise` `get` method to block until the Activity method result is available. - -Sometimes an Activity Execution lifecycle goes beyond a synchronous method invocation. -For example, a request can be put in a queue and later a reply comes and is picked up by a different Worker process. -The whole request-reply interaction can be modeled as a single Activity. - -To indicate that an Activity should not be completed upon its method return, call `ActivityExecutionContext.doNotCompleteOnReturn()` from the original Activity thread. - -Then later, when replies come, complete the Activity using the `ActivityCompletionClient`. -To correlate Activity invocation with completion, use either a `TaskToken` or Workflow and Activity Ids. - -Following is an example of using `ActivityExecutionContext.doNotCompleteOnReturn()`: - -```java -public class FileProcessingActivitiesImpl implements FileProcessingActivities { - - public String download(String bucketName, String remoteName, String localName) { - - ActivityExecutionContext ctx = Activity.getExecutionContext(); - - // Used to correlate reply - byte[] taskToken = ctx.getInfo().getTaskToken(); - - asyncDownloadFileFromS3(taskToken, bucketName, remoteName, localDirectory + localName); - ctx.doNotCompleteOnReturn(); - - // Return value is ignored when doNotCompleteOnReturn was called. - return "ignored"; - } - ... -} -``` - -When the download is complete, the download service potentially can complete the Activity, or fail it from a different process, for example: - -```java - public void completeActivity(byte[] taskToken, R result) { - completionClient.complete(taskToken, result); - } - - public void failActivity(byte[] taskToken, Exception failure) { - completionClient.completeExceptionally(taskToken, failure); - } -``` - -## Develop a Worker Program in Java {#run-a-dev-worker} - -**How to develop a Worker Program using the Java SDK.** - -The [Worker Process](/workers#worker-process) is where Workflow Functions and Activity Functions are executed. - -- Each [Worker Entity](/workers#worker-entity) in the Worker Process must register the exact Workflow Types and Activity Types it may execute. -- Each Worker Entity must also associate itself with exactly one [Task Queue](/task-queue). -- Each Worker Entity polling the same Task Queue must be registered with the same Workflow Types and Activity Types. - -A [Worker Entity](/workers#worker-entity) is the component within a Worker Process that listens to a specific Task Queue. - -Although multiple Worker Entities can be in a single Worker Process, a single Worker Entity Worker Process may be perfectly sufficient. -For more information, see the [Worker tuning guide](/develop/worker-performance). - -A Worker Entity contains a Workflow Worker and/or an Activity Worker, which makes progress on Workflow Executions and Activity Executions, respectively. - -Use the `newWorker` method on an instance of a [`WorkerFactory`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/worker/WorkerFactory.html) to create a new Worker in Java. - -A single Worker Entity can contain many Worker Objects. -Call the `start()` method on the instance of the `WorkerFactory` to start all the Workers created in this process. - -```java -// ... -import io.temporal.client.WorkflowClient; -import io.temporal.serviceclient.WorkflowServiceStubs; -import io.temporal.worker.Worker; -import io.temporal.worker.WorkerFactory; - -public class YourWorker { - - public static void main(String[] args) { - - WorkflowServiceStubs service = WorkflowServiceStubs.newLocalServiceStubs(); - WorkflowClient client = WorkflowClient.newInstance(service); - WorkerFactory factory = WorkerFactory.newInstance(client); - Worker yourWorker = factory.newWorker("your_task_queue"); - - // Register Workflow - // and/or register Activities - - factory.start(); - } -} -``` - -After creating the Worker entity, register all Workflow Types and all Activity Types that the Worker can execute. -A Worker can be registered with just Workflows, just Activities, or both. - -**Operation guides:** - -- [How to tune Workers](/develop/worker-performance) - -### How to register types {#register-types} - -**How to register Workflow and Activity Types with a Worker using the Java SDK.** - -All Workers listening to the same Task Queue name must be registered to handle the exact same Workflows Types and Activity Types. - -If a Worker polls a Task for a Workflow Type or Activity Type it does not know about, it fails that Task. -However, the failure of the Task does not cause the associated Workflow Execution to fail. - -Use `worker.registerWorkflowImplementationTypes` to register Workflow Type and `worker.registerActivitiesImplementations` to register Activity implementation with Workers. - -For Workflows, the Workflow Type is registered with a Worker. -A Workflow Type can be registered only once per Worker entity. -If you define multiple Workflow implementations of the same type, you get an exception at the time of registration. - -For Activities, Activity implementation instances are registered with a Worker because they are stateless and thread-safe. -You can pass any number of dependencies in the Activity implementation constructor, such as the database connections, services, etc. - -The following example shows how to register a Workflow and an Activity with a Worker. - -```java -Worker worker = workerFactory.newWorker("your_task_queue"); -... -// Register Workflow -worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class); -// Register Activity -worker.registerActivitiesImplementations(new GreetingActivitiesImpl()); -``` - -When you register a single instance of an Activity, you can have multiple instances of Workflow Executions calling the same Activity. -Activity code must be thread-safe because the same instance of the Activity code is run for every Workflow Execution that calls it. - -For `DynamicWorkflow`, only one Workflow implementation that extends `DynamicWorkflow` can be registered with a Worker. -The following example shows how to register the `DynamicWorkflow` and `DynamicActivity` implementation with a Worker. - -```java - public static void main(String[] arg) { - - WorkflowServiceStubs service = WorkflowServiceStubs.newInstance(); - WorkflowClient client = WorkflowClient.newInstance(service); - WorkerFactory factory = WorkerFactory.newInstance(client); - Worker worker = factory.newWorker(TASK_QUEUE); - - /* Register the Dynamic Workflow implementation with the Worker. Workflow implementations - ** must be known to the Worker at runtime to dispatch Workflow Tasks. - */ - worker.registerWorkflowImplementationTypes(DynamicGreetingWorkflowImpl.class); - - // Start all the Workers that are in this process. - factory.start(); - - /* Create the Workflow stub. Note that the Workflow Type is not explicitly registered with the Worker. */ - WorkflowOptions workflowOptions = - WorkflowOptions.newBuilder().setTaskQueue(TASK_QUEUE).setWorkflowId(WORKFLOW_ID).build(); - WorkflowStub workflow = client.newUntypedWorkflowStub("DynamicWF", workflowOptions); - /** - * Register Dynamic Activity implementation with the Worker. Since Activities are stateless - * and thread-safe, we need to register a shared instance. - */ - worker.registerActivitiesImplementations(new DynamicGreetingActivityImpl()); - - /* Start Workflow Execution and immmediately send Signal. Pass in the Workflow args and Signal args. */ - workflow.signalWithStart("greetingSignal", new Object[] {"John"}, new Object[] {"Hello"}); - - // Wait for the Workflow to finish getting the results. - String result = workflow.getResult(String.class); - - System.out.println(result); - - System.exit(0); - } -} -``` - -You can register multiple type-specific Workflow implementations alongside a single `DynamicWorkflow` implementation. -You can register only one Activity instance that implements `DynamicActivity` with a Worker. diff --git a/docs/develop/java/index.mdx b/docs/develop/java/index.mdx index e83a69e80e..eb855c9194 100644 --- a/docs/develop/java/index.mdx +++ b/docs/develop/java/index.mdx @@ -15,168 +15,75 @@ import * as Components from '@site/src/components'; ![Java SDK Banner](/img/assets/banner-java-temporal.png) -:::info JAVA SPECIFIC RESOURCES -Build Temporal Applications with the Java SDK. +## Install and get started -**Temporal Java Technical Resources:** +You can find detailed installation instructions for the Java SDK in the [Quickstart](/develop/java/set-up-your-local-java). -- [Java SDK Quickstart - Setup Guide](https://docs.temporal.io/develop/java/set-up-your-local-java) -- [Java API Documentation](https://javadoc.io/doc/io.temporal/temporal-sdk) -- [Java SDK Code Samples](https://github.com/temporalio/samples-java) -- [Java SDK GitHub](https://github.com/temporalio/sdk-java) -- [Temporal 101 in Java Free Course](https://learn.temporal.io/courses/temporal_101/java/) - -**Get Connected with the Temporal Java Community:** - -- [Temporal Java Community Slack](https://temporalio.slack.com/archives/CTT84KXK9) -- [Java SDK Forum](https://community.temporal.io/tag/java-sdk) - ::: - -## [Core application](/develop/java/core-application) - -Use the essential components of a Temporal Application (Workflows, Activities, and Workers) to build and run a Temporal application. - -- [How to develop a Workflow Definition in Java](/develop/java/core-application#develop-workflows) -- [How to develop a basic Activity](/develop/java/core-application#develop-activities) -- [How to start an Activity Execution](/develop/java/core-application#activity-execution) -- [How to develop a Worker Program in Java](/develop/java/core-application#run-a-dev-worker) - -## [Temporal Client](/develop/java/temporal-client) - -Connect to a Temporal Service and start a Workflow Execution. - -- [Connect to a development Temporal Service](/develop/java/temporal-client#connect-to-development-service) -- [Connect to Temporal Cloud](/develop/java/temporal-client#connect-to-temporal-cloud) -- [Start a Workflow Execution](/develop/java/temporal-client#start-workflow-execution) - -## [Testing](/develop/java/testing-suite) - -Set up the testing suite and test Workflows and Activities. - -- [Test frameworks](/develop/java/testing-suite#test-frameworks) -- [Test Activities](/develop/java/testing-suite#test-activities) -- [Testing Workflows](/develop/java/testing-suite#test-workflows) -- [How to Replay a Workflow Execution](/develop/java/testing-suite#replay) - -## [Failure detection](/develop/java/failure-detection) - -Explore how your application can detect failures using timeouts and automatically attempt to mitigate them with retries. - -- [Workflow timeouts](/develop/java/failure-detection#workflow-timeouts) -- [How to set Activity timeouts](/develop/java/failure-detection#activity-timeouts) -- [How to Heartbeat an Activity](/develop/java/failure-detection#activity-heartbeats) - -## [Workflow message passing](/develop/java/message-passing) - -Send messages to and read the state of Workflow Executions. - -- [How to develop with Signals](/develop/java/message-passing#signals) -- [How to develop with Queries](/develop/java/message-passing#queries) -- [What is a Dynamic Handler?](/develop/java/message-passing#dynamic-handler) -- [How to develop with Updates](/develop/java/message-passing#updates) - -## [Asynchronous Activity completion](/develop/java/asynchronous-activity-completion) - -Complete Activities asynchronously. - -- [How to asynchronously complete an Activity](/develop/java/asynchronous-activity-completion) - -## [Versioning](/develop/java/versioning) +There's also a short walkthrough of how to use the Temporal primitives (Activities, Workflows, and Workers) to build and run a Temporal application to get you up and running. -Change Workflow Definitions without causing non-deterministic behavior in running Workflows. +Once your local Temporal Service is set up, continue building with the following resources: -- [Temporal Java SDK Versioning APIs](/develop/java/versioning#patching) +- [Develop a Basic Activity](/develop/java/activities/basic-activity) +- [Develop a Basic Workflow](/develop/java/workflows/basic-workflow) +- [Start an Activity Execution](/develop/java/activities/execution) +- [Run Worker Processes](/develop/java/workers/run-worker-process) -## [Observability](/develop/java/observability) +From there, you can dive deeper into any of the Temporal primitives to start building Workflows that fit your use cases. -Configure and use the Temporal Observability APIs. +## [Workflows](/develop/java/workflows) -- [How to emit metrics](/develop/java/observability#metrics) -- [How to setup Tracing](/develop/java/observability#tracing) -- [How to log from a Workflow](/develop/java/observability#logging) -- [How to use Visibility APIs](/develop/java/observability#visibility) +- [Basic Workflow](/develop/java/workflows/basic-workflow) +- [Child Workflows](/develop/java/workflows/child-workflows) +- [Continue-As-New](/develop/java/workflows/continue-as-new) +- [Cancellation](/develop/java/workflows/cancellation) +- [Timeouts](/develop/java/workflows/timeouts) +- [Message Passing](/develop/java/workflows/message-passing) +- [Enriching the UI](/develop/java/workflows/enriching-ui) +- [Schedules](/develop/java/workflows/schedules) +- [Side Effects](/develop/java/workflows/side-effects) +- [Timers](/develop/java/workflows/timers) -## [Debugging](/develop/java/debugging) +## [Activities](/develop/java/activities) -Explore various ways to debug your application. +- [Basic Activity](/develop/java/activities/basic-activity) +- [Activity Execution](/develop/java/activities/execution) +- [Timeouts](/develop/java/activities/timeouts) +- [Asynchronous Activity Completion](/develop/java/activities/asynchronous-activity-completion) +- [Benign exceptions](/develop/java/activities/benign-exceptions) -- [How to debug in a development environment](/develop/java/debugging#debug-in-a-development-environment) -- [How to debug in a production environment](/develop/java/debugging#debug-in-a-production-environment) +## [Workers](/develop/java/workers) -## [Schedules](/develop/java/schedules) +- [Run Worker processes](/develop/java/workers/run-worker-process) +- [Observability](/develop/java/workers/observability) -Run Workflows on a schedule and delay the start of a Workflow. +## [Temporal Client](/develop/java/client) -- [How to Schedule a Workflow](/develop/java/schedules#schedule-a-workflow) -- [How to set a Cron Schedule in Java](/develop/java/schedules#cron-schedule) +- [Temporal Client](/develop/java/client/temporal-client) +- [Namespaces](/develop/java/client/namespaces) -## [Data encryption](/develop/java/converters-and-encryption) +## [Temporal Nexus](/develop/java/nexus) -Use compression, encryption, and other data handling by implementing custom converters and codecs. +- [Service Handlers](/develop/java/nexus/service-handler) -- [How to use a custom Payload Codec in Java](/develop/java/converters-and-encryption#custom-payload-codec) -- [How to use custom Payload conversion](/develop/java/converters-and-encryption#custom-payload-conversion) +## [Best practices](/develop/java/best-practices) -## Temporal Nexus +- [Testing](/develop/java/best-practices/testing-suite) +- [Debugging](/develop/java/best-practices/debugging) +- [Converters and encryption](/develop/java/best-practices/converters-and-encryption) -The [Temporal Nexus](/develop/java/nexus) feature guide shows how to use Temporal Nexus to connect Durable Executions within and across Namespaces using a Nexus Endpoint, a Nexus Service contract, and Nexus Operations. +## Spring Boot Integration -- [Create a Nexus Endpoint to route requests from caller to handler](/develop/java/nexus#create-nexus-endpoint) -- [Define the Nexus Service contract](/develop/java/nexus#define-nexus-service-contract) -- [Develop a Nexus Service and Operation handlers](/develop/java/nexus#develop-nexus-service-operation-handlers) -- [Develop a caller Workflow that uses a Nexus Service](/develop/java/nexus#develop-caller-workflow-nexus-service) -- [Make Nexus calls across Namespaces with a development Server](/develop/java/nexus#nexus-calls-across-namespaces-dev-server) -- [Make Nexus calls across Namespaces in Temporal Cloud](/develop/java/nexus#nexus-calls-across-namespaces-temporal-cloud) +- [Spring Boot Integration](/develop/java/integrations/spring-boot-integration) -## [Interrupt a Workflow feature guide](/develop/java/cancellation) +## Temporal Java Technical Resources -Interrupt a Workflow Execution with a Cancel or Terminate action. - -- [Cancel a Workflow](/develop/java/cancellation#cancellation) -- [Terminate a Workflow](/develop/java/cancellation#termination) -- [Reset a Workflow](/develop/java/cancellation#reset): Resume a Workflow Execution from an earlier point in its Event History. -- [Cancel an Activity from a Workflow](/develop/java/cancellation#cancel-activity) - -## [Child Workflows](/develop/java/child-workflows) - -Explore how to spawn a Child Workflow Execution and handle Child Workflow Events. - -- [Start a Child Workflow Execution](/develop/java/child-workflows#start-child-workflow) -- [Set a Parent Close Policy](/develop/java/child-workflows#parent-close-policy) - -## [Continue-As-New](/develop/java/continue-as-new) - -Continue the Workflow Execution with a new Workflow Execution using the same Workflow ID. - -- [Continue a Workflow as New](/develop/java/continue-as-new) - -## [Durable Timers](/develop/java/timers) - -Use Timers to make a Workflow Execution pause or "sleep" for seconds, minutes, days, months, or years. - -- [What is a Timer?](/develop/java/timers#timers) - -## [Side Effects](/develop/java/side-effects) - -Use Side Effects in Workflows. - -- [Side Effects](/develop/java/side-effects#side-effects) - -## [Enriching the User Interface](/develop/java/enriching-ui) - -Add descriptive information to workflows and events for better visibility and context in the UI. - -- [Adding Summary and Details to Workflows](/develop/java/enriching-ui#adding-summary-and-details-to-workflows) - -## [Manage Namespaces](/develop/java/namespaces) - -Create and manage Namespaces. - -- [Create a Namespace](/develop/java/namespaces#register-namespace) -- [Manage Namespaces](/develop/java/namespaces#manage-namespaces) - -## [Spring Boot](/develop/java/spring-boot-integration) +- [Java SDK Quickstart - Setup Guide](https://docs.temporal.io/develop/java/set-up-your-local-java) +- [Java API Documentation](https://javadoc.io/doc/io.temporal/temporal-sdk) +- [Java SDK Code Samples](https://github.com/temporalio/samples-java) +- [Java SDK GitHub](https://github.com/temporalio/sdk-java) +- [Temporal 101 in Java Free Course](https://learn.temporal.io/courses/temporal_101/java/) -Use Temporal in your Spring Boot application. +## Get Connected with the Temporal Java Community -- [Spring Boot](/develop/java/spring-boot-integration#setup-dependency) +- [Temporal Java Community Slack](https://temporalio.slack.com/archives/CTT84KXK9) +- [Java SDK Forum](https://community.temporal.io/tag/java-sdk) \ No newline at end of file diff --git a/docs/develop/java/integrations/index.mdx b/docs/develop/java/integrations/index.mdx new file mode 100644 index 0000000000..6c805a1d30 --- /dev/null +++ b/docs/develop/java/integrations/index.mdx @@ -0,0 +1,20 @@ +--- +id: index +title: Integrations - Java SDK +sidebar_label: Integrations +description: This section covers integrations with the Java SDK +toc_max_heading_level: 4 +keywords: + - Java SDK +tags: + - Java SDK + - Temporal SDKs +--- + +import * as Components from '@site/src/components'; + +![Java SDK Banner](/img/assets/banner-java-temporal.png) + +## Integrations + +- [Spring Boot](/develop/java/integrations/spring-boot-integration) \ No newline at end of file diff --git a/docs/develop/java/spring-boot-integration.mdx b/docs/develop/java/integrations/spring-boot.mdx similarity index 94% rename from docs/develop/java/spring-boot-integration.mdx rename to docs/develop/java/integrations/spring-boot.mdx index eee77735e5..cca1c9a369 100644 --- a/docs/develop/java/spring-boot-integration.mdx +++ b/docs/develop/java/integrations/spring-boot.mdx @@ -1,8 +1,8 @@ --- -id: spring-boot-integration +id: spring-boot title: Spring Boot integration - Java SDK sidebar_label: Spring Boot integration -slug: /develop/java/spring-boot-integration +slug: /develop/java/integrations/spring-boot-integration toc_max_heading_level: 2 keywords: - spring-boot-integration @@ -52,7 +52,7 @@ implementation ("io.temporal:temporal-spring-boot-starter:1.31.0") ## Connect {#connect} -See the [Temporal Client documentation](/develop/java/temporal-client) for more information about connecting to a Temporal Service. +See the [Temporal Client documentation](/develop/java/client/temporal-client) for more information about connecting to a Temporal Service. To create an autoconfigured `WorkflowClient`, you need to specify some connection details in your `application.yml` file, as described in the next section. @@ -89,7 +89,7 @@ spring.temporal: You can also connect to Temporal Cloud, using either an API key or mTLS for authentication. -See the [Connect to Temporal Cloud](/develop/java/temporal-client#connect-to-temporal-cloud) section for more information about connecting to Temporal Cloud. +See the [Connect to Temporal Cloud](/develop/java/client/temporal-client#connect-to-temporal-cloud) section for more information about connecting to Temporal Cloud. ### Using an API key @@ -240,4 +240,4 @@ public class Test { } ``` -See the [Java SDK test frameworks documentation](/develop/java/testing-suite#test-frameworks) for more information about testing. +See the [Java SDK test frameworks documentation](/develop/java/best-practices/testing-suite#test-frameworks) for more information about testing. diff --git a/docs/develop/java/nexus/index.mdx b/docs/develop/java/nexus/index.mdx new file mode 100644 index 0000000000..ee619f2533 --- /dev/null +++ b/docs/develop/java/nexus/index.mdx @@ -0,0 +1,20 @@ +--- +id: index +title: Nexus - Java SDK +sidebar_label: Nexus +description: This section covers Nexus with the Java SDK +toc_max_heading_level: 4 +keywords: + - Java SDK +tags: + - Java SDK + - Temporal SDKs +--- + +import * as Components from '@site/src/components'; + +![Java SDK Banner](/img/assets/banner-java-temporal.png) + +## Temporal Nexus + +- [Service Handlers](/develop/java/nexus/service-handler) \ No newline at end of file diff --git a/docs/develop/java/temporal-nexus.mdx b/docs/develop/java/nexus/service-handler.mdx similarity index 98% rename from docs/develop/java/temporal-nexus.mdx rename to docs/develop/java/nexus/service-handler.mdx index 3d883cdd95..699f08af5f 100644 --- a/docs/develop/java/temporal-nexus.mdx +++ b/docs/develop/java/nexus/service-handler.mdx @@ -1,8 +1,8 @@ --- -id: nexus -title: Temporal Nexus - Java SDK feature guide -sidebar_label: Temporal Nexus -description: Use Temporal Nexus within the Java SDK to connect Durable Executions within and across Namespaces using a Nexus Endpoint, a Nexus Service contract, and Nexus Operations. +id: service-handler +title: Service Handler - Java SDK feature guide +sidebar_label: Service Handler +description: Use Temporal Nexus Service Handler within the Java SDK to connect Durable Executions within and across Namespaces using a Nexus Endpoint, a Nexus Service contract, and Nexus Operations. toc_max_heading_level: 4 keywords: - temporal @@ -589,7 +589,7 @@ See the [Nexus cancelation sample](https://github.com/temporalio/samples-java/tr ## Make Nexus calls across Namespaces in Temporal Cloud {#nexus-calls-across-namespaces-temporal-cloud} -This section assumes you are already familiar with [how connect a Worker to Temporal Cloud](https://docs.temporal.io/develop/java/core-application#run-a-temporal-cloud-worker). +This section assumes you are already familiar with [how connect a Worker to Temporal Cloud](/develop/java/client/temporal-client#start-workflow-execution). The same [source code](https://github.com/temporalio/samples-go/tree/main/nexus) is used in this section, but the `tcld` CLI will be used to create Namespaces and the Nexus Endpoint, and mTLS client certificates will be used to securely connect the caller and handler Workers to their respective Temporal Cloud Namespaces. ### Install the latest `tcld` CLI and generate certificates diff --git a/docs/develop/java/workers/index.mdx b/docs/develop/java/workers/index.mdx new file mode 100644 index 0000000000..dee0195a93 --- /dev/null +++ b/docs/develop/java/workers/index.mdx @@ -0,0 +1,21 @@ +--- +id: index +title: Workers - Java SDK +sidebar_label: Nexus +description: This section covers Workers with the Java SDK +toc_max_heading_level: 4 +keywords: + - Java SDK +tags: + - Java SDK + - Temporal SDKs +--- + +import * as Components from '@site/src/components'; + +![Java SDK Banner](/img/assets/banner-java-temporal.png) + +## Workers + +- [Run Worker processes](/develop/java/workers/run-worker-process) +- [Observability](/develop/java/workers/observability) \ No newline at end of file diff --git a/docs/develop/java/observability.mdx b/docs/develop/java/workers/observability.mdx similarity index 99% rename from docs/develop/java/observability.mdx rename to docs/develop/java/workers/observability.mdx index 11363a6e0f..a19a3ba5a6 100644 --- a/docs/develop/java/observability.mdx +++ b/docs/develop/java/workers/observability.mdx @@ -2,7 +2,7 @@ id: observability title: Observability - Java SDK sidebar_label: Observability -slug: /develop/java/observability +slug: /develop/java/workers/observability description: Explore the observability features of Temporal, including Metrics, Tracing, Logging, and Visibility. Emit Metrics with the Java SDK, set up Tracing, and use Search Attributes. toc_max_heading_level: 4 keywords: diff --git a/docs/develop/java/workers/run-process.mdx b/docs/develop/java/workers/run-process.mdx new file mode 100644 index 0000000000..8b5c1695a0 --- /dev/null +++ b/docs/develop/java/workers/run-process.mdx @@ -0,0 +1,138 @@ +--- +id: run-worker-process +title: Run Worker processes - Java SDK +sidebar_label: Worker processes +description: This section explains how to implement a Worker with the Java SDK +toc_max_heading_level: 4 +keywords: + - Java SDK +tags: + - Java SDK + - Temporal SDKs +--- + +## How to run Worker Processes {#run-a-dev-worker} + +The [Worker Process](/workers#worker-process) is where Workflow Functions and Activity Functions are executed. + +- Each [Worker Entity](/workers#worker-entity) in the Worker Process must register the exact Workflow Types and Activity Types it may execute. +- Each Worker Entity must also associate itself with exactly one [Task Queue](/task-queue). +- Each Worker Entity polling the same Task Queue must be registered with the same Workflow Types and Activity Types. + +A [Worker Entity](/workers#worker-entity) is the component within a Worker Process that listens to a specific Task Queue. + +Although multiple Worker Entities can be in a single Worker Process, a single Worker Entity Worker Process may be perfectly sufficient. +For more information, see the [Worker tuning guide](/develop/worker-performance). + +A Worker Entity contains a Workflow Worker and/or an Activity Worker, which makes progress on Workflow Executions and Activity Executions, respectively. + +Use the `newWorker` method on an instance of a [`WorkerFactory`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/worker/WorkerFactory.html) to create a new Worker in Java. + +A single Worker Entity can contain many Worker Objects. +Call the `start()` method on the instance of the `WorkerFactory` to start all the Workers created in this process. + +```java +// ... +import io.temporal.client.WorkflowClient; +import io.temporal.serviceclient.WorkflowServiceStubs; +import io.temporal.worker.Worker; +import io.temporal.worker.WorkerFactory; + +public class YourWorker { + + public static void main(String[] args) { + + WorkflowServiceStubs service = WorkflowServiceStubs.newLocalServiceStubs(); + WorkflowClient client = WorkflowClient.newInstance(service); + WorkerFactory factory = WorkerFactory.newInstance(client); + Worker yourWorker = factory.newWorker("your_task_queue"); + + // Register Workflow + // and/or register Activities + + factory.start(); + } +} +``` + +After creating the Worker entity, register all Workflow Types and all Activity Types that the Worker can execute. +A Worker can be registered with just Workflows, just Activities, or both. + +**Operation guides:** + +- [How to tune Workers](/develop/worker-performance) + +## How to register types {#register-types} + +All Workers listening to the same Task Queue name must be registered to handle the exact same Workflows Types and Activity Types. + +If a Worker polls a Task for a Workflow Type or Activity Type it does not know about, it fails that Task. +However, the failure of the Task does not cause the associated Workflow Execution to fail. + +Use `worker.registerWorkflowImplementationTypes` to register Workflow Type and `worker.registerActivitiesImplementations` to register Activity implementation with Workers. + +For Workflows, the Workflow Type is registered with a Worker. +A Workflow Type can be registered only once per Worker entity. +If you define multiple Workflow implementations of the same type, you get an exception at the time of registration. + +For Activities, Activity implementation instances are registered with a Worker because they are stateless and thread-safe. +You can pass any number of dependencies in the Activity implementation constructor, such as the database connections, services, etc. + +The following example shows how to register a Workflow and an Activity with a Worker. + +```java +Worker worker = workerFactory.newWorker("your_task_queue"); +... +// Register Workflow +worker.registerWorkflowImplementationTypes(GreetingWorkflowImpl.class); +// Register Activity +worker.registerActivitiesImplementations(new GreetingActivitiesImpl()); +``` + +When you register a single instance of an Activity, you can have multiple instances of Workflow Executions calling the same Activity. +Activity code must be thread-safe because the same instance of the Activity code is run for every Workflow Execution that calls it. + +For `DynamicWorkflow`, only one Workflow implementation that extends `DynamicWorkflow` can be registered with a Worker. +The following example shows how to register the `DynamicWorkflow` and `DynamicActivity` implementation with a Worker. + +```java + public static void main(String[] arg) { + + WorkflowServiceStubs service = WorkflowServiceStubs.newInstance(); + WorkflowClient client = WorkflowClient.newInstance(service); + WorkerFactory factory = WorkerFactory.newInstance(client); + Worker worker = factory.newWorker(TASK_QUEUE); + + /* Register the Dynamic Workflow implementation with the Worker. Workflow implementations + ** must be known to the Worker at runtime to dispatch Workflow Tasks. + */ + worker.registerWorkflowImplementationTypes(DynamicGreetingWorkflowImpl.class); + + // Start all the Workers that are in this process. + factory.start(); + + /* Create the Workflow stub. Note that the Workflow Type is not explicitly registered with the Worker. */ + WorkflowOptions workflowOptions = + WorkflowOptions.newBuilder().setTaskQueue(TASK_QUEUE).setWorkflowId(WORKFLOW_ID).build(); + WorkflowStub workflow = client.newUntypedWorkflowStub("DynamicWF", workflowOptions); + /** + * Register Dynamic Activity implementation with the Worker. Since Activities are stateless + * and thread-safe, we need to register a shared instance. + */ + worker.registerActivitiesImplementations(new DynamicGreetingActivityImpl()); + + /* Start Workflow Execution and immmediately send Signal. Pass in the Workflow args and Signal args. */ + workflow.signalWithStart("greetingSignal", new Object[] {"John"}, new Object[] {"Hello"}); + + // Wait for the Workflow to finish getting the results. + String result = workflow.getResult(String.class); + + System.out.println(result); + + System.exit(0); + } +} +``` + +You can register multiple type-specific Workflow implementations alongside a single `DynamicWorkflow` implementation. +You can register only one Activity instance that implements `DynamicActivity` with a Worker. diff --git a/docs/develop/java/workflows/basic-workflow.mdx b/docs/develop/java/workflows/basic-workflow.mdx new file mode 100644 index 0000000000..50e0e512d3 --- /dev/null +++ b/docs/develop/java/workflows/basic-workflow.mdx @@ -0,0 +1,244 @@ +--- +id: basic-workflow +title: Basic Workflow - Java SDK +sidebar_label: Basic Workflow +description: This section explains how to implement Activities with the Java SDK +toc_max_heading_level: 4 +keywords: + - Java SDK +tags: + - Java SDK + - Temporal SDKs +--- + +## How to develop a basic Workflow {#develop-workflows} + +Workflows are the fundamental unit of a Temporal Application, and it all starts with the development of a [Workflow Definition](/workflow-definition). + +In the Temporal Java SDK programming model, a Workflow Definition comprises a Workflow interface annotated with `@WorkflowInterface` and a Workflow implementation that implements the Workflow interface. + +The Workflow interface is a Java interface and is annotated with `@WorkflowInterface`. +Each Workflow interface must have only one method annotated with `@WorkflowMethod`. + +```java +// Workflow interface +@WorkflowInterface +public interface YourWorkflow { + + @WorkflowMethod + String yourWFMethod(Arguments args); +} +``` + +However, when using dynamic Workflows, do not specify a `@WorkflowMethod`, and implement the `DynamicWorkflow` directly in the Workflow implementation code. + +The `@WorkflowMethod` identifies the method that is the starting point of the Workflow Execution. +The Workflow Execution completes when this method completes. + +You can create [interface inheritance hierarchies](#interface-inheritance) to reuse components across other Workflow interfaces. +The interface inheritance approach does not apply to `@WorkflowMethod` annotations. + +A Workflow implementation implements a Workflow interface. + +```java +// Define the Workflow implementation which implements our getGreeting Workflow method. + public static class GreetingWorkflowImpl implements GreetingWorkflow { + ... + } + } +``` + +To call Activities in your Workflow, call the Activity implementation. + +Use `ExternalWorkflowStub` to start or send Signals from within a Workflow to other running Workflow Executions. + +You can also invoke other Workflows as Child Workflows with `Workflow.newChildWorkflowStub()` or `Workflow.newUntypedChildWorkflowStub()` within a Workflow Definition. + +## Workflow interface inheritance {#interface-inheritance} + +Workflow interfaces can form inheritance hierarchies. +It may be useful for creating reusable components across multiple +Workflow interfaces. +For example imagine a UI or CLI button that allows a `retryNow` Signal on any Workflow. To implement this feature you can redesign an interface like the following: + +```java +public interface Retryable { + @SignalMethod + void retryNow(); +} + +@WorkflowInterface +public interface FileProcessingWorkflow extends Retryable { + + @WorkflowMethod + String processFile(Arguments args); + + @QueryMethod(name="history") + List getHistory(); + + @QueryMethod + String getStatus(); + + @SignalMethod + void abandon(); +} +``` + +Then some other Workflow interface can extend just `Retryable`, for example: + +```java +@WorkflowInterface +public interface MediaProcessingWorkflow extends Retryable { + + @WorkflowMethod + String processBlob(Arguments args); +} +``` + +Now if we have two running Workflows, one that implements the `FileProcessingWorkflow` interface and another that implements the `MediaProcessingWorkflow` interface, we can Signal to both using their common interface and knowing their WorkflowIds, for example: + +```java +Retryable r1 = client.newWorkflowStub(Retryable.class, firstWorkflowId); +Retryable r2 = client.newWorkflowStub(Retryable.class, secondWorkflowId); +r1.retryNow(); +r2.retryNow(); +``` + +The same technique can be used to query Workflows using a base Workflow interface. + +Note that this approach does not apply to `@WorkflowMethod` annotations, meaning that when using a base interface, it should not include any `@WorkflowMethod` methods. +To illustrate this, lets' say that we define the following **invalid** code: + +```java +// INVALID CODE! +public interface BaseWorkflow { + @WorkflowMethod + void retryNow(); +} + +@WorkflowInterface +public interface Workflow1 extends BaseWorkflow {} + +@WorkflowInterface +public interface Workflow2 extends BaseWorkflow {} +``` + +Any attempt to register both implementations with the Worker will fail. +Let's say that we have: + +```java +worker.registerWorkflowImplementationTypes( + Workflow1Impl.class, Workflow2Impl.class); +``` + +This registration will fail with: + +```text +java.lang.IllegalStateException: BaseWorkflow workflow type is already registered with the worker +``` + +## Define Workflow parameters {#workflow-parameters} + +Temporal Workflows may have any number of custom parameters. +However, we strongly recommend that objects are used as parameters, so that the object's individual fields may be altered without breaking the signature of the Workflow. +All Workflow Definition parameters must be serializable. + +A method annotated with `@WorkflowMethod` can have any number of parameters. + +We recommend passing a single parameter that contains all the input fields to allow for adding fields in a backward-compatible manner. + +Note that all inputs should be serializable by the default Jackson JSON Payload Converter. + +You can create a custom object and pass it to the Workflow method, as shown in the following example. + +```java +//... +@WorkflowInterface +public interface YourWorkflow { + @WorkflowMethod + String yourWFMethod(CustomObj customobj); +// ... +} +``` + +## Define Workflow return parameters {#workflow-return-values} + +Workflow return values must also be serializable. +Returning results, returning errors, or throwing exceptions is fairly idiomatic in each language that is supported. +However, Temporal APIs that must be used to get the result of a Workflow Execution will only ever receive one of either the result or the error. + +Workflow method arguments and return values must be serializable and deserializable using the provided [`DataConverter`](https://www.javadoc.io/static/io.temporal/temporal-sdk/1.17.0/io/temporal/common/converter/DataConverter.html). + +The `execute` method for `DynamicWorkflow` can return type Object. +Ensure that your Client can handle an Object type return or is able to convert the Object type response. + +Related references: + +- [Data Converter](/dataconversion) +- [Java DataConverter reference](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/common/converter/DataConverter.html) + +## Customize your Workflow Type {#workflow-type} + +Workflows have a Type that are referred to as the Workflow name. + +The following examples demonstrate how to set a custom name for your Workflow Type. + +The Workflow Type defaults to the short name of the Workflow interface. +In the following example, the Workflow Type defaults to `NotifyUserAccounts`. + +```java + @WorkflowInterface + + public interface NotifyUserAccounts { + @WorkflowMethod + void notify(String[] accountIds); +} +``` + +To overwrite this default naming and assign a custom Workflow Type, use the `@WorkflowMethod` annotation with the `name` parameter. +In the following example, the Workflow Type is set to `your-workflow`. + +```java +@WorkflowInterface + + public interface NotifyUserAccounts { + @WorkflowMethod(name = "your-workflow") + void notify(String[] accountIds); + } +``` + +When you set the Workflow Type this way, the value of the `name` parameter does not have to start with an uppercase letter. + +## Workflow logic requirements {#workflow-logic-requirements} + +Workflow logic is constrained by [deterministic execution requirements](/workflow-definition#deterministic-constraints). +Therefore, each language is limited to the use of certain idiomatic techniques. +However, each Temporal SDK provides a set of APIs that can be used inside your Workflow to interact with external (to the Workflow) application code. + +When defining Workflows using the Temporal Java SDK, the Workflow code must be written to execute effectively once and to completion. + +The following constraints apply when writing Workflow Definitions: + +- Do not use mutable global variables in your Workflow implementations. + This will ensure that multiple Workflow instances are fully isolated. +- Your Workflow code must be deterministic. + Do not call non-deterministic functions (such as non-seeded random or `UUID.randomUUID()`) directly from the Workflow code. + The Temporal SDK provides specific API for calling non-deterministic code in your Workflows. +- Do not use programming language constructs that rely on system time. + For example, only use `Workflow.currentTimeMillis()` to get the current time inside a Workflow. +- Do not use native Java `Thread` or any other multi-threaded classes like `ThreadPoolExecutor`. + Use `Async.function` or `Async.procedure`, provided by the Temporal SDK, to execute code asynchronously. +- Do not use synchronization, locks, or other standard Java blocking concurrency-related classes besides those provided by the Workflow class. + There is no need for explicit synchronization because multi-threaded code inside a Workflow is executed one thread at a time and under a global lock. + - Call `Workflow.sleep` instead of `Thread.sleep`. + - Use `Promise` and `CompletablePromise` instead of `Future` and `CompletableFuture`. + - Use `WorkflowQueue` instead of `BlockingQueue`. +- Use `Workflow.getVersion` when making any changes to the Workflow code. + Without this, any deployment of updated Workflow code might break already running Workflows. +- Do not access configuration APIs directly from a Workflow because changes in the configuration might affect a Workflow Execution path. + Pass it as an argument to a Workflow function or use an Activity to load it. +- Use `DynamicWorkflow` when you need a default Workflow that can handle all Workflow Types that are not registered with a Worker. + A single implementation can implement a Workflow Type which by definition is dynamically loaded from some external source. + All standard `WorkflowOptions` and determinism rules apply to Dynamic Workflow implementations. + +Java Workflow reference: [https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/workflow/package-summary.html](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/workflow/package-summary.html) diff --git a/docs/develop/java/cancellation.mdx b/docs/develop/java/workflows/cancellation.mdx similarity index 100% rename from docs/develop/java/cancellation.mdx rename to docs/develop/java/workflows/cancellation.mdx diff --git a/docs/develop/java/child-workflows.mdx b/docs/develop/java/workflows/child-workflows.mdx similarity index 97% rename from docs/develop/java/child-workflows.mdx rename to docs/develop/java/workflows/child-workflows.mdx index aca3de5d5e..365995f403 100644 --- a/docs/develop/java/child-workflows.mdx +++ b/docs/develop/java/workflows/child-workflows.mdx @@ -20,8 +20,6 @@ This page shows how to do the following: ## Start a Child Workflow Execution {#start-child-workflow} -**How to start a Child Workflow Execution using the Java SDK.** - A [Child Workflow Execution](/child-workflows) is a Workflow Execution that is scheduled from within another Workflow using a Child Workflow API. When using a Child Workflow API, Child Workflow related Events ([StartChildWorkflowExecutionInitiated](/references/events#startchildworkflowexecutioninitiated), [ChildWorkflowExecutionStarted](/references/events#childworkflowexecutionstarted), [ChildWorkflowExecutionCompleted](/references/events#childworkflowexecutioncompleted), etc...) are logged in the Workflow Execution Event History. @@ -142,14 +140,12 @@ The following examples show how to spawn a Child Workflow: Related reads: -- [How to develop a Workflow Definition](/develop/java/core-application#develop-workflows) +- [How to develop a Workflow Definition](/develop/java/workflows/basic-workflow) - Java Workflow reference: [https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/workflow/package-summary.html](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/workflow/package-summary.html) ## Parent Close Policy {#parent-close-policy} -**How to set a Parent Close Policy for a Child Workflow using the Java SDK.** - A [Parent Close Policy](/parent-close-policy) determines what happens to a Child Workflow Execution if its Parent changes to a Closed status (Completed, Failed, or Timed Out). The default Parent Close Policy option is set to terminate the Child Workflow Execution. diff --git a/docs/develop/java/continue-as-new.mdx b/docs/develop/java/workflows/continue-as-new.mdx similarity index 100% rename from docs/develop/java/continue-as-new.mdx rename to docs/develop/java/workflows/continue-as-new.mdx diff --git a/docs/develop/java/enriching-ui.mdx b/docs/develop/java/workflows/enriching-ui.mdx similarity index 100% rename from docs/develop/java/enriching-ui.mdx rename to docs/develop/java/workflows/enriching-ui.mdx diff --git a/docs/develop/java/workflows/index.mdx b/docs/develop/java/workflows/index.mdx new file mode 100644 index 0000000000..4f7e237036 --- /dev/null +++ b/docs/develop/java/workflows/index.mdx @@ -0,0 +1,29 @@ +--- +id: index +title: Workflows - Java SDK +sidebar_label: Nexus +description: This section covers Workflows with the Java SDK +toc_max_heading_level: 4 +keywords: + - Java SDK +tags: + - Java SDK + - Temporal SDKs +--- + +import * as Components from '@site/src/components'; + +![Java SDK Banner](/img/assets/banner-java-temporal.png) + +## Workflows + +- [Basic Workflow](/develop/java/workflows/basic-workflow) +- [Child Workflows](/develop/java/workflows/child-workflows) +- [Continue-As-New](/develop/java/workflows/continue-as-new) +- [Cancellation](/develop/java/workflows/cancellation) +- [Timeouts](/develop/java/workflows/timeouts) +- [Message Passing](/develop/java/workflows/message-passing) +- [Enriching the UI](/develop/java/workflows/enriching-ui) +- [Schedules](/develop/java/workflows/schedules) +- [Side Effects](/develop/java/workflows/side-effects) +- [Timers](/develop/java/workflows/timers) \ No newline at end of file diff --git a/docs/develop/java/message-passing.mdx b/docs/develop/java/workflows/message-passing.mdx similarity index 98% rename from docs/develop/java/message-passing.mdx rename to docs/develop/java/workflows/message-passing.mdx index 12283d556e..62563c9609 100644 --- a/docs/develop/java/message-passing.mdx +++ b/docs/develop/java/workflows/message-passing.mdx @@ -395,7 +395,7 @@ For open source server users, Temporal Server version [Temporal Server version 1 ::: [Update-with-Start](/sending-messages#update-with-start) lets you -[send an Update](/develop/java/message-passing#send-update-from-client) that checks whether an already-running Workflow with that ID exists: +[send an Update](/develop/java/workflows/message-passing#send-update-from-client) that checks whether an already-running Workflow with that ID exists: - If the Workflow exists, the Update is processed. - If the Workflow does not exist, a new Workflow Execution is started with the given ID, and the Update is processed before the main Workflow method starts to execute. @@ -413,7 +413,7 @@ You will need to provide: For example, specifying a Cron Schedule will result in an error. - [`UpdateOptions`](https://javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/UpdateOptions.html). - Same as for [Update Workflow](/develop/java/message-passing#send-update-from-client), the update wait stage must be specified. + Same as for [Update Workflow](/develop/java/workflows/message-passing#send-update-from-client), the update wait stage must be specified. For Update-with-Start, the Workflow Id is optional. When specified, the Id must match the one used in `WorkflowOptions`. Since a running Workflow Execution may not already exist, you can't set a Run Id. @@ -588,8 +588,8 @@ See [Finishing handlers before the Workflow completes](/handling-messages#finish ### Use `@WorkflowInit` to operate on Workflow input before any handler executes Normally, your Workflows constructor won't have any parameters. -However, if you use the `@WorkflowInit` annotation on your constructor, you can give it the same [Workflow parameters](/develop/java/core-application#workflow-parameters) as your `@WorkflowMethod`. -The SDK will then ensure that your constructor receives the Workflow input arguments that the [Client sent](/develop/java/temporal-client#start-workflow-execution). +However, if you use the `@WorkflowInit` annotation on your constructor, you can give it the same [Workflow parameters](/develop/java/workflows/basic-workflow#workflow-parameters) as your `@WorkflowMethod`. +The SDK will then ensure that your constructor receives the Workflow input arguments that the [Client sent](/develop/java/client/temporal-client#start-workflow-execution). The Workflow input arguments are also passed to your `@WorkflowMethod` method -- that always happens, whether or not you use the `@WorkflowInit` annotation. This is useful if you have message handlers that need access to Workflow input: see [Initializing the Workflow first](/handling-messages#workflow-initializers). diff --git a/docs/develop/java/schedules.mdx b/docs/develop/java/workflows/schedules.mdx similarity index 99% rename from docs/develop/java/schedules.mdx rename to docs/develop/java/workflows/schedules.mdx index 53b91d617d..8d5e80f55e 100644 --- a/docs/develop/java/schedules.mdx +++ b/docs/develop/java/workflows/schedules.mdx @@ -2,7 +2,7 @@ id: schedules title: Schedules - Java SDK sidebar_label: Schedules -slug: /develop/java/schedules +slug: /develop/java/workflows/schedules toc_max_heading_level: 2 keywords: - schedules diff --git a/docs/develop/java/side-effects.mdx b/docs/develop/java/workflows/side-effects.mdx similarity index 98% rename from docs/develop/java/side-effects.mdx rename to docs/develop/java/workflows/side-effects.mdx index 37db23e9a2..cb8e8dac20 100644 --- a/docs/develop/java/side-effects.mdx +++ b/docs/develop/java/workflows/side-effects.mdx @@ -2,7 +2,7 @@ id: side-effects title: Side Effects - Java SDK sidebar_label: Side Effects -slug: /develop/java/side-effects +slug: /develop/java/workflows/side-effects toc_max_heading_level: 2 keywords: - side-effects diff --git a/docs/develop/java/workflows/timeouts.mdx b/docs/develop/java/workflows/timeouts.mdx new file mode 100644 index 0000000000..2339879fd6 --- /dev/null +++ b/docs/develop/java/workflows/timeouts.mdx @@ -0,0 +1,83 @@ +--- +id: timeouts +title: Workflow Timeouts - Java SDK +sidebar_label: Timeouts +description: Optimize Workflow Execution with Temporal Java SDK - Set Workflow Timeouts and Retry Policies efficiently. +toc_max_heading_level: 4 +keywords: + - Java + - failure detection + - timeouts +tags: + - Activities + - Workflows + - Errors + - Failures + - Java SDK + - Temporal SDKs +--- + +## Workflow timeouts {#workflow-timeouts} + +Each Workflow timeout controls the maximum duration of a different aspect of a Workflow Execution. + +Workflow timeouts are set when [starting the Workflow Execution](#workflow-timeouts). + +Before we continue, we want to note that we generally do not recommend setting Workflow Timeouts, because Workflows are designed to be long-running and resilient. +Instead, setting a Timeout can limit its ability to handle unexpected delays or long-running processes. +If you need to perform an action inside your Workflow after a specific period of time, we recommend using a Timer. + +- **[Workflow Execution Timeout](/encyclopedia/detecting-workflow-failures#workflow-execution-timeout)** - restricts the maximum amount of time that a single Workflow Execution can be executed. +- **[Workflow Run Timeout](/encyclopedia/detecting-workflow-failures#workflow-run-timeout):** restricts the maximum amount of time that a single Workflow Run can last. +- **[Workflow Task Timeout](/encyclopedia/detecting-workflow-failures#workflow-task-timeout):** restricts the maximum amount of time that a Worker can execute a Workflow Task. + +Create an instance of [`WorkflowStub`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowStub.html) in the Client code and set your timeout. + +Available timeouts are: + +- [setWorkflowExecutionTimeout()](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html#setWorkflowExecutionTimeout(java.time.Duration)) +- [setWorkflowRunTimeout()](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html#setWorkflowRunTimeout(java.time.Duration)) +- [setWorkflowTaskTimeout()](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html#setWorkflowTaskTimeout(java.time.Duration)) + +```java +//create Workflow stub for YourWorkflowInterface +YourWorkflowInterface workflow1 = + WorkerGreet.greetclient.newWorkflowStub( + GreetWorkflowInterface.class, + WorkflowOptions.newBuilder() + .setWorkflowId("YourWorkflow") + .setTaskQueue(WorkerGreet.TASK_QUEUE) + // Set Workflow Timeout duration + .setWorkflowExecutionTimeout(Duration.ofSeconds(10)) + // .setWorkflowRunTimeout(Duration.ofSeconds(10)) + // .setWorkflowTaskTimeout(Duration.ofSeconds(10)) + .build()); +``` + +## Workflow Retry Policy {#workflow-retries} + +**How to set a Workflow Retry Policy in Java.** + +A Retry Policy can work in cooperation with the timeouts to provide fine controls to optimize the execution experience. + +Use a [Retry Policy](/encyclopedia/retry-policies) to retry a Workflow Execution in the event of a failure. + +Workflow Executions do not retry by default, and Retry Policies should be used with Workflow Executions only in certain situations. + +To set a 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.setWorkflowRetryOptions`](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/io/temporal/client/WorkflowOptions.Builder.html). + +- Type: `RetryOptions` +- Default: `Null` which means no retries will be attempted. + +```java +//create Workflow stub for GreetWorkflowInterface +GreetWorkflowInterface workflow1 = + WorkerGreet.greetclient.newWorkflowStub( + GreetWorkflowInterface.class, + WorkflowOptions.newBuilder() + .setWorkflowId("GreetWF") + .setTaskQueue(WorkerGreet.TASK_QUEUE) + // Set Workflow Retry Options + .setRetryOptions(RetryOptions.newBuilder() + .build()); +``` \ No newline at end of file diff --git a/docs/develop/java/timers.mdx b/docs/develop/java/workflows/timers.mdx similarity index 96% rename from docs/develop/java/timers.mdx rename to docs/develop/java/workflows/timers.mdx index 9898061bbf..08f5d7bf82 100644 --- a/docs/develop/java/timers.mdx +++ b/docs/develop/java/workflows/timers.mdx @@ -2,7 +2,7 @@ id: timers title: Durable Timers - Java SDK sidebar_label: Durable Timers -slug: /develop/java/timers +slug: /develop/java/workflows/timers toc_max_heading_level: 2 keywords: - timers diff --git a/docs/develop/java/versioning.mdx b/docs/develop/java/workflows/versioning.mdx similarity index 99% rename from docs/develop/java/versioning.mdx rename to docs/develop/java/workflows/versioning.mdx index 721701e0cd..57fd597b7a 100644 --- a/docs/develop/java/versioning.mdx +++ b/docs/develop/java/workflows/versioning.mdx @@ -246,4 +246,4 @@ This method also does not provide a way to version any still-running Workflows - ### Testing a Workflow for replay safety -To determine whether your Workflow your needs a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/java/testing-suite#replay). +To determine whether your Workflow your needs a patch, or that you've patched it successfully, you should incorporate [Replay Testing](/develop/java/best-practices/testing-suite#replay). diff --git a/docs/encyclopedia/activities/activity-definition.mdx b/docs/encyclopedia/activities/activity-definition.mdx index 5acbfba998..a71e110ab1 100644 --- a/docs/encyclopedia/activities/activity-definition.mdx +++ b/docs/encyclopedia/activities/activity-definition.mdx @@ -34,7 +34,7 @@ An Activity Definition is the code that defines the constraints of an [Activity Activities encapsulate business logic that is prone to failure, allowing for automatic retries when issues occur. - [How to develop an Activity Definition using the Go SDK](/develop/go/core-application#activity-definition) -- [How to develop an Activity Definition using the Java SDK](/develop/java/core-application#develop-activities) +- [How to develop an Activity Definition using the Java SDK](/develop/java/activities/basic-activity) - [How to develop an Activity Definition using the PHP SDK](/develop/php/core-application#develop-activities) - [How to develop an Activity Definition using the Python SDK](/develop/python/core-application#develop-activities) - [How to develop an Activity Definition using the TypeScript SDK](/develop/typescript/core-application#develop-activities) diff --git a/docs/encyclopedia/activities/activity-execution.mdx b/docs/encyclopedia/activities/activity-execution.mdx index 5696d66a19..8e22aba100 100644 --- a/docs/encyclopedia/activities/activity-execution.mdx +++ b/docs/encyclopedia/activities/activity-execution.mdx @@ -32,7 +32,7 @@ An Activity Execution is the full chain of [Activity Task Executions](/tasks#act :::info - [How to start an Activity Execution using the Go SDK](/develop/go/core-application#activity-execution) -- [How to start an Activity Execution using the Java SDK](/develop/java/core-application#activity-execution) +- [How to start an Activity Execution using the Java SDK](/develop/java/activities/execution) - [How to start an Activity Execution using the PHP SDK](/develop/php/core-application#activity-execution) - [How to start an Activity Execution using the Python SDK](/develop/python/core-application#activity-execution) - [How to start an Activity Execution using the TypeScript SDK](/develop/typescript/core-application#activity-execution) @@ -122,7 +122,7 @@ and eventually complete the Activity Execution and provide a result. How to complete an Activity Asynchronously in: - [Go](/develop/go/asynchronous-activity-completion) -- [Java](/develop/java/asynchronous-activity-completion) +- [Java](/develop/java/activities/asynchronous-activity-completion) - [PHP](/develop/php/asynchronous-activity-completion) - [Python](/develop/python/asynchronous-activity-completion) - [TypeScript](/develop/typescript/asynchronous-activity-completion) diff --git a/docs/encyclopedia/child-workflows/child-workflows.mdx b/docs/encyclopedia/child-workflows/child-workflows.mdx index c6881a77ee..3bdd88774f 100644 --- a/docs/encyclopedia/child-workflows/child-workflows.mdx +++ b/docs/encyclopedia/child-workflows/child-workflows.mdx @@ -31,7 +31,7 @@ import { CaptionedImage } from '@site/src/components'; A Child Workflow Execution is a [Workflow Execution](/workflow-execution) that is spawned from within another Workflow in the same Namespace. - [Go SDK Child Workflow feature guide](/develop/go/child-workflows) -- [Java SDK Child Workflow feature guide](/develop/java/child-workflows) +- [Java SDK Child Workflow feature guide](/develop/java/workflows/child-workflows) - [PHP SDK Child Workflow feature guide](/develop/php/child-workflows) - [Python SDK Child Workflow feature guide](/develop/python/child-workflows) - [TypeScript SDK Child Workflow feature guide](/develop/typescript/child-workflows) diff --git a/docs/encyclopedia/child-workflows/parent-close-policy.mdx b/docs/encyclopedia/child-workflows/parent-close-policy.mdx index 8f75186071..dfe02f3537 100644 --- a/docs/encyclopedia/child-workflows/parent-close-policy.mdx +++ b/docs/encyclopedia/child-workflows/parent-close-policy.mdx @@ -36,7 +36,7 @@ This page discusses [Parent Close Policy](#parent-close-policy). A Parent Close Policy determines what happens to a Child Workflow Execution if its Parent changes to a Closed status (Completed, Failed, or Timed out). - [How to set a Parent Close Policy using the Go SDK](/develop/go/child-workflows#parent-close-policy) -- [How to set a Parent Close Policy using the Java SDK](/develop/java/child-workflows#parent-close-policy) +- [How to set a Parent Close Policy using the Java SDK](/develop/java/workflows/child-workflows#parent-close-policy) - [How to set a Parent Close Policy using the PHP SDK](/develop/php/child-workflows#parent-close-policy) - [How to set a Parent Close Policy using the Python SDK](/develop/python/child-workflows#parent-close-policy) - [How to set a Parent Close Policy using the TypeScript SDK](/develop/typescript/child-workflows#parent-close-policy) diff --git a/docs/encyclopedia/detecting-activity-failures.mdx b/docs/encyclopedia/detecting-activity-failures.mdx index 9a2355d719..48acc7b79b 100644 --- a/docs/encyclopedia/detecting-activity-failures.mdx +++ b/docs/encyclopedia/detecting-activity-failures.mdx @@ -33,7 +33,7 @@ In other words, it's a limit for how long an Activity Task can be enqueued. - + @@ -80,7 +80,7 @@ A Start-To-Close Timeout is the maximum time allowed for a single [Activity Task - + @@ -132,7 +132,7 @@ A Schedule-To-Close Timeout is the maximum amount of time allowed for the overal - + @@ -172,7 +172,7 @@ Each ping informs the Temporal Service that the Activity Execution is making pro - + @@ -254,7 +254,7 @@ A Heartbeat Timeout is the maximum time between [Activity Heartbeats](#activity- - + diff --git a/docs/encyclopedia/detecting-workflow-failures.mdx b/docs/encyclopedia/detecting-workflow-failures.mdx index 0bd8267c03..fdeafe6b65 100644 --- a/docs/encyclopedia/detecting-workflow-failures.mdx +++ b/docs/encyclopedia/detecting-workflow-failures.mdx @@ -35,7 +35,7 @@ A Workflow Execution Timeout is the maximum time that a Workflow Execution can b - + @@ -63,7 +63,7 @@ A Workflow Run Timeout restricts the maximum duration of a single Workflow Run. - + @@ -89,7 +89,7 @@ This Timeout is primarily available to recognize whether a Worker has gone down - + diff --git a/docs/encyclopedia/retry-policies.mdx b/docs/encyclopedia/retry-policies.mdx index ae019e3559..ee9ca8f980 100644 --- a/docs/encyclopedia/retry-policies.mdx +++ b/docs/encyclopedia/retry-policies.mdx @@ -52,7 +52,7 @@ Try out the [Activity retry simulator](/develop/activity-retry-simulator) to vis archetype="feature-guide" /> @@ -82,7 +82,7 @@ Try out the [Activity retry simulator](/develop/activity-retry-simulator) to vis archetype="feature-guide" /> @@ -384,7 +384,7 @@ timeouts. For an Activity, its Schedule-to-Close Timeout applies. For a Workflow diff --git a/docs/encyclopedia/temporal-sdks.mdx b/docs/encyclopedia/temporal-sdks.mdx index 36bef5eaa7..2a3446aeba 100644 --- a/docs/encyclopedia/temporal-sdks.mdx +++ b/docs/encyclopedia/temporal-sdks.mdx @@ -182,7 +182,7 @@ The following code is for example purposes only. For tested code samples and best practices, use your preferred language SDK's developer's guide. - [Go SDK Temporal Client feature guide](/develop/go/temporal-client) -- [Java SDK Temporal Client feature guide](/develop/java/temporal-client) +- [Java SDK Temporal Client feature guide](/develop/java/client/temporal-client) - [PHP SDK Temporal Client feature guide](/develop/php/temporal-client) - [Python SDK Temporal Client feature guide](/develop/python/temporal-client) - [TypeScript SDK Temporal Client feature guide](/develop/typescript/core-application) diff --git a/docs/encyclopedia/temporal-service/temporal-server.mdx b/docs/encyclopedia/temporal-service/temporal-server.mdx index 541d0be8f6..5871d5f60e 100644 --- a/docs/encyclopedia/temporal-service/temporal-server.mdx +++ b/docs/encyclopedia/temporal-service/temporal-server.mdx @@ -209,7 +209,7 @@ Retention Period is the duration for which the Temporal Service stores data asso - [How to set the Retention Period for a Namespace](/cli/operator#create) - [How to set the Retention Period for a Namespace using the Go SDK](/develop/go/namespaces) -- [How to set the Retention Period for a Namespace using the Java SDK](/develop/java/namespaces) +- [How to set the Retention Period for a Namespace using the Java SDK](/develop/java/client/namespaces) A Retention Period applies to all closed Workflow Executions within a [Namespace](/namespaces) and is set when the Namespace is registered. diff --git a/docs/encyclopedia/visibility/search-attributes.mdx b/docs/encyclopedia/visibility/search-attributes.mdx index 264027c984..ec9fe43c9d 100644 --- a/docs/encyclopedia/visibility/search-attributes.mdx +++ b/docs/encyclopedia/visibility/search-attributes.mdx @@ -214,7 +214,7 @@ With Workflows you can do the following: :::info Manage Search Attributes by SDK - [How to manage Search Attributes using the Go SDK](/develop/go/observability#visibility) -- [How to manage Search Attributes using the Java SDK](/develop/java/observability#visibility) +- [How to manage Search Attributes using the Java SDK](/develop/java/workers/observability#visibility) - [How to manage Search Attributes using the PHP SDK](/develop/php/observability#visibility) - [How to manage Search Attributes using the Python SDK](/develop/python/observability#visibility) - [How to manage Search Attributes using the TypeScript SDK](/develop/typescript/observability#visibility) diff --git a/docs/encyclopedia/workers/task-queues.mdx b/docs/encyclopedia/workers/task-queues.mdx index f68072c482..4c3064ab9d 100644 --- a/docs/encyclopedia/workers/task-queues.mdx +++ b/docs/encyclopedia/workers/task-queues.mdx @@ -80,7 +80,7 @@ There are five places where the name of the Task Queue can be set by the develop - [How to start a Workflow Execution using the Temporal CLI](/cli/workflow#start) - [How to start a Workflow Execution using the Go SDK](/develop/go/temporal-client#start-workflow-execution) - - [How to start a Workflow Execution using the Java SDK](/develop/java/temporal-client#start-workflow-execution) + - [How to start a Workflow Execution using the Java SDK](/develop/java/client/temporal-client#start-workflow-execution) - [How to start a Workflow Execution using the PHP SDK](/develop/php/temporal-client#start-workflow-execution) - [How to start a Workflow Execution using the Python SDK](/develop/python/temporal-client#start-workflow-execution) - [How to start a Workflow Execution using the TypeScript SDK](/develop/typescript/temporal-client#start-workflow-execution) @@ -89,7 +89,7 @@ There are five places where the name of the Task Queue can be set by the develop 2. A Task Queue name must be set when creating a Worker Entity and when running a Worker Process: - [How to run a development Worker using the Go SDK](/develop/go/core-application#develop-worker) - - [How to run a development Worker using the Java SDK](/develop/java/core-application#run-a-dev-worker) + - [How to run a development Worker using the Java SDK](/develop/java/workers/run-worker-process) - [How to run a development Worker using the PHP SDK](/develop/php/core-application#run-a-dev-worker) - [How to run a development Worker using the Python SDK](/develop/python/core-application#run-a-dev-worker) - [How to run a development Worker using the TypeScript SDK](/develop/typescript/core-application#run-a-dev-worker) @@ -108,7 +108,7 @@ There are five places where the name of the Task Queue can be set by the develop An Activity Execution inherits the Task Queue name from its Workflow Execution if one is not provided. - [How to start an Activity Execution using the Go SDK](/develop/go/core-application#activity-execution) - - [How to start an Activity Execution using the Java SDK](/develop/java/core-application#activity-execution) + - [How to start an Activity Execution using the Java SDK](/develop/java/activities/execution) - [How to start an Activity Execution using the PHP SDK](/develop/php/core-application#activity-execution) - [How to start an Activity Execution using the Python SDK](/develop/python/core-application#activity-execution) - [How to start an Activity Execution using the TypeScript SDK](/develop/typescript/core-application#activity-execution) @@ -120,7 +120,7 @@ There are five places where the name of the Task Queue can be set by the develop A Child Workflow Execution inherits the Task Queue name from its Parent Workflow Execution if one is not provided. - [How to start a Child Workflow Execution using the Go SDK](/develop/go/child-workflows) - - [How to start a Child Workflow Execution using the Java SDK](/develop/java/child-workflows) + - [How to start a Child Workflow Execution using the Java SDK](/develop/java/workflows/child-workflows) - [How to start a Child Workflow Execution using the PHP SDK](/develop/php/continue-as-new) - [How to start a Child Workflow Execution using the Python SDK](/develop/python/child-workflows) - [How to start a Child Workflow Execution using the TypeScript SDK](/develop/typescript/child-workflows) diff --git a/docs/encyclopedia/workers/workers.mdx b/docs/encyclopedia/workers/workers.mdx index 72d4529bd8..5b1cb09031 100644 --- a/docs/encyclopedia/workers/workers.mdx +++ b/docs/encyclopedia/workers/workers.mdx @@ -35,7 +35,7 @@ A Worker Program is the static code that defines the constraints of the Worker P :::info - [How to run a development Worker using the Go SDK](/develop/go/core-application#develop-worker) -- [How to run a development Worker using the Java SDK](/develop/java/core-application#run-a-dev-worker) +- [How to run a development Worker using the Java SDK](/develop/java/workers/run-worker-process) - [How to run a development Worker using the PHP SDK](/develop/php/core-application#run-a-dev-worker) - [How to run a development Worker using the Python SDK](/develop/python/core-application#run-a-dev-worker) - [How to run a development Worker using the TypeScript SDK](/develop/typescript/core-application#run-a-dev-worker) diff --git a/docs/encyclopedia/workflow-message-passing/handling-messages.mdx b/docs/encyclopedia/workflow-message-passing/handling-messages.mdx index 5987ce4675..893bbc565e 100644 --- a/docs/encyclopedia/workflow-message-passing/handling-messages.mdx +++ b/docs/encyclopedia/workflow-message-passing/handling-messages.mdx @@ -130,7 +130,7 @@ See examples of the above patterns. - + @@ -153,7 +153,7 @@ Once the Update handler is finished and has returned a value, the operation is c - + @@ -197,7 +197,7 @@ Use these links to see a simple Signal handler. - + @@ -210,7 +210,7 @@ Use these links to see a simple update handler. - + @@ -223,7 +223,7 @@ Author queries using these per-language guides. - + diff --git a/docs/encyclopedia/workflow-message-passing/sending-messages.mdx b/docs/encyclopedia/workflow-message-passing/sending-messages.mdx index 70deb90c48..3f43bd35a2 100644 --- a/docs/encyclopedia/workflow-message-passing/sending-messages.mdx +++ b/docs/encyclopedia/workflow-message-passing/sending-messages.mdx @@ -49,7 +49,7 @@ You can also Signal-With-Start to lazily initialize a Workflow while sending a S - + @@ -60,7 +60,7 @@ You can also Signal-With-Start to lazily initialize a Workflow while sending a S - + @@ -73,7 +73,7 @@ Signal-With-Start is a great tool for lazily initializing Workflows. When you se - + @@ -115,7 +115,7 @@ Use [Update Validators](/handling-messages#update-validators) and [Update IDs](/ - + @@ -163,7 +163,7 @@ The SDKs will retry the Update-With-Start request, but there is no guarantee tha - + @@ -178,7 +178,7 @@ You can also send a built-in "Stack Trace Query" for debugging. - + diff --git a/docs/encyclopedia/workflow/cron-job.mdx b/docs/encyclopedia/workflow/cron-job.mdx index 241f08596e..4857decd12 100644 --- a/docs/encyclopedia/workflow/cron-job.mdx +++ b/docs/encyclopedia/workflow/cron-job.mdx @@ -29,7 +29,7 @@ Schedules were built to provide a better developer experience, including more co A Temporal Cron Job is the series of Workflow Executions that occur when a Cron Schedule is provided in the call to spawn a Workflow Execution. - [How to set a Cron Schedule using the Go SDK](/develop/go/schedules#temporal-cron-jobs) -- [How to set a Cron Schedule using the Java SDK](/develop/java/schedules#cron-schedule) +- [How to set a Cron Schedule using the Java SDK](/develop/java/workflows/schedules#cron-schedule) - [How to set a Cron Schedule using the PHP SDK](/develop/php/schedules#temporal-cron-jobs) - [How to set a Cron Schedule using the Python SDK](/develop/python/schedules#temporal-cron-jobs) - [How to set a Cron Schedule using the TypeScript SDK](/develop/typescript/schedules#temporal-cron-jobs) diff --git a/docs/encyclopedia/workflow/dynamic-handler.mdx b/docs/encyclopedia/workflow/dynamic-handler.mdx index f5bb536da1..d1cc56ee44 100644 --- a/docs/encyclopedia/workflow/dynamic-handler.mdx +++ b/docs/encyclopedia/workflow/dynamic-handler.mdx @@ -23,7 +23,7 @@ Temporal supports Dynamic Workflows, Activities, Signals, and Queries. Currently, the Temporal SDKs that support Dynamic Handlers are: -- [Java](/develop/java/message-passing#dynamic-handler) +- [Java](/develop/java/workflows/message-passing#dynamic-handler) - [Python](/develop/python/message-passing#dynamic-handler) - [.NET](/develop/dotnet/message-passing#dynamic-handler) - [Go](/develop/go/core-application#set-a-dynamic-workflow) diff --git a/docs/encyclopedia/workflow/workflow-definition.mdx b/docs/encyclopedia/workflow/workflow-definition.mdx index 51f31e89ad..ccb00f8a00 100644 --- a/docs/encyclopedia/workflow/workflow-definition.mdx +++ b/docs/encyclopedia/workflow/workflow-definition.mdx @@ -55,7 +55,7 @@ func YourBasicWorkflow(ctx workflow.Context) error { -**[Workflow Definition in Java (Interface)](/develop/java/core-application#develop-workflows)** +**[Workflow Definition in Java (Interface)](/develop/java/workflows/basic-workflow)** ```java // Workflow interface @@ -67,7 +67,7 @@ public interface YourBasicWorkflow { } ``` -**[Workflow Definition in Java (Implementation)](/develop/java/core-application#develop-workflows)** +**[Workflow Definition in Java (Implementation)](/develop/java/workflows/basic-workflow)** ```java // Workflow implementation diff --git a/docs/encyclopedia/workflow/workflow-execution/continue-as-new.mdx b/docs/encyclopedia/workflow/workflow-execution/continue-as-new.mdx index 9ef1ff61e4..1ac37b4ec8 100644 --- a/docs/encyclopedia/workflow/workflow-execution/continue-as-new.mdx +++ b/docs/encyclopedia/workflow/workflow-execution/continue-as-new.mdx @@ -37,7 +37,7 @@ You can repeat Continue-As-New as often as needed, which means that your Workflo Workflows that do this are often called Entity Workflows because they represent durable objects, not just processes. - [How to Continue-As-New using the Go SDK](/develop/go/continue-as-new#how) -- [How to Continue-As-New using the Java SDK](/develop/java/continue-as-new) +- [How to Continue-As-New using the Java SDK](/develop/java/workflows/continue-as-new) - [How to Continue-As-New using the PHP SDK](/develop/php/continue-as-new) - [How to Continue-As-New using the Python SDK](/develop/python/continue-as-new#how) - [How to Continue-As-New using the TypeScript SDK](/develop/typescript/continue-as-new) @@ -51,7 +51,7 @@ Find out if it's time by checking Continue-As-New Suggested in your Workflow at To prevent long-running Workflows from running on stale versions of code, you may also want to Continue-as-New periodically, depending on how often you deploy. This makes sure you're running only a couple of versions, which avoids some backwards compatibility problems. - [Determine when to Continue-As-New using the Go SDK](/develop/go/continue-as-new#when) -- [Determine when to Continue-As-New using the Java SDK](/develop/java/continue-as-new) +- [Determine when to Continue-As-New using the Java SDK](/develop/java/workflows/continue-as-new) - [Determine when to Continue-As-New using the PHP SDK](/develop/php/continue-as-new) - [Determine when to Continue-As-New using the Python SDK](/develop/python/continue-as-new#when) - [Determine when to Continue-As-New using the TypeScript SDK](/develop/typescript/continue-as-new) diff --git a/docs/encyclopedia/workflow/workflow-execution/timers-delays.mdx b/docs/encyclopedia/workflow/workflow-execution/timers-delays.mdx index 2da07e0453..2e3c507fb4 100644 --- a/docs/encyclopedia/workflow/workflow-execution/timers-delays.mdx +++ b/docs/encyclopedia/workflow/workflow-execution/timers-delays.mdx @@ -24,7 +24,7 @@ Timers are reliable and efficient. Workers consume no additional resources while waiting for a Timer to fire, so a single Worker can await millions of Timers concurrently. - [How to set Timers in Go](/develop/go/timers) -- [How to set Timers in Java](/develop/java/timers) +- [How to set Timers in Java](/develop/java/workflows/timers) - [How to set Timers in PHP](/develop/php/timers) - [How to set Timers in Python](/develop/python/timers) - [How to set Timers in TypeScript](/develop/typescript/timers) diff --git a/docs/encyclopedia/workflow/workflow-execution/workflow-execution.mdx b/docs/encyclopedia/workflow/workflow-execution/workflow-execution.mdx index 6c334226b4..142cdd09bb 100644 --- a/docs/encyclopedia/workflow/workflow-execution/workflow-execution.mdx +++ b/docs/encyclopedia/workflow/workflow-execution/workflow-execution.mdx @@ -34,7 +34,7 @@ It is the main unit of execution of a [Temporal Application](/temporal#temporal- - [How to start a Workflow Execution using temporal](/cli/workflow#start) - [How to start a Workflow Execution using the Go SDK](/develop/go/temporal-client#start-workflow-execution) -- [How to start a Workflow Execution using the Java SDK](/develop/java/temporal-client#start-workflow-execution) +- [How to start a Workflow Execution using the Java SDK](/develop/java/client/temporal-client#start-workflow-execution) - [How to start a Workflow Execution using the PHP SDK](/develop/php/temporal-client#start-workflow-execution) - [How to start a Workflow Execution using the Python SDK](/develop/python/temporal-client#start-workflow-execution) - [How to start a Workflow Execution using the TypeScript SDK](/develop/typescript/temporal-client#start-workflow-execution) @@ -73,7 +73,7 @@ For more information, see [Deterministic constraints](/workflow-definition#deter If a failure occurs, the Workflow Execution picks up where the last recorded event occurred in the Event History. - [How to use Replay APIs using the Go SDK](/develop/go/testing-suite#replay) -- [How to use Replay APIs using the Java SDK](/develop/java/testing-suite#replay) +- [How to use Replay APIs using the Java SDK](/develop/java/best-practices/testing-suite#replay) - [How to use Replay APIs using the Python SDK](/develop/python/testing-suite#replay) - [How to use Replay APIs using the TypeScript SDK](/develop/typescript/testing-suite#replay) - [How to use Replay APIs using the .NET SDK](/develop/dotnet/testing-suite#replay) diff --git a/docs/evaluate/development-production-features/core-application.mdx b/docs/evaluate/development-production-features/core-application.mdx index 632c860040..e06f439c2c 100644 --- a/docs/evaluate/development-production-features/core-application.mdx +++ b/docs/evaluate/development-production-features/core-application.mdx @@ -46,7 +46,7 @@ Or jump straight to a Temporal SDK feature guide: - + diff --git a/docs/evaluate/development-production-features/data-encryption.mdx b/docs/evaluate/development-production-features/data-encryption.mdx index 7047f311dd..2c98f6e57f 100644 --- a/docs/evaluate/development-production-features/data-encryption.mdx +++ b/docs/evaluate/development-production-features/data-encryption.mdx @@ -30,7 +30,7 @@ Jump straight to a Temporal SDK feature guide. - + diff --git a/docs/evaluate/development-production-features/debugging.mdx b/docs/evaluate/development-production-features/debugging.mdx index ad6beaebd7..ee3b7d664f 100644 --- a/docs/evaluate/development-production-features/debugging.mdx +++ b/docs/evaluate/development-production-features/debugging.mdx @@ -34,7 +34,7 @@ Jump straight to a Temporal SDK feature guide. - + diff --git a/docs/evaluate/development-production-features/failure-detection.mdx b/docs/evaluate/development-production-features/failure-detection.mdx index 9ed8340540..b46a0f108b 100644 --- a/docs/evaluate/development-production-features/failure-detection.mdx +++ b/docs/evaluate/development-production-features/failure-detection.mdx @@ -42,7 +42,7 @@ Or jump straight to a Temporal SDK feature guide. - + @@ -52,7 +52,7 @@ Or jump straight to a Temporal SDK feature guide. - + diff --git a/docs/evaluate/development-production-features/interrupt-a-workflow.mdx b/docs/evaluate/development-production-features/interrupt-a-workflow.mdx index 3732d4e353..46707b3393 100644 --- a/docs/evaluate/development-production-features/interrupt-a-workflow.mdx +++ b/docs/evaluate/development-production-features/interrupt-a-workflow.mdx @@ -40,7 +40,7 @@ robust and responsive. archetype="feature-guide" /> diff --git a/docs/evaluate/development-production-features/observability.mdx b/docs/evaluate/development-production-features/observability.mdx index e781938868..2364bd184b 100644 --- a/docs/evaluate/development-production-features/observability.mdx +++ b/docs/evaluate/development-production-features/observability.mdx @@ -53,7 +53,7 @@ Jump straight into the Temporal SDK feature guide. - + diff --git a/docs/evaluate/development-production-features/schedules.mdx b/docs/evaluate/development-production-features/schedules.mdx index 5a0955cd33..1a2de67145 100644 --- a/docs/evaluate/development-production-features/schedules.mdx +++ b/docs/evaluate/development-production-features/schedules.mdx @@ -37,7 +37,7 @@ Jump straight to a Temporal SDK feature guide. - + diff --git a/docs/evaluate/development-production-features/testing-suite.mdx b/docs/evaluate/development-production-features/testing-suite.mdx index f3f8b0cd2e..9b880efc1c 100644 --- a/docs/evaluate/development-production-features/testing-suite.mdx +++ b/docs/evaluate/development-production-features/testing-suite.mdx @@ -38,7 +38,7 @@ Jump straight to a Temporal SDK feature guide. - + diff --git a/docs/evaluate/development-production-features/throughput-composability.mdx b/docs/evaluate/development-production-features/throughput-composability.mdx index 1c11f5d923..019e26dbfa 100644 --- a/docs/evaluate/development-production-features/throughput-composability.mdx +++ b/docs/evaluate/development-production-features/throughput-composability.mdx @@ -33,7 +33,7 @@ See the SDK feature guides for implementation details: - + diff --git a/docs/evaluate/development-production-features/workflow-message-passing.mdx b/docs/evaluate/development-production-features/workflow-message-passing.mdx index 5220949f8d..dd3fcdf056 100644 --- a/docs/evaluate/development-production-features/workflow-message-passing.mdx +++ b/docs/evaluate/development-production-features/workflow-message-passing.mdx @@ -54,7 +54,7 @@ If you want to jump to straight to implementation details, see the SDK feature g - + diff --git a/docs/production-deployment/self-hosted-guide/monitoring.mdx b/docs/production-deployment/self-hosted-guide/monitoring.mdx index cb1e4b978f..b84d12c92b 100644 --- a/docs/production-deployment/self-hosted-guide/monitoring.mdx +++ b/docs/production-deployment/self-hosted-guide/monitoring.mdx @@ -94,7 +94,7 @@ SDK metrics are emitted by Temporal Workers and other Clients, and must be confi The Metrics section in the Observability guide details how to create hooks for all supported SDKs: - [Go](/develop/go/observability#metrics) -- [Java](/develop/java/observability#metrics) +- [Java](/develop/java/workers/observability#metrics) - [PHP](/develop/php/observability) - [Python](/develop/python/observability#metrics) - [TypeScript](/develop/typescript/observability#metrics) diff --git a/docs/production-deployment/self-hosted-guide/namespaces.mdx b/docs/production-deployment/self-hosted-guide/namespaces.mdx index d625f40749..8c26e90f39 100644 --- a/docs/production-deployment/self-hosted-guide/namespaces.mdx +++ b/docs/production-deployment/self-hosted-guide/namespaces.mdx @@ -31,7 +31,7 @@ You can create Namespaces using: - **Temporal CLI** (recommended): [`temporal operator namespace create`](/cli/operator#create) - **Go SDK**: [`RegisterNamespace`](/develop/go/namespaces#register-namespace) -- **Java SDK**: [`RegisterNamespace`](/develop/java/namespaces#register-namespace) +- **Java SDK**: [`RegisterNamespace`](/develop/java/client/namespaces#register-namespace) - **TypeScript SDK**: [Namespace management](/develop/typescript/namespaces#register-namespace) ### The default Namespace @@ -63,7 +63,7 @@ Common namespace management operations: For SDK-based namespace management: - [Go SDK namespace management](/develop/go/namespaces#manage-namespaces) -- [Java SDK namespace management](/develop/java/namespaces#manage-namespaces) +- [Java SDK namespace management](/develop/java/client/namespaces#manage-namespaces) - [TypeScript SDK namespace management](/develop/typescript/namespaces#manage-namespaces) ### Deprecate vs Delete diff --git a/docs/references/failures.mdx b/docs/references/failures.mdx index 0d8e1a5b46..2f3dee7533 100644 --- a/docs/references/failures.mdx +++ b/docs/references/failures.mdx @@ -175,7 +175,7 @@ When a non-retryable error is returned from a Nexus handler, the overall Nexus O By setting the Next Retry Delay for a given Application Failure, you can tell the server to wait that amount of time before trying the Activity or Workflow again. This will override whatever the Retry Policy would have computed for your specific exception. -Java: [NextRetryDelay](/develop/java/failure-detection#activity-next-retry-delay) +Java: [NextRetryDelay](/develop/java/activities/timeouts#activity-next-retry-delay) TypeScript: [nextRetryDelay](/develop/typescript/failure-detection#activity-next-retry-delay) PHP: [NextRetryDelay](/develop/php/failure-detection#activity-next-retry-delay) diff --git a/docs/references/sdk-metrics.mdx b/docs/references/sdk-metrics.mdx index c87792e0fa..b4adbc07b1 100644 --- a/docs/references/sdk-metrics.mdx +++ b/docs/references/sdk-metrics.mdx @@ -28,7 +28,7 @@ Other metrics are considered deprecated, inconsistent or experimental. The Temporal SDKs emit a set of metrics from Temporal Client usage and Worker Processes. - [How to emit metrics using the Go SDK](/develop/go/observability#metrics) -- [How to emit metrics using the Java SDK](/develop/java/observability#metrics) +- [How to emit metrics using the Java SDK](/develop/java/workers/observability#metrics) - [How to emit metrics using the Python SDK](/develop/python/observability#metrics) - [How to emit metrics using the TypeScript SDK](/develop/typescript/observability#metrics) - [How to emit metrics using the .NET SDK](/develop/dotnet/observability#metrics) diff --git a/docs/web-ui.mdx b/docs/web-ui.mdx index aee2192560..515595d916 100644 --- a/docs/web-ui.mdx +++ b/docs/web-ui.mdx @@ -257,7 +257,7 @@ To read more about Schedules, explore these links: - +