-
Notifications
You must be signed in to change notification settings - Fork 224
Adding remote activities example with Spring Boot #1550
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
69b2cde
Revert "Generate updated javadocs for 1.15.1"
salaboy 23c0d71
git add remote activities example, refactor modules
salaboy 481d069
Revert "Revert "Generate updated javadocs for 1.15.1""
salaboy 4f2063b
updating pipeline for MM
salaboy ff952fc
updating tests to cover multiple apps
salaboy 6142860
fix right path
salaboy f5e3af2
adding tests to orchestrator
salaboy 9c3ff8e
fixing failsafe classpath
salaboy 2737510
refactor multi-app
salaboy e37b38c
Add Tool Calling to Java SDK (#1481)
siri-varma 3cc84b9
rename cross app -> multi app (#1555)
cicoyle fd80260
updating tests to validate output from APIs
salaboy 0077ffc
moving tests to IT for failsafe, update failsafe version, and update …
salaboy b04bc21
fixing comments from Javi
salaboy 7e3c6f7
removing else blocks
salaboy 06516c4
fix Cassie's suggestions
salaboy 2bf6fc7
fixing path
salaboy 4a88bca
Merge branch 'master' into 1548-remote-activities-sb
salaboy 748caab
Merge branch 'master' into 1548-remote-activities-sb
siri-varma File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ jobs: | |
distribution: 'temurin' | ||
java-version: ${{ env.JDK_VER }} | ||
- name: Run tests | ||
run: ./mvnw clean install -B -q | ||
run: ./mvnw clean install -B -q -DskipITs=true | ||
- name: Codecov | ||
uses: codecov/[email protected] | ||
- name: Upload test report for sdk | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
# Multi App workflow Example | ||
|
||
This example demonstrates how you can create distributed workflows where the orchestrator doesn't host the workflow activities. | ||
|
||
For more documentation about how Multi App Workflows work [check the official documentation here](https://v1-16.docs.dapr.io/developing-applications/building-blocks/workflow/workflow-multi-app/). | ||
|
||
This example is composed by three Spring Boot applications: | ||
- `orchestrator`: The `orchestrator` app contains the Dapr Workflow definition and expose REST endpoints to create and raise events against workflow instances. | ||
- `worker-one`: The `worker-one` app contains the `RegisterCustomerActivity` definition, which will be called by the `orchestrator` app. | ||
- `worker-two`: The `worker-two` app contains the `CustomerFollowupActivity` definition, which will be called by the `orchestrator` app. | ||
|
||
To start the applications you need to run the following commands on separate terminals, starting from the `multi-app` directory. | ||
To start the `orchestrator` app run: | ||
```bash | ||
cd orchestrator/ | ||
mvn -Dspring-boot.run.arguments="--reuse=true" clean spring-boot:test-run | ||
``` | ||
|
||
The `orchestrator` application will run on port `8080`. | ||
|
||
On a separate terminal, to start the `worker-one` app run: | ||
```bash | ||
cd worker-one/ | ||
mvn -Dspring-boot.run.arguments="--reuse=true" clean spring-boot:test-run | ||
``` | ||
|
||
The `worker-one` application will run on port `8081`. | ||
|
||
On a separate terminal, to start the `worker-two` app run: | ||
```bash | ||
cd worker-two/ | ||
mvn -Dspring-boot.run.arguments="--reuse=true" clean spring-boot:test-run | ||
``` | ||
|
||
The `worker-two` application will run on port `8082`. | ||
|
||
You can create new workflow instances of the `CustomerWorkflow` by calling the `/customers` endpoint of the `orchestrator` application. | ||
|
||
```bash | ||
curl -X POST localhost:8080/customers -H 'Content-Type: application/json' -d '{ "customerName": "salaboy" }' | ||
``` | ||
|
||
The workflow definition [`CustomerWorkflow`](orchstrator/src/main/java/io/dapr/springboot/examples/orchestrator/CustomerWorkflow.java) that you can find inside the `orchestrator` app, | ||
performs the following orchestration when a new workflow instance is created: | ||
|
||
- Call the `RegisterCustomerActivity` activity which can be found inside the `worker-one` application. | ||
- You can find in the workflow definition the configuration to make reference to an Activity that is hosted by a different Dapr application. | ||
```java | ||
customer = ctx.callActivity("io.dapr.springboot.examples.workerone.RegisterCustomerActivity", | ||
customer, | ||
new WorkflowTaskOptions("worker-one"), | ||
Customer.class). | ||
await(); | ||
``` | ||
- Wait for an external event of type `CustomerReachOut` with a timeout of 5 minutes: | ||
```java | ||
ctx.waitForExternalEvent("CustomerReachOut", Duration.ofMinutes(5), Customer.class).await(); | ||
``` | ||
- You can check the status of the workflow for a given customer by sending the following request: | ||
```shell | ||
curl -X POST localhost:8080/customers/status -H 'Content-Type: application/json' -d '{ "customerName": "salaboy" }' | ||
``` | ||
- You can call the following endpoint on the `orchestrator` app to raise the external event: | ||
```shell | ||
curl -X POST localhost:8080/customers/followup -H 'Content-Type: application/json' -d '{ "customerName": "salaboy" }' | ||
``` | ||
- When the event is received, the workflow move forward to the last activity called `CustomerFollowUpActivity`, that can be found on the `worker-two` app. | ||
```java | ||
customer = ctx.callActivity("io.dapr.springboot.examples.workertwo.CustomerFollowupActivity", | ||
customer, | ||
new WorkflowTaskOptions("worker-two"), | ||
Customer.class). | ||
await(); | ||
``` | ||
- The workflow completes by handing out the final version of the `Customer` object that has been modified the workflow activities. You can retrieve the `Customer` payload | ||
by running the following command: | ||
```shell | ||
curl -X POST localhost:8080/customers/output -H 'Content-Type: application/json' -d '{ "customerName": "salaboy" }' | ||
``` | ||
|
||
## Testing Multi App Workflows | ||
|
||
Testing becomes a complex task when you are dealing with multiple Spring Boot applications. For testing this workflow, | ||
we rely on [Testcontainers](https://testcontainers.com) to create the entire setup which enable us to run the workflow end to end. | ||
|
||
You can find the end-to-end test in the [`OrchestratorAppIT.java`](orchestrator/src/test/java/io/dapr/springboot/examples/orchestrator/OrchestratorAppIT.java) class inside the `orchestrator` application. | ||
This test interact with the application REST endpoints to validate their correct execution. | ||
|
||
But the magic behind the test can be located in the [`DaprTestContainersConfig.class`](orchestrator/src/test/java/io/dapr/springboot/examples/orchestrator/DaprTestContainersConfig.java) which defines the configuration for | ||
all the Dapr containers and the `worker-one` and `worker-two` applications. Check this class to gain a deeper understand how to configure | ||
multiple Dapr-enabled applications. |
81 changes: 81 additions & 0 deletions
81
spring-boot-examples/workflows/multi-app/orchestrator/pom.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>io.dapr</groupId> | ||
<artifactId>multi-app</artifactId> | ||
<version>1.17.0-SNAPSHOT</version> | ||
cicoyle marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</parent> | ||
|
||
<artifactId>orchestrator</artifactId> | ||
<name>orchestrator</name> | ||
<description>Spring Boot, Testcontainers and Dapr Integration Examples :: Orchestrator App</description> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-actuator</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-web</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-starter-test</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.dapr.spring</groupId> | ||
<artifactId>dapr-spring-boot-starter</artifactId> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.dapr.spring</groupId> | ||
<artifactId>dapr-spring-boot-starter-test</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.redis</groupId> | ||
<artifactId>testcontainers-redis</artifactId> | ||
<version>2.2.2</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>io.rest-assured</groupId> | ||
<artifactId>rest-assured</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.springframework.boot</groupId> | ||
<artifactId>spring-boot-maven-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>repackage</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-site-plugin</artifactId> | ||
<configuration> | ||
<skip>true</skip> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-checkstyle-plugin</artifactId> | ||
<configuration> | ||
<!-- Skip checkstyle for auto-generated code --> | ||
<skip>true</skip> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
59 changes: 59 additions & 0 deletions
59
...lti-app/orchestrator/src/main/java/io/dapr/springboot/examples/orchestrator/Customer.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright 2025 The Dapr Authors | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package io.dapr.springboot.examples.orchestrator; | ||
|
||
public class Customer { | ||
private String customerName; | ||
private String workflowId; | ||
private boolean inCustomerDB = false; | ||
private boolean followUp = false; | ||
|
||
public boolean isFollowUp() { | ||
return followUp; | ||
} | ||
|
||
public void setFollowUp(boolean followUp) { | ||
this.followUp = followUp; | ||
} | ||
|
||
public boolean isInCustomerDB() { | ||
return inCustomerDB; | ||
} | ||
|
||
public void setInCustomerDB(boolean inCustomerDB) { | ||
this.inCustomerDB = inCustomerDB; | ||
} | ||
|
||
public String getWorkflowId() { | ||
return workflowId; | ||
} | ||
|
||
public void setWorkflowId(String workflowId) { | ||
this.workflowId = workflowId; | ||
} | ||
|
||
public String getCustomerName() { | ||
return customerName; | ||
} | ||
|
||
public void setCustomerName(String customerName) { | ||
this.customerName = customerName; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Customer [customerName=" + customerName + ", workflowId=" + workflowId + ", inCustomerDB=" | ||
+ inCustomerDB + ", followUp=" + followUp + "]"; | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
...orchestrator/src/main/java/io/dapr/springboot/examples/orchestrator/CustomerWorkflow.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* Copyright 2025 The Dapr Authors | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package io.dapr.springboot.examples.orchestrator; | ||
|
||
import io.dapr.durabletask.TaskCanceledException; | ||
import io.dapr.durabletask.TaskFailedException; | ||
import io.dapr.workflows.Workflow; | ||
import io.dapr.workflows.WorkflowStub; | ||
import io.dapr.workflows.WorkflowTaskOptions; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.time.Duration; | ||
|
||
@Component | ||
public class CustomerWorkflow implements Workflow { | ||
|
||
@Override | ||
public WorkflowStub create() { | ||
return ctx -> { | ||
String instanceId = ctx.getInstanceId(); | ||
Customer customer = ctx.getInput(Customer.class); | ||
customer.setWorkflowId(instanceId); | ||
ctx.getLogger().info("Let's register the customer: {}", customer.getCustomerName()); | ||
|
||
customer = ctx.callActivity("io.dapr.springboot.examples.workerone.RegisterCustomerActivity", customer, | ||
new WorkflowTaskOptions("worker-one"), Customer.class).await(); | ||
|
||
ctx.getLogger().info("Let's wait for the customer: {} to request a follow up.", customer.getCustomerName()); | ||
ctx.waitForExternalEvent("CustomerReachOut", Duration.ofMinutes(5), Customer.class).await(); | ||
|
||
ctx.getLogger().info("Let's book a follow up for the customer: {}", customer.getCustomerName()); | ||
customer = ctx.callActivity("io.dapr.springboot.examples.workertwo.CustomerFollowupActivity", | ||
customer, new WorkflowTaskOptions("worker-two"), Customer.class).await(); | ||
|
||
ctx.getLogger().info("Congratulations the customer: {} is happy!", customer.getCustomerName()); | ||
|
||
ctx.getLogger().info("Final customer: {} ", customer); | ||
ctx.complete(customer); | ||
}; | ||
} | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.