From e48d9d98193e50b73d6d00c310682084f358c393 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 2 Aug 2023 15:24:57 -0400 Subject: [PATCH 1/8] scaffold out docs for java sdk Signed-off-by: Hannah Hunter --- .../en/java-sdk-docs/workflow/_index.md | 7 ++ .../java-sdk-docs/workflow/java-workflow.md | 104 ++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 daprdocs/content/en/java-sdk-docs/workflow/_index.md create mode 100644 daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md diff --git a/daprdocs/content/en/java-sdk-docs/workflow/_index.md b/daprdocs/content/en/java-sdk-docs/workflow/_index.md new file mode 100644 index 000000000..b7493ebc4 --- /dev/null +++ b/daprdocs/content/en/java-sdk-docs/workflow/_index.md @@ -0,0 +1,7 @@ +--- +type: docs +title: "Workflow" +linkTitle: "Workflow" +weight: 10000 +description: How to get up and running with the Dapr Workflow extension +--- diff --git a/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md b/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md new file mode 100644 index 000000000..7c75838f1 --- /dev/null +++ b/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md @@ -0,0 +1,104 @@ +--- +type: docs +title: "Getting started with the Dapr Workflow Java SDK" +linkTitle: "Workflow" +weight: 20000 +description: How to get up and running with workflows using the Dapr Java SDK +--- + +{{% alert title="Note" color="primary" %}} +Dapr Workflow is currently in alpha. +{{% /alert %}} + +Let’s create a Dapr workflow and invoke it using the console. With the [provided hello world workflow example](todo), you will: + +- Run a [Java console application using `todo`](todo) +- Utilize the Java workflow SDK and API calls to start, pause, resume, terminate, and purge workflow instances + +This example uses the default configuration from `dapr init` in [self-hosted mode](https://github.com/dapr/cli#install-dapr-on-your-local-machine-self-hosted). + +In the Java example project, the `todo` file contains the setup of the app, including: +- The workflow definition +- The workflow activity definitions +- The registration of the workflow and workflow activities + +## Prerequisites +- [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started). +- Java JDK 11 (or greater): + - [Oracle JDK](https://www.oracle.com/java/technologies/downloads), or + - OpenJDK +- [Apache Maven](https://maven.apache.org/install.html), version 3.x. + +- [Docker Desktop](https://www.docker.com/products/docker-desktop) + +- Verify you're using the latest proto bindings + +## Set up the environment + +Run the following command to install the requirements for running this workflow sample with the Dapr Java SDK. + +```bash +todo +``` + +Clone the Java SDK repo. + +```bash +git clone https://github.com/dapr/java-sdk.git +``` + +From the Java SDK root directory, navigate to the Dapr Workflow example. + +```bash +todo +``` + +## Run the application locally + +To run the Dapr application, you need to start the Java program and a Dapr sidecar. In the terminal, run: + +```bash +todo +``` + + +**Expected output** + +``` +todo +``` + +## What happened? + +When you ran `dapr run`, the Dapr client: +1. Registered the workflow (`todo`) and its actvity (`todo`) +1. Started the workflow engine + +```java +``` + +Dapr then paused and resumed the workflow: + +```java +``` + +Once the workflow resumed, Dapr raised a workflow event and printed the new counter value: + +```java +``` + +To clear out the workflow state from your state store, Dapr purged the workflow: + +```java +``` + +The sample then demonstrated terminating a workflow by: +- Starting a new workflow using the same `instanceId` as the purged workflow. +- Terminating the workflow and purging before shutting down the workflow. + +```java +``` + +## Next steps +- [Learn more about Dapr workflow]({{< ref workflow >}}) +- [Workflow API reference]({{< ref workflow_api.md >}}) \ No newline at end of file From df46d2a227e107e1f886b1034df5a733c8c75c28 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 2 Aug 2023 16:08:20 -0400 Subject: [PATCH 2/8] reformat toc Signed-off-by: Hannah Hunter --- daprdocs/content/en/java-sdk-docs/_index.md | 428 +----------------- .../en/java-sdk-docs/workflow/_index.md | 2 +- 2 files changed, 14 insertions(+), 416 deletions(-) diff --git a/daprdocs/content/en/java-sdk-docs/_index.md b/daprdocs/content/en/java-sdk-docs/_index.md index d387251a6..6d0f557ae 100644 --- a/daprdocs/content/en/java-sdk-docs/_index.md +++ b/daprdocs/content/en/java-sdk-docs/_index.md @@ -24,427 +24,25 @@ cascade: - [Maven 3.x](https://maven.apache.org/install.html) - [Gradle 6.x](https://gradle.org/install/) -## Importing Dapr's Java SDK +## Installation -For a Maven project, add the following to your `pom.xml` file: -```xml - - ... - - ... - - - io.dapr - dapr-sdk - 1.9.0 - - - - io.dapr - dapr-sdk-actors - 1.9.0 - - - - io.dapr - dapr-sdk-springboot - 1.9.0 - - ... - - ... - -``` - -For a Gradle project, add the following to your `build.gradle` file: - -```java -dependencies { -... - // Dapr's core SDK with all features, except Actors. - compile('io.dapr:dapr-sdk:1.9.0') - // Dapr's SDK for Actors (optional). - compile('io.dapr:dapr-sdk-actors:1.9.0') - // Dapr's SDK integration with SpringBoot (optional). - compile('io.dapr:dapr-sdk-springboot:1.9.0') -} -``` - -If you are also using Spring Boot, you may run into a common issue where the OkHttp version that the Dapr SDK uses conflicts with the one specified in the Spring Boot _Bill of Materials_. -You can fix this by specifying a compatible OkHttp version in your project to match the version that the Dapr SDK uses: - -```xml - - com.squareup.okhttp3 - okhttp - 4.9.0 - -``` - -## Building blocks - -The Java SDK allows you to interface with all of the [Dapr building blocks]({{< ref building-blocks >}}). - -### Invoke a service - -```java -import io.dapr.client.DaprClient; -import io.dapr.client.DaprClientBuilder; - -try (DaprClient client = (new DaprClientBuilder()).build()) { - // invoke a 'GET' method (HTTP) skipping serialization: \say with a Mono return type - // for gRPC set HttpExtension.NONE parameters below - response = client.invokeMethod(SERVICE_TO_INVOKE, METHOD_TO_INVOKE, "{\"name\":\"World!\"}", HttpExtension.GET, byte[].class).block(); - - // invoke a 'POST' method (HTTP) skipping serialization: to \say with a Mono return type - response = client.invokeMethod(SERVICE_TO_INVOKE, METHOD_TO_INVOKE, "{\"id\":\"100\", \"FirstName\":\"Value\", \"LastName\":\"Value\"}", HttpExtension.POST, byte[].class).block(); - - System.out.println(new String(response)); - - // invoke a 'POST' method (HTTP) with serialization: \employees with a Mono return type - Employee newEmployee = new Employee("Nigel", "Guitarist"); - Employee employeeResponse = client.invokeMethod(SERVICE_TO_INVOKE, "employees", newEmployee, HttpExtension.POST, Employee.class).block(); -} -``` - -- For a full guide on service invocation visit [How-To: Invoke a service]({{< ref howto-invoke-discover-services.md >}}). -- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/invoke) for code samples and instructions to try out service invocation - -### Save & get application state - -```java -import io.dapr.client.DaprClient; -import io.dapr.client.DaprClientBuilder; -import io.dapr.client.domain.State; -import reactor.core.publisher.Mono; - -try (DaprClient client = (new DaprClientBuilder()).build()) { - // Save state - client.saveState(STATE_STORE_NAME, FIRST_KEY_NAME, myClass).block(); - - // Get state - State retrievedMessage = client.getState(STATE_STORE_NAME, FIRST_KEY_NAME, MyClass.class).block(); +Install the required JDK using [SDKMAN!](https://sdkman.io/): - // Delete state - client.deleteState(STATE_STORE_NAME, FIRST_KEY_NAME).block(); -} +```bash +sdk env install ``` -- For a full list of state operations visit [How-To: Get & save state]({{< ref howto-get-save-state.md >}}). -- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/state) for code samples and instructions to try out state management - -### Publish & subscribe to messages - -##### Publish messages - -```java -import io.dapr.client.DaprClient; -import io.dapr.client.DaprClientBuilder; -import io.dapr.client.domain.Metadata; -import static java.util.Collections.singletonMap; - -try (DaprClient client = (new DaprClientBuilder()).build()) { - client.publishEvent(PUBSUB_NAME, TOPIC_NAME, message, singletonMap(Metadata.TTL_IN_SECONDS, MESSAGE_TTL_IN_SECONDS)).block(); -} -``` - -##### Subscribe to messages - -```java -import com.fasterxml.jackson.databind.ObjectMapper; -import io.dapr.Topic; -import io.dapr.client.domain.BulkSubscribeAppResponse; -import io.dapr.client.domain.BulkSubscribeAppResponseEntry; -import io.dapr.client.domain.BulkSubscribeAppResponseStatus; -import io.dapr.client.domain.BulkSubscribeMessage; -import io.dapr.client.domain.BulkSubscribeMessageEntry; -import io.dapr.client.domain.CloudEvent; -import io.dapr.springboot.annotations.BulkSubscribe; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; -import reactor.core.publisher.Mono; - -@RestController -public class SubscriberController { - - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - @Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}") - @PostMapping(path = "/testingtopic") - public Mono handleMessage(@RequestBody(required = false) CloudEvent cloudEvent) { - return Mono.fromRunnable(() -> { - try { - System.out.println("Subscriber got: " + cloudEvent.getData()); - System.out.println("Subscriber got: " + OBJECT_MAPPER.writeValueAsString(cloudEvent)); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } - - @Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}", - rule = @Rule(match = "event.type == 'myevent.v2'", priority = 1)) - @PostMapping(path = "/testingtopicV2") - public Mono handleMessageV2(@RequestBody(required = false) CloudEvent envelope) { - return Mono.fromRunnable(() -> { - try { - System.out.println("Subscriber got: " + cloudEvent.getData()); - System.out.println("Subscriber got: " + OBJECT_MAPPER.writeValueAsString(cloudEvent)); - } catch (Exception e) { - throw new RuntimeException(e); - } - }); - } - - @BulkSubscribe() - @Topic(name = "testingtopicbulk", pubsubName = "${myAppProperty:messagebus}") - @PostMapping(path = "/testingtopicbulk") - public Mono handleBulkMessage( - @RequestBody(required = false) BulkSubscribeMessage> bulkMessage) { - return Mono.fromCallable(() -> { - if (bulkMessage.getEntries().size() == 0) { - return new BulkSubscribeAppResponse(new ArrayList()); - } - - System.out.println("Bulk Subscriber received " + bulkMessage.getEntries().size() + " messages."); - - List entries = new ArrayList(); - for (BulkSubscribeMessageEntry entry : bulkMessage.getEntries()) { - try { - System.out.printf("Bulk Subscriber message has entry ID: %s\n", entry.getEntryId()); - CloudEvent cloudEvent = (CloudEvent) entry.getEvent(); - System.out.printf("Bulk Subscriber got: %s\n", cloudEvent.getData()); - entries.add(new BulkSubscribeAppResponseEntry(entry.getEntryId(), BulkSubscribeAppResponseStatus.SUCCESS)); - } catch (Exception e) { - e.printStackTrace(); - entries.add(new BulkSubscribeAppResponseEntry(entry.getEntryId(), BulkSubscribeAppResponseStatus.RETRY)); - } - } - return new BulkSubscribeAppResponse(entries); - }); - } -} -``` - -##### Bulk Publish Messages -> Note: API is in Alpha stage - - -```java -import io.dapr.client.DaprClientBuilder; -import io.dapr.client.DaprPreviewClient; -import io.dapr.client.domain.BulkPublishResponse; -import io.dapr.client.domain.BulkPublishResponseFailedEntry; -import java.util.ArrayList; -import java.util.List; -class Solution { - public void publishMessages() { - try (DaprPreviewClient client = (new DaprClientBuilder()).buildPreviewClient()) { - // Create a list of messages to publish - List messages = new ArrayList<>(); - for (int i = 0; i < NUM_MESSAGES; i++) { - String message = String.format("This is message #%d", i); - messages.add(message); - System.out.println("Going to publish message : " + message); - } - - // Publish list of messages using the bulk publish API - BulkPublishResponse res = client.publishEvents(PUBSUB_NAME, TOPIC_NAME, "text/plain", messages).block() - } - } -} -``` +[Next, import the Java SDK packages to get started]({{< ref java-client.md >}}). -- For a full guide on publishing messages and subscribing to a topic [How-To: Publish & subscribe]({{< ref howto-publish-subscribe.md >}}). -- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/pubsub/http) for code samples and instructions to try out pub/sub +## Try it out -### Interact with output bindings +Put the Dapr Java SDK to the test. Walk through the Java quickstarts adn tutorials to see Dapr in action: -```java -import io.dapr.client.DaprClient; -import io.dapr.client.DaprClientBuilder; +| SDK samples | Description | +| ----------- | ----------- | +| [Quickstarts] | Experience Dapr's API building blocks in just a few minutes using the Java SDK. | +| [SDK samples](https://github.com/dapr/java-sdk/tree/master/examples) | Clone the SDK repo to try out some examples and get started. | -try (DaprClient client = (new DaprClientBuilder()).build()) { - // sending a class with message; BINDING_OPERATION="create" - client.invokeBinding(BINDING_NAME, BINDING_OPERATION, myClass).block(); - - // sending a plain string - client.invokeBinding(BINDING_NAME, BINDING_OPERATION, message).block(); -} -``` - -- For a full guide on output bindings visit [How-To: Output bindings]({{< ref howto-bindings.md >}}). -- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/bindings/http) for code samples and instructions to try out output bindings. - -### Interact with input bindings - -```java -import org.springframework.web.bind.annotation.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@RestController -@RequestMapping("/") -public class myClass { - private static final Logger log = LoggerFactory.getLogger(myClass); - @PostMapping(path = "/checkout") - public Mono getCheckout(@RequestBody(required = false) byte[] body) { - return Mono.fromRunnable(() -> - log.info("Received Message: " + new String(body))); - } -} -``` - -- For a full guide on input bindings, visit [How-To: Input bindings]({{< ref howto-triggers >}}). -- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/bindings/http) for code samples and instructions to try out input bindings. - -### Retrieve secrets - -```java -import com.fasterxml.jackson.databind.ObjectMapper; -import io.dapr.client.DaprClient; -import io.dapr.client.DaprClientBuilder; -import java.util.Map; - -try (DaprClient client = (new DaprClientBuilder()).build()) { - Map secret = client.getSecret(SECRET_STORE_NAME, secretKey).block(); - System.out.println(JSON_SERIALIZER.writeValueAsString(secret)); -} -``` - -- For a full guide on secrets visit [How-To: Retrieve secrets]({{< ref howto-secrets.md >}}). -- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/secrets) for code samples and instructions to try out retrieving secrets - -### Actors -An actor is an isolated, independent unit of compute and state with single-threaded execution. Dapr provides an actor implementation based on the [Virtual Actor pattern](https://www.microsoft.com/en-us/research/project/orleans-virtual-actors/), which provides a single-threaded programming model and where actors are garbage collected when not in use. With Dapr's implementaiton, you write your Dapr actors according to the Actor model, and Dapr leverages the scalability and reliability that the underlying platform provides. - -```java -import io.dapr.actors.ActorMethod; -import io.dapr.actors.ActorType; -import reactor.core.publisher.Mono; - -@ActorType(name = "DemoActor") -public interface DemoActor { - - void registerReminder(); - - @ActorMethod(name = "echo_message") - String say(String something); - - void clock(String message); - - @ActorMethod(returns = Integer.class) - Mono incrementAndGet(int delta); -} -``` - -- For a full guide on actors visit [How-To: Use virtual actors in Dapr]({{< ref howto-actors.md >}}). -- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/actors) for code samples and instructions to try actors - -### Get & Subscribe to application configurations - -> Note this is a preview API and thus will only be accessible via the DaprPreviewClient interface and not the normal DaprClient interface - -```java -import io.dapr.client.DaprClientBuilder; -import io.dapr.client.DaprPreviewClient; -import io.dapr.client.domain.ConfigurationItem; -import io.dapr.client.domain.GetConfigurationRequest; -import io.dapr.client.domain.SubscribeConfigurationRequest; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -try (DaprPreviewClient client = (new DaprClientBuilder()).buildPreviewClient()) { - // Get configuration for a single key - Mono item = client.getConfiguration(CONFIG_STORE_NAME, CONFIG_KEY).block(); - - // Get configurations for multiple keys - Mono> items = - client.getConfiguration(CONFIG_STORE_NAME, CONFIG_KEY_1, CONFIG_KEY_2); - - // Subscribe to configuration changes - Flux outFlux = client.subscribeConfiguration(CONFIG_STORE_NAME, CONFIG_KEY_1, CONFIG_KEY_2); - outFlux.subscribe(configItems -> configItems.forEach(...)); - - // Unsubscribe from configuration changes - Mono unsubscribe = client.unsubscribeConfiguration(SUBSCRIPTION_ID, CONFIG_STORE_NAME) -} -``` - -- For a full list of configuration operations visit [How-To: Manage configuration from a store]({{< ref howto-manage-configuration.md >}}). -- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/configuration) for code samples and instructions to try out different configuration operations. - -### Query saved state - -> Note this is a preview API and thus will only be accessible via the DaprPreviewClient interface and not the normal DaprClient interface - -```java -import io.dapr.client.DaprClient; -import io.dapr.client.DaprClientBuilder; -import io.dapr.client.DaprPreviewClient; -import io.dapr.client.domain.QueryStateItem; -import io.dapr.client.domain.QueryStateRequest; -import io.dapr.client.domain.QueryStateResponse; -import io.dapr.client.domain.query.Query; -import io.dapr.client.domain.query.Sorting; -import io.dapr.client.domain.query.filters.EqFilter; - -try (DaprClient client = builder.build(); DaprPreviewClient previewClient = builder.buildPreviewClient()) { - String searchVal = args.length == 0 ? "searchValue" : args[0]; - - // Create JSON data - Listing first = new Listing(); - first.setPropertyType("apartment"); - first.setId("1000"); - ... - Listing second = new Listing(); - second.setPropertyType("row-house"); - second.setId("1002"); - ... - Listing third = new Listing(); - third.setPropertyType("apartment"); - third.setId("1003"); - ... - Listing fourth = new Listing(); - fourth.setPropertyType("apartment"); - fourth.setId("1001"); - ... - Map meta = new HashMap<>(); - meta.put("contentType", "application/json"); - - // Save state - SaveStateRequest request = new SaveStateRequest(STATE_STORE_NAME).setStates( - new State<>("1", first, null, meta, null), - new State<>("2", second, null, meta, null), - new State<>("3", third, null, meta, null), - new State<>("4", fourth, null, meta, null) - ); - client.saveBulkState(request).block(); - - - // Create query and query state request - - Query query = new Query() - .setFilter(new EqFilter<>("propertyType", "apartment")) - .setSort(Arrays.asList(new Sorting("id", Sorting.Order.DESC))); - QueryStateRequest request = new QueryStateRequest(STATE_STORE_NAME) - .setQuery(query); - - // Use preview client to call query state API - QueryStateResponse result = previewClient.queryState(request, MyData.class).block(); - - // View Query state response - System.out.println("Found " + result.getResults().size() + " items."); - for (QueryStateItem item : result.getResults()) { - System.out.println("Key: " + item.getKey()); - System.out.println("Data: " + item.getValue()); - } -} - -``` -- For a full list of configuration operations visit [How-To: Query state]({{< ref howto-state-query-api.md >}}). -- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/querystate) for complete code sample. +## More information -## Related links -- [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples) +Learn more about the [Dapr Java SDK packages available to add to your Java applications](https://dapr.github.io/java-sdk/). \ No newline at end of file diff --git a/daprdocs/content/en/java-sdk-docs/workflow/_index.md b/daprdocs/content/en/java-sdk-docs/workflow/_index.md index b7493ebc4..ecfb7adeb 100644 --- a/daprdocs/content/en/java-sdk-docs/workflow/_index.md +++ b/daprdocs/content/en/java-sdk-docs/workflow/_index.md @@ -2,6 +2,6 @@ type: docs title: "Workflow" linkTitle: "Workflow" -weight: 10000 +weight: 3000 description: How to get up and running with the Dapr Workflow extension --- From 730752850c26455707557ba8a168737281be30f0 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 6 Sep 2023 13:25:17 -0400 Subject: [PATCH 3/8] pre-test filling in doc Signed-off-by: Hannah Hunter --- .../java-sdk-docs/workflow/java-workflow.md | 115 ++++++++++++------ 1 file changed, 79 insertions(+), 36 deletions(-) diff --git a/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md b/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md index 7c75838f1..496ed9ebc 100644 --- a/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md +++ b/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md @@ -1,7 +1,7 @@ --- type: docs -title: "Getting started with the Dapr Workflow Java SDK" -linkTitle: "Workflow" +title: "How to: Author and manage Dapr Workflow in the Java SDK" +linkTitle: "How to: Author and manage workflows" weight: 20000 description: How to get up and running with workflows using the Dapr Java SDK --- @@ -10,19 +10,15 @@ description: How to get up and running with workflows using the Dapr Java SDK Dapr Workflow is currently in alpha. {{% /alert %}} -Let’s create a Dapr workflow and invoke it using the console. With the [provided hello world workflow example](todo), you will: +Let’s create a Dapr workflow and invoke it using the console. With the [provided workflow example](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/workflows), you will: -- Run a [Java console application using `todo`](todo) -- Utilize the Java workflow SDK and API calls to start, pause, resume, terminate, and purge workflow instances +- Execute the workflow instance using the [Java workflow worker](https://github.com/dapr/java-sdk/blob/master/examples/src/main/java/io/dapr/examples/workflows/DemoWorkflowWorker.java) +- Utilize the Java workflow client and API calls to [start and terminate workflow instances](https://github.com/dapr/java-sdk/blob/master/examples/src/main/java/io/dapr/examples/workflows/DemoWorkflowClient.java) This example uses the default configuration from `dapr init` in [self-hosted mode](https://github.com/dapr/cli#install-dapr-on-your-local-machine-self-hosted). -In the Java example project, the `todo` file contains the setup of the app, including: -- The workflow definition -- The workflow activity definitions -- The registration of the workflow and workflow activities - ## Prerequisites + - [Dapr CLI and initialized environment](https://docs.dapr.io/getting-started). - Java JDK 11 (or greater): - [Oracle JDK](https://www.oracle.com/java/technologies/downloads), or @@ -35,32 +31,56 @@ In the Java example project, the `todo` file contains the setup of the app, incl ## Set up the environment -Run the following command to install the requirements for running this workflow sample with the Dapr Java SDK. +Clone the Java SDK repo and navigate into it. ```bash -todo +git clone https://github.com/dapr/java-sdk.git +cd java-sdk ``` -Clone the Java SDK repo. +Run the following command to install the requirements for running this workflow sample with the Dapr Java SDK. ```bash -git clone https://github.com/dapr/java-sdk.git +mvn install ``` From the Java SDK root directory, navigate to the Dapr Workflow example. ```bash -todo +cd examples ``` -## Run the application locally +## Run the `DemoWorkflowWorker` -To run the Dapr application, you need to start the Java program and a Dapr sidecar. In the terminal, run: +The `DemoWorkflowWorker` registers an implementation of `DemoWorkflow` in the Dapr Workflow runtime engine. In the following excerpt from the [`DemoWorkflowWorker.java` file](https://github.com/dapr/java-sdk/blob/master/examples/src/main/java/io/dapr/examples/workflows/DemoWorkflowWorker.java), notice the `DemoWorkflowWorker` class and the main method. -```bash -todo +```java +public class DemoWorkflowWorker { + + public static void main(String[] args) throws Exception { + // Register the Workflow with the builder. + WorkflowRuntimeBuilder builder = new WorkflowRuntimeBuilder().registerWorkflow(DemoWorkflow.class); + + // Build and then start the workflow runtime pulling and executing tasks + try (WorkflowRuntime runtime = builder.build()) { + System.out.println("Start workflow runtime"); + runtime.start(); + } + + System.exit(0); + } +} ``` +In the code above: +- `WorkflowRuntime.getInstance().registerWorkflow()` registers `DemoWorkflow` as a workflow in the Dapr Workflow runtime. +- `runtime.start();` builds and starts the engine within the Dapr Workflow runtime. + +Execute the following command to run `DemoWorkflowWorker`: + +```sh +dapr run --app-id demoworkflowworker --resources-path ./components/workflows --dapr-grpc-port 50001 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.workflows.DemoWorkflowWorker +``` **Expected output** @@ -68,36 +88,59 @@ todo todo ``` -## What happened? +## Run the `DemoWorkflowClient -When you ran `dapr run`, the Dapr client: -1. Registered the workflow (`todo`) and its actvity (`todo`) -1. Started the workflow engine +Now that the workflow worker is running, you can start workflow instances registered with Dapr using the `DemoWorkflowClient`. In the following excerpt from the [`DemoWorkflowClient.java` file](https://github.com/dapr/java-sdk/blob/master/examples/src/main/java/io/dapr/examples/workflows/DemoWorkflowClient.java), notice the `DemoWorkflowClient` class and the main method that starts the workflow instances. ```java +public class DemoWorkflowClient { + + public static void main(String[] args) throws InterruptedException { + DaprWorkflowClient client = new DaprWorkflowClient(); + + // Start the workflow instances + try (client) { + System.out.println("*****"); + String instanceId = client.scheduleNewWorkflow(DemoWorkflow.class); + System.out.printf("Started new workflow instance with random ID: %s%n", instanceId); + + System.out.println("Sleep and allow this workflow instance to timeout..."); + TimeUnit.SECONDS.sleep(10); + + System.out.println("*****"); + String instanceToTerminateId = "terminateMe"; + client.scheduleNewWorkflow(DemoWorkflow.class, null, instanceToTerminateId); + System.out.printf("Started new workflow instance with specified ID: %s%n", instanceToTerminateId); + + TimeUnit.SECONDS.sleep(5); + System.out.println("Terminate this workflow instance manually before the timeout is reached"); + client.terminateWorkflow(instanceToTerminateId, null); + System.out.println("*****"); + } + + System.out.println("Exiting DemoWorkflowClient."); + System.exit(0); + } +} ``` -Dapr then paused and resumed the workflow: +Start the workflow by running the following command: -```java +```sh +java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.workflows.DemoWorkflowClient ``` -Once the workflow resumed, Dapr raised a workflow event and printed the new counter value: +**Expected output:** -```java ``` - -To clear out the workflow state from your state store, Dapr purged the workflow: - -```java +todo ``` -The sample then demonstrated terminating a workflow by: -- Starting a new workflow using the same `instanceId` as the purged workflow. -- Terminating the workflow and purging before shutting down the workflow. +## What happened? + +1. When you ran `dapr run`, the workflow worker registered the workflow (`DemoWorkflow`) and its actvities to the Dapr Workflow engine. +1. When you ran `java`, the workflow client started the workflow instances. -```java -``` ## Next steps - [Learn more about Dapr workflow]({{< ref workflow >}}) From b85772a15c9f721264720003037233cc3ef780b7 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 13 Sep 2023 11:41:07 -0400 Subject: [PATCH 4/8] update java how to Signed-off-by: Hannah Hunter --- .../java-sdk-docs/workflow/java-workflow.md | 60 ++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md b/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md index 496ed9ebc..d278ac51c 100644 --- a/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md +++ b/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md @@ -76,7 +76,7 @@ In the code above: - `WorkflowRuntime.getInstance().registerWorkflow()` registers `DemoWorkflow` as a workflow in the Dapr Workflow runtime. - `runtime.start();` builds and starts the engine within the Dapr Workflow runtime. -Execute the following command to run `DemoWorkflowWorker`: +In the terminal, execute the following command to kick off the `DemoWorkflowWorker`: ```sh dapr run --app-id demoworkflowworker --resources-path ./components/workflows --dapr-grpc-port 50001 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.workflows.DemoWorkflowWorker @@ -85,12 +85,18 @@ dapr run --app-id demoworkflowworker --resources-path ./components/workflows --d **Expected output** ``` -todo +You're up and running! Both Dapr and your app logs will appear here. + +... + +== APP == Start workflow runtime +== APP == Sep 13, 2023 9:02:03 AM com.microsoft.durabletask.DurableTaskGrpcWorker startAndBlock +== APP == INFO: Durable Task worker is connecting to sidecar at 127.0.0.1:50001. ``` ## Run the `DemoWorkflowClient -Now that the workflow worker is running, you can start workflow instances registered with Dapr using the `DemoWorkflowClient`. In the following excerpt from the [`DemoWorkflowClient.java` file](https://github.com/dapr/java-sdk/blob/master/examples/src/main/java/io/dapr/examples/workflows/DemoWorkflowClient.java), notice the `DemoWorkflowClient` class and the main method that starts the workflow instances. +Now that the workflow worker is ready to go, you can start workflow instances registered with Dapr using the `DemoWorkflowClient`. In the following excerpt from the [`DemoWorkflowClient.java` file](https://github.com/dapr/java-sdk/blob/master/examples/src/main/java/io/dapr/examples/workflows/DemoWorkflowClient.java), notice the `DemoWorkflowClient` class and the main method that starts the workflow instances. ```java public class DemoWorkflowClient { @@ -124,23 +130,61 @@ public class DemoWorkflowClient { } ``` -Start the workflow by running the following command: +In a second terminal window, start the workflow by running the following command: ```sh java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.workflows.DemoWorkflowClient ``` -**Expected output:** +**Expected output** ``` -todo +******* +Started new workflow instance with random ID: 0b4cc0d5-413a-4c1c-816a-a71fa24740d4 +******* +**GetInstanceMetadata:Running Workflow** +Result: [Name: 'io.dapr.examples.workflows.DemoWorkflow', ID: '0b4cc0d5-413a-4c1c-816a-a71fa24740d4', RuntimeStatus: RUNNING, CreatedAt: 2023-09-13T13:02:30.547Z, LastUpdatedAt: 2023-09-13T13:02:30.699Z, Input: '"input data"', Output: ''] +******* +**WaitForInstanceStart** +Result: [Name: 'io.dapr.examples.workflows.DemoWorkflow', ID: '0b4cc0d5-413a-4c1c-816a-a71fa24740d4', RuntimeStatus: RUNNING, CreatedAt: 2023-09-13T13:02:30.547Z, LastUpdatedAt: 2023-09-13T13:02:30.699Z, Input: '"input data"', Output: ''] +******* +**SendExternalMessage** +******* +** Registering parallel Events to be captured by allOf(t1,t2,t3) ** +Events raised for workflow with instanceId: 0b4cc0d5-413a-4c1c-816a-a71fa24740d4 +******* +** Registering Event to be captured by anyOf(t1,t2,t3) ** +Event raised for workflow with instanceId: 0b4cc0d5-413a-4c1c-816a-a71fa24740d4 +******* +**WaitForInstanceCompletion** +Result: [Name: 'io.dapr.examples.workflows.DemoWorkflow', ID: '0b4cc0d5-413a-4c1c-816a-a71fa24740d4', RuntimeStatus: FAILED, CreatedAt: 2023-09-13T13:02:30.547Z, LastUpdatedAt: 2023-09-13T13:02:55.054Z, Input: '"input data"', Output: ''] +******* +**purgeInstance** +purgeResult: true +******* +**raiseEvent** +Started new workflow instance with random ID: 7707d141-ebd0-4e54-816e-703cb7a52747 +Event raised for workflow with instanceId: 7707d141-ebd0-4e54-816e-703cb7a52747 +******* +Started new workflow instance with specified ID: terminateMe +Terminate this workflow instance manually before the timeout is reached +******* +Started new workflow instance with ID: restarting +Sleeping 30 seconds to restart the workflow +**SendExternalMessage: RestartEvent** +Sleeping 30 seconds to terminate the eternal workflow +Exiting DemoWorkflowClient. ``` ## What happened? 1. When you ran `dapr run`, the workflow worker registered the workflow (`DemoWorkflow`) and its actvities to the Dapr Workflow engine. -1. When you ran `java`, the workflow client started the workflow instances. - +1. When you ran `java`, the workflow client started the workflow instance with the following activities. You can follow along with the output in the terminal where you ran `dapr run`. + 1. The workflow is started, raises three parallel tasks, and waits for them to complete. + 1. The workflow client calls the activity and sends the "Hello Activity" message to the console. + 1. The workflow times out and is purged. + 1. The workflow client starts a new workflow instance with a random ID, uses another workflow instance called `terminateMe` to terminate it, and restarts it with the workflow called `restarting`. + 1. The worfklow client is then exited. ## Next steps - [Learn more about Dapr workflow]({{< ref workflow >}}) From 65d467737370bf95d43f17e8cff6c2956b61f45c Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 13 Sep 2023 11:56:39 -0400 Subject: [PATCH 5/8] add workflow to client doc Signed-off-by: Hannah Hunter --- .../content/en/java-sdk-docs/java-client.md | 568 ++++++++++++++++++ 1 file changed, 568 insertions(+) create mode 100644 daprdocs/content/en/java-sdk-docs/java-client.md diff --git a/daprdocs/content/en/java-sdk-docs/java-client.md b/daprdocs/content/en/java-sdk-docs/java-client.md new file mode 100644 index 000000000..985dcb0c7 --- /dev/null +++ b/daprdocs/content/en/java-sdk-docs/java-client.md @@ -0,0 +1,568 @@ +--- +type: docs +title: "Dapr Java SDK" +linkTitle: "Java" +weight: 2000 +description: Java SDK packages for developing Dapr applications +--- + +## Pre-requisites + +- [Dapr CLI]({{< ref install-dapr-cli.md >}}) installed +- Initialized [Dapr environment]({{< ref install-dapr-selfhost.md >}}) +- JDK 11 or above - the published jars are compatible with Java 8: + - [AdoptOpenJDK 11 - LTS](https://adoptopenjdk.net/) + - [Oracle's JDK 15](https://www.oracle.com/java/technologies/javase-downloads.html) + - [Oracle's JDK 11 - LTS](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html) + - [OpenJDK](https://openjdk.java.net/) +- Install one of the following build tools for Java: + - [Maven 3.x](https://maven.apache.org/install.html) + - [Gradle 6.x](https://gradle.org/install/) + +## Importing Dapr's Java SDK + +For a Maven project, add the following to your `pom.xml` file: +```xml + + ... + + ... + + + io.dapr + dapr-sdk + 1.9.0 + + + + io.dapr + dapr-sdk-actors + 1.9.0 + + + + io.dapr + dapr-sdk-springboot + 1.9.0 + + ... + + ... + +``` + +For a Gradle project, add the following to your `build.gradle` file: + +```java +dependencies { +... + // Dapr's core SDK with all features, except Actors. + compile('io.dapr:dapr-sdk:1.9.0') + // Dapr's SDK for Actors (optional). + compile('io.dapr:dapr-sdk-actors:1.9.0') + // Dapr's SDK integration with SpringBoot (optional). + compile('io.dapr:dapr-sdk-springboot:1.9.0') +} +``` + +If you are also using Spring Boot, you may run into a common issue where the OkHttp version that the Dapr SDK uses conflicts with the one specified in the Spring Boot _Bill of Materials_. +You can fix this by specifying a compatible OkHttp version in your project to match the version that the Dapr SDK uses: + +```xml + + com.squareup.okhttp3 + okhttp + 4.9.0 + +``` + +## Building blocks + +The Java SDK allows you to interface with all of the [Dapr building blocks]({{< ref building-blocks >}}). + +### Invoke a service + +```java +import io.dapr.client.DaprClient; +import io.dapr.client.DaprClientBuilder; + +try (DaprClient client = (new DaprClientBuilder()).build()) { + // invoke a 'GET' method (HTTP) skipping serialization: \say with a Mono return type + // for gRPC set HttpExtension.NONE parameters below + response = client.invokeMethod(SERVICE_TO_INVOKE, METHOD_TO_INVOKE, "{\"name\":\"World!\"}", HttpExtension.GET, byte[].class).block(); + + // invoke a 'POST' method (HTTP) skipping serialization: to \say with a Mono return type + response = client.invokeMethod(SERVICE_TO_INVOKE, METHOD_TO_INVOKE, "{\"id\":\"100\", \"FirstName\":\"Value\", \"LastName\":\"Value\"}", HttpExtension.POST, byte[].class).block(); + + System.out.println(new String(response)); + + // invoke a 'POST' method (HTTP) with serialization: \employees with a Mono return type + Employee newEmployee = new Employee("Nigel", "Guitarist"); + Employee employeeResponse = client.invokeMethod(SERVICE_TO_INVOKE, "employees", newEmployee, HttpExtension.POST, Employee.class).block(); +} +``` + +- For a full guide on service invocation visit [How-To: Invoke a service]({{< ref howto-invoke-discover-services.md >}}). +- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/invoke) for code samples and instructions to try out service invocation + +### Save & get application state + +```java +import io.dapr.client.DaprClient; +import io.dapr.client.DaprClientBuilder; +import io.dapr.client.domain.State; +import reactor.core.publisher.Mono; + +try (DaprClient client = (new DaprClientBuilder()).build()) { + // Save state + client.saveState(STATE_STORE_NAME, FIRST_KEY_NAME, myClass).block(); + + // Get state + State retrievedMessage = client.getState(STATE_STORE_NAME, FIRST_KEY_NAME, MyClass.class).block(); + + // Delete state + client.deleteState(STATE_STORE_NAME, FIRST_KEY_NAME).block(); +} +``` + +- For a full list of state operations visit [How-To: Get & save state]({{< ref howto-get-save-state.md >}}). +- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/state) for code samples and instructions to try out state management + +### Publish & subscribe to messages + +##### Publish messages + +```java +import io.dapr.client.DaprClient; +import io.dapr.client.DaprClientBuilder; +import io.dapr.client.domain.Metadata; +import static java.util.Collections.singletonMap; + +try (DaprClient client = (new DaprClientBuilder()).build()) { + client.publishEvent(PUBSUB_NAME, TOPIC_NAME, message, singletonMap(Metadata.TTL_IN_SECONDS, MESSAGE_TTL_IN_SECONDS)).block(); +} +``` + +##### Subscribe to messages + +```java +import com.fasterxml.jackson.databind.ObjectMapper; +import io.dapr.Topic; +import io.dapr.client.domain.BulkSubscribeAppResponse; +import io.dapr.client.domain.BulkSubscribeAppResponseEntry; +import io.dapr.client.domain.BulkSubscribeAppResponseStatus; +import io.dapr.client.domain.BulkSubscribeMessage; +import io.dapr.client.domain.BulkSubscribeMessageEntry; +import io.dapr.client.domain.CloudEvent; +import io.dapr.springboot.annotations.BulkSubscribe; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import reactor.core.publisher.Mono; + +@RestController +public class SubscriberController { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + @Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}") + @PostMapping(path = "/testingtopic") + public Mono handleMessage(@RequestBody(required = false) CloudEvent cloudEvent) { + return Mono.fromRunnable(() -> { + try { + System.out.println("Subscriber got: " + cloudEvent.getData()); + System.out.println("Subscriber got: " + OBJECT_MAPPER.writeValueAsString(cloudEvent)); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + @Topic(name = "testingtopic", pubsubName = "${myAppProperty:messagebus}", + rule = @Rule(match = "event.type == 'myevent.v2'", priority = 1)) + @PostMapping(path = "/testingtopicV2") + public Mono handleMessageV2(@RequestBody(required = false) CloudEvent envelope) { + return Mono.fromRunnable(() -> { + try { + System.out.println("Subscriber got: " + cloudEvent.getData()); + System.out.println("Subscriber got: " + OBJECT_MAPPER.writeValueAsString(cloudEvent)); + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + } + + @BulkSubscribe() + @Topic(name = "testingtopicbulk", pubsubName = "${myAppProperty:messagebus}") + @PostMapping(path = "/testingtopicbulk") + public Mono handleBulkMessage( + @RequestBody(required = false) BulkSubscribeMessage> bulkMessage) { + return Mono.fromCallable(() -> { + if (bulkMessage.getEntries().size() == 0) { + return new BulkSubscribeAppResponse(new ArrayList()); + } + + System.out.println("Bulk Subscriber received " + bulkMessage.getEntries().size() + " messages."); + + List entries = new ArrayList(); + for (BulkSubscribeMessageEntry entry : bulkMessage.getEntries()) { + try { + System.out.printf("Bulk Subscriber message has entry ID: %s\n", entry.getEntryId()); + CloudEvent cloudEvent = (CloudEvent) entry.getEvent(); + System.out.printf("Bulk Subscriber got: %s\n", cloudEvent.getData()); + entries.add(new BulkSubscribeAppResponseEntry(entry.getEntryId(), BulkSubscribeAppResponseStatus.SUCCESS)); + } catch (Exception e) { + e.printStackTrace(); + entries.add(new BulkSubscribeAppResponseEntry(entry.getEntryId(), BulkSubscribeAppResponseStatus.RETRY)); + } + } + return new BulkSubscribeAppResponse(entries); + }); + } +} +``` + +##### Bulk Publish Messages +> Note: API is in Alpha stage + + +```java +import io.dapr.client.DaprClientBuilder; +import io.dapr.client.DaprPreviewClient; +import io.dapr.client.domain.BulkPublishResponse; +import io.dapr.client.domain.BulkPublishResponseFailedEntry; +import java.util.ArrayList; +import java.util.List; +class Solution { + public void publishMessages() { + try (DaprPreviewClient client = (new DaprClientBuilder()).buildPreviewClient()) { + // Create a list of messages to publish + List messages = new ArrayList<>(); + for (int i = 0; i < NUM_MESSAGES; i++) { + String message = String.format("This is message #%d", i); + messages.add(message); + System.out.println("Going to publish message : " + message); + } + + // Publish list of messages using the bulk publish API + BulkPublishResponse res = client.publishEvents(PUBSUB_NAME, TOPIC_NAME, "text/plain", messages).block() + } + } +} +``` + +- For a full guide on publishing messages and subscribing to a topic [How-To: Publish & subscribe]({{< ref howto-publish-subscribe.md >}}). +- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/pubsub/http) for code samples and instructions to try out pub/sub + +### Interact with output bindings + +```java +import io.dapr.client.DaprClient; +import io.dapr.client.DaprClientBuilder; + +try (DaprClient client = (new DaprClientBuilder()).build()) { + // sending a class with message; BINDING_OPERATION="create" + client.invokeBinding(BINDING_NAME, BINDING_OPERATION, myClass).block(); + + // sending a plain string + client.invokeBinding(BINDING_NAME, BINDING_OPERATION, message).block(); +} +``` + +- For a full guide on output bindings visit [How-To: Output bindings]({{< ref howto-bindings.md >}}). +- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/bindings/http) for code samples and instructions to try out output bindings. + +### Interact with input bindings + +```java +import org.springframework.web.bind.annotation.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@RestController +@RequestMapping("/") +public class myClass { + private static final Logger log = LoggerFactory.getLogger(myClass); + @PostMapping(path = "/checkout") + public Mono getCheckout(@RequestBody(required = false) byte[] body) { + return Mono.fromRunnable(() -> + log.info("Received Message: " + new String(body))); + } +} +``` + +- For a full guide on input bindings, visit [How-To: Input bindings]({{< ref howto-triggers >}}). +- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/bindings/http) for code samples and instructions to try out input bindings. + +### Retrieve secrets + +```java +import com.fasterxml.jackson.databind.ObjectMapper; +import io.dapr.client.DaprClient; +import io.dapr.client.DaprClientBuilder; +import java.util.Map; + +try (DaprClient client = (new DaprClientBuilder()).build()) { + Map secret = client.getSecret(SECRET_STORE_NAME, secretKey).block(); + System.out.println(JSON_SERIALIZER.writeValueAsString(secret)); +} +``` + +- For a full guide on secrets visit [How-To: Retrieve secrets]({{< ref howto-secrets.md >}}). +- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/secrets) for code samples and instructions to try out retrieving secrets + +### Actors +An actor is an isolated, independent unit of compute and state with single-threaded execution. Dapr provides an actor implementation based on the [Virtual Actor pattern](https://www.microsoft.com/en-us/research/project/orleans-virtual-actors/), which provides a single-threaded programming model and where actors are garbage collected when not in use. With Dapr's implementaiton, you write your Dapr actors according to the Actor model, and Dapr leverages the scalability and reliability that the underlying platform provides. + +```java +import io.dapr.actors.ActorMethod; +import io.dapr.actors.ActorType; +import reactor.core.publisher.Mono; + +@ActorType(name = "DemoActor") +public interface DemoActor { + + void registerReminder(); + + @ActorMethod(name = "echo_message") + String say(String something); + + void clock(String message); + + @ActorMethod(returns = Integer.class) + Mono incrementAndGet(int delta); +} +``` + +- For a full guide on actors visit [How-To: Use virtual actors in Dapr]({{< ref howto-actors.md >}}). +- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/actors) for code samples and instructions to try actors + +### Get & Subscribe to application configurations + +> Note this is a preview API and thus will only be accessible via the DaprPreviewClient interface and not the normal DaprClient interface + +```java +import io.dapr.client.DaprClientBuilder; +import io.dapr.client.DaprPreviewClient; +import io.dapr.client.domain.ConfigurationItem; +import io.dapr.client.domain.GetConfigurationRequest; +import io.dapr.client.domain.SubscribeConfigurationRequest; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +try (DaprPreviewClient client = (new DaprClientBuilder()).buildPreviewClient()) { + // Get configuration for a single key + Mono item = client.getConfiguration(CONFIG_STORE_NAME, CONFIG_KEY).block(); + + // Get configurations for multiple keys + Mono> items = + client.getConfiguration(CONFIG_STORE_NAME, CONFIG_KEY_1, CONFIG_KEY_2); + + // Subscribe to configuration changes + Flux outFlux = client.subscribeConfiguration(CONFIG_STORE_NAME, CONFIG_KEY_1, CONFIG_KEY_2); + outFlux.subscribe(configItems -> configItems.forEach(...)); + + // Unsubscribe from configuration changes + Mono unsubscribe = client.unsubscribeConfiguration(SUBSCRIPTION_ID, CONFIG_STORE_NAME) +} +``` + +- For a full list of configuration operations visit [How-To: Manage configuration from a store]({{< ref howto-manage-configuration.md >}}). +- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/configuration) for code samples and instructions to try out different configuration operations. + +### Query saved state + +> Note this is a preview API and thus will only be accessible via the DaprPreviewClient interface and not the normal DaprClient interface + +```java +import io.dapr.client.DaprClient; +import io.dapr.client.DaprClientBuilder; +import io.dapr.client.DaprPreviewClient; +import io.dapr.client.domain.QueryStateItem; +import io.dapr.client.domain.QueryStateRequest; +import io.dapr.client.domain.QueryStateResponse; +import io.dapr.client.domain.query.Query; +import io.dapr.client.domain.query.Sorting; +import io.dapr.client.domain.query.filters.EqFilter; + +try (DaprClient client = builder.build(); DaprPreviewClient previewClient = builder.buildPreviewClient()) { + String searchVal = args.length == 0 ? "searchValue" : args[0]; + + // Create JSON data + Listing first = new Listing(); + first.setPropertyType("apartment"); + first.setId("1000"); + ... + Listing second = new Listing(); + second.setPropertyType("row-house"); + second.setId("1002"); + ... + Listing third = new Listing(); + third.setPropertyType("apartment"); + third.setId("1003"); + ... + Listing fourth = new Listing(); + fourth.setPropertyType("apartment"); + fourth.setId("1001"); + ... + Map meta = new HashMap<>(); + meta.put("contentType", "application/json"); + + // Save state + SaveStateRequest request = new SaveStateRequest(STATE_STORE_NAME).setStates( + new State<>("1", first, null, meta, null), + new State<>("2", second, null, meta, null), + new State<>("3", third, null, meta, null), + new State<>("4", fourth, null, meta, null) + ); + client.saveBulkState(request).block(); + + + // Create query and query state request + + Query query = new Query() + .setFilter(new EqFilter<>("propertyType", "apartment")) + .setSort(Arrays.asList(new Sorting("id", Sorting.Order.DESC))); + QueryStateRequest request = new QueryStateRequest(STATE_STORE_NAME) + .setQuery(query); + + // Use preview client to call query state API + QueryStateResponse result = previewClient.queryState(request, MyData.class).block(); + + // View Query state response + System.out.println("Found " + result.getResults().size() + " items."); + for (QueryStateItem item : result.getResults()) { + System.out.println("Key: " + item.getKey()); + System.out.println("Data: " + item.getValue()); + } +} +``` +- For a full how-to on query state, visit [How-To: Query state]({{< ref howto-state-query-api.md >}}). +- Visit [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/querystate) for complete code sample. + +### Workflow + +> Dapr Workflow is currently in beta state. + +```java +package io.dapr.examples.workflows; + +import io.dapr.workflows.client.DaprWorkflowClient; +import io.dapr.workflows.client.WorkflowInstanceStatus; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +/** + * For setup instructions, see the README. + */ +public class DemoWorkflowClient { + + /** + * The main method. + * + * @param args Input arguments (unused). + * @throws InterruptedException If program has been interrupted. + */ + public static void main(String[] args) throws InterruptedException { + DaprWorkflowClient client = new DaprWorkflowClient(); + + try (client) { + String separatorStr = "*******"; + System.out.println(separatorStr); + String instanceId = client.scheduleNewWorkflow(DemoWorkflow.class, "input data"); + System.out.printf("Started new workflow instance with random ID: %s%n", instanceId); + + System.out.println(separatorStr); + System.out.println("**GetInstanceMetadata:Running Workflow**"); + WorkflowInstanceStatus workflowMetadata = client.getInstanceState(instanceId, true); + System.out.printf("Result: %s%n", workflowMetadata); + + System.out.println(separatorStr); + System.out.println("**WaitForInstanceStart**"); + try { + WorkflowInstanceStatus waitForInstanceStartResult = + client.waitForInstanceStart(instanceId, Duration.ofSeconds(60), true); + System.out.printf("Result: %s%n", waitForInstanceStartResult); + } catch (TimeoutException ex) { + System.out.printf("waitForInstanceStart has an exception:%s%n", ex); + } + + System.out.println(separatorStr); + System.out.println("**SendExternalMessage**"); + client.raiseEvent(instanceId, "TestEvent", "TestEventPayload"); + + System.out.println(separatorStr); + System.out.println("** Registering parallel Events to be captured by allOf(t1,t2,t3) **"); + client.raiseEvent(instanceId, "event1", "TestEvent 1 Payload"); + client.raiseEvent(instanceId, "event2", "TestEvent 2 Payload"); + client.raiseEvent(instanceId, "event3", "TestEvent 3 Payload"); + System.out.printf("Events raised for workflow with instanceId: %s\n", instanceId); + + System.out.println(separatorStr); + System.out.println("** Registering Event to be captured by anyOf(t1,t2,t3) **"); + client.raiseEvent(instanceId, "e2", "event 2 Payload"); + System.out.printf("Event raised for workflow with instanceId: %s\n", instanceId); + + + System.out.println(separatorStr); + System.out.println("**WaitForInstanceCompletion**"); + try { + WorkflowInstanceStatus waitForInstanceCompletionResult = + client.waitForInstanceCompletion(instanceId, Duration.ofSeconds(60), true); + System.out.printf("Result: %s%n", waitForInstanceCompletionResult); + } catch (TimeoutException ex) { + System.out.printf("waitForInstanceCompletion has an exception:%s%n", ex); + } + + System.out.println(separatorStr); + System.out.println("**purgeInstance**"); + boolean purgeResult = client.purgeInstance(instanceId); + System.out.printf("purgeResult: %s%n", purgeResult); + + System.out.println(separatorStr); + System.out.println("**raiseEvent**"); + + String eventInstanceId = client.scheduleNewWorkflow(DemoWorkflow.class); + System.out.printf("Started new workflow instance with random ID: %s%n", eventInstanceId); + client.raiseEvent(eventInstanceId, "TestException", null); + System.out.printf("Event raised for workflow with instanceId: %s\n", eventInstanceId); + + System.out.println(separatorStr); + String instanceToTerminateId = "terminateMe"; + client.scheduleNewWorkflow(DemoWorkflow.class, null, instanceToTerminateId); + System.out.printf("Started new workflow instance with specified ID: %s%n", instanceToTerminateId); + + TimeUnit.SECONDS.sleep(5); + System.out.println("Terminate this workflow instance manually before the timeout is reached"); + client.terminateWorkflow(instanceToTerminateId, null); + System.out.println(separatorStr); + + String restartingInstanceId = "restarting"; + client.scheduleNewWorkflow(DemoWorkflow.class, null, restartingInstanceId); + System.out.printf("Started new workflow instance with ID: %s%n", restartingInstanceId); + System.out.println("Sleeping 30 seconds to restart the workflow"); + TimeUnit.SECONDS.sleep(30); + + System.out.println("**SendExternalMessage: RestartEvent**"); + client.raiseEvent(restartingInstanceId, "RestartEvent", "RestartEventPayload"); + + System.out.println("Sleeping 30 seconds to terminate the eternal workflow"); + TimeUnit.SECONDS.sleep(30); + client.terminateWorkflow(restartingInstanceId, null); + } + + System.out.println("Exiting DemoWorkflowClient."); + System.exit(0); + } +} +``` + +- For a full guide on workflows, visit: + - [How-To: Author workflows]({{< ref howto-author-workflow.md >}}). + - [How-To: Manage workflows]({{< ref howto-manage-workflow.md >}}). +- [Learn more about how to use workflows with the Java SDK]({{< ref java-workflow.md >}}). + +## Related links +- [Java SDK examples](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples) From 835a677fcf9c59238d3039b5b2c11df6b18f8f89 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 13 Sep 2023 12:12:36 -0400 Subject: [PATCH 6/8] small edits Signed-off-by: Hannah Hunter --- daprdocs/content/en/java-sdk-docs/_index.md | 76 +++++++++++++++++-- .../content/en/java-sdk-docs/java-client.md | 70 +---------------- 2 files changed, 72 insertions(+), 74 deletions(-) diff --git a/daprdocs/content/en/java-sdk-docs/_index.md b/daprdocs/content/en/java-sdk-docs/_index.md index 6d0f557ae..7778608f0 100644 --- a/daprdocs/content/en/java-sdk-docs/_index.md +++ b/daprdocs/content/en/java-sdk-docs/_index.md @@ -11,7 +11,7 @@ cascade: github_branch: master --- -## Pre-requisites +## Prerequisites - [Dapr CLI]({{< ref install-dapr-cli.md >}}) installed - Initialized [Dapr environment]({{< ref install-dapr-selfhost.md >}}) @@ -24,15 +24,79 @@ cascade: - [Maven 3.x](https://maven.apache.org/install.html) - [Gradle 6.x](https://gradle.org/install/) -## Installation +## Import Dapr's Java SDK -Install the required JDK using [SDKMAN!](https://sdkman.io/): +Next, import the Java SDK packages to get started. Select your preferred build tool to learn how to import. -```bash -sdk env install +{{< tabs Maven Gradle >}} + +{{% codetab %}} + + +For a Maven project, add the following to your `pom.xml` file: + +```xml + + ... + + ... + + + io.dapr + dapr-sdk + 1.9.0 + + + + io.dapr + dapr-sdk-actors + 1.9.0 + + + + io.dapr + dapr-sdk-springboot + 1.9.0 + + ... + + ... + +``` +{{% /codetab %}} + +{{% codetab %}} + + +For a Gradle project, add the following to your `build.gradle` file: + +```java +dependencies { +... + // Dapr's core SDK with all features, except Actors. + compile('io.dapr:dapr-sdk:1.9.0') + // Dapr's SDK for Actors (optional). + compile('io.dapr:dapr-sdk-actors:1.9.0') + // Dapr's SDK integration with SpringBoot (optional). + compile('io.dapr:dapr-sdk-springboot:1.9.0') +} ``` -[Next, import the Java SDK packages to get started]({{< ref java-client.md >}}). +{{% /codetab %}} + +{{< /tabs >}} + +If you are also using Spring Boot, you may run into a common issue where the `OkHttp` version that the Dapr SDK uses conflicts with the one specified in the Spring Boot _Bill of Materials_. + +You can fix this by specifying a compatible `OkHttp` version in your project to match the version that the Dapr SDK uses: + +```xml + + com.squareup.okhttp3 + okhttp + 4.9.0 + +``` ## Try it out diff --git a/daprdocs/content/en/java-sdk-docs/java-client.md b/daprdocs/content/en/java-sdk-docs/java-client.md index 985dcb0c7..7f1321953 100644 --- a/daprdocs/content/en/java-sdk-docs/java-client.md +++ b/daprdocs/content/en/java-sdk-docs/java-client.md @@ -6,75 +6,9 @@ weight: 2000 description: Java SDK packages for developing Dapr applications --- -## Pre-requisites - -- [Dapr CLI]({{< ref install-dapr-cli.md >}}) installed -- Initialized [Dapr environment]({{< ref install-dapr-selfhost.md >}}) -- JDK 11 or above - the published jars are compatible with Java 8: - - [AdoptOpenJDK 11 - LTS](https://adoptopenjdk.net/) - - [Oracle's JDK 15](https://www.oracle.com/java/technologies/javase-downloads.html) - - [Oracle's JDK 11 - LTS](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html) - - [OpenJDK](https://openjdk.java.net/) -- Install one of the following build tools for Java: - - [Maven 3.x](https://maven.apache.org/install.html) - - [Gradle 6.x](https://gradle.org/install/) - -## Importing Dapr's Java SDK - -For a Maven project, add the following to your `pom.xml` file: -```xml - - ... - - ... - - - io.dapr - dapr-sdk - 1.9.0 - - - - io.dapr - dapr-sdk-actors - 1.9.0 - - - - io.dapr - dapr-sdk-springboot - 1.9.0 - - ... - - ... - -``` - -For a Gradle project, add the following to your `build.gradle` file: - -```java -dependencies { -... - // Dapr's core SDK with all features, except Actors. - compile('io.dapr:dapr-sdk:1.9.0') - // Dapr's SDK for Actors (optional). - compile('io.dapr:dapr-sdk-actors:1.9.0') - // Dapr's SDK integration with SpringBoot (optional). - compile('io.dapr:dapr-sdk-springboot:1.9.0') -} -``` +## Prerequisites -If you are also using Spring Boot, you may run into a common issue where the OkHttp version that the Dapr SDK uses conflicts with the one specified in the Spring Boot _Bill of Materials_. -You can fix this by specifying a compatible OkHttp version in your project to match the version that the Dapr SDK uses: - -```xml - - com.squareup.okhttp3 - okhttp - 4.9.0 - -``` +[Complete initial setup and import the Java SDK into your project]({{< ref java-sdk-docs >}}) ## Building blocks From 78642f7dd4d702e5c3e14d742f484459a4186de9 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 13 Sep 2023 18:22:49 -0400 Subject: [PATCH 7/8] tweaks Signed-off-by: Hannah Hunter --- daprdocs/content/en/java-sdk-docs/_index.md | 2 +- daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/daprdocs/content/en/java-sdk-docs/_index.md b/daprdocs/content/en/java-sdk-docs/_index.md index 7778608f0..73ddcae1a 100644 --- a/daprdocs/content/en/java-sdk-docs/_index.md +++ b/daprdocs/content/en/java-sdk-docs/_index.md @@ -104,7 +104,7 @@ Put the Dapr Java SDK to the test. Walk through the Java quickstarts adn tutoria | SDK samples | Description | | ----------- | ----------- | -| [Quickstarts] | Experience Dapr's API building blocks in just a few minutes using the Java SDK. | +| [Quickstarts]({{< ref quickstarts >}}) | Experience Dapr's API building blocks in just a few minutes using the Java SDK. | | [SDK samples](https://github.com/dapr/java-sdk/tree/master/examples) | Clone the SDK repo to try out some examples and get started. | ## More information diff --git a/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md b/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md index d278ac51c..5b645fe53 100644 --- a/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md +++ b/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md @@ -7,9 +7,10 @@ description: How to get up and running with workflows using the Dapr Java SDK --- {{% alert title="Note" color="primary" %}} -Dapr Workflow is currently in alpha. +Dapr Workflow is currently in beta. [See known limitations for {{% dapr-latest-version cli="true" %}}]({{< ref "workflow-overview.md#limitations" >}}). {{% /alert %}} + Let’s create a Dapr workflow and invoke it using the console. With the [provided workflow example](https://github.com/dapr/java-sdk/tree/master/examples/src/main/java/io/dapr/examples/workflows), you will: - Execute the workflow instance using the [Java workflow worker](https://github.com/dapr/java-sdk/blob/master/examples/src/main/java/io/dapr/examples/workflows/DemoWorkflowWorker.java) From d397e2109dd2ed1a9b87ef551e026dd09e872bf1 Mon Sep 17 00:00:00 2001 From: Hannah Hunter Date: Wed, 20 Sep 2023 16:47:13 -0400 Subject: [PATCH 8/8] update java sdk how to and client example Signed-off-by: Hannah Hunter --- daprdocs/content/en/java-sdk-docs/_index.md | 2 +- .../java-sdk-docs/workflow/java-workflow.md | 106 ++++++++++++++---- 2 files changed, 85 insertions(+), 23 deletions(-) diff --git a/daprdocs/content/en/java-sdk-docs/_index.md b/daprdocs/content/en/java-sdk-docs/_index.md index 73ddcae1a..5d4f4506f 100644 --- a/daprdocs/content/en/java-sdk-docs/_index.md +++ b/daprdocs/content/en/java-sdk-docs/_index.md @@ -100,7 +100,7 @@ You can fix this by specifying a compatible `OkHttp` version in your project to ## Try it out -Put the Dapr Java SDK to the test. Walk through the Java quickstarts adn tutorials to see Dapr in action: +Put the Dapr Java SDK to the test. Walk through the Java quickstarts and tutorials to see Dapr in action: | SDK samples | Description | | ----------- | ----------- | diff --git a/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md b/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md index 5b645fe53..333bffe24 100644 --- a/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md +++ b/daprdocs/content/en/java-sdk-docs/workflow/java-workflow.md @@ -42,7 +42,7 @@ cd java-sdk Run the following command to install the requirements for running this workflow sample with the Dapr Java SDK. ```bash -mvn install +mvn clean install ``` From the Java SDK root directory, navigate to the Dapr Workflow example. @@ -53,21 +53,16 @@ cd examples ## Run the `DemoWorkflowWorker` -The `DemoWorkflowWorker` registers an implementation of `DemoWorkflow` in the Dapr Workflow runtime engine. In the following excerpt from the [`DemoWorkflowWorker.java` file](https://github.com/dapr/java-sdk/blob/master/examples/src/main/java/io/dapr/examples/workflows/DemoWorkflowWorker.java), notice the `DemoWorkflowWorker` class and the main method. +The `DemoWorkflowWorker` class registers an implementation of `DemoWorkflow` in Dapr's workflow runtime engine. In the `DemoWorkflowWorker.java` file, you can find the `DemoWorkflowWorker` class and the `main` method: ```java public class DemoWorkflowWorker { public static void main(String[] args) throws Exception { - // Register the Workflow with the builder. - WorkflowRuntimeBuilder builder = new WorkflowRuntimeBuilder().registerWorkflow(DemoWorkflow.class); - - // Build and then start the workflow runtime pulling and executing tasks - try (WorkflowRuntime runtime = builder.build()) { - System.out.println("Start workflow runtime"); - runtime.start(); - } - + // Register the Workflow with the runtime. + WorkflowRuntime.getInstance().registerWorkflow(DemoWorkflow.class); + System.out.println("Start workflow runtime"); + WorkflowRuntime.getInstance().startAndBlock(); System.exit(0); } } @@ -75,7 +70,7 @@ public class DemoWorkflowWorker { In the code above: - `WorkflowRuntime.getInstance().registerWorkflow()` registers `DemoWorkflow` as a workflow in the Dapr Workflow runtime. -- `runtime.start();` builds and starts the engine within the Dapr Workflow runtime. +- `WorkflowRuntime.getInstance().start()` builds and starts the engine within the Dapr Workflow runtime. In the terminal, execute the following command to kick off the `DemoWorkflowWorker`: @@ -97,24 +92,78 @@ You're up and running! Both Dapr and your app logs will appear here. ## Run the `DemoWorkflowClient -Now that the workflow worker is ready to go, you can start workflow instances registered with Dapr using the `DemoWorkflowClient`. In the following excerpt from the [`DemoWorkflowClient.java` file](https://github.com/dapr/java-sdk/blob/master/examples/src/main/java/io/dapr/examples/workflows/DemoWorkflowClient.java), notice the `DemoWorkflowClient` class and the main method that starts the workflow instances. +The `DemoWorkflowClient` starts instances of workflows that have been registered with Dapr. + ```java public class DemoWorkflowClient { + // ... public static void main(String[] args) throws InterruptedException { DaprWorkflowClient client = new DaprWorkflowClient(); - - // Start the workflow instances + try (client) { - System.out.println("*****"); - String instanceId = client.scheduleNewWorkflow(DemoWorkflow.class); + String separatorStr = "*******"; + System.out.println(separatorStr); + String instanceId = client.scheduleNewWorkflow(DemoWorkflow.class, "input data"); System.out.printf("Started new workflow instance with random ID: %s%n", instanceId); - System.out.println("Sleep and allow this workflow instance to timeout..."); - TimeUnit.SECONDS.sleep(10); - - System.out.println("*****"); + System.out.println(separatorStr); + System.out.println("**GetInstanceMetadata:Running Workflow**"); + WorkflowInstanceStatus workflowMetadata = client.getInstanceState(instanceId, true); + System.out.printf("Result: %s%n", workflowMetadata); + + System.out.println(separatorStr); + System.out.println("**WaitForInstanceStart**"); + try { + WorkflowInstanceStatus waitForInstanceStartResult = + client.waitForInstanceStart(instanceId, Duration.ofSeconds(60), true); + System.out.printf("Result: %s%n", waitForInstanceStartResult); + } catch (TimeoutException ex) { + System.out.printf("waitForInstanceStart has an exception:%s%n", ex); + } + + System.out.println(separatorStr); + System.out.println("**SendExternalMessage**"); + client.raiseEvent(instanceId, "TestEvent", "TestEventPayload"); + + System.out.println(separatorStr); + System.out.println("** Registering parallel Events to be captured by allOf(t1,t2,t3) **"); + client.raiseEvent(instanceId, "event1", "TestEvent 1 Payload"); + client.raiseEvent(instanceId, "event2", "TestEvent 2 Payload"); + client.raiseEvent(instanceId, "event3", "TestEvent 3 Payload"); + System.out.printf("Events raised for workflow with instanceId: %s\n", instanceId); + + System.out.println(separatorStr); + System.out.println("** Registering Event to be captured by anyOf(t1,t2,t3) **"); + client.raiseEvent(instanceId, "e2", "event 2 Payload"); + System.out.printf("Event raised for workflow with instanceId: %s\n", instanceId); + + + System.out.println(separatorStr); + System.out.println("**WaitForInstanceCompletion**"); + try { + WorkflowInstanceStatus waitForInstanceCompletionResult = + client.waitForInstanceCompletion(instanceId, Duration.ofSeconds(60), true); + System.out.printf("Result: %s%n", waitForInstanceCompletionResult); + } catch (TimeoutException ex) { + System.out.printf("waitForInstanceCompletion has an exception:%s%n", ex); + } + + System.out.println(separatorStr); + System.out.println("**purgeInstance**"); + boolean purgeResult = client.purgeInstance(instanceId); + System.out.printf("purgeResult: %s%n", purgeResult); + + System.out.println(separatorStr); + System.out.println("**raiseEvent**"); + + String eventInstanceId = client.scheduleNewWorkflow(DemoWorkflow.class); + System.out.printf("Started new workflow instance with random ID: %s%n", eventInstanceId); + client.raiseEvent(eventInstanceId, "TestException", null); + System.out.printf("Event raised for workflow with instanceId: %s\n", eventInstanceId); + + System.out.println(separatorStr); String instanceToTerminateId = "terminateMe"; client.scheduleNewWorkflow(DemoWorkflow.class, null, instanceToTerminateId); System.out.printf("Started new workflow instance with specified ID: %s%n", instanceToTerminateId); @@ -122,7 +171,20 @@ public class DemoWorkflowClient { TimeUnit.SECONDS.sleep(5); System.out.println("Terminate this workflow instance manually before the timeout is reached"); client.terminateWorkflow(instanceToTerminateId, null); - System.out.println("*****"); + System.out.println(separatorStr); + + String restartingInstanceId = "restarting"; + client.scheduleNewWorkflow(DemoWorkflow.class, null, restartingInstanceId); + System.out.printf("Started new workflow instance with ID: %s%n", restartingInstanceId); + System.out.println("Sleeping 30 seconds to restart the workflow"); + TimeUnit.SECONDS.sleep(30); + + System.out.println("**SendExternalMessage: RestartEvent**"); + client.raiseEvent(restartingInstanceId, "RestartEvent", "RestartEventPayload"); + + System.out.println("Sleeping 30 seconds to terminate the eternal workflow"); + TimeUnit.SECONDS.sleep(30); + client.terminateWorkflow(restartingInstanceId, null); } System.out.println("Exiting DemoWorkflowClient.");