Skip to content

Commit cbabdab

Browse files
authored
Java workflow interpreter (#238)
* Add Java workflow interpreter example * Make the code more concise * Improve readme * Improve readme TS image workflows * Add to github workflows and to readmes * Remove unused methods * Fix jvm tests
1 parent c519d7c commit cbabdab

26 files changed

+1122
-6
lines changed

.github/workflows/release.yml

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ jobs:
3333
java-basics.zip
3434
java-food-ordering.zip
3535
java-subway-fare-calculator.zip
36+
java-workflow-interpreter.zip
3637
java-patterns-use-cases.zip
3738
java-hello-world-gradle.zip
3839
java-hello-world-maven.zip

.tools/run_jvm_tests.sh

+1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@ pushd $PROJECT_ROOT/java/tutorials/tour-of-restate-java && ./gradlew --console=p
2323

2424
pushd $PROJECT_ROOT/java/end-to-end-applications/food-ordering/app && ./gradlew --console=plain check && popd
2525
pushd $PROJECT_ROOT/java/end-to-end-applications/subway-fare-calculator && ./gradlew --console=plain check && popd
26+
pushd $PROJECT_ROOT/java/end-to-end-applications/workflow-interpreter && mvn verify && popd
2627
pushd $PROJECT_ROOT/kotlin/end-to-end-applications/food-ordering/app && ./gradlew --console=plain check && popd
2728
pushd $PROJECT_ROOT/kotlin/end-to-end-applications/kmp-android-todo-app && ./gradlew --console=plain check && popd

.tools/update_jvm_examples.sh

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ search_and_replace_version_gradle $PROJECT_ROOT/java/tutorials/tour-of-restate-j
3232
search_and_replace_version_gradle $PROJECT_ROOT/java/end-to-end-applications/subway-fare-calculator
3333
search_and_replace_version_gradle $PROJECT_ROOT/java/end-to-end-applications/food-ordering/app/restate-app
3434
search_and_replace_version_gradle $PROJECT_ROOT/java/end-to-end-applications/food-ordering/app/restaurant
35+
search_and_replace_version_gradle $PROJECT_ROOT/java/end-to-end-applications/workflow-interpreter
3536
search_and_replace_version_gradle $PROJECT_ROOT/kotlin/end-to-end-applications/food-ordering/app/restate-app
3637
search_and_replace_version_gradle $PROJECT_ROOT/kotlin/end-to-end-applications/food-ordering/app/restaurant
3738
search_and_replace_version_gradle $PROJECT_ROOT/kotlin/end-to-end-applications/kmp-android-todo-app/server

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Or have a look at the general catalog below:
8383
| Example Name | Languages |
8484
|-------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
8585
| <a id="food-ordering">Food Ordering App</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/end-to-end-applications/food-ordering) [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/end-to-end-applications/food-ordering) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/end-to-end-applications/food-ordering) [<img src="https://skillicons.dev/icons?i=kotlin&theme=light" width="24" height="24">](kotlin/end-to-end-applications/food-ordering) |
86-
| <a id="ai-image-workflows">AI Image Workflow Parser & Executor</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/end-to-end-applications/ai-image-workflows) |
86+
| <a id="ai-image-workflows">Image Workflow Parser & Executor</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/end-to-end-applications/ai-image-workflows) [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/end-to-end-applications/workflow-interpreter) |
8787
| <a id="chat-bot">LLM-powered Chat Bot / Task Agent</a> | [<img src="https://skillicons.dev/icons?i=ts" width="24" height="24">](typescript/end-to-end-applications/chat-bot) |
8888
| <a id="subway-fare-calculator">Subway Fare Calculator</a> | [<img src="https://skillicons.dev/icons?i=java&theme=light" width="24" height="24">](java/end-to-end-applications/subway-fare-calculator) |
8989
| <a id="rag-ingestion">RAG Ingestion</a> | [<img src="https://skillicons.dev/icons?i=python&theme=light" width="24" height="24">](python/end-to-end-applications/rag-ingestion) |

java/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Complete applications built with Restate:
4242

4343
- **[Food Ordering App](end-to-end-applications/food-ordering)**: A food delivery service (like DoorDash) that manages orders, restaurants, payments, and delivery drivers. The example mixes workflows (ordering) and stateful microservices (driver management), and uses Kafka as an event source for updates from delivery drivers.
4444
- **[Subway Fare Calculator](end-to-end-applications/subway-fare-calculator)**: A fare calculator for a subway system that calculates the fare based on distances traveled by customers. Implemented as Stateful Actors.
45+
- **[Image Workflow Parser & Executor](end-to-end-applications/workflow-interpreter)**: A dynamic workflow interpreter (Spring Boot) that parses a JSON list of image processing commands and runs them through image processing libraries.
4546

