Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
6656e4c
Add ElementType.Type to ActorType (#812)
LionTao Jan 25, 2023
869a231
Bump codecov/codecov-action from 3.1.0 to 3.1.1 (#788)
dependabot[bot] Jan 25, 2023
9e30733
Update springboot to latest minor.patch version. (#826)
artursouza Feb 2, 2023
69292a6
Use runtime 1.10.0-rc.X and CLI 1.10.0-rc.X (#827)
artursouza Feb 3, 2023
bffac88
Upgrade the version to 1.9.0-SNAPSHOT (#829)
artursouza Feb 3, 2023
27131ff
Generate updated javadocs for 1.8.0 (#836)
artursouza Feb 16, 2023
6635627
Update Dapr runtime and CLI to 1.10. (#837)
artursouza Feb 16, 2023
113220f
Inject autoconfiguration in the Spring Boot 3 style (#831)
champel Mar 22, 2023
8378bb0
Bump from reactor 2.3.5.RELEASE to 2.7.8 (#830)
champel Mar 22, 2023
7ade730
Test multiple reminder state types + improve timer tests. (#855)
artursouza May 5, 2023
022c0ee
Convert Config API to Stable endpoints. (#846)
mukundansundar May 9, 2023
64b3ad8
Add PubSub subscriber examples over gPRC (#833)
MregXN May 22, 2023
4117801
auto validate actors (#863)
mukundansundar May 24, 2023
d49c87b
Bump codecov/codecov-action from 3.1.1 to 3.1.4 (#862)
dependabot[bot] May 24, 2023
1f33417
Fix 787 (#832)
MatejNedic May 25, 2023
ae2e61c
Upgrade to 1.11 RCs. (#867)
artursouza May 26, 2023
03d5c2e
Init for workflows
bderusha May 10, 2023
fcfade9
Updating some javadocs and Years.
May 26, 2023
e40722d
Add missing Header
May 26, 2023
9270180
respond to PR feedback
bderusha Jun 1, 2023
1420b4c
Update workflow example README
bderusha Jun 1, 2023
95a2757
Address PR feedback
bderusha Jun 2, 2023
d5345cc
fixup deprecated pom.xml variable
bderusha Jun 2, 2023
94f121c
Updates based on PR feedback
bderusha Jun 6, 2023
7df0031
Update pom files per feedback
bderusha Jun 7, 2023
51d5b04
GetInstanceState implementation (#1)
Aymalla Jun 12, 2023
a2c4867
Management API
kusweta Jun 12, 2023
f6bfade
remove try/catch
kusweta Jun 13, 2023
8a0201d
implementing getIsReplaying() method for Authoring API (#7)
julioalex-rezende Jun 13, 2023
4448b62
Implementing getCurrentInstant() authoring method (#5)
julioalex-rezende Jun 13, 2023
03c0602
Activity Implementation (#3)
macromania Jun 14, 2023
84f89fb
fixing issue with getIsReplaying() call (#8)
julioalex-rezende Jun 15, 2023
1ed7192
Generate updated javadocs for 1.9.0 (#878)
artursouza Jun 12, 2023
4e17f3f
Add .sdkmanrc config file and JDK installation instructions (#873)
ejba Jun 13, 2023
06feae6
Add unit testing example
bderusha Jun 13, 2023
f2ee392
implementing getIsReplaying() method for Authoring API (#7)
julioalex-rezende Jun 13, 2023
aa9cea2
fix parent pom
macromania Jun 14, 2023
730d22d
Send Event Implementation (#10)
macromania Jun 15, 2023
4bba4a4
Implementing allOf, anyOf, createTimer methods (#11)
julioalex-rezende Jun 19, 2023
e7f4fbc
Support remote endpoint. (#877)
artursouza Jun 19, 2023
9816093
Add callSubWorkflow Implementation
Aymalla Jun 19, 2023
d1b64ba
rename DemoSubWorkflow
Aymalla Jun 19, 2023
34b8f82
continueAsNew Implementation (#13)
macromania Jun 20, 2023
1b3a3dd
Merge branch 'master' into master
macromania Jun 21, 2023
d3d8a52
Merge branch 'master' into master
macromania Jun 29, 2023
9343ea7
merge PR 857 changes
macromania Aug 15, 2023
5efc786
remove duplicate class
macromania Aug 15, 2023
93d617e
add missing mockito test dependency
macromania Aug 15, 2023
a1c379a
use new workflow client implementation
macromania Aug 15, 2023
af451cb
moved implementations to new workflow and context
macromania Aug 15, 2023
b596268
relocate duplicate implemantation
macromania Aug 15, 2023
7033b00
remove duplicate test and increase test coverage
macromania Aug 15, 2023
e5c6106
Implement retry and timeout policy for gRPC client. (#889)
artursouza Aug 16, 2023
a2cd162
renamed getIsReplaying
macromania Aug 21, 2023
147b237
rollback changes on client
macromania Aug 21, 2023
6fda032
move workflow runtime state package
macromania Aug 21, 2023
c5ead93
rename workflow instance state to status
macromania Aug 21, 2023
7c657cd
remove unnecessary else
macromania Aug 21, 2023
b9d984e
removed unknown state
macromania Aug 21, 2023
0f4b131
updated comment
macromania Aug 21, 2023
1f4c148
updated workflow failure details
macromania Aug 21, 2023
438001b
fix style issues
macromania Aug 21, 2023
7b31e22
Merge remote-tracking branch 'dapr-upstream/master'
macromania Aug 21, 2023
4c673e6
rollback merge change
macromania Aug 25, 2023
53fe882
fixed pom files
macromania Aug 25, 2023
2a9e49e
rollback actors pom changes on autoformat
macromania Aug 25, 2023
5229957
fixe actors pom
macromania Aug 25, 2023
bc35ee0
fix styling on actors pom
macromania Aug 25, 2023
ed640b8
fix pom spacing
macromania Aug 25, 2023
6278b4a
move test to match the package
macromania Aug 25, 2023
20aad31
add missing dependencies
macromania Aug 25, 2023
9d1abb4
increased test coverage
macromania Aug 25, 2023
e1a45e7
moved workflow runtime package
macromania Aug 25, 2023
980862f
add exception for missing case
macromania Aug 25, 2023
12e69d4
add null check for metadata
macromania Aug 25, 2023
319af01
add runtime exception error messages
macromania Aug 25, 2023
c787eee
update try catch scope
macromania Aug 25, 2023
cf0ec89
update activity definition to an interface
macromania Aug 25, 2023
7fb9a37
update comments
macromania Aug 25, 2023
3847626
removed redundant method
macromania Aug 25, 2023
be16ab1
update dapr workflow example to be quick start for new comer
skyao Sep 9, 2023
ad1a9c0
merge upstream to get the content of PR 880
skyao Sep 13, 2023
446ea84
fix merge
skyao Sep 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 31 additions & 19 deletions examples/src/main/java/io/dapr/examples/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ In this example, we'll use Dapr to test workflow features.

Visit [the Workflow documentation landing page](https://docs.dapr.io/developing-applications/building-blocks/workflow) for more information.

This example contains the follow classes:
This example contains the two parts :

1. WorkflowConsoleApp

It utilizes the workflow SDK as well as the workflow management API for starting workflows instances. The main WorkflowConsoleApp.java file contains the main setup of the app, including the registration of the workflow and workflow activities. The workflow definition is found in the workflows package and the workflow activity definitions are found in the activities package. All the models used by workflow activities are in models package.

2. WorkflowClient

It scheduales an instance of the OrderProcessingWorkflow (defined in the console package), starts it, and waits for the workflow result and output.

* DemoWorkflow: An example of a Dapr Workflow.
* DemoWorkflowClient: This application will start workflows using Dapr.
* DemoWorkflowWorker: An application that registers a workflow to the Dapr workflow runtime engine. It also executes the workflow instance.

## Pre-requisites

* [Dapr and Dapr Cli](https://docs.dapr.io/getting-started/install-dapr/).
Expand Down Expand Up @@ -43,36 +47,44 @@ cd examples

### Running the demo Workflow worker

The first Java class to consider is `DemoWorkflowWorker`. Its job is to register an implementation of `DemoWorkflow` in the Dapr's workflow runtime engine. In `DemoWorkflowWorker.java` file, you will find the `DemoWorkflowWorker` class and the `main` method. See the code snippet below:
The first Java class to consider is `WorkflowConsoleApp`. Its job is to register an implementation of `OrderProcessingWorkflow` in the Dapr's workflow runtime engine. In `WorkflowConsoleApp.java` file, you will find the `WorkflowConsoleApp` class and the `main` method. See the code snippet below:

```java
public class DemoWorkflowWorker {

public class WorkflowConsoleApp {
public static void main(String[] args) throws Exception {
// Register the Workflow with the runtime.
WorkflowRuntime.getInstance().registerWorkflow(DemoWorkflow.class);
System.out.println("Start workflow runtime");
WorkflowRuntime.getInstance().startAndBlock();
WorkflowRuntimeBuilder builder = new WorkflowRuntimeBuilder().registerWorkflow(OrderProcessingWorkflow.class);
builder.registerActivity(NotifyActivity.class);
builder.registerActivity(ProcessPaymentActivity.class);
builder.registerActivity(RequestApprovalActivity.class);
builder.registerActivity(ReserveInventoryActivity.class);
builder.registerActivity(UpdateInventoryActivity.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);
}
}
```

This application uses `WorkflowRuntime.getInstance().registerWorkflow()` in order to register `DemoWorkflow` as a Workflow in the Dapr Workflow runtime.
This application uses WorkflowRuntimeBuilder class to build up Dapr workflow runtime. `registerWorkflow()` method is used to register `OrderProcessingWorkflow` as a Workflow in the Dapr Workflow runtime, and `registerActivity()` method is used to register all the activities in `OrderProcessingWorkflow`.

`WorkflowRuntime.getInstance().start()` method will build and start the engine within the Dapr workflow runtime.
`runtime.start()` method will start the engine within the Dapr workflow runtime.

Now, execute the following script in order to run DemoWorkflowWorker:
Now, execute the following script in order to run WorkflowConsoleApp:
```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
dapr run --app-id WorkflowConsoleApp --resources-path ./components/workflows --dapr-grpc-port 50001 -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.workflows.console.WorkflowConsoleApp
```

### Running the Workflow client

The `DemoWorkflowClient` starts instances of workflows that have been registered with Dapr.
The `WorkflowClient` starts instances of OrderProcessingWorkflow that had been registered with Dapr.

With the DemoWorkflowWorker running, use the follow command to start the workflow with the DemoWorkflowClient:
With the WorkflowConsoleApp running, use the follow command to start the workflow with the WorkflowClient:

```sh
java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.workflows.DemoWorkflowClient
java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.workflows.client.WorkflowClient
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.dapr.examples.workflows.client;

import java.time.Duration;
import java.util.concurrent.TimeoutException;
import io.dapr.examples.workflows.console.models.OrderPayload;
import io.dapr.examples.workflows.console.workflows.OrderProcessingWorkflow;
import io.dapr.workflows.client.DaprWorkflowClient;
import io.dapr.workflows.client.WorkflowInstanceStatus;

public class WorkflowClient {

public static void main(String[] args) throws InterruptedException {
DaprWorkflowClient client = new DaprWorkflowClient();
try (client) {
testWorkflow(client);
}
}

private static void testWorkflow(DaprWorkflowClient client) {
// schedule Workflow to order two intel i7 13900KS CPUs
OrderPayload order = new OrderPayload();
order.setName("intel-i7-13900KS");
order.setTotalCost(9000);
order.setQuantity(2);
String instanceId = client.scheduleNewWorkflow(OrderProcessingWorkflow.class, order);
System.out.printf("scheduled new workflow instance of OrderProcessingWorkflow with instance ID: %s%n",
instanceId);

try {
client.waitForInstanceStart(instanceId, Duration.ofSeconds(10), false);
System.out.printf("workflow instance %s started%n", instanceId);
} catch (TimeoutException e) {
System.out.printf("workflow instance %s did not start within 10 seconds%n", instanceId);
return;
}

try {
WorkflowInstanceStatus workflowStatus = client.waitForInstanceCompletion(instanceId, Duration.ofSeconds(30),
true);
if (workflowStatus != null) {
System.out.printf("workflow instance %s completed, out is: %s %n", instanceId,
workflowStatus.getSerializedOutput());
} else {
System.out.printf("workflow instance %s not found%n", instanceId);
}
} catch (TimeoutException e) {
System.out.printf("workflow instance %s did not complete within 30 seconds%n", instanceId);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,33 @@
limitations under the License.
*/

package io.dapr.examples.workflows;
package io.dapr.examples.workflows.console;

import io.dapr.examples.workflows.console.activities.NotifyActivity;
import io.dapr.examples.workflows.console.activities.ProcessPaymentActivity;
import io.dapr.examples.workflows.console.activities.RequestApprovalActivity;
import io.dapr.examples.workflows.console.activities.ReserveInventoryActivity;
import io.dapr.examples.workflows.console.activities.UpdateInventoryActivity;
import io.dapr.examples.workflows.console.workflows.OrderProcessingWorkflow;
import io.dapr.workflows.runtime.WorkflowRuntime;
import io.dapr.workflows.runtime.WorkflowRuntimeBuilder;

/**
* For setup instructions, see the README.
*/
public class DemoWorkflowWorker {
public class WorkflowConsoleApp {

/**
* The main method of this app.
* The main method of this console app.
*
* @param args The port the app will listen on.
* @throws Exception An Exception.
*/
public static void main(String[] args) throws Exception {
// Register the Workflow with the builder.
WorkflowRuntimeBuilder builder = new WorkflowRuntimeBuilder().registerWorkflow(DemoWorkflow.class);
builder.registerActivity(DemoWorkflowActivity.class);
// Register the OrderProcessingWorkflow and its activities with the builder.
WorkflowRuntimeBuilder builder = new WorkflowRuntimeBuilder().registerWorkflow(OrderProcessingWorkflow.class);
builder.registerActivity(NotifyActivity.class);
builder.registerActivity(ProcessPaymentActivity.class);
builder.registerActivity(RequestApprovalActivity.class);
builder.registerActivity(ReserveInventoryActivity.class);
builder.registerActivity(UpdateInventoryActivity.class);

// Build and then start the workflow runtime pulling and executing tasks
try (WorkflowRuntime runtime = builder.build()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.dapr.examples.workflows.console.activities;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.dapr.examples.workflows.console.models.Notification;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;

public class NotifyActivity implements WorkflowActivity {
private static Logger logger = LoggerFactory.getLogger(NotifyActivity.class);

@Override
public Object run(WorkflowActivityContext ctx) {
Notification notification = ctx.getInput(Notification.class);
logger.info(notification.getMessage());

return "";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.dapr.examples.workflows.console.activities;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.dapr.examples.workflows.console.models.PaymentRequest;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;

public class ProcessPaymentActivity implements WorkflowActivity {
private static Logger logger = LoggerFactory.getLogger(ProcessPaymentActivity.class);

@Override
public Object run(WorkflowActivityContext ctx) {
PaymentRequest req = ctx.getInput(PaymentRequest.class);
logger.info("Processing payment: {} for {} {} at ${}",
req.getRequestId(), req.getAmount(), req.getItemName(), req.getCurrency());

// Simulate slow processing
try {
Thread.sleep(7 * 1000);
} catch (InterruptedException e) {
}
logger.info("Payment for request ID '{}' processed successfully", req.getRequestId());

return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.dapr.examples.workflows.console.activities;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.dapr.examples.workflows.console.models.ApprovalResult;
import io.dapr.examples.workflows.console.models.OrderPayload;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;

public class RequestApprovalActivity implements WorkflowActivity {
private static Logger logger = LoggerFactory.getLogger(RequestApprovalActivity.class);

@Override
public Object run(WorkflowActivityContext ctx) {
OrderPayload order = ctx.getInput(OrderPayload.class);
logger.info("Requesting approval for order: {}", order);

// hard code to Approved in example
logger.info("Approved requesting approval for order: {}", order);
return ApprovalResult.Approved;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package io.dapr.examples.workflows.console.activities;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.dapr.examples.workflows.console.models.InventoryItem;
import io.dapr.examples.workflows.console.models.InventoryRequest;
import io.dapr.examples.workflows.console.models.InventoryResult;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;

public class ReserveInventoryActivity implements WorkflowActivity {
private static Logger logger = LoggerFactory.getLogger(ReserveInventoryActivity.class);

@Override
public Object run(WorkflowActivityContext ctx) {
InventoryRequest inventoryRequest = ctx.getInput(InventoryRequest.class);
logger.info("Reserving inventory for order '{}' of {} {}",
inventoryRequest.getRequestId(), inventoryRequest.getQuantity(), inventoryRequest.getItemName());

// hard code that we have some inventory in this example
// TBD: use DaprClient to query state store for inventory
InventoryItem item = new InventoryItem();
item.setName(inventoryRequest.getItemName());
item.setQuantity(10);
item.setPerItemCost(10);
logger.info("There are {} {} available for purchase",
item.getQuantity(), item.getName());

// See if there're enough items to purchase
if (item.getQuantity() >= inventoryRequest.getQuantity()) {
// Simulate slow processing
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
}
logger.info("Reserved inventory for order '{}' of {} {}",
inventoryRequest.getRequestId(), inventoryRequest.getQuantity(), inventoryRequest.getItemName());
InventoryResult inventoryResult = new InventoryResult();
inventoryResult.setSuccess(true);
inventoryResult.setOrderPayload(item);
return inventoryResult;
}

// Not enough items.
logger.info("Not enough items to reserve inventory for order '{}' of {} {}",
inventoryRequest.getRequestId(), inventoryRequest.getQuantity(), inventoryRequest.getItemName());
InventoryResult inventoryResult = new InventoryResult();
inventoryResult.setSuccess(false);
inventoryResult.setOrderPayload(item);
return inventoryResult;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.dapr.examples.workflows.console.activities;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.dapr.examples.workflows.console.models.InventoryRequest;
import io.dapr.examples.workflows.console.models.InventoryResult;
import io.dapr.workflows.runtime.WorkflowActivity;
import io.dapr.workflows.runtime.WorkflowActivityContext;

public class UpdateInventoryActivity implements WorkflowActivity {
private static Logger logger = LoggerFactory.getLogger(UpdateInventoryActivity.class);

@Override
public Object run(WorkflowActivityContext ctx) {
InventoryRequest inventoryRequest = ctx.getInput(InventoryRequest.class);
logger.info("Updating inventory for order '{}' of {} {}",
inventoryRequest.getRequestId(), inventoryRequest.getQuantity(), inventoryRequest.getItemName());

// hard code that we updated inventory in this example
// TBD: use DaprClient to update state store for inventory
// Simulate slow processing
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
}
logger.info("Updated inventory for order '{}' of {} {}",
inventoryRequest.getRequestId(), inventoryRequest.getQuantity(), inventoryRequest.getItemName());
InventoryResult inventoryResult = new InventoryResult();
inventoryResult.setSuccess(true);
return inventoryResult;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.dapr.examples.workflows.console.models;

public enum ApprovalResult {
Unspecified,
Approved,
Rejected
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.dapr.examples.workflows.console.models;

public class InventoryItem {
private String name;
private double perItemCost;
private int quantity;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public double getPerItemCost() {
return perItemCost;
}

public void setPerItemCost(double perItemCost) {
this.perItemCost = perItemCost;
}

public int getQuantity() {
return quantity;
}

public void setQuantity(int quantity) {
this.quantity = quantity;
}

@Override
public String toString() {
return "InventoryItem [name=" + name + ", perItemCost=" + perItemCost + ", quantity=" + quantity + "]";
}
}
Loading