Skip to content

Commit 2013d29

Browse files
committed
adding exercise 1
1 parent f88081a commit 2013d29

27 files changed

+2164
-2
lines changed

.bash_aliases

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
alias workspace="cd ${GITPOD_REPO_ROOT}"
2+
alias webui="gp preview $(gp url 8080)"
3+
4+
alias microservce="cd ${GITPOD_REPO_ROOT}/utilities/microservice && mvn exec:java -Dexec.mainClass="translationapi.Microservice""
5+
6+
alias ex1="cd ${GITPOD_REPO_ROOT}/exercises/durable-execution/practice"
7+
alias ex1s="cd ${GITPOD_REPO_ROOT}/exercises/durable-execution/solution"
8+
alias ex1w="mvn exec:java -Dexec.mainClass='translationworkflow.TranslationWorker'"
9+
ex1st() {
10+
mvn exec:java -Dexec.mainClass="translationworkflow.Starter" -Dexec.args="${1}"
11+
}
12+
13+
alias ex2="cd ${GITPOD_REPO_ROOT}/exercises/testing-code/practice"
14+
alias ex2s="cd ${GITPOD_REPO_ROOT}/exercises/testing-code/solution"
15+
alias ex2t="mvn test"
16+
17+
18+
alias ex3="cd ${GITPOD_REPO_ROOT}/exercises/debug-activity/practice"
19+
alias ex3s="cd ${GITPOD_REPO_ROOT}/exercises/debug-activity/solution"
20+
alias ex3w="mvn exec:java -Dexec.mainClass='pizzaworkflow.PizzaWorker'"
21+
alias ex3st="mvn exec:java -Dexec.mainClass='pizzaworkflow.Starter'"
22+
23+
export PATH="$PATH:/workspace/bin"
24+
echo "temporal configured! try typing temporal -v"
25+
echo "Your workspace is located at: ${GITPOD_REPO_ROOT}"
26+
echo "Type the command workspace to return to the workspace directory at any time."

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*.zip
1919
*.tar.gz
2020
*.rar
21+
*.lst
2122

2223
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
2324
hs_err_pid*