4647
## Templates
4748

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/mvnw text eol=lf
2+
*.cmd text eol=crlf
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
HELP.md
2+
target/
3+
!.mvn/wrapper/maven-wrapper.jar
4+
!**/src/main/**/target/
5+
!**/src/test/**/target/
6+
7+
generated-images/
8+
9+
### STS ###
10+
.apt_generated
11+
.classpath
12+
.factorypath
13+
.project
14+
.settings
15+
.springBeans
16+
.sts4-cache
17+
18+
### IntelliJ IDEA ###
19+
.idea
20+
*.iws
21+
*.iml
22+
*.ipr
23+
24+
### NetBeans ###
25+
/nbproject/private/
26+
/nbbuild/
27+
/dist/
28+
/nbdist/
29+
/.nb-gradle/
30+
build/
31+
!**/src/main/**/build/
32+
!**/src/test/**/build/
33+
34+
### VS Code ###
35+
.vscode/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
wrapperVersion=3.3.2
18+
distributionType=only-script
19+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Image Workflow Parser & Executor
2+
3+
This example implements a workflow that executes various AI image processing steps,
4+
like image generation and transformations.
5+
6+
The workflow is specified dynamically in a json-based workflow definition.
7+
The workflow can contain steps that call different image processing services:
8+
- to generate images by taking a screenshot with Puppeteer
9+
- to rotate images
10+
- to blur images
11+
12+
```txt
13+
+--------+ Request +------------------------+
14+
| Client | ------> | ImageProcessingWorkflow|
15+
+--------+ +------------------------+
16+
^ |
17+
| | Parse JSON workflow definition
18+
| v
19+
| +------------------------+
20+
| | Workflow Execution |----+
21+
| +------------------------+ |
22+
| | |
23+
| | +------------------------+
24+
| | | Optional Services |
25+
| | | (any order) |
26+
| | | +-----------------+ |
27+
| | | | PuppeteerService| |
28+
| | | +-----------------+ |
29+
| | | | TransformerSvc | |
30+
| | | | (/blur) | |
31+
| | | +-----------------+ |
32+
| | | | TransformerSvc | |
33+
| | | | (/rotate) | |
34+
| | | +-----------------+ |
35+
| | +------------------------+
36+
| | |
37+
| <-----------------+
38+
| |
39+
| | Concatenate
40+
| v
41+
| +------------------------+
42+
| | Result Assembly |
43+
| +------------------------+
44+
| |
45+
+<-------------------------|
46+
Result Report
47+
```
48+
49+
**Note:** For simplicity, this example stores images locally in the folder `generated-images`.
50+
51+
The example deploys each of the possible steps (generation, transformation) as
52+
a separate service, and then has a workflow service call them as specified in the
53+
workflow definition.
54+
55+
## Download the example
56+
57+
You can clone the example repository (`git clone https://github.com/restatedev/examples`) or just download this example via
58+
59+
- **CLI:** `restate example java-workflow-interpreter`
60+
61+
- **Zip archive:** https://github.com/restatedev/examples/releases/latest/download/java-workflow-interpreter.zip
62+
63+
## Running the example
64+
65+
1. Start Restate Server in a separate shell: `restate-server`
66+
67+
2. Start the workflow and image transformation services: `mvn compile spring-boot:run`
68+
69+
3. Register the example at Restate server by calling
70+
`restate -y deployment register "localhost:9080"`.
71+
72+
## Demo scenario
73+
74+
Here is list of example workflow execution requests that you can send to the workflow executor:
75+
76+
### Example workflow
77+
Puppeteer screenshot -> rotate -> blur:
78+
79+
```shell
80+
curl localhost:8080/ImageProcessingWorkflow/user123-wf1/run -H 'content-type: application/json' \
81+
-d '[
82+
{"action":"puppeteer","parameters":{"url":"https://restate.dev"}},
83+
{"action":"rotate","parameters":{"angle":90}},
84+
{"action":"blur","parameters":{"blur":5}}
85+
]'
86+
```
87+
88+
Have a look at the `generated-images` folder to see the end result.
89+
90+
### Retrieving state
91+
You can retrieve the workflow state via via the CLI.
92+
For example for id `user123-wf1`, do:
93+
94+
```shell
95+
restate kv get ImageProcessingWorkflow user123-wf1
96+
```
97+
Result:
98+
```
99+
🤖 State:
100+
―――――――――
101+
102+
Service ImageProcessingWorkflow
103+
Key user123-wf1
104+
105+
KEY VALUE
106+
status {
107+
"imgName": "c7879b2b-c213-f723-60c1-593422c98bc2",
108+
"output": [
109+
"[Took screenshot of website with url: https://restate.dev]",
110+
"[Rotated image with angle: 90]",
111+
"[Blurred image with strength param 5]"
112+
],
113+
"status": "Finished"
114+
}
115+
```
116+
117+
### More complex workflows
118+
119+
Try more complex workflows, and have a look at the end result.
120+
121+
- Puppeteer screenshot -> blur -> rotate -> rotate -> rotate -> rotate:
122+
123+
```shell
124+
curl localhost:8080/ImageProcessingWorkflow/user123-wf2/run -H 'content-type: application/json' \
125+
-d '[
126+
{"action":"puppeteer","parameters":{"url":"https://restate.dev"}},
127+
{"action":"blur","parameters":{"blur":5}},
128+
{"action":"rotate","parameters":{"angle":90}},
129+
{"action":"rotate","parameters":{"angle":90}},
130+
{"action":"rotate","parameters":{"angle":90}},
131+
{"action":"rotate","parameters":{"angle":90}}
132+
]'
133+
```
134+
135+
- Invalid workflow definition (no image source is defined):
136+
137+
```shell
138+
curl localhost:8080/ImageProcessingWorkflow/user123-wf3/run -H 'content-type: application/json' \
139+
-d '[
140+
{"action":"invalid","parameters":{"angle":90}},
141+
{"action":"blur","parameters":{"blur":5}}]}'
142+
```

0 commit comments

Comments
 (0)