You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,7 +29,7 @@ These samples demonstrate various capabilities of Java Cadence client and server
29
29
30
30
***Custom Workflow Controls** ([`com.uber.cadence.samples.query`](src/main/java/com/uber/cadence/samples/query/)) — workflow queries that return **markdown** for Cadence Web (Markdoc buttons that **signal** workflows or **start** new workflows). **Requires Cadence Web v4.0.14+.** Copy-paste run instructions: [query samples README](src/main/java/com/uber/cadence/samples/query/README.md).
31
31
32
-
***DataConverter Samples** ([`com.uber.cadence.samples.dataconverter`](src/main/java/com/uber/cadence/samples/dataconverter/)) — three production-ready custom `DataConverter` patterns (gzip compression, AES-256-GCM encryption, and S3 / claim-check offload) that transparently transform every workflow input, output, and activity parameter. Copy-paste run instructions: [dataconverter samples README](src/main/java/com/uber/cadence/samples/dataconverter/README.md).
32
+
***DataConverter Samples** ([`com.uber.cadence.samples.dataconverter`](src/main/java/com/uber/cadence/samples/dataconverter/)) — three custom `DataConverter` patterns (gzip compression, AES-256-GCM encryption, and BlobStore / S3 claim-check offload) that transparently transform every workflow input, output, and activity parameter. Copy-paste run instructions: [dataconverter samples README](src/main/java/com/uber/cadence/samples/dataconverter/README.md).
Copy file name to clipboardExpand all lines: src/main/java/com/uber/cadence/samples/dataconverter/README.md
+12-12Lines changed: 12 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# DataConverter Samples
2
2
3
-
Three production-ready patterns for custom `DataConverter` implementations in the Cadence Java client: **compression**, **encryption**, and **S3 / claim-check offload**. A `DataConverter` controls how every workflow input, output, and activity parameter is serialized before it is written to Cadence history — making it the right place to add compression, encryption, or external offloading without changing any workflow or activity code.
3
+
Three practical patterns for custom `DataConverter` implementations in the Cadence Java client: **compression**, **encryption**, and **BlobStore / S3 claim-check offload**. A `DataConverter` controls how every workflow input, output, and activity parameter is serialized before it is written to Cadence history — making it the right place to add compression, encryption, or external offloading without changing any workflow or activity code.
4
4
5
5
## What is a DataConverter?
6
6
@@ -60,7 +60,7 @@ Run **one** of the starters per sample run. Each starts a new workflow execution
@@ -72,21 +72,21 @@ You can also start any of the three from the Cadence CLI; the commands are print
72
72
73
73
## Compression Sample
74
74
75
-
`CompressedDataConverterWorkflow` demonstrates gzip-over-JSON compression. For repetitive JSON data this typically achieves 60–80% size reduction, lowering storage cost and bandwidth for large workflow payloads. The converter is implemented in [`CompressedJsonDataConverter.java`](CompressedJsonDataConverter.java) — it wraps `JsonDataConverter.getInstance()` and post-processes the resulting bytes through `java.util.zip.GZIP*Stream`.
75
+
`CompressedDataConverterWorkflow` demonstrates gzip-over-JSON compression. For repetitive JSON data this typically achieves 60–80% size reduction, lowering storage cost and bandwidth for large workflow payloads. The converter is implemented in [`CompressedJsonDataConverter.java`](CompressedJsonDataConverter.java) — it wraps `JsonDataConverter.getInstance()`, post-processes the resulting bytes through `java.util.zip.GZIP*Stream`, and caps decompressed output to avoid unbounded memory growth on malformed input.
`EncryptedDataConverterWorkflow` demonstrates AES-256-GCM encryption. Every workflow input, output, and activity parameter is encrypted before being written to Cadence history. Without the key, the data stored by the Cadence server — including any operators browsing workflow history — is completely opaque.
84
+
`EncryptedDataConverterWorkflow` demonstrates AES-256-GCM encryption. Every workflow input, output, and activity parameter is encrypted before being written to Cadence history. Without the key, payloads stored by the Cadence server are unreadable to operators browsing workflow history. Logs, metrics, search attributes, and application output are separate disclosure surfaces.
85
85
86
86
The sample uses a `SensitiveCustomerRecord` containing realistic PII and PHI fields (name, email, SSN, credit card, medical notes) to make the use case concrete.
The GCM authentication tag (16 bytes) ensures any ciphertext tampering is detected. The random nonce means the same plaintext produces different ciphertext on every call, preventing replay detection by an attacker observing Cadence history.
107
+
The GCM authentication tag (16 bytes) ensures any ciphertext tampering is detected. The random nonce means the same plaintext produces different ciphertext on every call, which preserves semantic security for repeated payloads.
108
108
109
109
---
110
110
111
111
## S3 Offload Sample (claim-check pattern)
112
112
113
-
`S3OffloadDataConverterWorkflow` demonstrates the *claim-check* pattern: payloads larger than a configurable threshold are stored in an external [`BlobStore`](BlobStore.java) and only a small reference (a few dozen bytes) travels through Cadence workflow history. This solves Cadence's per-payload size limits (~2 MB) for workflows that pass very large datasets between the workflow and its activities.
113
+
`S3OffloadDataConverterWorkflow` demonstrates the *claim-check* pattern: payloads larger than a configurable threshold are stored in an external [`BlobStore`](BlobStore.java) and only a small reference (a few dozen bytes) travels through Cadence workflow history. The runnable sample uses [`LocalFsBlobStore`](LocalFsBlobStore.java) so it works without cloud credentials; the same abstraction can be backed by S3 in production. This solves Cadence's per-payload size limits (~2 MB) for workflows that pass very large datasets between the workflow and its activities.
-`toData`: JSON-encode → if `len(json) > thresholdBytes`, upload to `BlobStore` under a SHA-256 key and return `0x01 || {"__s3_ref":"<bucket>/<sha256hex>"}`. Otherwise return `0x00 || json` inline.
120
+
-`toData`: JSON-encode → if `len(json) > thresholdBytes`, upload to `BlobStore` under a SHA-256 key and return `0x01 || {"s3Ref":"<bucket>/<sha256hex>"}`. Otherwise return `0x00 || json` inline.
121
121
-`fromData` / `fromDataArray`: read prefix byte → if `0x01`, fetch from `BlobStore` and decode; if `0x00`, decode inline.
122
122
123
123
SHA-256-of-payload is used as the key so `toData` is idempotent across Cadence workflow replays. Using a fresh UUID per call would write a new orphaned blob on every replay.
@@ -150,9 +150,9 @@ You can also point the SDK at [LocalStack](https://localstack.cloud/) or [MinIO]
150
150
|---------|----------|
151
151
|**Compression**| Large repetitive JSON payloads; reducing storage cost without confidentiality requirements |
152
152
|**Encryption**| PII, PHI, secrets, or any data that must be unreadable in Cadence history |
Patterns can be composed: encrypt-then-compress, or encrypt-then-offload to S3 for maximum security and minimum history size.
155
+
Patterns can be composed, but order matters. Compress before encrypting when size reduction is a goal; encrypt before offloading when the external store should only receive ciphertext.
0 commit comments