diff --git a/.github/workflows/notify_slack.yml b/.github/workflows/notify_slack.yml
index d45ccd4..8ddb5d0 100644
--- a/.github/workflows/notify_slack.yml
+++ b/.github/workflows/notify_slack.yml
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Send issue notification to Slack
if: github.event_name == 'issues'
- uses: slackapi/slack-github-action@v3.0.1
+ uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3.0.1
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL_ISSUE }}
webhook-type: incoming-webhook
@@ -27,7 +27,7 @@ jobs:
- name: Send pull request notification to Slack
if: github.event_name == 'pull_request_target'
- uses: slackapi/slack-github-action@v3.0.1
+ uses: slackapi/slack-github-action@af78098f536edbc4de71162a307590698245be95 # v3.0.1
with:
webhook: ${{ secrets.SLACK_WEBHOOK_URL_PR }}
webhook-type: incoming-webhook
diff --git a/README.md b/README.md
index f6c7822..50086a3 100644
--- a/README.md
+++ b/README.md
@@ -64,6 +64,7 @@ for details.
- [AWS Lambda durable functions Documentation](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html)
- [JavaScript SDK Repository](https://github.com/aws/aws-durable-execution-sdk-js)
- [Python SDK Repository](https://github.com/aws/aws-durable-execution-sdk-python)
+- [Java SDK Repository](https://github.com/aws/aws-durable-execution-sdk-java)
## Feedback & Support
diff --git a/aws-lambda-durable-functions-power/POWER.md b/aws-lambda-durable-functions-power/POWER.md
index 578e286..ca7a587 100644
--- a/aws-lambda-durable-functions-power/POWER.md
+++ b/aws-lambda-durable-functions-power/POWER.md
@@ -31,6 +31,7 @@ Before using AWS Lambda durable functions, verify:
2. **Runtime environment** is ready:
- For TypeScript/JavaScript: Node.js 22+ (`node --version`)
- For Python: Python 3.11+ (`python --version`. Note that currently only Lambda runtime environments 3.13+ come with the Durable Execution SDK pre-installed. 3.11 is the min supported Python version by the Durable SDK itself, however, you could use OCI to bring your own container image with your own Python runtime + Durable SDK.)
+ - For Java: Java 17+ (`java --version`)
3. **Deployment capability** exists (one of):
- AWS SAM CLI (`sam --version`) 1.153.1 or higher
@@ -40,7 +41,8 @@ Before using AWS Lambda durable functions, verify:
## Step 2: Check user and project preferences
Ask which IaC framework to use for new projects.
-Ask which programming language to use if unclear, clarify between JavaScript and TypeScript if necessary.
+Ask which programming language to use. Supported languages are: **TypeScript**, **JavaScript**, **Python**, and **Java**. If the user says JavaScript or TypeScript, clarify between the two if necessary.
+**IMPORTANT**: Only install the SDK and set up the project for the language the user chose. Do NOT install SDKs or create project files for other languages.
Ask to create a git repo for projects if one doesn't exist already.
### Error Scenarios
@@ -59,6 +61,8 @@ Ask to create a git repo for projects if one doesn't exist already.
### Step 3: Install SDK
+Install **only** the SDK for the language the user selected in Step 2.
+
**For TypeScript/JavaScript:**
```bash
@@ -73,6 +77,24 @@ pip install aws-durable-execution-sdk-python
pip install aws-durable-execution-sdk-python-testing
```
+**For Java (Maven):**
+
+```xml
+
+ software.amazon.lambda.durable
+ aws-durable-execution-sdk-java
+ 1.0.0
+
+
+
+
+ software.amazon.lambda.durable
+ aws-durable-execution-sdk-java-testing
+ 1.0.0
+ test
+
+```
+
## When to Load Reference Files
Load the appropriate reference file based on what the user is working on:
@@ -115,12 +137,25 @@ def handler(event: dict, context: DurableContext) -> dict:
return result
```
+**Java:**
+
+```java
+public class MyHandler extends DurableHandler {
+ @Override
+ public MyOutput handleRequest(MyInput input, DurableContext ctx) {
+ var result = ctx.step("process", Result.class,
+ stepCtx -> processData(input));
+ return new MyOutput(result);
+ }
+}
+```
+
### Critical Rules
-1. **All non-deterministic code MUST be in steps** (Date.now, Math.random, API calls)
+1. **All non-deterministic code MUST be in steps** (Date.now, Math.random, UUID.randomUUID, API calls)
2. **Cannot nest durable operations** - use `runInChildContext` to group operations
3. **Closure mutations are lost on replay** - return values from steps
-4. **Side effects outside steps repeat** - use `context.logger` (replay-aware)
+4. **Side effects outside steps repeat** - use `context.logger` / `ctx.getLogger()` (replay-aware)
### Python API Differences
@@ -131,6 +166,22 @@ The Python SDK differs from TypeScript in several key areas:
- **Exceptions**: `ExecutionError` (permanent), `InvocationError` (transient), `CallbackError` (callback failures)
- **Testing**: Use `DurableFunctionTestRunner` class directly - instantiate with handler, use context manager, call `run(input=...)`
+### Java API Differences
+
+The Java SDK differs from TypeScript/Python in several key areas:
+
+- **Handler**: Extend `DurableHandler` and implement `handleRequest(I input, DurableContext ctx)`
+- **Steps**: `ctx.step("name", ResultType.class, stepCtx -> ...)` — type class required for deserialization
+- **Generic types**: Use `TypeToken` for parameterized types: `ctx.step("name", new TypeToken>() {}, stepCtx -> ...)`
+- **Wait**: `ctx.wait("name", Duration.ofMinutes(5))` — uses `java.time.Duration`
+- **Async**: `stepAsync()`, `waitAsync()`, `mapAsync()`, `runInChildContextAsync()` return `DurableFuture`
+- **Callbacks**: `ctx.createCallback("name", Type.class)` returns `DurableCallbackFuture`; or use `ctx.waitForCallback()`
+- **Map**: `ctx.map("name", items, Type.class, (item, index, childCtx) -> ...)` with `MapFunction` interface
+- **Configuration**: Override `createConfiguration()` to return `DurableConfig` for custom SerDes, thread pools, Lambda client
+- **Exceptions**: `StepFailedException`, `StepInterruptedException`, `CallbackTimeoutException`, `CallbackFailedException`, `WaitForConditionFailedException`
+- **Testing**: `LocalDurableTestRunner.create(InputType.class, handler)` with `runUntilComplete(input)` and `getOperation("name")`
+- **Logging**: `ctx.getLogger()` returns `DurableLogger` (SLF4J MDC-based, replay-aware)
+
### Invocation Requirements
Durable functions **require qualified ARNs** (version, alias, or `$LATEST`):
@@ -163,10 +214,10 @@ See here: https://docs.aws.amazon.com/lambda/latest/dg/durable-security.html
When writing or reviewing durable function code, ALWAYS check for these replay model violations:
-1. **Non-deterministic code outside steps**: `Date.now()`, `Math.random()`, UUID generation, API calls, database queries must all be inside steps
+1. **Non-deterministic code outside steps**: `Date.now()`, `Math.random()`, `UUID.randomUUID()`, API calls, database queries must all be inside steps
2. **Nested durable operations in step functions**: Cannot call `context.step()`, `context.wait()`, or `context.invoke()` inside a step function — use `context.runInChildContext()` instead
3. **Closure mutations that won't persist**: Variables mutated inside steps are NOT preserved across replays — return values from steps instead
-4. **Side effects outside steps that repeat on replay**: Use `context.logger` for logging (it is replay-aware and deduplicates automatically)
+4. **Side effects outside steps that repeat on replay**: Use `context.logger` / `ctx.getLogger()` for logging (it is replay-aware and deduplicates automatically)
When implementing or modifying tests for durable functions, ALWAYS verify:
@@ -175,10 +226,12 @@ When implementing or modifying tests for durable functions, ALWAYS verify:
3. Replay behavior is tested with multiple invocations
4. TypeScript: Use `LocalDurableTestRunner` for local testing
5. Python: Use `DurableFunctionTestRunner` class directly
+6. Java: Use `LocalDurableTestRunner.create(InputType.class, handler)` with `runUntilComplete(input)`
## Resources
- [AWS Lambda durable functions Documentation](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html)
- [JavaScript SDK Repository](https://github.com/aws/aws-durable-execution-sdk-js)
- [Python SDK Repository](https://github.com/aws/aws-durable-execution-sdk-python)
+- [Java SDK Repository](https://github.com/aws/aws-durable-execution-sdk-java)
- [IAM Policy Reference](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSLambdaBasicDurableExecutionRolePolicy.html)
diff --git a/aws-lambda-durable-functions-power/README.md b/aws-lambda-durable-functions-power/README.md
index d634613..956ad99 100644
--- a/aws-lambda-durable-functions-power/README.md
+++ b/aws-lambda-durable-functions-power/README.md
@@ -79,6 +79,7 @@ When you mention these keywords, Kiro will automatically load this power:
- [AWS Lambda durable functions Documentation](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html)
- [JavaScript SDK Repository](https://github.com/aws/aws-durable-execution-sdk-js)
- [Python SDK Repository](https://github.com/aws/aws-durable-execution-sdk-python)
+- [Java SDK Repository](https://github.com/aws/aws-durable-execution-sdk-java)
- [Kiro Powers Documentation](https://kiro.dev/docs/powers/create/)
## License
diff --git a/aws-lambda-durable-functions-power/steering/advanced-patterns.md b/aws-lambda-durable-functions-power/steering/advanced-patterns.md
index c0983ee..d3953f5 100644
--- a/aws-lambda-durable-functions-power/steering/advanced-patterns.md
+++ b/aws-lambda-durable-functions-power/steering/advanced-patterns.md
@@ -96,6 +96,32 @@ def handler(event: dict, context: DurableContext) -> str:
context.logger.debug('Tool result added', extra={'tool': tool['name']})
```
+**Java:**
+
+```java
+public class AIAgentHandler extends DurableHandler {
+ @Override
+ public String handleRequest(AgentInput input, DurableContext ctx) {
+ ctx.getLogger().info("Starting AI agent: {}", input.getPrompt());
+ var messages = new ArrayList