.gitpod.yml

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
image: gitpod/workspace-full:2023-01-16-03-31-28
2+
tasks:
3+
- name: Set up aliases
4+
init: cp .bash_aliases ~/.bash_aliases
5+
- name: Temporal Local Development Server
6+
init: |
7+
curl -sSf https://temporal.download/cli.sh | sh -s - --dir /workspace
8+
command: |
9+
cp .bash_aliases ~/.bash_aliases
10+
echo "waiting for server...."
11+
clear
12+
source /workspace/edu-converters-java-code/.bash_aliases
13+
export TEMPORAL_CORS_ORIGINS=http://localhost:3000
14+
/workspace/bin/temporal server start-dev --ui-port 8080 --db-filename /workspace/.cluster-persistence.db
15+
- name: Worker
16+
command: |
17+
gp ports await 7233 && gp ports await 8080 && sleep 5 && gp preview $(gp url 8080)
18+
source /workspace/edu-converters-java-code/.bash_aliases
19+
clear
20+
echo "Use this terminal to run your Worker"
21+
openMode: tab-after
22+
- name: Terminal
23+
command: |
24+
gp open README.md
25+
pushd exercises/testing-code/solution
26+
mvn compile
27+
mvn clean
28+
popd
29+
source /workspace/edu-converters-java-code/.bash_aliases
30+
clear
31+
echo "Use this terminal to run commands.."
32+
openMode: split-right
33+
34+
ports:
35+
- name: Temporal server
36+
port: 7233
37+
onOpen: ignore
38+
- name: Temporal Web UI v2
39+
port: 8080 # temporal UI
40+
description: New (v2) Temporal Web UI
41+
onOpen: ignore
42+
visibility: private
43+
- name: Greeting Service
44+
description: Local microservice used in exercises
45+
port: 9999
46+
onOpen: ignore
47+
visibility: private
48+
49+
vscode:
50+
extensions:
51+
- golang.Go
52+
- ms-python.python
53+
- redhat.java
54+
- vscjava.vscode-java-test
55+
- vscjava.vscode-java-debug
56+
- wingrunr21.vscode-ruby

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 temporal.io
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+38-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,38 @@
1-
# edu-converters-java-code
2-
Code exercises for Converters in java
1+
# Code Repository for Temporal Converters (Java)
2+
3+
This repository provides code used for exercises and demonstrations
4+
included in the Java version of the
5+
[Converters](https://learn.temporal.io/courses/converters)
6+
training course.
7+
8+
It's important to remember that the example code used in this course was designed
9+
to support learning a specific aspect of Temporal, not to serve as a ready-to-use
10+
template for implementing a production system.
11+
12+
## Hands-On Exercises
13+
14+
| Directory Name | Exercise |
15+
| :--------------------------- | :------------------------------------------------- |
16+
| `exercises/custom-converter` | [Exercise 1](exercises/custom-converter/README.md) |
17+
| `exercises/codec-server` | [Exercise 2](exercises/codec-server/README.md) |
18+
19+
## Reference
20+
21+
The following links provide additional information that you may find helpful as you work through this course.
22+
23+
- [General Temporal Documentation](https://docs.temporal.io/)
24+
- [Temporal Java SDK Documentation](https://www.javadoc.io/doc/io.temporal/temporal-sdk/latest/index.html)
25+
- [Java Language Documentation](https://docs.oracle.com/en/java/)
26+
- [GitPod Documentation: Troubleshooting](https://www.gitpod.io/docs/troubleshooting)
27+
28+
## Exercise Environment for this Course
29+
30+
You can launch an exercise environment for this course in GitPod by
31+
clicking the button below:
32+
33+
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/temporalio/edu-converters-java-code)
34+
35+
Alternatively, you can follow
36+
[these instructions](https://learn.temporal.io/getting_started/java/dev_environment/) to
37+
set up your own Temporal Cluster with Docker Compose, which you can use as an
38+
exercise environment.

exercises/custom-converter/README.md

+214
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# Exercise 1: Implement a Custom Data Converter
2+
3+
During this exercise, you will:
4+
5+
- Output typical payloads from a Temporal Workflow using the default Data Converter
6+
- Implement a Custom Data Converter that encrypts Workflow output
7+
- Implement a Failure Converter and demonstrate parsing its output
8+
9+
Make your changes to the code in the `practice` subdirectory (look for
10+
`TODO` comments that will guide you to where you should make changes to
11+
the code). If you need a hint or want to verify your changes, look at
12+
the complete version in the `solution` subdirectory.
13+
14+
### GitPod Environment Shortcuts
15+
16+
If you are executing the exercises in the provided GitPod environment, you
17+
can take advantage of certain aliases to aid in navigation and execution of
18+
the code.
19+
20+
| Command | Action |
21+
| :------ | :------------------------------------------------------------------------------------------------------------------------------ |
22+
| `ex1` | Change to Exercise 1 Practice Directory |
23+
| `ex1s` | Change to Exercise 1 Solution Directory |
24+
| `ex1w` | Execute the Exercise 1 Worker. Must be within the appropriate directory for this to succeed. (either `practice` or `solution`) |
25+
| `ex1st` | Execute the Exercise 1 Starter. Must be within the appropriate directory for this to succeed. (either `practice` or `solution`) |
26+
27+
## Part A: Implement a Custom Data Converter
28+
29+
1. Defining a Custom Data Converter is a straightforward change to your existing
30+
Worker and Starter code. The example in the `practice` subdirectory of this
31+
exercise is missing the necessary change to use a Custom Data Converter,
32+
meaning that you can run it out of the box, and produce JSON output using the
33+
Default Data Converter. You'll do this first, so you have an idea of the
34+
expected output. First, start the Worker:
35+
36+
```shell
37+
mvn exec:java -Dexec.mainClass="customconverter.ConverterWorker"
38+
```
39+
40+
2. Next, run the Workflow starter:
41+
42+
```shell
43+
mvn exec:java -Dexec.mainClass="customconverter.Starter"
44+
```
45+
46+
3. After that, you can use the `temporal` CLI to show the Workflow result:
47+
48+
```shell
49+
temporal workflow show -w converters_workflowID
50+
```
51+
52+
```
53+
Progress:
54+
ID Time Type
55+
1 2024-03-14T16:01:21Z WorkflowExecutionStarted
56+
2 2024-03-14T16:01:21Z WorkflowTaskScheduled
57+
3 2024-03-14T16:01:21Z WorkflowTaskStarted
58+
4 2024-03-14T16:01:21Z WorkflowTaskCompleted
59+
5 2024-03-14T16:01:21Z ActivityTaskScheduled
60+
6 2024-03-14T16:01:21Z ActivityTaskStarted
61+
7 2024-03-14T16:01:21Z ActivityTaskCompleted
62+
8 2024-03-14T16:01:21Z WorkflowTaskScheduled
63+
9 2024-03-14T16:01:21Z WorkflowTaskStarted
64+
10 2024-03-14T16:01:21Z WorkflowTaskCompleted
65+
11 2024-03-14T16:01:21Z WorkflowExecutionCompleted
66+
67+
Result:
68+
Status: COMPLETED
69+
Output: ["Received Plain text input"]
70+
```
71+
72+
You should now have an idea of how this Workflow runs ordinarily — it outputs
73+
the string "Received Plain text input". In the next step, you'll add a Custom
74+
Data Converter.
75+
76+
4. To add a Custom Data Converter, you don't need to change anything in your
77+
Workflow code. You only need to add a `CodecDataConverter` parameter to
78+
`WorkflowClient client = WorkflowClient.newInstance(service);` where it is used
79+
in both `ConverterWorker.java` and `Starter.java`.
80+
1. Replace `WorkflowClient client = WorkflowClient.newInstance(service);` in
81+
both files with
82+
```java
83+
WorkflowClient client = WorkflowClient.newInstance(service, WorkflowClientOptions.newBuilder()
84+
.setDataConverter(
85+
new CodecDataConverter(
86+
DefaultDataConverter.newDefaultInstance(),
87+
Collections.singletonList(new CustomPayloadCodec())))
88+
.build());
89+
```
90+
5. Next, review `CustomPayloadCodec.java`. This contains the Custom Converter
91+
code you'll be using. The `encode()` method applies the `encodePayload()` method
92+
to each element in the payload. The `encodePayload()` method compresses the payload
93+
using Java's [snappy](https://github.com/google/snappy) codec, and sets the
94+
file metadata. The `decode()` and `decodePayload()` methods do the same thing,
95+
but in reverse. Add the missing calls to the `encode` method (you can use the
96+
`decode()` function as a hint).
97+
6. Now you can re-run the Workflow with your Custom Converter.
98+
99+
1. Stop your Worker (with `Ctrl+C` in a blocking terminal)
100+
1. Recompile your code
101+
102+
```shell
103+
mvn clean compile
104+
```
105+
106+
1. Restart the worker using
107+
108+
```shell
109+
mvn exec:java -Dexec.mainClass="customconverter.ConverterWorker"
110+
```
111+
112+
1. Rerun the workflow with
113+
114+
```shell
115+
mvn exec:java -Dexec.mainClass="customconverter.Starter"
116+
```
117+
118+
1. Finally, get the result again with
119+
120+
```shell
121+
temporal workflow show -w converter-workflow
122+
```
123+
124+
This time, your output will be encoded:
125+
126+
```shell
127+
...
128+
Result:
129+
Status: COMPLETED
130+
Output: [encoding binary/snappy: payload encoding is not supported]
131+
```
132+
133+
The `payload encoding is not supported` message is normal — the Temporal
134+
Cluster itself can't use the `decode` method directly without a Codec
135+
Server, which you'll create in the next exercise. In the meantime, you have
136+
successfully implemented a Custom Data Converter, and in the next step, you'll
137+
add more features to it.
138+
139+
## Part B: Implement a Failure Converter
140+
141+
1. The next feature you may add is a Failure Converter. Failure messages and
142+
stack traces are not encoded as codec-capable Payloads by default; you must
143+
explicitly enable encoding these common attributes on failures. If your
144+
errors might contain sensitive information, you can encrypt the message and
145+
stack trace by configuring the default Failure Converter to use your encoded
146+
attributes, in which case it moves your `message` and `stack_trace` fields to a
147+
Payload that's run through your codec. To do this, you can override the
148+
default Failure Converter with a single additional parameter, `true`.
149+
1. Locate the `WorkflowClient.newInstance...` code you added in the previous exercise.
150+
1. Add the value `true` as the last value in the `new DataCodecConverter()` constructor.
151+
1. Do this in both `ConverterWorker.java` and `Starter.java`
152+
2. To test your Failure Converter, change your Workflow to return an artificial
153+
error.
154+
155+
1. Add the following code after executing your Activity.
156+
157+
```java
158+
throw ApplicationFailure.newFailure("Artificial Error", "Artificial Error");
159+
```
160+
161+
1. Comment out all code after the `throw` statement as that code will
162+
become unreachable.
163+
1. Stop your worker using `Ctrl-C`
164+
1. Recompile your code
165+
166+
```shell
167+
mvn clean compile
168+
```
169+
170+
1. Restart the worker using
171+
172+
```shell
173+
mvn exec:java -Dexec.mainClass="customconverter.ConverterWorker"
174+
```
175+
176+
1. Rerun the workflow with
177+
178+
```shell
179+
mvn exec:java -Dexec.mainClass="customconverter.Starter"
180+
```
181+
182+
1. You should see a stack trace appear. This was expected. Stop the execution
183+
using `Ctrl-C`.
184+
185+
1. Finally, get the result again with to get the status of your failed Workflow.
186+
187+
```shell
188+
temporal workflow show -w converter-workflow
189+
```
190+
191+
Notice that the `Failure:` field should now display an encoded
192+
result, rather than a plain text error:
193+
194+
```
195+
Progress:
196+
ID Time Type
197+
1 2024-03-14T17:08:20Z WorkflowExecutionStarted
198+
2 2024-03-14T17:08:20Z WorkflowTaskScheduled
199+
3 2024-03-14T17:08:20Z WorkflowTaskStarted
200+
4 2024-03-14T17:08:20Z WorkflowTaskCompleted
201+
5 2024-03-14T17:08:20Z ActivityTaskScheduled
202+
6 2024-03-14T17:08:20Z ActivityTaskStarted
203+
7 2024-03-14T17:08:20Z ActivityTaskCompleted
204+
8 2024-03-14T17:08:20Z WorkflowTaskScheduled
205+
9 2024-03-14T17:08:20Z WorkflowTaskStarted
206+
10 2024-03-14T17:08:20Z WorkflowTaskCompleted
207+
11 2024-03-14T17:08:20Z WorkflowExecutionFailed
208+
209+
Result:
210+
Status: FAILED
211+
Failure: &Failure{Message:Encoded failure,Source:JavaSDK,StackTrace:,Cause:nil,FailureType:Failure_ApplicationFailureInfo,}
212+
```
213+
214+
### This is the end of the exercise.

0 commit comments

Comments
 (0)