From 5dbccb63cef2d18c2b988b66401271055f579e21 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Sat, 11 Jul 2026 12:57:25 -0700 Subject: [PATCH 01/20] Added pattern lambda-durable-java-sam --- .../JavaLambdaDurableFunctions/.gitignore | 13 + .../DEVELOPER_GUIDE.md | 670 ++++++++++++++++++ .../JavaLambdaDurableFunctions/README.md | 208 ++++++ .../JavaLambdaDurableFunctions/USER_GUIDE.md | 485 +++++++++++++ .../build-and-deploy.sh | 75 ++ .../durable-functions/Dockerfile | 8 + .../durable-functions/pom.xml | 91 +++ .../chaining/OrderProcessingHandler.java | 107 +++ .../ResilientPaymentHandler.java | 162 +++++ .../fanout/ParallelProcessingHandler.java | 119 ++++ .../ApprovalWorkflowHandler.java | 122 ++++ .../BatchDataProcessorHandler.java | 122 ++++ .../samples/durable/models/OrderItem.java | 26 + .../samples/durable/models/OrderRequest.java | 27 + .../durable/models/ProcessingResult.java | 32 + .../durable/monitoring/JobMonitorHandler.java | 129 ++++ .../OrderFulfillmentHandler.java | 190 +++++ .../timer/ScheduledReminderHandler.java | 101 +++ .../events/approval-event.json | 6 + .../events/chaining-event.json | 7 + .../events/errorhandling-event.json | 5 + .../events/fanout-event.json | 5 + .../events/mapprocessing-event.json | 5 + .../events/monitoring-event.json | 5 + .../events/suborchestration-event.json | 9 + .../events/timer-event.json | 6 + .../durable-functions-sam/template.yaml | 290 ++++++++ .../infrastructure/ec2-client-instance.yaml | 354 +++++++++ .../sns-message-sender/pom.xml | 59 ++ .../sns/producer/DurableFunctionsTrigger.java | 166 +++++ .../javaSNSLambdaDynamoDB/.gitignore | 24 + .../sns_consumer_dynamo_sam/.gitignore | 25 + .../sns_consumer_dynamo_sam/README.md | 95 +++ .../sns_consumer_dynamo_sam/events/event.json | 31 + .../sns_event_consumer_function/.gitignore | 1 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../sns_event_consumer_function/pom.xml | 89 +++ .../samples/events/sns/DynamoDBUpdater.java | 79 +++ .../lambda/samples/events/sns/HandlerSNS.java | 84 +++ .../lambda/samples/events/sns/Person.java | 138 ++++ .../events/sns/DynamoDBUpdaterTest.java | 105 +++ .../samples/events/sns/HandlerSNSTest.java | 73 ++ .../samples/events/sns/TestContext.java | 45 ++ .../lambda/samples/events/sns/TestLogger.java | 14 + .../sns_consumer_dynamo_sam/template.yaml | 78 ++ .../sns_message_sender_json/.classpath | 38 + .../sns_message_sender_json/.gitignore | 1 + .../sns_message_sender_json/.project | 23 + .../org.eclipse.core.resources.prefs | 6 + .../.settings/org.eclipse.jdt.core.prefs | 8 + .../sns_message_sender_json/Commands | 4 + .../sns_message_sender_json/pom.xml | 73 ++ .../java/sns/producer/JsonSNSProducer.java | 143 ++++ .../src/main/java/sns/producer/Person.java | 133 ++++ .../src/main/resources/us-500.csv | 500 +++++++++++++ .../javaSNSLambdaDynamoDB/README.md | 2 + 56 files changed, 5424 insertions(+) create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/.gitignore create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/DEVELOPER_GUIDE.md create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/README.md create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/USER_GUIDE.md create mode 100755 lambda-durable-java-sam/JavaLambdaDurableFunctions/build-and-deploy.sh create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/Dockerfile create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/pom.xml create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderItem.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderRequest.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/ProcessingResult.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/approval-event.json create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/chaining-event.json create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/errorhandling-event.json create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/fanout-event.json create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/mapprocessing-event.json create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/monitoring-event.json create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/suborchestration-event.json create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/timer-event.json create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/template.yaml create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/infrastructure/ec2-client-instance.yaml create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/pom.xml create mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/src/main/java/sns/producer/DurableFunctionsTrigger.java create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/.gitignore create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/.gitignore create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/README.md create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/events/event.json create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.gitignore create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.settings/org.eclipse.jdt.core.prefs create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/pom.xml create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdater.java create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNS.java create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/Person.java create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdaterTest.java create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNSTest.java create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestContext.java create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestLogger.java create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/template.yaml create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.classpath create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.gitignore create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.project create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.core.resources.prefs create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.jdt.core.prefs create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/Commands create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/pom.xml create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/JsonSNSProducer.java create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/Person.java create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/resources/us-500.csv create mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/README.md diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/.gitignore b/lambda-durable-java-sam/JavaLambdaDurableFunctions/.gitignore new file mode 100644 index 0000000000..03d0710633 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/.gitignore @@ -0,0 +1,13 @@ +target/ +build/ +.aws-sam/ +*.class +*.jar +*.log +.idea/ +*.iml +.classpath +.project +.settings/ +.DS_Store +dependency-reduced-pom.xml diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/DEVELOPER_GUIDE.md b/lambda-durable-java-sam/JavaLambdaDurableFunctions/DEVELOPER_GUIDE.md new file mode 100644 index 0000000000..ccff063d0f --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/DEVELOPER_GUIDE.md @@ -0,0 +1,670 @@ +# Lambda Durable Functions in Java - Developer Guide + +## Table of Contents + +1. [Architecture Overview](#architecture-overview) +2. [The Durable Execution Model](#the-durable-execution-model) +3. [Java SDK Reference](#java-sdk-reference) +4. [DurableHandler Base Class](#durablehandler-base-class) +5. [Durable Operations](#durable-operations) +6. [Error Handling and Retries](#error-handling-and-retries) +7. [Deployment Model](#deployment-model) +8. [Best Practices](#best-practices) +9. [Testing](#testing) +10. [Common Pitfalls](#common-pitfalls) + +--- + +## Architecture Overview + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ AWS Cloud │ +│ │ +│ ┌───────────┐ ┌──────────────────────────────────────────┐ │ +│ │ SNS Topic │────>│ Lambda Durable Function │ │ +│ └───────────┘ │ │ │ +│ ▲ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ +│ │ │ │ Step 1 │─>│ Step 2 │─>│ Step 3 │ │ │ +│ ┌────┴────┐ │ │(chkpt) │ │(chkpt) │ │(chkpt) │ │ │ +│ │Producer │ │ └─────────┘ └─────────┘ └─────────┘ │ │ +│ │(EC2/CLI)│ │ │ │ │ │ │ +│ └─────────┘ │ ▼ ▼ ▼ │ │ +│ │ ┌────────────────────────────────────┐ │ │ +│ │ │ Checkpoint Store (managed) │ │ │ +│ │ └────────────────────────────────────┘ │ │ +│ └──────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌──────────┐ │ +│ │ DynamoDB │ │ +│ └──────────┘ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +### Components + +| Component | Role | +|-----------|------| +| **SNS Topic** | Event source that triggers the durable functions | +| **Lambda Durable Functions** | Business logic with automatic checkpointing | +| **Checkpoint Store** | Managed by Lambda; stores step results and execution state | +| **DynamoDB** | Optional application state for this workshop | +| **ECR** | Container registry for the Java function images | +| **Producer (EC2/CLI)** | Sends messages to SNS to trigger workflows | + +--- + +## The Durable Execution Model + +### Lifecycle of a Durable Execution + +``` +1. INVOKE → Function starts, SDK initializes +2. EXECUTE STEP → Business logic runs inside ctx.step() +3. CHECKPOINT → Result saved to checkpoint store +4. WAIT/SUSPEND → Function exits, no compute charges +5. RESUME → Backend re-invokes the function +6. REPLAY → SDK runs from top, skips checkpointed steps +7. CONTINUE → Execution continues from where it left off +``` + +### Replay: The Core Mechanism + +When a durable function resumes (after a wait, retry delay, or interruption), the SDK uses **replay**: + +1. Your code runs from the **beginning** of `handleRequest()` +2. When it hits a `step()` that already has a checkpoint, the SDK returns the **stored result** instantly +3. When it hits the first un-checkpointed operation, normal execution resumes + +This means your code must be **deterministic** between steps. Do NOT: +- Use `System.currentTimeMillis()` or `Math.random()` outside of steps +- Mutate external state outside of steps +- Branch on non-deterministic values between steps + +### What Goes Inside a Step vs. Outside + +| Inside `context.step()` | Outside steps | +|--------------------------|---------------| +| API calls | Control flow (if/else, loops) | +| Database operations | Variable assignments from step results | +| Current time / random values | Logging via `context.getLogger()` | +| Side effects (notifications) | Calling other durable operations | +| Non-deterministic code | Pure computation on step results | + +--- + +## Java SDK Reference + +### Maven Dependency + +```xml + + software.amazon.lambda.durable + aws-durable-execution-sdk-java + 1.0.0 + +``` + +### Key Packages + +```java +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableHandler; +import software.amazon.lambda.durable.DurableFuture; +import software.amazon.lambda.durable.DurableCallbackFuture; +import software.amazon.lambda.durable.StepContext; +import software.amazon.lambda.durable.TypeToken; + +import software.amazon.lambda.durable.config.StepConfig; +import software.amazon.lambda.durable.config.StepSemantics; +import software.amazon.lambda.durable.config.CallbackConfig; +import software.amazon.lambda.durable.config.WaitForCallbackConfig; +import software.amazon.lambda.durable.config.ParallelConfig; +import software.amazon.lambda.durable.config.MapConfig; +import software.amazon.lambda.durable.config.CompletionConfig; +import software.amazon.lambda.durable.config.WaitForConditionConfig; +import software.amazon.lambda.durable.config.RunInChildContextConfig; +import software.amazon.lambda.durable.config.InvokeConfig; + +import software.amazon.lambda.durable.retry.RetryStrategies; +import software.amazon.lambda.durable.retry.RetryStrategy; +import software.amazon.lambda.durable.retry.RetryDecision; +import software.amazon.lambda.durable.retry.JitterStrategy; +import software.amazon.lambda.durable.retry.WaitStrategies; +import software.amazon.lambda.durable.retry.WaitForConditionWaitStrategy; + +import software.amazon.lambda.durable.model.ParallelResult; +import software.amazon.lambda.durable.model.MapResult; +import software.amazon.lambda.durable.model.WaitForConditionResult; + +import software.amazon.lambda.durable.exception.StepFailedException; +import software.amazon.lambda.durable.exception.StepInterruptedException; +import software.amazon.lambda.durable.exception.CallbackFailedException; +import software.amazon.lambda.durable.exception.DurableOperationException; +``` + +--- + +## DurableHandler Base Class + +Every durable function extends `DurableHandler`: + +```java +public class MyHandler extends DurableHandler, Map> { + @Override + public Map handleRequest(Map event, DurableContext context) { + // Your durable workflow here + return result; + } +} +``` + +- `I` = Input type (the Lambda event) +- `O` = Output type (the return value) +- `DurableContext` replaces the standard Lambda `Context` + +### DurableContext Methods + +| Method | Description | +|--------|-------------| +| `step(name, resultType, func)` | Execute and checkpoint a unit of work | +| `stepAsync(name, resultType, func)` | Non-blocking step, returns `DurableFuture` | +| `wait(name, duration)` | Suspend for a duration (no compute) | +| `waitAsync(name, duration)` | Non-blocking wait | +| `waitForCondition(name, type, checkFunc, config)` | Poll until condition met | +| `createCallback(name, resultType)` | Create a callback and suspend | +| `waitForCallback(name, resultType, func)` | Create + submit + wait in one call | +| `parallel(name)` | Execute branches concurrently | +| `map(name, items, resultType, func)` | Process collection concurrently | +| `runInChildContext(name, resultType, func)` | Isolated sub-workflow | +| `runInChildContextAsync(name, resultType, func)` | Non-blocking sub-workflow | +| `invoke(name, functionName, payload, resultType)` | Call another Lambda function | +| `getLogger()` | Replay-aware logger | + +--- + +## Durable Operations + +### Step + +The fundamental building block. Executes code and checkpoints the result. + +```java +// Basic step +String result = context.step("my-step", String.class, stepCtx -> { + return "computed value"; +}); + +// Step with retry configuration +StepConfig config = StepConfig.builder() + .retryStrategy(RetryStrategies.exponentialBackoff( + 5, // maxAttempts + Duration.ofSeconds(2), // initialDelay + Duration.ofMinutes(1), // maxDelay + 2.0, // backoffRate + JitterStrategy.FULL)) // jitter + .build(); + +Map result = context.step("api-call", Map.class, stepCtx -> { + return callExternalApi(); +}, config); +``` + +**StepContext** provides: +- `stepCtx.getLogger()` - Durable logger +- `stepCtx.getAttempt()` - Current retry attempt (0-based) +- `stepCtx.isReplaying()` - Whether this is a replay + +### Wait + +Suspends execution without compute charges. + +```java +// Fixed delay +context.wait("delay-30s", Duration.ofSeconds(30)); + +// Async wait (minimum duration pattern) +DurableFuture timer = context.waitAsync("min-5s", Duration.ofSeconds(5)); +DurableFuture work = context.stepAsync("process", String.class, ctx -> doWork()); +timer.get(); // Ensure at least 5s elapsed +String r = work.get(); // Get the work result +``` + +### Wait for Condition (Polling) + +Polls an external system with configurable backoff. + +```java +WaitForConditionWaitStrategy> strategy = (state, attempt) -> { + if (attempt >= 20) throw new RuntimeException("Timeout"); + return Duration.ofSeconds(Math.min(5 * (long)Math.pow(2, attempt - 1), 300)); +}; + +Map finalState = context.waitForCondition( + "poll-status", + new TypeToken<>() {}, + (state, stepCtx) -> { + String status = checkStatus((String) state.get("id")); + Map updated = Map.of("id", state.get("id"), "status", status); + if ("DONE".equals(status)) { + return WaitForConditionResult.stopPolling(updated); + } + return WaitForConditionResult.continuePolling(updated); + }, + WaitForConditionConfig.>builder() + .initialState(Map.of("id", "job-123", "status", "PENDING")) + .waitStrategy(strategy) + .build() +); +``` + +### Callback (Human Interaction) + +Suspend and wait for an external system to respond. + +```java +// Approach 1: Manual callback +DurableCallbackFuture> callback = + context.createCallback("wait-approval", (Class>)(Class)Map.class, + CallbackConfig.builder().timeout(Duration.ofHours(72)).build()); + +// Send callback.callbackId() to the approver +notifyApprover(callback.callbackId()); + +// Execution suspends here until external callback arrives +Map decision = callback.get(); + +// Approach 2: Composite (create + submit + wait) +String result = context.waitForCallback("approval", String.class, + (callbackId, stepCtx) -> sendApprovalEmail(callbackId)); +``` + +**External system completes callback via AWS CLI:** +```bash +aws lambda send-durable-execution-callback-success \ + --callback-id --result '{"approved":true}' +``` + +### Parallel (Fan-Out/Fan-In) + +Execute different operations concurrently. + +```java +DurableFuture aFuture; +DurableFuture bFuture; + +try (var parallel = context.parallel("my-parallel")) { + aFuture = parallel.branch("branch-a", String.class, ctx -> + ctx.step("work-a", String.class, s -> computeA())); + bFuture = parallel.branch("branch-b", Integer.class, ctx -> + ctx.step("work-b", Integer.class, s -> computeB())); + ParallelResult result = parallel.get(); + // result.succeeded(), result.failed() +} + +String a = aFuture.get(); +int b = bFuture.get(); +``` + +**Configuration options:** +```java +ParallelConfig config = ParallelConfig.builder() + .maxConcurrency(5) + .completionConfig(CompletionConfig.firstSuccessful()) // Race pattern + .build(); +``` + +### Map (Collection Processing) + +Apply the same operation to every item in a collection. + +```java +MapResult result = context.map( + "process-items", + List.of("a", "b", "c"), + String.class, + (item, index, ctx) -> ctx.step("transform-" + index, String.class, + s -> item.toUpperCase()), + MapConfig.builder() + .maxConcurrency(3) + .completionConfig(CompletionConfig.toleratedFailureCount(1)) + .build() +); + +List successes = result.succeeded(); +``` + +### Child Context (Sub-Orchestration) + +Isolate groups of operations into reusable sub-workflows. + +```java +// Sequential sub-workflow +Map result = context.runInChildContext( + "payment-flow", Map.class, + child -> { + String auth = child.step("authorize", String.class, s -> authorize()); + child.wait("delay", Duration.ofSeconds(2)); + return child.step("capture", Map.class, s -> capture(auth)); + }); + +// Concurrent sub-workflows +DurableFuture paymentFuture = context.runInChildContextAsync( + "payment", String.class, child -> processPayment(child)); +DurableFuture inventoryFuture = context.runInChildContextAsync( + "inventory", String.class, child -> reserveInventory(child)); + +List results = DurableFuture.allOf(paymentFuture, inventoryFuture); +``` + +### Invoke (Cross-Function Calls) + +Call another Lambda function and suspend until it completes. + +```java +OrderResult result = context.invoke( + "process-order", + "order-processor-function:live", // Must include alias/version qualifier + event, + OrderResult.class +); +``` + +--- + +## Error Handling and Retries + +### Exception Hierarchy + +``` +DurableExecutionException (base) +├── UnrecoverableDurableExecutionException +│ ├── IllegalDurableOperationException +│ └── NonDeterministicExecutionException +├── DurableOperationException +│ ├── StepFailedException ← retry exhausted +│ ├── StepInterruptedException ← at-most-once interrupted +│ ├── CallbackFailedException ← external system reported failure +│ └── CallbackTimeoutException ← callback timed out +└── SerDesException ← serialization failed +``` + +### Retry Strategies + +```java +// Built-in exponential backoff +RetryStrategies.exponentialBackoff(maxAttempts, initialDelay, maxDelay, backoffRate, jitter) + +// Fixed delay +RetryStrategies.fixedDelay(maxAttempts, fixedDelay) + +// Presets +RetryStrategies.Presets.DEFAULT // 6 attempts, 5s initial, 60s max, 2x, full jitter +RetryStrategies.Presets.NO_RETRY // Fail immediately + +// Custom strategy +RetryStrategy custom = (error, attempt) -> { + if (error instanceof BusinessLogicException) return RetryDecision.fail(); + if (attempt >= 5) return RetryDecision.fail(); + return RetryDecision.retry(Duration.ofSeconds(attempt * 3)); +}; +``` + +### At-Most-Once Semantics + +For non-idempotent operations (payments, notifications): + +```java +StepConfig config = StepConfig.builder() + .semantics(StepSemantics.AT_MOST_ONCE_PER_RETRY) + .build(); + +try { + String txnId = context.step("charge", String.class, s -> chargeCard(), config); +} catch (StepInterruptedException e) { + // Step started but was interrupted before checkpointing + // Check external system for actual status +} +``` + +### Saga Compensation Pattern + +```java +Map payment = context.step("charge", Map.class, s -> charge()); + +try { + context.step("ship", Map.class, s -> shipOrder()); +} catch (StepFailedException e) { + // Compensation: refund the payment + context.step("refund", Map.class, s -> refund(payment.get("txnId"))); + return Map.of("status", "COMPENSATED"); +} +``` + +--- + +## Deployment Model + +### Container Image (Required for Java) + +Java durable functions deploy as **container images** (not zip files). + +**Dockerfile:** +```dockerfile +FROM --platform=linux/amd64 amazoncorretto:21-alpine AS builder +WORKDIR /build +COPY pom.xml . +COPY src ./src +RUN apk add --no-cache maven && mvn clean package -DskipTests + +FROM public.ecr.aws/lambda/java:21 +COPY --from=builder /build/target/*.jar ${LAMBDA_TASK_ROOT}/lib/ +CMD ["com.example.MyHandler::handleRequest"] +``` + +### DurableConfig + +When creating the function via CLI: +```bash +aws lambda create-function \ + --function-name my-function \ + --package-type Image \ + --code ImageUri= \ + --role \ + --durable-config '{"ExecutionTimeout": 900, "RetentionPeriodInDays": 7}' +``` + +| Parameter | Description | Range | +|-----------|-------------|-------| +| `ExecutionTimeout` | Max total execution time (seconds) | 1 - 31536000 (1 year) | +| `RetentionPeriodInDays` | How long to keep execution history | 1 - 365 | + +### IAM Role + +Use the managed policy: +``` +arn:aws:iam::aws:policy/service-role/AWSLambdaBasicDurableExecutionRolePolicy +``` + +For callback support, also add: +```json +{ + "Effect": "Allow", + "Action": [ + "lambda:SendDurableExecutionCallbackSuccess", + "lambda:SendDurableExecutionCallbackFailure", + "lambda:SendDurableExecutionCallbackHeartbeat" + ], + "Resource": "*" +} +``` + +### Versioning + +Always invoke with a published version or alias: +```bash +aws lambda publish-version --function-name my-function +# Invoke with :1 or :my-alias, not $LATEST +``` + +--- + +## Best Practices + +### 1. Keep Steps Focused + +Each step should do ONE thing. Don't put multiple API calls in a single step. + +```java +// GOOD: One concern per step +String userId = context.step("create-user", String.class, s -> createUser(email)); +String walletId = context.step("create-wallet", String.class, s -> createWallet(userId)); + +// BAD: Multiple concerns in one step +Map result = context.step("setup", Map.class, s -> { + String userId = createUser(email); + String walletId = createWallet(userId); // If this fails, createUser re-runs! + return Map.of("userId", userId, "walletId", walletId); +}); +``` + +### 2. Pass Data Via Return Values + +Never rely on shared mutable state between steps. + +```java +// GOOD: Data flows through step return values +String userId = context.step("register", String.class, s -> register(email)); +context.wait("delay", Duration.ofMinutes(10)); +context.step("welcome", Void.class, s -> { sendWelcome(userId); return null; }); + +// BAD: Shared variable mutation lost on replay +AtomicReference userId = new AtomicReference<>(""); +context.step("register", Void.class, s -> { userId.set(register(email)); return null; }); +context.wait("delay", Duration.ofMinutes(10)); +// userId is "" after replay! +``` + +### 3. Deterministic Code Between Steps + +Code between steps runs on every replay. Keep it deterministic. + +```java +// GOOD: Deterministic branching +String status = context.step("check", String.class, s -> getStatus()); +if ("READY".equals(status)) { // Deterministic: same value on replay + context.step("process", ...); +} + +// BAD: Non-deterministic branching +if (System.currentTimeMillis() % 2 == 0) { // Different on each replay! + context.step("process", ...); +} +``` + +### 4. Use Descriptive Step Names + +Names appear in logs, execution history, and debugging tools. + +```java +// GOOD +context.step("validate-shipping-address", ...); +context.step("charge-credit-card", ...); + +// BAD +context.step("step1", ...); +context.step("s", ...); +``` + +### 5. Configure Appropriate Timeouts + +Set `ExecutionTimeout` based on your longest expected execution path including all waits. + +### 6. Use Replay-Aware Logging + +```java +// GOOD: Uses the durable logger (logs once, not on every replay) +context.getLogger().info("Order processed"); + +// Inside steps: +context.step("work", String.class, stepCtx -> { + stepCtx.getLogger().info("Processing..."); // Only logs on actual execution + return result; +}); +``` + +--- + +## Testing + +### Local Test Runner + +```java +import software.amazon.lambda.durable.testing.LocalDurableTestRunner; +import software.amazon.lambda.durable.model.ExecutionStatus; + +@Test +void testChainingHandler() { + var handler = new OrderProcessingHandler(); + var runner = LocalDurableTestRunner.create(Map.class, handler); + + Map event = Map.of( + "orderId", "TEST-001", + "totalAmount", 99.99, + "customerId", "CUST-001" + ); + + var result = runner.runUntilComplete(event); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + Map output = result.getResult(Map.class); + assertEquals("COMPLETED", output.get("finalStatus")); +} +``` + +### SAM CLI Local Invoke + +```bash +# Build and run locally +sam build +sam local invoke ChainingFunction --event events/chaining-event.json + +# For callbacks, use sam local callback +sam local callback succeed --result '{"decision":"APPROVED"}' +``` + +--- + +## Common Pitfalls + +| Pitfall | Problem | Solution | +|---------|---------|----------| +| Side effects outside steps | Not checkpointed, re-executes on replay | Wrap in `context.step()` | +| Mutable shared state | Lost on replay after wait/resume | Return values from steps | +| Non-deterministic branching | Different path on replay | Only branch on step results | +| `Thread.sleep()` | Blocks compute, charges you | Use `context.wait()` | +| Very large step results | May exceed checkpoint size limit | Keep results under 256KB | +| Nested steps | Not supported | Use `runInChildContext()` | +| Steps inside parallel branches accessing parent context | Corrupts execution state | Use the child context parameter | +| Missing version qualifier | Non-deterministic replay on $LATEST | Always use published version/alias | +| `new Date()` between steps | Non-deterministic on replay | Put inside a step | + +--- + +## Comparison with Python Workshop + +This Java workshop covers all patterns from the Python durable functions workshop, with working implementations: + +| Python Workshop Module | Java Workshop Equivalent | +|------------------------|--------------------------| +| Function Chaining | Module 3: `OrderProcessingHandler` | +| Fan-Out/Fan-In | Module 4: `ParallelProcessingHandler` | +| Human Interaction | Module 5: `ApprovalWorkflowHandler` | +| Monitor (Polling) | Module 6: `JobMonitorHandler` | +| Timer/Delay | Module 7: `ScheduledReminderHandler` | +| Error Handling | Module 8: `ResilientPaymentHandler` | +| (Not in Python) | Module 9: `BatchDataProcessorHandler` (Map) | +| (Not in Python) | Module 10: `OrderFulfillmentHandler` (Sub-orchestration) | + +The Java workshop adds Map Processing and Sub-Orchestration patterns not present in the Python workshop, providing more comprehensive coverage of the SDK's capabilities. diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/README.md b/lambda-durable-java-sam/JavaLambdaDurableFunctions/README.md new file mode 100644 index 0000000000..3944209944 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/README.md @@ -0,0 +1,208 @@ +# Java Lambda Durable Functions - Workshop Examples + +This project demonstrates **AWS Lambda Durable Functions** patterns in Java. It provides working examples of all major durable execution patterns including chaining, fan-out/fan-in, human interaction, monitoring/polling, timers, error handling with saga compensation, map processing, and sub-orchestration. + +## Architecture + +``` +SNS Topic (Producer) --> Lambda Durable Functions (Consumers) --> DynamoDB (Results) +``` + +- **SNS Message Sender**: A Java CLI application that sends messages to SNS to trigger the durable functions +- **Durable Functions**: Eight Lambda functions, each demonstrating a different durable execution pattern +- **Infrastructure**: CloudFormation template for a VPC + EC2 instance with all tools pre-installed + +## Patterns Demonstrated + +| # | Pattern | Handler | Description | +|---|---------|---------|-------------| +| 1 | **Chaining** | `OrderProcessingHandler` | Sequential steps where each output feeds the next | +| 2 | **Fan-Out/Fan-In** | `ParallelProcessingHandler` | Parallel execution with result aggregation | +| 3 | **Human Interaction** | `ApprovalWorkflowHandler` | Callbacks for external human approval | +| 4 | **Monitoring/Polling** | `JobMonitorHandler` | waitForCondition with exponential backoff | +| 5 | **Timer/Delays** | `ScheduledReminderHandler` | Suspending execution without compute charges | +| 6 | **Error Handling** | `ResilientPaymentHandler` | Retries, at-most-once, and saga compensation | +| 7 | **Map Processing** | `BatchDataProcessorHandler` | Concurrent collection processing with tolerance | +| 8 | **Sub-Orchestration** | `OrderFulfillmentHandler` | Child contexts for workflow composition | + +## Prerequisites + +- AWS Account with permissions for Lambda, SNS, DynamoDB, ECR, IAM, CloudFormation +- Java 21 (Amazon Corretto recommended) +- Maven 3.8+ +- Docker +- AWS CLI v2 +- AWS SAM CLI + +## Quick Start + +### 1. Deploy Infrastructure (Optional - for EC2 dev environment) + +```bash +aws cloudformation create-stack \ + --stack-name durable-functions-infra \ + --template-body file://infrastructure/ec2-client-instance.yaml \ + --capabilities CAPABILITY_NAMED_IAM +``` + +### 2. Build the Durable Functions Container Image + +```bash +cd durable-functions-sam/durable-functions +mvn clean package -DskipTests +docker build -t durable-functions-java-examples . +``` + +### 3. Push to ECR + +```bash +AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +AWS_REGION=$(aws configure get region) + +aws ecr get-login-password --region $AWS_REGION \ + | docker login --username AWS --password-stdin \ + $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com + +# Create the repository (first time only) +aws ecr create-repository --repository-name durable-functions-java-examples + +docker tag durable-functions-java-examples:latest \ + $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/durable-functions-java-examples:latest + +docker push \ + $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/durable-functions-java-examples:latest +``` + +### 4. Deploy with SAM + +```bash +cd durable-functions-sam +sam deploy --guided +``` + +### 5. Build the SNS Message Sender + +```bash +cd sns-message-sender +mvn clean package +``` + +### 6. Trigger a Durable Function + +```bash +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic chaining +``` + +## Triggering Each Pattern + +```bash +# Pattern 1: Chaining - Sequential order processing +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic chaining + +# Pattern 2: Fan-Out/Fan-In - Parallel data analysis +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic fanout + +# Pattern 3: Human Interaction - Approval workflow (requires callback) +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic approval + +# Pattern 4: Monitoring - Job status polling +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic monitoring + +# Pattern 5: Timer - Scheduled reminders +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic timer + +# Pattern 6: Error Handling - Resilient payment with saga +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic errorhandling + +# Pattern 7: Map Processing - Batch concurrent processing +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic mapprocessing + +# Pattern 8: Sub-Orchestration - Nested child workflows +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic suborchestration +``` + +## Completing the Human Interaction Callback + +After triggering the `approval` pattern, check CloudWatch Logs for the callback ID, then: + +```bash +# To approve: +aws lambda send-durable-execution-callback-success \ + --callback-id \ + --cli-binary-format raw-in-base64-out \ + --result '{"decision":"APPROVED","approver":"manager@example.com"}' + +# To reject: +aws lambda send-durable-execution-callback-failure \ + --callback-id \ + --error ErrorType=Rejected,ErrorMessage="Budget exceeded policy limit" +``` + +## Key Concepts + +### DurableHandler +All durable functions extend `DurableHandler` instead of implementing `RequestHandler`. This provides a `DurableContext` with durable operations. + +### Steps +Steps checkpoint their results. On replay after a wait or failure, the SDK returns the stored result without re-executing the step body. + +### Waits +`context.wait()` suspends execution without consuming compute. The backend resumes the function when the duration elapses. + +### Callbacks +`context.createCallback()` suspends execution and waits for an external system to call `SendDurableExecutionCallbackSuccess`. + +### Parallel & Map +`context.parallel()` runs different operations concurrently. `context.map()` applies the same operation to each item in a collection. + +### Child Contexts +`context.runInChildContext()` creates isolated sub-workflows with their own operation namespaces. + +### Retry Strategies +Configure automatic retries with exponential backoff, jitter, and error filtering using `StepConfig` and `RetryStrategies`. + +## Monitoring + +View durable execution status: +```bash +aws lambda list-durable-executions --function-name durable-chaining-example:1 +aws lambda get-durable-execution --function-name durable-chaining-example:1 --execution-id +``` + +## Project Structure + +``` +lambda-durable-java-sam/ +└── JavaLambdaDurableFunctions/ + ├── README.md + ├── infrastructure/ + │ └── ec2-client-instance.yaml # VPC + EC2 CloudFormation template + ├── durable-functions-sam/ + │ ├── template.yaml # SAM template for all Lambda functions + │ └── durable-functions/ + │ ├── pom.xml + │ ├── Dockerfile + │ └── src/main/java/com/amazonaws/samples/durable/ + │ ├── models/ # Shared model classes + │ ├── chaining/ # Pattern 1: Sequential steps + │ ├── fanout/ # Pattern 2: Parallel execution + │ ├── humaninteraction/ # Pattern 3: Callbacks + │ ├── monitoring/ # Pattern 4: Polling + │ ├── timer/ # Pattern 5: Scheduled delays + │ ├── errorhandling/ # Pattern 6: Retries & compensation + │ ├── mapprocessing/ # Pattern 7: Collection processing + │ └── suborchestration/ # Pattern 8: Child contexts + └── sns-message-sender/ + ├── pom.xml + └── src/main/java/sns/producer/ + └── DurableFunctionsTrigger.java +``` diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/USER_GUIDE.md b/lambda-durable-java-sam/JavaLambdaDurableFunctions/USER_GUIDE.md new file mode 100644 index 0000000000..3d663f89bd --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/USER_GUIDE.md @@ -0,0 +1,485 @@ +# Lambda Durable Functions in Java - Workshop User Guide + +## Introduction + +Welcome to the **AWS Lambda Durable Functions in Java** workshop! In this workshop, you will learn how to build resilient, long-running workflows using Lambda Durable Functions. You'll deploy and run eight different patterns that demonstrate the full capability of durable execution in Java. + +### What are Lambda Durable Functions? + +Lambda Durable Functions enable you to build multi-step applications that can execute for up to **one year** while maintaining reliable progress despite interruptions. Key capabilities: + +- **Automatic checkpointing**: Each step's result is saved. If the function is interrupted, it resumes from the last checkpoint without re-executing completed work. +- **Suspend without cost**: The `wait()` operation suspends your function without incurring compute charges. You pay only for actual processing time. +- **Replay mechanism**: After resuming, your code runs from the beginning but skips completed checkpoints, using stored results instead. + +### How is this different from Step Functions? + +| Feature | Durable Functions | Step Functions | +|---------|-------------------|----------------| +| Definition | Code (Java/Python/TypeScript) | JSON/YAML DSL or visual designer | +| Runs in | Lambda | Standalone service | +| Best for | Tightly-coupled business logic | Service orchestration across AWS | +| State management | SDK handles automatically | Managed by service | + +--- + +## Prerequisites + +Before starting this workshop, ensure you have: + +- An AWS account with admin permissions +- Basic familiarity with Java and AWS Lambda +- One of: + - **Option A**: Deploy the EC2 instance (everything pre-installed) + - **Option B**: Local machine with Java 21, Maven 3.8+, Docker, AWS CLI v2, and SAM CLI + +--- + +## Module 1: Environment Setup + +### Option A: Deploy EC2 Development Environment + +This creates a VPC with a public subnet and an EC2 instance pre-configured with all tools. + +```bash +aws cloudformation create-stack \ + --stack-name durable-functions-infra \ + --template-body file://infrastructure/ec2-client-instance.yaml \ + --capabilities CAPABILITY_NAMED_IAM \ + --parameters \ + ParameterKey=JavaVersion,ParameterValue=java21 +``` + +Wait for the stack to complete (~5 minutes): +```bash +aws cloudformation wait stack-create-complete --stack-name durable-functions-infra +``` + +Connect to the instance via EC2 Instance Connect: +```bash +INSTANCE_ID=$(aws cloudformation describe-stacks --stack-name durable-functions-infra \ + --query 'Stacks[0].Outputs[?OutputKey==`EC2InstanceId`].OutputValue' --output text) +aws ec2-instance-connect ssh --instance-id $INSTANCE_ID +``` + +### Option B: Local Development + +Ensure you have: +```bash +java -version # Should be 21+ +mvn -version # Should be 3.8+ +docker --version +aws --version # Should be v2 +sam --version +``` + +Clone the project: +```bash +git clone https://github.com/aws-samples/serverless-patterns.git +cd serverless-patterns/lambda-durable-java-sam/JavaLambdaDurableFunctions +``` + +--- + +## Module 2: Build and Deploy + +### Step 1: Build the Lambda functions + +```bash +cd durable-functions-sam/durable-functions +mvn clean package -DskipTests +``` + +You should see `BUILD SUCCESS`. + +### Step 2: Build the Docker container image + +```bash +docker build -t durable-functions-java-examples . +``` + +### Step 3: Create ECR repository and push + +```bash +AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +AWS_REGION=$(aws configure get region) + +# Create repository +aws ecr create-repository --repository-name durable-functions-java-examples + +# Login to ECR +aws ecr get-login-password --region $AWS_REGION \ + | docker login --username AWS --password-stdin \ + $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com + +# Tag and push +docker tag durable-functions-java-examples:latest \ + $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/durable-functions-java-examples:latest + +docker push \ + $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/durable-functions-java-examples:latest +``` + +### Step 4: Deploy with SAM + +```bash +cd .. +sam deploy --guided +``` + +Accept the defaults or customize: +- Stack name: `durable-functions-java-examples` +- Region: your preferred region +- Confirm changeset: Yes +- Allow SAM CLI to create IAM roles: Yes + +### Step 5: Build the SNS message sender + +```bash +cd ../sns-message-sender +mvn clean package +``` + +--- + +## Module 3: Function Chaining + +**Pattern**: Execute steps sequentially where each step's output feeds the next. + +**Why durable**: If the function is interrupted after step 3 of 5, it resumes from step 4 on replay without re-executing steps 1-3. + +### Run it + +```bash +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic chaining +``` + +### What happens + +1. **validate-order** - Validates order ID and amount +2. **reserve-inventory** - Reserves items in warehouse +3. **process-payment** - Charges the customer +4. **ship-order** - Creates shipping label and tracking number +5. **notify-customer** - Sends shipment notification + +### Observe + +Check CloudWatch Logs: +```bash +aws logs tail /aws/lambda/durable-chaining-example --follow +``` + +Check execution status: +```bash +aws lambda list-durable-executions --function-name durable-chaining-example:1 +``` + +### Key takeaway + +Each `context.step()` checkpoints its result. The variable returned from step N is safely used in step N+1 even after a replay because the SDK restores it from the checkpoint. + +--- + +## Module 4: Fan-Out / Fan-In + +**Pattern**: Execute multiple independent operations in parallel, then aggregate results. + +**Why durable**: Each parallel branch checkpoints independently. If one branch fails after others complete, only the failed branch re-executes. + +### Run it + +```bash +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic fanout +``` + +### What happens + +1. Three analyses run **concurrently** via `parallel()`: + - Sentiment analysis + - Entity extraction + - Summarization +2. Five documents are processed via `map()` with the same logic per item +3. All results are aggregated in a final step + +### Key takeaway + +- `parallel()` is for **different** operations running concurrently +- `map()` is for the **same** operation applied to each item in a collection +- Both support concurrency limits and failure tolerance + +--- + +## Module 5: Human Interaction (Callbacks) + +**Pattern**: Suspend execution while waiting for external human input. + +**Why durable**: The function suspends (no compute charges) for hours or days while waiting for a human to respond. + +### Run it + +```bash +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic approval +``` + +### Complete the callback + +Check the logs for the callback ID: +```bash +aws logs tail /aws/lambda/durable-human-interaction-example --follow +``` + +Look for: `Approval callback created. Callback ID: ` + +Then approve: +```bash +aws lambda send-durable-execution-callback-success \ + --callback-id \ + --cli-binary-format raw-in-base64-out \ + --result '{"decision":"APPROVED","approver":"manager@example.com"}' +``` + +Or reject: +```bash +aws lambda send-durable-execution-callback-failure \ + --callback-id \ + --error ErrorType=Rejected,ErrorMessage="Budget exceeded" +``` + +### Key takeaway + +- `createCallback()` returns a callback ID that you send to the external system +- The function **suspends** (exits) - no compute charges while waiting +- When the external system calls `send-durable-execution-callback-success`, the function resumes +- Timeout and heartbeat can detect stalled approvers + +--- + +## Module 6: Monitoring / Polling + +**Pattern**: Poll an external system on a schedule until a condition is met. + +**Why durable**: The function suspends between polling attempts. You don't consume compute while waiting for the external system. + +### Run it + +```bash +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic monitoring +``` + +### What happens + +1. Acknowledges the job +2. Polls every few seconds with exponential backoff (5s, 10s, 20s...) +3. Between polls, the function **suspends** (no compute) +4. When the job reports COMPLETED, polling stops +5. Processes the final result + +### Key takeaway + +- `waitForCondition()` handles the entire poll-wait-check cycle +- Return `WaitForConditionResult.stopPolling(state)` to end +- Return `WaitForConditionResult.continuePolling(state)` to keep going +- The wait strategy controls backoff between attempts + +--- + +## Module 7: Timers / Scheduled Delays + +**Pattern**: Insert delays between steps without consuming compute. + +**Why durable**: `context.wait()` suspends the function. You pay nothing during the wait, whether it's 5 seconds or 5 days. + +### Run it + +```bash +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic timer +``` + +### What happens + +1. Creates a task assignment +2. Sends initial notification +3. **Waits 30 seconds** (function suspends, no compute) +4. Sends first reminder +5. **Waits 60 seconds** (function suspends again) +6. Escalates to manager +7. Demonstrates async wait pattern (minimum duration guarantee) + +### Key takeaway + +- `context.wait("name", Duration.ofSeconds(30))` suspends for 30s at zero cost +- `context.waitAsync()` combined with `stepAsync()` ensures minimum elapsed time +- Maximum wait is 1 year +- Minimum wait is 1 second + +--- + +## Module 8: Error Handling and Compensation + +**Pattern**: Automatic retries with saga compensation when later steps fail. + +**Why durable**: Retry delays don't consume compute. Failed steps checkpoint the error so compensation logic runs only once. + +### Run it (success path) + +```bash +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic errorhandling +``` + +### Run it (compensation path) + +Trigger with `simulateInventoryFailure=true` by modifying the event or using the AWS CLI directly: +```bash +aws lambda invoke \ + --function-name durable-error-handling-example:1 \ + --cli-binary-format raw-in-base64-out \ + --payload '{"orderId":"ORD-FAIL","amount":99.99,"simulateInventoryFailure":true}' \ + response.json && cat response.json +``` + +### What happens + +1. **Validate** - Standard retry (3 attempts, exponential backoff) +2. **Charge payment** - Custom retry strategy + at-most-once semantics +3. **Reserve inventory** - If this fails, triggers compensation +4. **Compensation** - Refunds the payment (saga pattern) + +### Key takeaway + +- `RetryStrategies.exponentialBackoff()` for standard retries +- Custom `RetryStrategy` lambda for error-type filtering +- `StepSemantics.AT_MOST_ONCE_PER_RETRY` prevents double-charging +- Catch `StepFailedException` to implement compensation logic +- Between retry attempts, the function suspends (no compute) + +--- + +## Module 9: Map Processing + +**Pattern**: Process a collection of items concurrently with rate limiting and failure tolerance. + +**Why durable**: Each item checkpoints independently. Partial failures don't prevent successful items from being recorded. + +### Run it + +```bash +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic mapprocessing +``` + +### What happens + +1. Generates a batch of 10 items +2. Processes them with `maxConcurrency=3` (only 3 run at once) +3. Each item goes through: validate → transform → store +4. Every 5th item fails validation (to demonstrate failure tolerance) +5. With `toleratedFailures=2`, the overall operation succeeds +6. Produces a summary with success/failure counts + +### Key takeaway + +- `MapConfig.builder().maxConcurrency(N)` limits parallel execution +- `CompletionConfig.toleratedFailureCount(N)` allows N failures +- Each item runs in its own child context (isolated checkpoints) +- `mapResult.succeeded()` and `mapResult.failed()` access results + +--- + +## Module 10: Sub-Orchestration + +**Pattern**: Compose complex workflows from isolated, reusable sub-workflows. + +**Why durable**: Each child context checkpoints as a unit. On replay, entire sub-workflows are skipped if already complete. + +### Run it + +```bash +java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ + sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic suborchestration +``` + +### What happens + +1. Validates the order (main context) +2. Runs **Payment** and **Inventory** sub-workflows **concurrently** via `runInChildContextAsync()` +3. Runs **Shipping** sub-workflow (sequential, depends on inventory) +4. Runs **Notification** sub-workflow + +Each sub-workflow contains multiple steps internally (e.g., Payment: authorize → fraud check → capture). + +### Key takeaway + +- `runInChildContext()` creates an isolated scope with its own checkpoints +- `runInChildContextAsync()` + `DurableFuture.allOf()` runs sub-workflows concurrently +- Child contexts provide namespace isolation (operation IDs don't conflict) +- On replay, a completed child context returns its checkpointed result instantly + +--- + +## Module 11: Cleanup + +Delete all deployed resources: + +```bash +# Delete the SAM stack +aws cloudformation delete-stack --stack-name durable-functions-java-examples +aws cloudformation wait stack-delete-complete --stack-name durable-functions-java-examples + +# Delete the ECR repository +aws ecr delete-repository --repository-name durable-functions-java-examples --force + +# Delete the infrastructure stack (if deployed) +aws cloudformation delete-stack --stack-name durable-functions-infra +aws cloudformation wait stack-delete-complete --stack-name durable-functions-infra +``` + +--- + +## Troubleshooting + +### Build fails with "package software.amazon.lambda.durable does not exist" + +The Durable Execution SDK may not yet be in Maven Central. Check the [SDK repository](https://github.com/aws/aws-durable-execution-sdk-java) for the latest installation instructions. You may need to build from source or use a pre-release repository. + +### "Function not found" when invoking + +Ensure you published a version and are using the qualified ARN: +```bash +aws lambda publish-version --function-name durable-chaining-example +# Then invoke with :1 qualifier +``` + +### Callback not resuming + +- Verify the callback ID is correct (check CloudWatch Logs) +- Ensure you're using `--cli-binary-format raw-in-base64-out` +- Check that the function's IAM role has `lambda:SendDurableExecutionCallbackSuccess` permission + +### Durable execution stuck + +List and inspect executions: +```bash +aws lambda list-durable-executions --function-name :1 +aws lambda get-durable-execution --function-name :1 --execution-id +``` + +Stop a stuck execution: +```bash +aws lambda stop-durable-execution --function-name :1 --execution-id +``` + +--- + +## Next Steps + +- Read the [AWS Durable Execution SDK Developer Guide](https://docs.aws.amazon.com/durable-execution/) +- Explore the [Lambda Durable Functions documentation](https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html) +- Try combining patterns (e.g., chaining + callbacks + map processing in one workflow) +- Add DynamoDB persistence to store execution results +- Implement idempotency keys for production payment flows diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/build-and-deploy.sh b/lambda-durable-java-sam/JavaLambdaDurableFunctions/build-and-deploy.sh new file mode 100755 index 0000000000..3cd997f708 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/build-and-deploy.sh @@ -0,0 +1,75 @@ +#!/bin/bash +set -e + +echo "============================================================" +echo " Lambda Durable Functions Java - Build and Deploy" +echo "============================================================" + +AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +AWS_REGION=$(aws configure get region) +ECR_REPO="durable-functions-java-examples" +IMAGE_URI="$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPO:latest" + +echo "" +echo "AWS Account: $AWS_ACCOUNT_ID" +echo "Region: $AWS_REGION" +echo "ECR Image: $IMAGE_URI" +echo "" + +# Step 1: Build the durable functions JAR +echo ">>> Step 1: Building durable functions JAR..." +cd durable-functions-sam/durable-functions +mvn clean package -DskipTests +echo " Build complete." + +# Step 2: Build Docker image +echo "" +echo ">>> Step 2: Building Docker image..." +docker build -t $ECR_REPO . +echo " Docker image built." + +# Step 3: Create ECR repository (ignore error if exists) +echo "" +echo ">>> Step 3: Ensuring ECR repository exists..." +aws ecr create-repository --repository-name $ECR_REPO 2>/dev/null || echo " Repository already exists." + +# Step 4: Login to ECR and push +echo "" +echo ">>> Step 4: Pushing image to ECR..." +aws ecr get-login-password --region $AWS_REGION \ + | docker login --username AWS --password-stdin \ + $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com + +docker tag $ECR_REPO:latest $IMAGE_URI +docker push $IMAGE_URI +echo " Image pushed." + +# Step 5: Deploy SAM stack +echo "" +echo ">>> Step 5: Deploying SAM stack..." +cd .. +sam deploy \ + --template-file template.yaml \ + --stack-name durable-functions-java-examples \ + --capabilities CAPABILITY_NAMED_IAM \ + --no-confirm-changeset \ + --resolve-image-repos + +# Step 6: Build the SNS sender +echo "" +echo ">>> Step 6: Building SNS message sender..." +cd ../sns-message-sender +mvn clean package -DskipTests +echo " SNS sender built." + +echo "" +echo "============================================================" +echo " Deployment Complete!" +echo "============================================================" +echo "" +echo "To trigger a pattern, run:" +echo " cd sns-message-sender" +echo " java -cp target/sns-message-sender-1.0-SNAPSHOT.jar sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic " +echo "" +echo "Available patterns: chaining, fanout, approval, monitoring, timer, errorhandling, mapprocessing, suborchestration" +echo "" diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/Dockerfile b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/Dockerfile new file mode 100644 index 0000000000..b7ab0d71e9 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/Dockerfile @@ -0,0 +1,8 @@ +FROM --platform=linux/amd64 amazoncorretto:21-alpine AS builder +WORKDIR /build +COPY pom.xml . +COPY src ./src +RUN apk add --no-cache maven && mvn clean package -DskipTests + +FROM public.ecr.aws/lambda/java:21 +COPY --from=builder /build/target/*.jar ${LAMBDA_TASK_ROOT}/lib/ diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/pom.xml b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/pom.xml new file mode 100644 index 0000000000..16d7c83452 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/pom.xml @@ -0,0 +1,91 @@ + + 4.0.0 + com.amazonaws.samples.durable + durable-functions-examples + 1.0 + jar + Lambda Durable Functions Java Examples + + + 21 + 21 + UTF-8 + + + + + software.amazon.lambda.durable + aws-durable-execution-sdk-java + 1.0.0 + + + com.amazonaws + aws-lambda-java-core + 1.2.3 + + + com.amazonaws + aws-lambda-java-events + 3.14.0 + + + software.amazon.awssdk + dynamodb + 2.25.0 + + + software.amazon.awssdk + sns + 2.25.0 + + + com.fasterxml.jackson.core + jackson-databind + 2.17.0 + + + org.junit.jupiter + junit-jupiter-api + 5.10.2 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.10.2 + test + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.2 + + false + + + + package + + shade + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 21 + 21 + + + + + diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java new file mode 100644 index 0000000000..5050382a3f --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java @@ -0,0 +1,107 @@ +package com.amazonaws.samples.durable.chaining; + +import java.util.Map; + +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableHandler; +import software.amazon.lambda.durable.config.StepConfig; +import software.amazon.lambda.durable.retry.RetryStrategies; +import software.amazon.lambda.durable.retry.JitterStrategy; + +import java.time.Duration; + +/** + * PATTERN: Function Chaining + * + * Demonstrates sequential step execution where each step's output feeds + * into the next step. The durable execution SDK checkpoints each step's + * result so that on replay (after a wait or failure), completed steps + * are not re-executed. + * + * Flow: Validate Order -> Reserve Inventory -> Process Payment -> Ship Order -> Notify Customer + */ +public class OrderProcessingHandler extends DurableHandler, Map> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + context.getLogger().info("Starting order processing chain for: " + event.get("orderId")); + + StepConfig retryConfig = StepConfig.builder() + .retryStrategy(RetryStrategies.exponentialBackoff( + 3, Duration.ofSeconds(2), Duration.ofSeconds(30), 2.0, JitterStrategy.FULL)) + .build(); + + // Step 1: Validate the order + Map validationResult = context.step("validate-order", Map.class, stepCtx -> { + stepCtx.getLogger().info("Validating order..."); + String orderId = (String) event.get("orderId"); + double amount = ((Number) event.get("totalAmount")).doubleValue(); + if (orderId == null || orderId.isEmpty()) { + throw new IllegalArgumentException("Order ID is required"); + } + if (amount <= 0) { + throw new IllegalArgumentException("Order amount must be positive"); + } + return Map.of( + "orderId", orderId, + "status", "VALIDATED", + "amount", amount, + "customerId", event.getOrDefault("customerId", "unknown") + ); + }, retryConfig); + + // Step 2: Reserve inventory + Map inventoryResult = context.step("reserve-inventory", Map.class, stepCtx -> { + stepCtx.getLogger().info("Reserving inventory for order: " + validationResult.get("orderId")); + return Map.of( + "orderId", validationResult.get("orderId"), + "status", "INVENTORY_RESERVED", + "reservationId", "RES-" + validationResult.get("orderId"), + "warehouse", "WAREHOUSE-EAST-1" + ); + }, retryConfig); + + // Step 3: Process payment + Map paymentResult = context.step("process-payment", Map.class, stepCtx -> { + stepCtx.getLogger().info("Processing payment for order: " + inventoryResult.get("orderId")); + return Map.of( + "orderId", inventoryResult.get("orderId"), + "status", "PAYMENT_PROCESSED", + "transactionId", "TXN-" + System.currentTimeMillis(), + "amount", validationResult.get("amount") + ); + }, retryConfig); + + // Step 4: Ship order + Map shippingResult = context.step("ship-order", Map.class, stepCtx -> { + stepCtx.getLogger().info("Shipping order: " + paymentResult.get("orderId")); + return Map.of( + "orderId", paymentResult.get("orderId"), + "status", "SHIPPED", + "trackingNumber", "TRACK-" + paymentResult.get("transactionId"), + "estimatedDelivery", "3-5 business days" + ); + }, retryConfig); + + // Step 5: Notify customer + Map notificationResult = context.step("notify-customer", Map.class, stepCtx -> { + stepCtx.getLogger().info("Notifying customer about shipment"); + return Map.of( + "orderId", shippingResult.get("orderId"), + "status", "CUSTOMER_NOTIFIED", + "trackingNumber", shippingResult.get("trackingNumber"), + "message", "Your order has been shipped!" + ); + }); + + context.getLogger().info("Order processing chain completed successfully"); + + return Map.of( + "pattern", "CHAINING", + "orderId", event.get("orderId"), + "finalStatus", "COMPLETED", + "trackingNumber", shippingResult.get("trackingNumber"), + "transactionId", paymentResult.get("transactionId") + ); + } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java new file mode 100644 index 0000000000..7aeb5cb43a --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java @@ -0,0 +1,162 @@ +package com.amazonaws.samples.durable.errorhandling; + +import java.time.Duration; +import java.util.Map; + +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableHandler; +import software.amazon.lambda.durable.config.StepConfig; +import software.amazon.lambda.durable.config.StepSemantics; +import software.amazon.lambda.durable.exception.StepFailedException; +import software.amazon.lambda.durable.exception.StepInterruptedException; +import software.amazon.lambda.durable.retry.JitterStrategy; +import software.amazon.lambda.durable.retry.RetryDecision; +import software.amazon.lambda.durable.retry.RetryStrategies; +import software.amazon.lambda.durable.retry.RetryStrategy; + +/** + * PATTERN: Error Handling and Compensation (Saga Pattern) + * + * Demonstrates: + * 1. Retry strategies with exponential backoff + * 2. Custom retry strategies with error-type filtering + * 3. At-most-once semantics for non-idempotent operations + * 4. Saga pattern: compensation logic when later steps fail + * 5. Catching and handling StepFailedException + * + * Flow: Validate -> Charge Payment (with retries) -> Reserve Inventory + * If inventory fails -> Refund Payment (compensation) + */ +public class ResilientPaymentHandler extends DurableHandler, Map> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + context.getLogger().info("Starting resilient payment workflow"); + + String orderId = (String) event.getOrDefault("orderId", "ORD-001"); + double amount = ((Number) event.getOrDefault("amount", 99.99)).doubleValue(); + boolean simulateInventoryFailure = Boolean.TRUE.equals(event.get("simulateInventoryFailure")); + + // Step 1: Validate with standard retry + StepConfig validationConfig = StepConfig.builder() + .retryStrategy(RetryStrategies.exponentialBackoff( + 3, Duration.ofSeconds(1), Duration.ofSeconds(10), 2.0, JitterStrategy.FULL)) + .build(); + + Map validation = context.step("validate-payment", Map.class, stepCtx -> { + stepCtx.getLogger().info("Validating payment for order: " + orderId); + if (amount <= 0) { + throw new IllegalArgumentException("Invalid amount: " + amount); + } + return Map.of("orderId", orderId, "amount", amount, "valid", true); + }, validationConfig); + + // Step 2: Charge payment with at-most-once semantics and custom retry + // At-most-once ensures we never double-charge even if Lambda is interrupted + RetryStrategy paymentRetry = (error, attempt) -> { + // Only retry on transient errors, not business logic errors + if (error instanceof IllegalArgumentException) { + return RetryDecision.fail(); + } + if (attempt >= 4) { + return RetryDecision.fail(); + } + return RetryDecision.retry(Duration.ofSeconds(2 * attempt)); + }; + + StepConfig paymentConfig = StepConfig.builder() + .retryStrategy(paymentRetry) + .semantics(StepSemantics.AT_MOST_ONCE_PER_RETRY) + .build(); + + Map paymentResult; + try { + paymentResult = context.step("charge-payment", Map.class, stepCtx -> { + stepCtx.getLogger().info("Charging payment: $" + amount + " for order: " + orderId); + stepCtx.getLogger().info("Attempt: " + stepCtx.getAttempt()); + // Simulate transient failure on first attempt + if (stepCtx.getAttempt() == 0) { + throw new RuntimeException("Payment gateway timeout - transient error"); + } + return Map.of( + "orderId", orderId, + "transactionId", "TXN-" + orderId + "-" + System.currentTimeMillis(), + "amount", amount, + "status", "CHARGED" + ); + }, paymentConfig); + } catch (StepInterruptedException e) { + // At-most-once step was interrupted - check external system + context.getLogger().warn("Payment step interrupted - checking payment system"); + paymentResult = context.step("check-payment-status", Map.class, stepCtx -> { + return Map.of("orderId", orderId, "status", "UNKNOWN", "requiresManualCheck", true); + }); + return Map.of( + "pattern", "ERROR_HANDLING", + "orderId", orderId, + "status", "INTERRUPTED", + "paymentResult", paymentResult + ); + } catch (StepFailedException e) { + context.getLogger().info("Payment failed permanently: " + e.getMessage()); + return Map.of( + "pattern", "ERROR_HANDLING", + "orderId", orderId, + "status", "PAYMENT_FAILED", + "error", e.getErrorObject().errorMessage() + ); + } + + // Step 3: Reserve inventory - may fail, triggering compensation + Map inventoryResult; + try { + StepConfig inventoryConfig = StepConfig.builder() + .retryStrategy(RetryStrategies.exponentialBackoff( + 2, Duration.ofSeconds(1), Duration.ofSeconds(5), 2.0, JitterStrategy.NONE)) + .build(); + + inventoryResult = context.step("reserve-inventory", Map.class, stepCtx -> { + stepCtx.getLogger().info("Reserving inventory for order: " + orderId); + if (simulateInventoryFailure) { + throw new RuntimeException("Inventory unavailable - out of stock"); + } + return Map.of( + "orderId", orderId, + "reservationId", "INV-" + orderId, + "status", "RESERVED" + ); + }, inventoryConfig); + } catch (StepFailedException e) { + // SAGA COMPENSATION: Inventory failed, refund the payment + context.getLogger().info("Inventory reservation failed - initiating compensation"); + + final Map capturedPayment = paymentResult; + Map refundResult = context.step("refund-payment", Map.class, stepCtx -> { + stepCtx.getLogger().info("Refunding payment: " + capturedPayment.get("transactionId")); + return Map.of( + "orderId", orderId, + "originalTransactionId", capturedPayment.get("transactionId"), + "refundId", "REFUND-" + orderId, + "amount", amount, + "status", "REFUNDED" + ); + }); + + return Map.of( + "pattern", "ERROR_HANDLING", + "orderId", orderId, + "status", "COMPENSATED", + "reason", "Inventory unavailable", + "refund", refundResult + ); + } + + return Map.of( + "pattern", "ERROR_HANDLING", + "orderId", orderId, + "status", "COMPLETED", + "transactionId", paymentResult.get("transactionId"), + "reservationId", inventoryResult.get("reservationId") + ); + } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java new file mode 100644 index 0000000000..23193384d7 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java @@ -0,0 +1,119 @@ +package com.amazonaws.samples.durable.fanout; + +import java.util.List; +import java.util.Map; + +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableFuture; +import software.amazon.lambda.durable.DurableHandler; +import software.amazon.lambda.durable.config.CompletionConfig; +import software.amazon.lambda.durable.config.ParallelConfig; +import software.amazon.lambda.durable.model.MapResult; +import software.amazon.lambda.durable.model.ParallelResult; + +/** + * PATTERN: Fan-Out / Fan-In + * + * Demonstrates parallel execution of multiple independent operations that are + * then aggregated. Uses both the parallel() API for heterogeneous tasks and + * map() for homogeneous collection processing. + * + * Flow: Receive data -> Fan-out to multiple processors -> Aggregate results + */ +public class ParallelProcessingHandler extends DurableHandler, Map> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + context.getLogger().info("Starting fan-out/fan-in processing"); + + String dataId = (String) event.getOrDefault("dataId", "DATA-001"); + + // Fan-out using parallel(): Execute different analyses concurrently + DurableFuture sentimentFuture; + DurableFuture entityFuture; + DurableFuture summaryFuture; + + try (var parallel = context.parallel("analyze-data")) { + sentimentFuture = parallel.branch("sentiment-analysis", String.class, ctx -> + ctx.step("run-sentiment", String.class, stepCtx -> { + stepCtx.getLogger().info("Running sentiment analysis on: " + dataId); + simulateProcessing(500); + return "POSITIVE (confidence: 0.87)"; + }) + ); + + entityFuture = parallel.branch("entity-extraction", String.class, ctx -> + ctx.step("run-entity-extraction", String.class, stepCtx -> { + stepCtx.getLogger().info("Running entity extraction on: " + dataId); + simulateProcessing(300); + return "Entities: [AWS, Lambda, DurableFunctions, Java]"; + }) + ); + + summaryFuture = parallel.branch("summarization", String.class, ctx -> + ctx.step("run-summarization", String.class, stepCtx -> { + stepCtx.getLogger().info("Running summarization on: " + dataId); + simulateProcessing(700); + return "Summary: Document discusses Lambda Durable Functions patterns in Java"; + }) + ); + + ParallelResult result = parallel.get(); + context.getLogger().info("Parallel analysis complete. Succeeded: " + result.succeeded() + + ", Failed: " + result.failed()); + } + + String sentiment = sentimentFuture.get(); + String entities = entityFuture.get(); + String summary = summaryFuture.get(); + + // Fan-in using map(): Process a collection of items with the same operation + List documents = List.of("doc-1", "doc-2", "doc-3", "doc-4", "doc-5"); + + MapResult> mapResult = context.map( + "process-documents", + documents, + (Class>) (Class) Map.class, + (doc, index, ctx) -> ctx.step("process-" + doc, (Class>) (Class) Map.class, + stepCtx -> { + stepCtx.getLogger().info("Processing document: " + doc); + simulateProcessing(200); + return Map.of( + "documentId", doc, + "wordCount", String.valueOf((index + 1) * 150), + "status", "PROCESSED" + ); + }) + ); + + // Aggregate all results + Map aggregatedResult = context.step("aggregate-results", Map.class, stepCtx -> { + stepCtx.getLogger().info("Aggregating all results"); + int totalDocsProcessed = mapResult.succeeded().size(); + return Map.of( + "dataId", dataId, + "sentiment", sentiment, + "entities", entities, + "summary", summary, + "documentsProcessed", totalDocsProcessed, + "allSucceeded", mapResult.allSucceeded() + ); + }); + + context.getLogger().info("Fan-out/fan-in processing completed"); + + return Map.of( + "pattern", "FAN_OUT_FAN_IN", + "status", "COMPLETED", + "result", aggregatedResult + ); + } + + private void simulateProcessing(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java new file mode 100644 index 0000000000..b61a174b08 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java @@ -0,0 +1,122 @@ +package com.amazonaws.samples.durable.humaninteraction; + +import java.time.Duration; +import java.util.Map; + +import software.amazon.lambda.durable.DurableCallbackFuture; +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableHandler; +import software.amazon.lambda.durable.config.CallbackConfig; +import software.amazon.lambda.durable.exception.CallbackFailedException; + +/** + * PATTERN: Human Interaction (Approval Workflow) + * + * Demonstrates waiting for external human input using callbacks. + * The function suspends (no compute charges) while waiting for + * a human to approve or reject a request. Uses the callback mechanism + * where an external system calls SendDurableExecutionCallbackSuccess + * or SendDurableExecutionCallbackFailure. + * + * Flow: Submit Request -> Wait for Manager Approval -> Process Approved Request + * + * To complete the callback externally, use: + * aws lambda send-durable-execution-callback-success \ + * --callback-id \ + * --cli-binary-format raw-in-base64-out \ + * --result '{"decision":"APPROVED","approver":"manager@example.com"}' + * + * Or to reject: + * aws lambda send-durable-execution-callback-failure \ + * --callback-id \ + * --error ErrorType=Rejected,ErrorMessage="Budget exceeded" + */ +public class ApprovalWorkflowHandler extends DurableHandler, Map> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + context.getLogger().info("Starting approval workflow"); + + String requestId = (String) event.getOrDefault("requestId", "REQ-" + System.currentTimeMillis()); + double amount = ((Number) event.getOrDefault("amount", 5000)).doubleValue(); + String requestor = (String) event.getOrDefault("requestor", "employee@example.com"); + + // Step 1: Validate and prepare the approval request + Map approvalRequest = context.step("prepare-approval", Map.class, stepCtx -> { + stepCtx.getLogger().info("Preparing approval request: " + requestId); + String approvalLevel = amount > 10000 ? "VP" : "MANAGER"; + return Map.of( + "requestId", requestId, + "amount", amount, + "requestor", requestor, + "approvalLevel", approvalLevel, + "status", "PENDING_APPROVAL" + ); + }); + + // Step 2: Send notification to approver (simulated) + context.step("notify-approver", String.class, stepCtx -> { + stepCtx.getLogger().info("Sending approval notification to: " + approvalRequest.get("approvalLevel")); + return "Notification sent to " + approvalRequest.get("approvalLevel"); + }); + + // Step 3: Wait for human approval using callback + // The function SUSPENDS here - no compute charges while waiting + Map approvalDecision; + try { + CallbackConfig callbackConfig = CallbackConfig.builder() + .timeout(Duration.ofHours(72)) + .heartbeatTimeout(Duration.ofHours(24)) + .build(); + + DurableCallbackFuture> callback = + context.createCallback("wait-for-approval", (Class>) (Class) Map.class, callbackConfig); + + // Log the callback ID so the approver can use it + context.getLogger().info("Approval callback created. Callback ID: " + callback.callbackId()); + context.getLogger().info("To approve, run: aws lambda send-durable-execution-callback-success " + + "--callback-id " + callback.callbackId() + + " --cli-binary-format raw-in-base64-out" + + " --result '{\"decision\":\"APPROVED\",\"approver\":\"manager@example.com\"}'"); + + // Execution suspends here until the external system calls back + approvalDecision = callback.get(); + context.getLogger().info("Received approval decision: " + approvalDecision.get("decision")); + + } catch (CallbackFailedException e) { + context.getLogger().info("Approval was rejected: " + e.getMessage()); + return Map.of( + "pattern", "HUMAN_INTERACTION", + "requestId", requestId, + "status", "REJECTED", + "reason", e.getMessage() + ); + } + + // Step 4: Process the approved request + Map processingResult = context.step("process-approved-request", Map.class, stepCtx -> { + stepCtx.getLogger().info("Processing approved request: " + requestId); + return Map.of( + "requestId", requestId, + "status", "PROCESSED", + "approvedBy", approvalDecision.getOrDefault("approver", "unknown"), + "decision", approvalDecision.getOrDefault("decision", "APPROVED"), + "processedAmount", amount + ); + }); + + // Step 5: Send confirmation + context.step("send-confirmation", String.class, stepCtx -> { + stepCtx.getLogger().info("Sending confirmation to requestor: " + requestor); + return "Confirmation sent"; + }); + + return Map.of( + "pattern", "HUMAN_INTERACTION", + "requestId", requestId, + "status", "COMPLETED", + "approvedBy", processingResult.get("approvedBy"), + "amount", amount + ); + } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java new file mode 100644 index 0000000000..69956729ec --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java @@ -0,0 +1,122 @@ +package com.amazonaws.samples.durable.mapprocessing; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableHandler; +import software.amazon.lambda.durable.config.CompletionConfig; +import software.amazon.lambda.durable.config.MapConfig; +import software.amazon.lambda.durable.model.MapResult; + +/** + * PATTERN: Map Processing (Collection Processing) + * + * Demonstrates the map() operation which processes each item in a collection + * concurrently. Each item runs in its own child context with independent + * checkpointing. Supports concurrency limits, failure tolerance, and + * completion strategies. + * + * Use cases: + * - Batch processing of records + * - Parallel API calls with rate limiting + * - ETL pipelines with partial failure tolerance + * + * Flow: Receive batch -> Map over items (concurrent) -> Collect results -> Summarize + */ +public class BatchDataProcessorHandler extends DurableHandler, Map> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + context.getLogger().info("Starting batch data processing"); + + int batchSize = ((Number) event.getOrDefault("batchSize", 10)).intValue(); + int maxConcurrency = ((Number) event.getOrDefault("maxConcurrency", 3)).intValue(); + int toleratedFailures = ((Number) event.getOrDefault("toleratedFailures", 2)).intValue(); + + // Step 1: Generate or receive the batch of items to process + List> batch = context.step("prepare-batch", + (Class>>) (Class) List.class, stepCtx -> { + stepCtx.getLogger().info("Preparing batch of " + batchSize + " items"); + return IntStream.range(0, batchSize) + .mapToObj(i -> Map.of( + "itemId", "ITEM-" + String.format("%03d", i), + "data", "payload-for-item-" + i, + "priority", i % 3 == 0 ? "HIGH" : "NORMAL" + )) + .collect(Collectors.toList()); + }); + + // Step 2: Process all items using map() with concurrency control + MapConfig mapConfig = MapConfig.builder() + .maxConcurrency(maxConcurrency) + .completionConfig(CompletionConfig.toleratedFailureCount(toleratedFailures)) + .build(); + + MapResult> processingResult = context.map( + "process-batch-items", + batch, + (Class>) (Class) Map.class, + (item, index, ctx) -> { + // Each item gets its own child context with independent checkpoints + // Multi-step processing per item + String validated = ctx.step("validate-" + index, String.class, stepCtx -> { + stepCtx.getLogger().info("Validating item: " + item.get("itemId")); + // Simulate validation failure for every 5th item + if (index % 5 == 4) { + throw new RuntimeException("Validation failed for item: " + item.get("itemId")); + } + return "VALID"; + }); + + Map transformed = ctx.step("transform-" + index, Map.class, stepCtx -> { + stepCtx.getLogger().info("Transforming item: " + item.get("itemId")); + return Map.of( + "itemId", item.get("itemId"), + "originalData", item.get("data"), + "transformedData", item.get("data").toUpperCase(), + "priority", item.get("priority") + ); + }); + + return ctx.step("store-" + index, Map.class, stepCtx -> { + stepCtx.getLogger().info("Storing transformed item: " + item.get("itemId")); + return Map.of( + "itemId", transformed.get("itemId"), + "status", "STORED", + "transformedData", transformed.get("transformedData") + ); + }); + }, + mapConfig + ); + + // Step 3: Summarize results + Map summary = context.step("summarize-results", Map.class, stepCtx -> { + int succeeded = processingResult.succeeded().size(); + int failed = processingResult.failed().size(); + stepCtx.getLogger().info("Batch processing complete. Succeeded: " + succeeded + ", Failed: " + failed); + + List failureReasons = processingResult.failed().stream() + .map(error -> error.errorType() + ": " + error.errorMessage()) + .collect(Collectors.toList()); + + return Map.of( + "totalItems", batchSize, + "succeeded", succeeded, + "failed", failed, + "allSucceeded", processingResult.allSucceeded(), + "completionReason", processingResult.completionReason().name(), + "failureReasons", failureReasons + ); + }); + + return Map.of( + "pattern", "MAP_PROCESSING", + "status", processingResult.allSucceeded() ? "ALL_SUCCEEDED" : "PARTIAL_SUCCESS", + "summary", summary + ); + } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderItem.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderItem.java new file mode 100644 index 0000000000..e29cfe43a3 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderItem.java @@ -0,0 +1,26 @@ +package com.amazonaws.samples.durable.models; + +public class OrderItem { + private String productId; + private String productName; + private int quantity; + private double price; + + public OrderItem() {} + + public OrderItem(String productId, String productName, int quantity, double price) { + this.productId = productId; + this.productName = productName; + this.quantity = quantity; + this.price = price; + } + + public String getProductId() { return productId; } + public void setProductId(String productId) { this.productId = productId; } + public String getProductName() { return productName; } + public void setProductName(String productName) { this.productName = productName; } + public int getQuantity() { return quantity; } + public void setQuantity(int quantity) { this.quantity = quantity; } + public double getPrice() { return price; } + public void setPrice(double price) { this.price = price; } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderRequest.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderRequest.java new file mode 100644 index 0000000000..2aa63061f8 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderRequest.java @@ -0,0 +1,27 @@ +package com.amazonaws.samples.durable.models; + +import java.util.List; + +public class OrderRequest { + private String orderId; + private String customerId; + private String customerEmail; + private List items; + private double totalAmount; + private String shippingAddress; + + public OrderRequest() {} + + public String getOrderId() { return orderId; } + public void setOrderId(String orderId) { this.orderId = orderId; } + public String getCustomerId() { return customerId; } + public void setCustomerId(String customerId) { this.customerId = customerId; } + public String getCustomerEmail() { return customerEmail; } + public void setCustomerEmail(String customerEmail) { this.customerEmail = customerEmail; } + public List getItems() { return items; } + public void setItems(List items) { this.items = items; } + public double getTotalAmount() { return totalAmount; } + public void setTotalAmount(double totalAmount) { this.totalAmount = totalAmount; } + public String getShippingAddress() { return shippingAddress; } + public void setShippingAddress(String shippingAddress) { this.shippingAddress = shippingAddress; } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/ProcessingResult.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/ProcessingResult.java new file mode 100644 index 0000000000..169dfe3270 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/ProcessingResult.java @@ -0,0 +1,32 @@ +package com.amazonaws.samples.durable.models; + +import java.util.Map; + +public class ProcessingResult { + private String executionId; + private String pattern; + private String status; + private Map data; + private String timestamp; + + public ProcessingResult() {} + + public ProcessingResult(String executionId, String pattern, String status, Map data) { + this.executionId = executionId; + this.pattern = pattern; + this.status = status; + this.data = data; + this.timestamp = java.time.Instant.now().toString(); + } + + public String getExecutionId() { return executionId; } + public void setExecutionId(String executionId) { this.executionId = executionId; } + public String getPattern() { return pattern; } + public void setPattern(String pattern) { this.pattern = pattern; } + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + public Map getData() { return data; } + public void setData(Map data) { this.data = data; } + public String getTimestamp() { return timestamp; } + public void setTimestamp(String timestamp) { this.timestamp = timestamp; } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java new file mode 100644 index 0000000000..a031c590c4 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java @@ -0,0 +1,129 @@ +package com.amazonaws.samples.durable.monitoring; + +import java.time.Duration; +import java.util.Map; + +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableHandler; +import software.amazon.lambda.durable.TypeToken; +import software.amazon.lambda.durable.config.WaitForConditionConfig; +import software.amazon.lambda.durable.model.WaitForConditionResult; +import software.amazon.lambda.durable.retry.JitterStrategy; +import software.amazon.lambda.durable.retry.WaitStrategies; +import software.amazon.lambda.durable.retry.WaitForConditionWaitStrategy; + +/** + * PATTERN: Monitoring / Polling + * + * Demonstrates the waitForCondition operation which polls an external + * system on a schedule until a terminal condition is reached. The function + * suspends between polling attempts without consuming compute. + * + * Use case: Monitor a long-running batch job, waiting for it to complete. + * + * Flow: Start monitoring -> Poll for status -> (suspend between polls) -> Return final status + */ +public class JobMonitorHandler extends DurableHandler, Map> { + + private static int pollCount = 0; + + @Override + public Map handleRequest(Map event, DurableContext context) { + context.getLogger().info("Starting job monitor"); + + String jobId = (String) event.getOrDefault("jobId", "JOB-" + System.currentTimeMillis()); + int maxPolls = ((Number) event.getOrDefault("maxPolls", 5)).intValue(); + + // Step 1: Submit or acknowledge the job + Map jobInfo = context.step("acknowledge-job", Map.class, stepCtx -> { + stepCtx.getLogger().info("Acknowledging job: " + jobId); + return Map.of( + "jobId", jobId, + "status", "SUBMITTED", + "submittedAt", java.time.Instant.now().toString() + ); + }); + + // Step 2: Use waitForCondition to poll until job completes + // The function suspends between each poll - no compute charges during waits + WaitForConditionWaitStrategy> strategy = (state, attempt) -> { + if (attempt >= maxPolls) { + throw new RuntimeException("Job monitoring timed out after " + maxPolls + " attempts"); + } + // Exponential backoff: 5s, 10s, 20s, 40s... + long delaySeconds = Math.min(5L * (long) Math.pow(2, attempt - 1), 60); + return Duration.ofSeconds(delaySeconds); + }; + + Map initialState = Map.of( + "jobId", jobId, + "status", "SUBMITTED", + "attempts", 0, + "done", false + ); + + WaitForConditionConfig> config = WaitForConditionConfig + .>builder() + .initialState(initialState) + .waitStrategy(strategy) + .build(); + + Map finalJobState = context.waitForCondition( + "poll-job-status", + new TypeToken<>() {}, + (state, stepCtx) -> { + int attempts = ((Number) state.getOrDefault("attempts", 0)).intValue() + 1; + stepCtx.getLogger().info("Polling job status, attempt: " + attempts); + + // Simulate checking external job status + // In production, this would call an external API + String currentStatus = simulateJobStatus(attempts, maxPolls); + + Map updatedState = Map.of( + "jobId", state.get("jobId"), + "status", currentStatus, + "attempts", attempts, + "done", "COMPLETED".equals(currentStatus) || "FAILED".equals(currentStatus), + "lastChecked", java.time.Instant.now().toString() + ); + + boolean isDone = "COMPLETED".equals(currentStatus) || "FAILED".equals(currentStatus); + if (isDone) { + return WaitForConditionResult.stopPolling(updatedState); + } + return WaitForConditionResult.continuePolling(updatedState); + }, + config + ); + + // Step 3: Process the final result + Map finalResult = context.step("process-job-result", Map.class, stepCtx -> { + String status = (String) finalJobState.get("status"); + stepCtx.getLogger().info("Job completed with status: " + status); + return Map.of( + "jobId", jobId, + "finalStatus", status, + "totalAttempts", finalJobState.get("attempts"), + "completedAt", java.time.Instant.now().toString() + ); + }); + + return Map.of( + "pattern", "MONITORING", + "jobId", jobId, + "status", finalResult.get("finalStatus"), + "pollAttempts", finalResult.get("totalAttempts") + ); + } + + private String simulateJobStatus(int attempt, int maxPolls) { + // Simulate a job that completes after a few polling attempts + if (attempt >= maxPolls - 1) { + return "COMPLETED"; + } else if (attempt == 1) { + return "RUNNING"; + } else { + return "IN_PROGRESS"; + } + } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java new file mode 100644 index 0000000000..c752e9cdd5 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java @@ -0,0 +1,190 @@ +package com.amazonaws.samples.durable.suborchestration; + +import java.time.Duration; +import java.util.List; +import java.util.Map; + +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableFuture; +import software.amazon.lambda.durable.DurableHandler; + +/** + * PATTERN: Sub-Orchestration (Child Contexts) + * + * Demonstrates runInChildContext() for organizing complex workflows into + * isolated, reusable sub-workflows. Each child context has its own operation + * namespace and checkpoints results as a single unit. + * + * Also demonstrates concurrent child contexts using runInChildContextAsync(). + * + * Use cases: + * - Breaking complex workflows into logical sub-workflows + * - Running independent sub-workflows concurrently + * - Reusable workflow components + * + * Flow: Order Received -> [Payment Sub-workflow || Inventory Sub-workflow] -> Shipping Sub-workflow -> Complete + */ +public class OrderFulfillmentHandler extends DurableHandler, Map> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + context.getLogger().info("Starting order fulfillment orchestration"); + + String orderId = (String) event.getOrDefault("orderId", "ORD-" + System.currentTimeMillis()); + double amount = ((Number) event.getOrDefault("amount", 149.99)).doubleValue(); + String customerId = (String) event.getOrDefault("customerId", "CUST-001"); + + // Step 1: Order validation (in main context) + Map orderDetails = context.step("validate-order", Map.class, stepCtx -> { + stepCtx.getLogger().info("Validating order: " + orderId); + return Map.of( + "orderId", orderId, + "customerId", customerId, + "amount", amount, + "status", "VALIDATED" + ); + }); + + // Step 2: Run Payment and Inventory sub-workflows CONCURRENTLY + // Each runs in its own isolated child context + DurableFuture> paymentFuture = context.runInChildContextAsync( + "payment-workflow", (Class>) (Class) Map.class, + child -> processPayment(child, orderId, amount) + ); + + DurableFuture> inventoryFuture = context.runInChildContextAsync( + "inventory-workflow", (Class>) (Class) Map.class, + child -> reserveInventory(child, orderId, event) + ); + + // Wait for both concurrent sub-workflows to complete + List results = DurableFuture.allOf(paymentFuture, inventoryFuture); + Map paymentResult = paymentFuture.get(); + Map inventoryResult = inventoryFuture.get(); + + context.getLogger().info("Payment and inventory sub-workflows completed"); + + // Step 3: Shipping sub-workflow (sequential, depends on previous results) + Map shippingResult = context.runInChildContext( + "shipping-workflow", (Class>) (Class) Map.class, + child -> processShipping(child, orderId, inventoryResult) + ); + + // Step 4: Notification sub-workflow + Map notificationResult = context.runInChildContext( + "notification-workflow", (Class>) (Class) Map.class, + child -> sendNotifications(child, orderId, customerId, shippingResult) + ); + + return Map.of( + "pattern", "SUB_ORCHESTRATION", + "orderId", orderId, + "status", "FULFILLED", + "payment", paymentResult, + "inventory", inventoryResult, + "shipping", shippingResult, + "notification", notificationResult + ); + } + + private Map processPayment(DurableContext child, String orderId, double amount) { + // Sub-workflow with multiple steps, isolated in its own context + Map authorization = child.step("authorize-card", Map.class, stepCtx -> { + stepCtx.getLogger().info("Authorizing payment for order: " + orderId); + return Map.of( + "authCode", "AUTH-" + orderId, + "amount", amount, + "status", "AUTHORIZED" + ); + }); + + child.wait("fraud-check-delay", Duration.ofSeconds(2)); + + Map fraudCheck = child.step("fraud-check", Map.class, stepCtx -> { + stepCtx.getLogger().info("Running fraud check for: " + authorization.get("authCode")); + return Map.of( + "authCode", authorization.get("authCode"), + "fraudScore", 0.05, + "passed", true + ); + }); + + return child.step("capture-payment", Map.class, stepCtx -> { + stepCtx.getLogger().info("Capturing payment: " + authorization.get("authCode")); + return Map.of( + "transactionId", "TXN-" + orderId, + "authCode", authorization.get("authCode"), + "amount", amount, + "status", "CAPTURED" + ); + }); + } + + private Map reserveInventory(DurableContext child, String orderId, Map event) { + Map availability = child.step("check-availability", Map.class, stepCtx -> { + stepCtx.getLogger().info("Checking inventory availability for order: " + orderId); + return Map.of( + "orderId", orderId, + "available", true, + "warehouse", "WAREHOUSE-EAST-1" + ); + }); + + return child.step("reserve-stock", Map.class, stepCtx -> { + stepCtx.getLogger().info("Reserving stock in: " + availability.get("warehouse")); + return Map.of( + "reservationId", "RES-" + orderId, + "warehouse", availability.get("warehouse"), + "status", "RESERVED" + ); + }); + } + + private Map processShipping(DurableContext child, String orderId, Map inventoryResult) { + Map label = child.step("create-shipping-label", Map.class, stepCtx -> { + stepCtx.getLogger().info("Creating shipping label for order: " + orderId); + return Map.of( + "labelId", "LBL-" + orderId, + "warehouse", inventoryResult.get("warehouse"), + "carrier", "EXPRESS-SHIPPING" + ); + }); + + child.step("schedule-pickup", Map.class, stepCtx -> { + stepCtx.getLogger().info("Scheduling pickup from: " + label.get("warehouse")); + return Map.of("pickupScheduled", true, "estimatedPickup", "2 hours"); + }); + + return child.step("generate-tracking", Map.class, stepCtx -> { + stepCtx.getLogger().info("Generating tracking number"); + return Map.of( + "trackingNumber", "TRACK-" + orderId, + "carrier", label.get("carrier"), + "estimatedDelivery", "2-3 business days", + "status", "LABEL_CREATED" + ); + }); + } + + private Map sendNotifications(DurableContext child, String orderId, String customerId, + Map shippingResult) { + child.step("send-order-confirmation", String.class, stepCtx -> { + stepCtx.getLogger().info("Sending order confirmation to customer: " + customerId); + return "Order confirmation sent"; + }); + + child.step("send-shipping-notification", String.class, stepCtx -> { + stepCtx.getLogger().info("Sending shipping notification with tracking: " + shippingResult.get("trackingNumber")); + return "Shipping notification sent"; + }); + + return child.step("notification-summary", Map.class, stepCtx -> { + return Map.of( + "orderId", orderId, + "customerId", customerId, + "notificationsSent", 2, + "trackingNumber", shippingResult.get("trackingNumber") + ); + }); + } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java new file mode 100644 index 0000000000..46e2253476 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java @@ -0,0 +1,101 @@ +package com.amazonaws.samples.durable.timer; + +import java.time.Duration; +import java.util.Map; + +import software.amazon.lambda.durable.DurableContext; +import software.amazon.lambda.durable.DurableFuture; +import software.amazon.lambda.durable.DurableHandler; + +/** + * PATTERN: Timer / Scheduled Delays + * + * Demonstrates the wait() operation which suspends execution for a specified + * duration WITHOUT consuming compute. The function exits, and the backend + * automatically resumes it when the wait completes. + * + * Use cases: + * - Scheduled reminders + * - Rate limiting between API calls + * - Delayed retry patterns + * - SLA-based escalations + * + * Flow: Process event -> Wait (suspend) -> Send reminder -> Wait -> Escalate + */ +public class ScheduledReminderHandler extends DurableHandler, Map> { + + @Override + public Map handleRequest(Map event, DurableContext context) { + context.getLogger().info("Starting scheduled reminder workflow"); + + String taskId = (String) event.getOrDefault("taskId", "TASK-001"); + String assignee = (String) event.getOrDefault("assignee", "developer@example.com"); + int reminderIntervalSeconds = ((Number) event.getOrDefault("reminderIntervalSeconds", 30)).intValue(); + int escalationSeconds = ((Number) event.getOrDefault("escalationSeconds", 60)).intValue(); + + // Step 1: Create the task assignment + Map taskAssignment = context.step("create-task", Map.class, stepCtx -> { + stepCtx.getLogger().info("Creating task assignment: " + taskId + " -> " + assignee); + return Map.of( + "taskId", taskId, + "assignee", assignee, + "status", "ASSIGNED", + "createdAt", java.time.Instant.now().toString() + ); + }); + + // Step 2: Send initial notification + context.step("send-initial-notification", String.class, stepCtx -> { + stepCtx.getLogger().info("Sending initial task notification to: " + assignee); + return "Initial notification sent to " + assignee; + }); + + // Step 3: Wait for the first reminder interval + // Function SUSPENDS here - no compute charges during this wait + context.getLogger().info("Waiting " + reminderIntervalSeconds + " seconds before first reminder"); + context.wait("first-reminder-delay", Duration.ofSeconds(reminderIntervalSeconds)); + + // Step 4: Send first reminder + context.step("send-first-reminder", String.class, stepCtx -> { + stepCtx.getLogger().info("Sending first reminder to: " + assignee); + return "First reminder sent"; + }); + + // Step 5: Wait for escalation period + context.getLogger().info("Waiting " + escalationSeconds + " seconds before escalation"); + context.wait("escalation-delay", Duration.ofSeconds(escalationSeconds)); + + // Step 6: Escalate to manager + Map escalation = context.step("escalate-to-manager", Map.class, stepCtx -> { + stepCtx.getLogger().info("Escalating task " + taskId + " to manager"); + return Map.of( + "taskId", taskId, + "originalAssignee", assignee, + "escalatedTo", "manager@example.com", + "reason", "Task not completed within SLA", + "escalatedAt", java.time.Instant.now().toString() + ); + }); + + // Step 7: Demonstrate async wait with concurrent step (minimum duration pattern) + DurableFuture minimumWait = context.waitAsync("minimum-processing-time", Duration.ofSeconds(5)); + DurableFuture processingFuture = context.stepAsync("final-processing", String.class, stepCtx -> { + stepCtx.getLogger().info("Running final processing (guaranteed minimum 5s total)"); + return "Final processing complete"; + }); + + // Both must complete - ensures at least 5 seconds elapsed + minimumWait.get(); + String processingResult = processingFuture.get(); + + // Step 8: Final summary + return Map.of( + "pattern", "TIMER", + "taskId", taskId, + "status", "ESCALATED", + "assignee", assignee, + "escalatedTo", escalation.get("escalatedTo"), + "totalWaitTime", (reminderIntervalSeconds + escalationSeconds + 5) + " seconds" + ); + } +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/approval-event.json b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/approval-event.json new file mode 100644 index 0000000000..26687a659c --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/approval-event.json @@ -0,0 +1,6 @@ +{ + "requestId": "REQ-TEST-001", + "requestor": "employee@example.com", + "amount": 15000.00, + "description": "Conference travel budget request" +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/chaining-event.json b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/chaining-event.json new file mode 100644 index 0000000000..76e1898ced --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/chaining-event.json @@ -0,0 +1,7 @@ +{ + "orderId": "ORD-TEST-001", + "customerId": "CUST-001", + "customerEmail": "test@example.com", + "totalAmount": 299.99, + "shippingAddress": "123 Main St, Seattle, WA 98101" +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/errorhandling-event.json b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/errorhandling-event.json new file mode 100644 index 0000000000..43ad80c6c4 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/errorhandling-event.json @@ -0,0 +1,5 @@ +{ + "orderId": "ORD-TEST-001", + "amount": 199.99, + "simulateInventoryFailure": true +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/fanout-event.json b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/fanout-event.json new file mode 100644 index 0000000000..5b114d3239 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/fanout-event.json @@ -0,0 +1,5 @@ +{ + "dataId": "DATA-TEST-001", + "source": "s3://my-bucket/documents/report.pdf", + "analysisTypes": ["sentiment", "entities", "summary"] +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/mapprocessing-event.json b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/mapprocessing-event.json new file mode 100644 index 0000000000..8ea1598798 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/mapprocessing-event.json @@ -0,0 +1,5 @@ +{ + "batchSize": 10, + "maxConcurrency": 3, + "toleratedFailures": 2 +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/monitoring-event.json b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/monitoring-event.json new file mode 100644 index 0000000000..54c93b3d3a --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/monitoring-event.json @@ -0,0 +1,5 @@ +{ + "jobId": "JOB-TEST-001", + "jobType": "DATA_EXPORT", + "maxPolls": 5 +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/suborchestration-event.json b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/suborchestration-event.json new file mode 100644 index 0000000000..7605b16dd8 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/suborchestration-event.json @@ -0,0 +1,9 @@ +{ + "orderId": "ORD-TEST-001", + "customerId": "CUST-TEST-001", + "amount": 499.99, + "items": [ + {"productId": "PROD-001", "name": "Widget", "qty": 2}, + {"productId": "PROD-002", "name": "Gadget", "qty": 1} + ] +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/timer-event.json b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/timer-event.json new file mode 100644 index 0000000000..4c6b4ff80a --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/timer-event.json @@ -0,0 +1,6 @@ +{ + "taskId": "TASK-TEST-001", + "assignee": "developer@example.com", + "reminderIntervalSeconds": 10, + "escalationSeconds": 20 +} diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/template.yaml b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/template.yaml new file mode 100644 index 0000000000..9098460cc0 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/template.yaml @@ -0,0 +1,290 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + Lambda Durable Functions Java Examples + Demonstrates chaining, fan-out/fan-in, human interaction, monitoring, timers, + error handling, map processing, and sub-orchestration patterns. + +Globals: + Function: + Timeout: 60 + MemorySize: 512 + Architectures: + - x86_64 + +Parameters: + SNSTopicName: + Type: String + Description: Name of the SNS Topic used to trigger durable functions + Default: DurableFunctionsSNSTopic + +Resources: + # ECR Repository for the container image + DurableFunctionsECRRepo: + Type: AWS::ECR::Repository + Properties: + RepositoryName: durable-functions-java-examples + ImageScanningConfiguration: + ScanOnPush: true + + # SNS Topic for triggering the durable functions + DurableFunctionsSNSTopic: + Type: AWS::SNS::Topic + Properties: + TopicName: !Ref SNSTopicName + + # DynamoDB table for storing results + DurableFunctionsDynamoDBTable: + Type: AWS::DynamoDB::Table + Properties: + TableName: DurableFunctionsResultsTable + AttributeDefinitions: + - AttributeName: ExecutionId + AttributeType: S + - AttributeName: Timestamp + AttributeType: S + KeySchema: + - AttributeName: ExecutionId + KeyType: HASH + - AttributeName: Timestamp + KeyType: RANGE + BillingMode: PAY_PER_REQUEST + + # IAM Role for Durable Lambda Functions + DurableFunctionRole: + Type: AWS::IAM::Role + Properties: + RoleName: !Sub "${AWS::StackName}-durable-function-role" + AssumeRolePolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Principal: + Service: lambda.amazonaws.com + Action: sts:AssumeRole + ManagedPolicyArns: + - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicDurableExecutionRolePolicy + Policies: + - PolicyName: DynamoDBAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:PutItem + - dynamodb:UpdateItem + - dynamodb:Query + - dynamodb:Scan + Resource: + - !GetAtt DurableFunctionsDynamoDBTable.Arn + - !Sub "${DurableFunctionsDynamoDBTable.Arn}/index/*" + - PolicyName: SNSAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - sns:Publish + - sns:Subscribe + Resource: !Ref DurableFunctionsSNSTopic + - PolicyName: LambdaInvokeAccess + PolicyDocument: + Version: '2012-10-17' + Statement: + - Effect: Allow + Action: + - lambda:InvokeFunction + - lambda:SendDurableExecutionCallbackSuccess + - lambda:SendDurableExecutionCallbackFailure + - lambda:SendDurableExecutionCallbackHeartbeat + Resource: "*" + + # Example 1: Chaining Pattern - Sequential steps with data passing + ChainingFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: durable-chaining-example + PackageType: Image + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + ImageConfig: + Command: ["com.amazonaws.samples.durable.chaining.OrderProcessingHandler::handleRequest"] + Role: !GetAtt DurableFunctionRole.Arn + Environment: + Variables: + DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable + Events: + SNSEvent: + Type: SNS + Properties: + Topic: !Ref DurableFunctionsSNSTopic + FilterPolicy: + pattern: + - chaining + + # Example 2: Fan-Out/Fan-In Pattern - Parallel processing + FanOutFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: durable-fanout-example + PackageType: Image + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + ImageConfig: + Command: ["com.amazonaws.samples.durable.fanout.ParallelProcessingHandler::handleRequest"] + Role: !GetAtt DurableFunctionRole.Arn + Environment: + Variables: + DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable + Events: + SNSEvent: + Type: SNS + Properties: + Topic: !Ref DurableFunctionsSNSTopic + FilterPolicy: + pattern: + - fanout + + # Example 3: Human Interaction Pattern - Callbacks + HumanInteractionFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: durable-human-interaction-example + PackageType: Image + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + ImageConfig: + Command: ["com.amazonaws.samples.durable.humaninteraction.ApprovalWorkflowHandler::handleRequest"] + Role: !GetAtt DurableFunctionRole.Arn + Environment: + Variables: + DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable + SNS_TOPIC_ARN: !Ref DurableFunctionsSNSTopic + Events: + SNSEvent: + Type: SNS + Properties: + Topic: !Ref DurableFunctionsSNSTopic + FilterPolicy: + pattern: + - approval + + # Example 4: Monitoring/Polling Pattern - Wait for condition + MonitoringFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: durable-monitoring-example + PackageType: Image + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + ImageConfig: + Command: ["com.amazonaws.samples.durable.monitoring.JobMonitorHandler::handleRequest"] + Role: !GetAtt DurableFunctionRole.Arn + Environment: + Variables: + DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable + Events: + SNSEvent: + Type: SNS + Properties: + Topic: !Ref DurableFunctionsSNSTopic + FilterPolicy: + pattern: + - monitoring + + # Example 5: Timer Pattern - Scheduled delays + TimerFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: durable-timer-example + PackageType: Image + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + ImageConfig: + Command: ["com.amazonaws.samples.durable.timer.ScheduledReminderHandler::handleRequest"] + Role: !GetAtt DurableFunctionRole.Arn + Environment: + Variables: + DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable + SNS_TOPIC_ARN: !Ref DurableFunctionsSNSTopic + Events: + SNSEvent: + Type: SNS + Properties: + Topic: !Ref DurableFunctionsSNSTopic + FilterPolicy: + pattern: + - timer + + # Example 6: Error Handling Pattern - Retries and compensation + ErrorHandlingFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: durable-error-handling-example + PackageType: Image + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + ImageConfig: + Command: ["com.amazonaws.samples.durable.errorhandling.ResilientPaymentHandler::handleRequest"] + Role: !GetAtt DurableFunctionRole.Arn + Environment: + Variables: + DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable + Events: + SNSEvent: + Type: SNS + Properties: + Topic: !Ref DurableFunctionsSNSTopic + FilterPolicy: + pattern: + - errorhandling + + # Example 7: Map Processing Pattern - Collection processing + MapProcessingFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: durable-map-processing-example + PackageType: Image + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + ImageConfig: + Command: ["com.amazonaws.samples.durable.mapprocessing.BatchDataProcessorHandler::handleRequest"] + Role: !GetAtt DurableFunctionRole.Arn + Environment: + Variables: + DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable + Events: + SNSEvent: + Type: SNS + Properties: + Topic: !Ref DurableFunctionsSNSTopic + FilterPolicy: + pattern: + - mapprocessing + + # Example 8: Sub-Orchestration Pattern - Child contexts + SubOrchestrationFunction: + Type: AWS::Serverless::Function + Properties: + FunctionName: durable-sub-orchestration-example + PackageType: Image + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + ImageConfig: + Command: ["com.amazonaws.samples.durable.suborchestration.OrderFulfillmentHandler::handleRequest"] + Role: !GetAtt DurableFunctionRole.Arn + Environment: + Variables: + DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable + Events: + SNSEvent: + Type: SNS + Properties: + Topic: !Ref DurableFunctionsSNSTopic + FilterPolicy: + pattern: + - suborchestration + +Outputs: + SNSTopicArn: + Description: SNS Topic ARN for triggering durable functions + Value: !Ref DurableFunctionsSNSTopic + DynamoDBTableName: + Description: DynamoDB Table for storing results + Value: !Ref DurableFunctionsDynamoDBTable + ECRRepositoryUri: + Description: ECR Repository URI for container images + Value: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples" diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/infrastructure/ec2-client-instance.yaml b/lambda-durable-java-sam/JavaLambdaDurableFunctions/infrastructure/ec2-client-instance.yaml new file mode 100644 index 0000000000..8bfc12fcde --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/infrastructure/ec2-client-instance.yaml @@ -0,0 +1,354 @@ +AWSTemplateFormatVersion: '2010-09-09' +Parameters: + LatestAmiId: + Type: 'AWS::SSM::Parameter::Value' + Default: '/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64' + JavaVersion: + Type: String + Description: Choose the version of Java. Lambda currently supports Java 17 and 21 + AllowedValues: + - java17 + - java21 + Default: java21 + ServerlessLandGithubLocation: + Type: String + Default: https://github.com/aws-samples/serverless-patterns + Description: Github location of the serverless-patterns repo. Make sure to leave the .git at the end even if you are using a fork + +Mappings: + SubnetConfig: + VPC: + CIDR: '10.1.0.0/16' + PublicOne: + CIDR: '10.1.0.0/24' + +Resources: + VPC: + Type: AWS::EC2::VPC + Properties: + EnableDnsSupport: true + EnableDnsHostnames: true + CidrBlock: !FindInMap ['SubnetConfig', 'VPC', 'CIDR'] + Tags: + - Key: 'Name' + Value: 'DurableFunctionsVPC' + + PublicSubnetOne: + Type: AWS::EC2::Subnet + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: {Ref: 'AWS::Region'} + VpcId: !Ref 'VPC' + CidrBlock: !FindInMap ['SubnetConfig', 'PublicOne', 'CIDR'] + MapPublicIpOnLaunch: true + Tags: + - Key: 'Name' + Value: 'DurableFunctionsPublicSubnet' + + InternetGateway: + Type: AWS::EC2::InternetGateway + GatewayAttachement: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + VpcId: !Ref 'VPC' + InternetGatewayId: !Ref 'InternetGateway' + + PublicRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref 'VPC' + + PublicRoute: + Type: AWS::EC2::Route + DependsOn: GatewayAttachement + Properties: + RouteTableId: !Ref 'PublicRouteTable' + DestinationCidrBlock: '0.0.0.0/0' + GatewayId: !Ref 'InternetGateway' + + PublicSubnetOneRouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref PublicSubnetOne + RouteTableId: !Ref PublicRouteTable + + ClientInstanceSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Security group for the Durable Functions client EC2 instance + GroupName: !Sub "${AWS::StackName}-client-sg" + VpcId: !Ref VPC + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: 10.0.0.0/16 + + ClientEC2Instance: + Type: AWS::EC2::Instance + Properties: + InstanceType: m5.large + IamInstanceProfile: !Ref EC2InstanceProfile + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: {Ref: 'AWS::Region'} + SubnetId: !Ref PublicSubnetOne + SecurityGroupIds: [!GetAtt ClientInstanceSecurityGroup.GroupId] + ImageId: !Ref LatestAmiId + Tags: + - Key: 'Name' + Value: 'DurableFunctionsClientInstance' + BlockDeviceMappings: + - DeviceName: /dev/xvda + Ebs: + VolumeSize: 50 + VolumeType: gp2 + DeleteOnTermination: true + UserData: + Fn::Base64: + !Sub + - | + #!/bin/bash + yum update -y + + # install Java + max_attempts=5 + attempt_num=1 + success=false + while [ $success = false ] && [ $attempt_num -le $max_attempts ]; do + echo "Trying yum install Java" + JAVA_VERSION=${java_version} + echo "export JAVA_VERSION=$JAVA_VERSION" >> /home/ec2-user/.bash_profile + if [ "$JAVA_VERSION" == "java17" ]; then + sudo yum install java-17-amazon-corretto-devel -y + elif [ "$JAVA_VERSION" == "java21" ]; then + sudo yum install java-21-amazon-corretto-devel -y + else + sudo yum install java-21-amazon-corretto-devel -y + fi + if [ $? -eq 0 ]; then + echo "Yum install of Java succeeded" + success=true + else + echo "Attempt $attempt_num failed. Sleeping for 3 seconds and trying again..." + sleep 3 + ((attempt_num++)) + fi + done + + max_attempts=5 + attempt_num=1 + success=false + while [ $success = false ] && [ $attempt_num -le $max_attempts ]; do + echo "Trying yum install git" + yum install git -y + if [ $? -eq 0 ]; then + echo "Yum install of git succeeded" + success=true + else + echo "Attempt $attempt_num failed. Sleeping for 3 seconds and trying again..." + sleep 3 + ((attempt_num++)) + fi + done + + max_attempts=5 + attempt_num=1 + success=false + while [ $success = false ] && [ $attempt_num -le $max_attempts ]; do + echo "Trying yum install jq" + yum install jq -y + if [ $? -eq 0 ]; then + echo "Yum install of jq succeeded" + success=true + else + echo "Attempt $attempt_num failed. Sleeping for 3 seconds and trying again..." + sleep 3 + ((attempt_num++)) + fi + done + + max_attempts=5 + attempt_num=1 + success=false + while [ $success = false ] && [ $attempt_num -le $max_attempts ]; do + echo "Trying yum install docker" + sudo yum install -y docker + if [ $? -eq 0 ]; then + echo "Yum install of docker succeeded" + success=true + else + echo "Attempt $attempt_num failed. Sleeping for 3 seconds and trying again..." + sleep 3 + ((attempt_num++)) + fi + done + + service docker start + usermod -a -G docker ec2-user + + max_attempts=5 + attempt_num=1 + success=false + while [ $success = false ] && [ $attempt_num -le $max_attempts ]; do + echo "Trying yum install maven" + sudo yum install -y maven + if [ $? -eq 0 ]; then + echo "Yum install of maven succeeded" + success=true + else + echo "Attempt $attempt_num failed. Sleeping for 3 seconds and trying again..." + sleep 3 + ((attempt_num++)) + fi + done + + # Remove old AWS CLI and install AWS CLI 2 + yum erase awscli -y + cd /home/ec2-user + mkdir -p awscli + cd awscli + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + unzip awscliv2.zip + sudo ./aws/install + + # Install AWS SAM CLI + cd /home/ec2-user + mkdir -p awssam + cd awssam + wget https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip + unzip aws-sam-cli-linux-x86_64.zip -d sam-installation + sudo ./sam-installation/install + + # Set environment variables + AWS_REGION=${aws_region} + echo "export AWS_REGION=$AWS_REGION" >> /home/ec2-user/.bash_profile + + # Clone the durable functions project from serverless-patterns + cd /home/ec2-user + SERVERLESS_LAND_GITHUB_LOCATION=${serverless_land_github_location} + git clone -n --depth=1 --filter=tree:0 $SERVERLESS_LAND_GITHUB_LOCATION + cd ./serverless-patterns + git sparse-checkout set --no-cone /lambda-durable-java-sam + git checkout + cd lambda-durable-java-sam/JavaLambdaDurableFunctions + sudo chown -R ec2-user . + + # Get IP CIDR range for EC2 Instance Connect + cd /home/ec2-user + mkdir -p ip_prefix + cd ip_prefix + git clone https://github.com/joetek/aws-ip-ranges-json.git + cd aws-ip-ranges-json + EC2_CONNECT_IP=$(cat ip-ranges-ec2-instance-connect.json | jq -r --arg AWS_REGION "$AWS_REGION" '.prefixes[] | select(.region==$AWS_REGION).ip_prefix') + echo "export EC2_CONNECT_IP=$EC2_CONNECT_IP" >> /home/ec2-user/.bash_profile + SECURITY_GROUP=${security_group_id} + echo "export SECURITY_GROUP=$SECURITY_GROUP" >> /home/ec2-user/.bash_profile + aws ec2 authorize-security-group-ingress --region $AWS_REGION --group-id $SECURITY_GROUP --protocol tcp --port 22 --cidr $EC2_CONNECT_IP + + - serverless_land_github_location: !Ref ServerlessLandGithubLocation + aws_region: !Ref 'AWS::Region' + java_version: !Ref JavaVersion + security_group_id: !GetAtt ClientInstanceSecurityGroup.GroupId + + EC2InstanceEndpoint: + Type: AWS::EC2::InstanceConnectEndpoint + Properties: + PreserveClientIp: true + SecurityGroupIds: + - !GetAtt ClientInstanceSecurityGroup.GroupId + SubnetId: !Ref PublicSubnetOne + + EC2Role: + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Sid: '' + Effect: Allow + Principal: + Service: ec2.amazonaws.com + Action: 'sts:AssumeRole' + Path: "/" + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AWSCloudFormationFullAccess + - arn:aws:iam::aws:policy/CloudWatchFullAccess + - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore + - arn:aws:iam::aws:policy/AmazonS3FullAccess + - arn:aws:iam::aws:policy/IAMFullAccess + - arn:aws:iam::aws:policy/AWSLambda_FullAccess + - arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess_v2 + - arn:aws:iam::aws:policy/AmazonSNSFullAccess + - arn:aws:iam::aws:policy/AmazonECR_FullAccess + Policies: + - PolicyName: SecurityGroupsPolicy + PolicyDocument: !Sub '{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "ec2:DescribeSecurityGroups", + "ec2:DescribeSecurityGroupRules", + "ec2:DescribeTags" + ], + "Resource": "*" + }, + { + "Effect": "Allow", + "Action": [ + "ec2:AuthorizeSecurityGroupIngress", + "ec2:RevokeSecurityGroupIngress", + "ec2:AuthorizeSecurityGroupEgress", + "ec2:RevokeSecurityGroupEgress", + "ec2:ModifySecurityGroupRules", + "ec2:UpdateSecurityGroupRuleDescriptionsIngress", + "ec2:UpdateSecurityGroupRuleDescriptionsEgress" + ], + "Resource": [ + "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:security-group/*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "ec2:ModifySecurityGroupRules" + ], + "Resource": [ + "arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:security-group-rule/*" + ] + } + ] + }' + + EC2InstanceProfile: + Type: AWS::IAM::InstanceProfile + Properties: + InstanceProfileName: !Join + - '-' + - - 'EC2DurableFunctionsProfile' + - !Ref 'AWS::StackName' + Roles: + - !Ref EC2Role + +Outputs: + VPCId: + Description: The ID of the VPC created + Value: !Ref 'VPC' + Export: + Name: !Sub "${AWS::StackName}-VPCID" + PublicSubnetOne: + Description: The name of the public subnet created + Value: !Ref 'PublicSubnetOne' + Export: + Name: !Sub "${AWS::StackName}-PublicSubnetOne" + EC2InstanceEndpointID: + Description: The ID of the EC2 Instance Connect Endpoint + Value: !Ref EC2InstanceEndpoint + EC2InstanceId: + Description: The ID of the EC2 Client Instance + Value: !Ref ClientEC2Instance diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/pom.xml b/lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/pom.xml new file mode 100644 index 0000000000..0bc510ef95 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/pom.xml @@ -0,0 +1,59 @@ + + 4.0.0 + com.amazonaws.samples.durable + sns-message-sender + 1.0-SNAPSHOT + jar + SNS Message Sender for Durable Functions + + + UTF-8 + 21 + 21 + + + + + software.amazon.awssdk + sns + 2.25.0 + + + com.fasterxml.jackson.core + jackson-databind + 2.17.0 + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.6.2 + + false + + + + package + + shade + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 21 + 21 + + + + + diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/src/main/java/sns/producer/DurableFunctionsTrigger.java b/lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/src/main/java/sns/producer/DurableFunctionsTrigger.java new file mode 100644 index 0000000000..159e72d4c8 --- /dev/null +++ b/lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/src/main/java/sns/producer/DurableFunctionsTrigger.java @@ -0,0 +1,166 @@ +package sns.producer; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import software.amazon.awssdk.services.sns.SnsClient; +import software.amazon.awssdk.services.sns.model.ListTopicsRequest; +import software.amazon.awssdk.services.sns.model.ListTopicsResponse; +import software.amazon.awssdk.services.sns.model.MessageAttributeValue; +import software.amazon.awssdk.services.sns.model.PublishRequest; +import software.amazon.awssdk.services.sns.model.PublishResponse; +import software.amazon.awssdk.services.sns.model.Topic; + +/** + * SNS Message Sender for triggering Lambda Durable Function examples. + * + * Usage: + * java -cp target/sns-message-sender-1.0-SNAPSHOT.jar sns.producer.DurableFunctionsTrigger + * + * Patterns: + * chaining - Order processing with sequential steps + * fanout - Parallel data analysis + * approval - Human-in-the-loop approval workflow + * monitoring - Job status polling + * timer - Scheduled reminders with delays + * errorhandling - Resilient payment with saga compensation + * mapprocessing - Batch data processing + * suborchestration - Order fulfillment with sub-workflows + */ +public class DurableFunctionsTrigger { + + private static final ObjectMapper mapper = new ObjectMapper(); + + public static void main(String[] args) { + if (args.length < 2) { + System.out.println("Usage: DurableFunctionsTrigger "); + System.out.println("Patterns: chaining, fanout, approval, monitoring, timer, errorhandling, mapprocessing, suborchestration"); + System.exit(1); + } + + String topicName = args[0]; + String pattern = args[1]; + + Map message = buildMessage(pattern); + sendToSNS(topicName, message, pattern); + } + + private static Map buildMessage(String pattern) { + switch (pattern) { + case "chaining": + return Map.of( + "orderId", "ORD-" + System.currentTimeMillis(), + "customerId", "CUST-001", + "customerEmail", "customer@example.com", + "totalAmount", 299.99, + "shippingAddress", "123 Main St, Seattle, WA 98101" + ); + case "fanout": + return Map.of( + "dataId", "DATA-" + System.currentTimeMillis(), + "source", "s3://my-bucket/documents/report.pdf", + "analysisTypes", List.of("sentiment", "entities", "summary") + ); + case "approval": + return Map.of( + "requestId", "REQ-" + System.currentTimeMillis(), + "requestor", "employee@example.com", + "amount", 15000.00, + "description", "Conference travel budget request" + ); + case "monitoring": + return Map.of( + "jobId", "JOB-" + System.currentTimeMillis(), + "jobType", "DATA_EXPORT", + "maxPolls", 5 + ); + case "timer": + return Map.of( + "taskId", "TASK-" + System.currentTimeMillis(), + "assignee", "developer@example.com", + "reminderIntervalSeconds", 30, + "escalationSeconds", 60 + ); + case "errorhandling": + return Map.of( + "orderId", "ORD-" + System.currentTimeMillis(), + "amount", 199.99, + "simulateInventoryFailure", false + ); + case "mapprocessing": + return Map.of( + "batchSize", 10, + "maxConcurrency", 3, + "toleratedFailures", 2 + ); + case "suborchestration": + return Map.of( + "orderId", "ORD-" + System.currentTimeMillis(), + "customerId", "CUST-" + System.currentTimeMillis(), + "amount", 499.99, + "items", List.of( + Map.of("productId", "PROD-001", "name", "Widget", "qty", 2), + Map.of("productId", "PROD-002", "name", "Gadget", "qty", 1) + ) + ); + default: + System.err.println("Unknown pattern: " + pattern); + System.exit(1); + return Map.of(); + } + } + + private static void sendToSNS(String topicName, Map message, String pattern) { + SnsClient snsClient = SnsClient.builder().build(); + String topicArn = getTopicArnFromName(snsClient, topicName); + + if (topicArn.isEmpty()) { + System.err.println("Topic not found: " + topicName); + System.exit(1); + } + + try { + String messageBody = mapper.writeValueAsString(message); + + Map attributes = new HashMap<>(); + attributes.put("pattern", MessageAttributeValue.builder() + .dataType("String").stringValue(pattern).build()); + + PublishRequest request = PublishRequest.builder() + .topicArn(topicArn) + .message(messageBody) + .messageAttributes(attributes) + .subject("Durable Functions Trigger - " + pattern) + .build(); + + System.out.println("============================================================"); + System.out.println("Sending SNS message to trigger: " + pattern); + System.out.println("Topic: " + topicArn); + System.out.println("Message: " + messageBody); + System.out.println("============================================================"); + + PublishResponse response = snsClient.publish(request); + System.out.println("Message sent! ID: " + response.messageId()); + System.out.println("Status: " + response.sdkHttpResponse().statusCode()); + System.out.println("============================================================"); + + } catch (JsonProcessingException e) { + System.err.println("Failed to serialize message: " + e.getMessage()); + System.exit(1); + } + } + + private static String getTopicArnFromName(SnsClient snsClient, String topicName) { + ListTopicsResponse response = snsClient.listTopics(ListTopicsRequest.builder().build()); + for (Topic topic : response.topics()) { + if (topic.topicArn().endsWith(topicName)) { + return topic.topicArn(); + } + } + return ""; + } +} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/.gitignore b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/.gitignore new file mode 100755 index 0000000000..524f0963bd --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/.gitignore @@ -0,0 +1,24 @@ +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/.gitignore b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/.gitignore new file mode 100755 index 0000000000..c90d3bd6ee --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/.gitignore @@ -0,0 +1,25 @@ +node_modules +npm-debug.log +package-lock.json +package +*out.yml +out.json +bucket-name.txt +target +build +.gradle +*.zip +bin +obj +Gemfile.lock +lib +__pycache__ +*.pyc +.classpath +.factorypath +.project +.settings/* +.aws +.sam +.aws-sam +*.toml diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/README.md b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/README.md new file mode 100755 index 0000000000..5d37d8fa60 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/README.md @@ -0,0 +1,95 @@ +# sns-consumer-dynamo-sam + +This project contains source code and supporting files for a serverless application that you can deploy with the SAM CLI. It includes the following files and folders. + +- sns_event_consumer_function/src/main/java - Code for the application's Lambda function. +- events - Invocation events that you can use to invoke the function. +- sns_event_consumer_function/src/test/java - Unit tests for the application code. +- template.yaml - A template that defines the application's AWS resources. + +The application uses several AWS resources, including a Lambda function, an SNS event source and a DynamoDB table to which the lambda function will write. These resources are defined in the `template.yaml` file in this project. You can update the template to add AWS resources through the same deployment process that updates your application code. + + +## Use the SAM CLI to build and test locally + +Build your application with the `sam build` command. + +```bash +sam build +``` + +The SAM CLI installs dependencies defined in `sns_event_consumer_function/pom.xml`, creates a deployment package, and saves it in the `.aws-sam/build` folder. + +Test a single function by invoking it directly with a test event. An event is a JSON document that represents the input that the function receives from the event source. Test events are included in the `events` folder in this project. + +Run functions locally and invoke them with the `sam local invoke` command. + +```bash +sam local invoke --event events/event.json +``` + +## Deploy the sample application + +The Serverless Application Model Command Line Interface (SAM CLI) is an extension of the AWS CLI that adds functionality for building and testing Lambda applications. It uses Docker to run your functions in an Amazon Linux environment that matches Lambda. It can also emulate your application's build environment and API. + +To use the SAM CLI, you need the following tools. + +* SAM CLI - [Install the SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) +* Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community) + +To build and deploy your application for the first time, run the following in your shell: + +```bash +sam build +sam deploy --guided +``` + +The first command will build the source of your application. The second command will package and deploy your application to AWS, with a series of prompts: + +* **Stack Name**: The name of the stack to deploy to CloudFormation. This should be unique to your account and region, and a good starting point would be something matching your project name. +* **AWS Region**: The AWS region you want to deploy your app to. +* **Parameter SNSTopicName**: The name of the SNS Topic +* **Confirm changes before deploy**: If set to yes, any change sets will be shown to you before execution for manual review. If set to no, the AWS SAM CLI will automatically deploy application changes. +* **Allow SAM CLI IAM role creation**: Many AWS SAM templates, including this example, create AWS IAM roles required for the AWS Lambda function(s) included to access AWS services. By default, these are scoped down to minimum required permissions. To deploy an AWS CloudFormation stack which creates or modifies IAM roles, the `CAPABILITY_IAM` value for `capabilities` must be provided. If permission isn't provided through this prompt, to deploy this example you must explicitly pass `--capabilities CAPABILITY_IAM` to the `sam deploy` command. +* **Disable rollback**: Defaults to No and it preserves the state of previously provisioned resources when an operation fails +* **Save arguments to configuration file**: If set to yes, your choices will be saved to a configuration file inside the project, so that in the future you can just re-run `sam deploy` without parameters to deploy changes to your application. +* **SAM configuration file [samconfig.toml]**: Name of the configuration file to store configuration information locally +* **SAM configuration environment [default]**: Environment for storing deployment information locally + +You should get a message "Successfully created/updated stack - in " if all goes well + + +## Test the sample application + +Once the lambda function is deployed, send some SNS messages on the queue that the lambda function is listening on. + +Use the project ../sns_message_sender_json. + +Look at the Readme of that project to determine how to build that project and run the command that will send SNS messages with a Json payload to the lambda function built using this project. The lambda function will receive the SNS messages with a JSON payload and input fields from the SNS message into a DynamoDB table. + +The value field of each SNS message that will be sent out will be a Json element of the format + +"person": { + "firstname": "Myra", + "lastname": "Munns", + "company": "Anker Law Office", + "street": "461 Prospect Pl #316", + "city": "Euless", + "county": "Tarrant", + "state": "TX", + "zip": "76040", + "homePhone": "817-914-7518", + "cellPhone": "817-451-3518", + "email": "mmunns@cox.net", + "website": "http://www.ankerlawoffice.com" +} + +Then check Cloudwatch logs and you should see messages for the Cloudwatch Log Group with the name of the deployed Lambda function. + +The lambda code parses the SNS messages and outputs the fields in the SNS messages to Cloudwatch logs + +Unlike SQS, a single invocation of the lambda function receives a single message. + +The code in this example prints out the fields in the SNS message and logs them in Cloudwatch logs. + +Apart from outputting to Cloudwatch logs, the lambda function also inputs fields from the SNS message (both message metadata fields as well as payload fields from the JSON payload) into a DynamoDB table created by the SAM template. You can log into the AWS console and look at the DynamoDB table and run a scan to see data getting input from the SNS message into the DynamoDB table diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/events/event.json b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/events/event.json new file mode 100755 index 0000000000..39f3c5ce76 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/events/event.json @@ -0,0 +1,31 @@ +{ + "Records": [ + { + "EventVersion": "1.0", + "EventSubscriptionArn": "arn:aws:sns:us-east-1:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486", + "EventSource": "aws:sns", + "Sns": { + "SignatureVersion": "1", + "Timestamp": "2019-01-02T12:45:07.000Z", + "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==", + "SigningCertUrl": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem", + "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e", + "Message": "{\"firstname\":\"Mitsue\",\"lastname\":\"Tollner\",\"company\":\"Morlong Associates\",\"street\":\"7 Eads St\",\"city\":\"Chicago\",\"county\":\"Cook\",\"state\":\"IL\",\"zip\":\"60632\",\"homePhone\":\"773-573-6914\",\"cellPhone\":\"773-924-8565\",\"email\":\"mitsue_tollner@yahoo.com\",\"website\":\"http://www.morlongassociates.com\"}", + "MessageAttributes": { + "MessageKey": { + "Type": "String", + "Value": "TestKey07-05-29-2023-10-05-75" + }, + "MessageNumber": { + "Type": "String", + "Value": "6" + } + }, + "Type": "Notification", + "UnsubscribeUrl": "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486", + "TopicArn":"arn:aws:sns:us-east-1:123456789012:sns-lambda", + "Subject": "TestInvoke" + } + } + ] +} \ No newline at end of file diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.gitignore b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.gitignore new file mode 100755 index 0000000000..b83d22266a --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.settings/org.eclipse.jdt.core.prefs b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 0000000000..2af1e7b99c --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/pom.xml b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/pom.xml new file mode 100755 index 0000000000..584edecdfc --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/pom.xml @@ -0,0 +1,89 @@ + + 4.0.0 + com.amazonaws.services.lambda.samples.events.sns + SNSConsumer + 1.0 + jar + A sample Lambda SNS consumer + + 11 + 11 + + + + com.amazonaws + aws-lambda-java-core + 1.2.1 + + + com.amazonaws + aws-lambda-java-events + 3.11.0 + + + + com.amazonaws + aws-java-sdk-dynamodb + 1.12.445 + + + org.junit.jupiter + junit-jupiter-api + 5.6.0 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.6.0 + test + + + org.mockito + mockito-core + 3.7.7 + test + + + org.mockito + mockito-junit-jupiter + 3.8.0 + test + + + software.amazon.awssdk + sns + 2.20.73 + + + + com.fasterxml.jackson.core + jackson-core + 2.15.1 + + + com.fasterxml.jackson.datatype + jackson-datatype-joda + 2.15.1 + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + + package + + shade + + + + + + + diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdater.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdater.java new file mode 100755 index 0000000000..7a44f73ece --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdater.java @@ -0,0 +1,79 @@ +package com.amazonaws.services.lambda.samples.events.sns; + + +import java.util.Map; +import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; +import com.amazonaws.services.dynamodbv2.document.DynamoDB; +import com.amazonaws.services.dynamodbv2.document.Item; +import com.amazonaws.services.dynamodbv2.document.PutItemOutcome; +import com.amazonaws.services.dynamodbv2.document.Table; +import com.amazonaws.services.lambda.runtime.LambdaLogger; +import com.amazonaws.services.lambda.runtime.events.SNSEvent; +import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord; + +public class DynamoDBUpdater { + + String dynamoDBTableName; + AmazonDynamoDB client; + DynamoDB dynamoDB; + Table dynamoTable; + + + public DynamoDBUpdater(String dynamoDBTableName) { + super(); + if (null == dynamoDBTableName) { + this.dynamoDBTableName = "SNS_LAMBDA_DYNAMO_TABLE"; + } else { + this.dynamoDBTableName = dynamoDBTableName; + } + String AWS_SAM_LOCAL = System.getenv("AWS_SAM_LOCAL"); + if (null == AWS_SAM_LOCAL) { + this.client = AmazonDynamoDBClientBuilder.standard().build(); + } else { + this.client = AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(new EndpointConfiguration("http://127.0.0.1:8000", "")).build(); + this.dynamoDBTableName = "SQS_LAMBDA_DYNAMO_TABLE"; + } + //this.client = AmazonDynamoDBClientBuilder.standard().build(); + this.dynamoDB = new DynamoDB(client); + this.dynamoTable = dynamoDB.getTable(this.dynamoDBTableName); + } + + public PutItemOutcome insertIntoDynamoDB(SNSRecord record, Person thisPerson, LambdaLogger logger) { + logger.log("Now inserting a row in DynamoDB for messageID = " + record.getSNS().getMessageId()); + Item item = new Item(); + item.withPrimaryKey("MessageID", record.getSNS().getMessageId()); + item.withString("EventSource", record.getEventSource()); + item.withString("EventSubscriptionARN", record.getEventSubscriptionArn()); + item.withString("EventVersion", record.getEventVersion()); + item.withString("SigningCertURL", record.getSNS().getSigningCertUrl()); + item.withString("MessageID", record.getSNS().getMessageId()); + item.withString("Subject", record.getSNS().getSubject()); + item.withString("UnsubscribeURL", record.getSNS().getUnsubscribeUrl()); + item.withString("SignatureURL", record.getSNS().getSignatureVersion()); + item.withString("Signature", record.getSNS().getSignature()); + item.withString("Type", record.getSNS().getType()); + item.withString("TopicARN", record.getSNS().getTopicArn()); + item.withString("Timestamp", record.getSNS().getTimestamp().toString()); + item.withString("Firstname", thisPerson.getFirstname()); + item.withString("Lastname", thisPerson.getLastname()); + item.withString("Company", thisPerson.getCompany()); + item.withString("Address_Street", thisPerson.getStreet()); + item.withString("City", thisPerson.getCity()); + item.withString("County", thisPerson.getCounty()); + item.withString("State", thisPerson.getState()); + item.withString("Zip", thisPerson.getZip()); + item.withString("Home_Phone", thisPerson.getHomePhone()); + item.withString("Cell_Phone", thisPerson.getCellPhone()); + item.withString("Email", thisPerson.getEmail()); + item.withString("Website", thisPerson.getWebsite()); + Map attributes = record.getSNS().getMessageAttributes(); + attributes.forEach((k,v) -> { + item.withString(k, v.getValue()); + }); + logger.log("Now done inserting a row in DynamoDB for messageID = " + record.getSNS().getMessageId()); + return dynamoTable.putItem(item); + } + +} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNS.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNS.java new file mode 100755 index 0000000000..694b453689 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNS.java @@ -0,0 +1,84 @@ +//Lambda Runtime delivers a batch of messages to the lambda function +//Each batch of messages has two fields EventSource and EventSourceARN +//Each batch of messages also has a field called Records +//The Records is a map with multiple keys and values +//Each key is a combination of the Topic Name and the Partition Number +//One batch of messages can contain messages from multiple partitions + +/* +To simplify representing a batch of Kafka messages as a list of messages +We have created a Java class called KafkaMessage under the models package +Here we are mapping the structure of an incoming Kafka event to a list of +objects of the KafkaMessage class + */ + +package com.amazonaws.services.lambda.samples.events.sns; + +import java.util.List; +import java.util.Map; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.LambdaLogger; +import com.amazonaws.services.lambda.runtime.RequestHandler; +import com.amazonaws.services.lambda.runtime.events.SNSEvent; +import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.joda.JodaModule; + +public class HandlerSNS implements RequestHandler{ + //Gson gson = new GsonBuilder().setPrettyPrinting().create(); + String dynamoDBTableName = System.getenv("DYNAMO_DB_TABLE"); + DynamoDBUpdater ddbUpdater = new DynamoDBUpdater(dynamoDBTableName); + boolean addToDynamoDB=true; + ObjectMapper objectMapper = new ObjectMapper().registerModule(new JodaModule()); + @Override + public String handleRequest(SNSEvent event, Context context) + { + LambdaLogger logger = context.getLogger(); + try { + logger.log("Begin Event *************"); + try { + logger.log(objectMapper.writeValueAsString(event)); + } catch (JsonProcessingException e1) { + logger.log("An exception occurred " + e1.getMessage()); + throw new RuntimeException(e1); + } + logger.log("End Event ***************"); + List records = event.getRecords(); + for (SNSRecord record : records) { + logger.log("Event Source = " + record.getEventSource()); + logger.log("Event Subscription ARN = " + record.getEventSubscriptionArn()); + logger.log("Event Version = " + record.getEventVersion()); + logger.log("Signing Cert URL = " + record.getSNS().getSigningCertUrl()); + logger.log("Message ID = " + record.getSNS().getMessageId()); + logger.log("Subject = " + record.getSNS().getSubject()); + logger.log("Unsubscribe URL = " + record.getSNS().getUnsubscribeUrl()); + logger.log("Signature URL = " + record.getSNS().getSignatureVersion()); + logger.log("Signature = " + record.getSNS().getSignature()); + logger.log("Type = " + record.getSNS().getType()); + logger.log("Topic ARN = " + record.getSNS().getTopicArn()); + logger.log("Timestamp = " + record.getSNS().getTimestamp().toString()); + String message = record.getSNS().getMessage(); + Person person = objectMapper.readValue(message, Person.class); + logger.log("This person = " + person.toString()); + Map attributes = record.getSNS().getMessageAttributes(); + attributes.forEach((k,v) -> { + logger.log("Attribute: " + k + ", Value: " + v.getValue()); + }); + logger.log(record.getSNS().getSignatureVersion()); + String AWS_SAM_LOCAL = System.getenv("AWS_SAM_LOCAL"); + if ((null == AWS_SAM_LOCAL) && (addToDynamoDB)) { + ddbUpdater.insertIntoDynamoDB(record, person, logger); + } + } + } catch (Exception e) { + logger.log("An exception occurred " + e.getMessage()); + throw new RuntimeException(e); + } + return new String("200-OK"); + } + + public void throwit(String message) throws Exception{ + throw new Exception(message); + } +} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/Person.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/Person.java new file mode 100755 index 0000000000..08ff03c7aa --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/Person.java @@ -0,0 +1,138 @@ +package com.amazonaws.services.lambda.samples.events.sns; + +import java.util.Objects; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + + +public class Person { + + String firstname; + String lastname; + String company; + String street; + String city; + String county; + String state; + String zip; + String homePhone; + String cellPhone; + String email; + String website; + public Person() { + super(); + } + public String getFirstname() { + return firstname; + } + public void setFirstname(String firstname) { + this.firstname = firstname; + } + public String getLastname() { + return lastname; + } + public void setLastname(String lastname) { + this.lastname = lastname; + } + public String getCompany() { + return company; + } + public void setCompany(String company) { + this.company = company; + } + public String getStreet() { + return street; + } + public void setStreet(String street) { + this.street = street; + } + public String getCity() { + return city; + } + public void setCity(String city) { + this.city = city; + } + public String getCounty() { + return county; + } + public void setCounty(String county) { + this.county = county; + } + public String getState() { + return state; + } + public void setState(String state) { + this.state = state; + } + public String getZip() { + return zip; + } + public void setZip(String zip) { + this.zip = zip; + } + public String getHomePhone() { + return homePhone; + } + public void setHomePhone(String homePhone) { + this.homePhone = homePhone; + } + public String getCellPhone() { + return cellPhone; + } + public void setCellPhone(String cellPhone) { + this.cellPhone = cellPhone; + } + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + public String getWebsite() { + return website; + } + public void setWebsite(String website) { + this.website = website; + } + @Override + public String toString() { + return "Person [firstname=" + firstname + ", lastname=" + lastname + ", company=" + company + ", street=" + + street + ", city=" + city + ", county=" + county + ", state=" + state + ", zip=" + zip + + ", homePhone=" + homePhone + ", cellPhone=" + cellPhone + ", email=" + email + ", website=" + website + + "]"; + } + + public String toJson() { + ObjectMapper om = new ObjectMapper(); + String personJson = ""; + try { + personJson = om.writeValueAsString(this); + } catch (JsonProcessingException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return personJson; + } + @Override + public int hashCode() { + return Objects.hash(cellPhone, city, company, county, email, firstname, homePhone, lastname, state, street, + website, zip); + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Person other = (Person) obj; + return Objects.equals(cellPhone, other.cellPhone) && Objects.equals(city, other.city) + && Objects.equals(company, other.company) && Objects.equals(county, other.county) + && Objects.equals(email, other.email) && Objects.equals(firstname, other.firstname) + && Objects.equals(homePhone, other.homePhone) && Objects.equals(lastname, other.lastname) + && Objects.equals(state, other.state) && Objects.equals(street, other.street) + && Objects.equals(website, other.website) && Objects.equals(zip, other.zip); + } + +} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdaterTest.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdaterTest.java new file mode 100755 index 0000000000..360953ed6a --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdaterTest.java @@ -0,0 +1,105 @@ +package com.amazonaws.services.lambda.samples.events.sns; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.List; + +import org.junit.jupiter.api.Test; +import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; +import com.amazonaws.services.dynamodbv2.document.DynamoDB; +import com.amazonaws.services.dynamodbv2.document.Item; +import com.amazonaws.services.dynamodbv2.document.PutItemOutcome; +import com.amazonaws.services.dynamodbv2.document.Table; +import com.amazonaws.services.lambda.runtime.LambdaLogger; +import com.amazonaws.services.lambda.runtime.events.SNSEvent; +import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.joda.JodaModule; + + +import org.mockito.ArgumentMatchers; + +class DynamoDBUpdaterTest { + + private static final String snsEventJson = "{\n" + + " \"records\": [\n" + + " {\n" + + " \"sns\": {\n" + + " \"messageAttributes\": {\n" + + " \"MessageKey\": {\n" + + " \"type\": \"String\",\n" + + " \"value\": \"TestKey03-05-29-2023-06-05-49\"\n" + + " },\n" + + " \"MessageNumber\": {\n" + + " \"type\": \"String\",\n" + + " \"value\": \"89\"\n" + + " }\n" + + " },\n" + + " \"signingCertUrl\": \"https://sns.us-west-2.amazonaws.com/SimpleNotificationService-01d088a6f77103d0fe307c0069e40ed6.pem\",\n" + + " \"messageId\": \"e31e34d1-7349-539d-9b0e-683f306298ac\",\n" + + " \"message\": \"{\\\"firstname\\\":\\\"Tyra\\\",\\\"lastname\\\":\\\"Shields\\\",\\\"company\\\":\\\"\\\\\\\"Assink, Anne H Esq\\\\\\\"\\\",\\\"street\\\":\\\"3 Fort Worth Ave\\\",\\\"city\\\":\\\"Philadelphia\\\",\\\"county\\\":\\\"Philadelphia\\\",\\\"state\\\":\\\"PA\\\",\\\"zip\\\":\\\"19106\\\",\\\"homePhone\\\":\\\"215-255-1641\\\",\\\"cellPhone\\\":\\\"215-228-8264\\\",\\\"email\\\":\\\"tshields@gmail.com\\\",\\\"website\\\":\\\"http://www.assinkannehesq.com\\\"}\",\n" + + " \"subject\": \"Sending Message with Key = TestKey03-05-29-2023-06-05-49 and message number = 89\",\n" + + " \"unsubscribeUrl\": \"https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM:740325aa-8302-42e6-ab5c-70c2c38633d3\",\n" + + " \"type\": \"Notification\",\n" + + " \"signatureVersion\": \"1\",\n" + + " \"signature\": \"VzYoZ8lESJ+s9sMsy1Xlb8CfV8Y7M8Qk/w18onb2jEd0Q71GI8q1688PGQU3EFHkRtKLB/DYFPCZzZDezhmpQo6iHqSW2yVGgb5nt9x6NcccFOhK7jRl7QEmEkTmVn1AbtmJOL7ya5U+CZDbMKebCJnRdWgRlrtbE06TaklPnv0REHavXJ4c3fPdkDWc8mBiOhRX6+aAVII9D9Zt7zQLl6ROI8xH6RzIe0ZOy7gv9pF3YycAnrjX3ibD+5+7hvFKZPvgnhDansm++MjHa/mON5L08VxTY9lEFiTlQv2L7bS6XihwhWpmk6uQHQWpdURMdZsL2l2WRUNR+IROhvEQqg==\",\n" + + " \"timestamp\": 1685340395498,\n" + + " \"topicArn\": \"arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM\"\n" + + " },\n" + + " \"eventVersion\": \"1.0\",\n" + + " \"eventSource\": \"aws:sns\",\n" + + " \"eventSubscriptionArn\": \"arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM:740325aa-8302-42e6-ab5c-70c2c38633d3\"\n" + + " }\n" + + " ]\n" + + "}"; + + @Test + void testDynamoDBUpdater() { + DynamoDBUpdater ddbUpdater = new DynamoDBUpdater("DBTable"); + assertNotNull(ddbUpdater); + assertEquals(ddbUpdater.dynamoDBTableName, "DBTable"); + assertNotNull(ddbUpdater.client); + assertNotNull(ddbUpdater.dynamoDB); + assertNotNull(ddbUpdater.dynamoTable); + } + + @Test + void testInsertIntoDynamoDB() { + ObjectMapper om = new ObjectMapper().registerModule(new JodaModule()); + SNSEvent event = null; + try { + event = om.readValue(snsEventJson, SNSEvent.class); + } catch (JsonMappingException e) { + e.printStackTrace(); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + List records = event.getRecords(); + for(SNSRecord msg : records){ + Table dynamoDbTable = mock(Table.class); + AmazonDynamoDB client = mock(AmazonDynamoDB.class); + DynamoDB dynamoDB = mock(DynamoDB.class); + PutItemOutcome putoutcome = mock(PutItemOutcome.class); + LambdaLogger logger = mock(LambdaLogger.class); + DynamoDBUpdater ddbUpdater = new DynamoDBUpdater("DBTable"); + ddbUpdater.client = client; + ddbUpdater.dynamoDB = dynamoDB; + ddbUpdater.dynamoTable = dynamoDbTable; + Person person = new Person(); + try { + person = om.readValue(msg.getSNS().getMessage(), Person.class); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + when(ddbUpdater.dynamoTable.putItem(ArgumentMatchers.any(Item.class))).thenReturn(putoutcome); + PutItemOutcome putOutcome = ddbUpdater.insertIntoDynamoDB(msg, person, logger); + assertNotNull(putOutcome); + } + + } +} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNSTest.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNSTest.java new file mode 100755 index 0000000000..1f43a52ef3 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNSTest.java @@ -0,0 +1,73 @@ +package com.amazonaws.services.lambda.samples.events.sns; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.events.SNSEvent; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.joda.JodaModule; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +class HandlerSNSTest { + private static final String snsEventJson = "{\n" + + " \"records\": [\n" + + " {\n" + + " \"sns\": {\n" + + " \"messageAttributes\": {\n" + + " \"MessageKey\": {\n" + + " \"type\": \"String\",\n" + + " \"value\": \"TestKey03-05-29-2023-06-05-49\"\n" + + " },\n" + + " \"MessageNumber\": {\n" + + " \"type\": \"String\",\n" + + " \"value\": \"89\"\n" + + " }\n" + + " },\n" + + " \"signingCertUrl\": \"https://sns.us-west-2.amazonaws.com/SimpleNotificationService-01d088a6f77103d0fe307c0069e40ed6.pem\",\n" + + " \"messageId\": \"e31e34d1-7349-539d-9b0e-683f306298ac\",\n" + + " \"message\": \"{\\\"firstname\\\":\\\"Tyra\\\",\\\"lastname\\\":\\\"Shields\\\",\\\"company\\\":\\\"\\\\\\\"Assink, Anne H Esq\\\\\\\"\\\",\\\"street\\\":\\\"3 Fort Worth Ave\\\",\\\"city\\\":\\\"Philadelphia\\\",\\\"county\\\":\\\"Philadelphia\\\",\\\"state\\\":\\\"PA\\\",\\\"zip\\\":\\\"19106\\\",\\\"homePhone\\\":\\\"215-255-1641\\\",\\\"cellPhone\\\":\\\"215-228-8264\\\",\\\"email\\\":\\\"tshields@gmail.com\\\",\\\"website\\\":\\\"http://www.assinkannehesq.com\\\"}\",\n" + + " \"subject\": \"Sending Message with Key = TestKey03-05-29-2023-06-05-49 and message number = 89\",\n" + + " \"unsubscribeUrl\": \"https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM:740325aa-8302-42e6-ab5c-70c2c38633d3\",\n" + + " \"type\": \"Notification\",\n" + + " \"signatureVersion\": \"1\",\n" + + " \"signature\": \"VzYoZ8lESJ+s9sMsy1Xlb8CfV8Y7M8Qk/w18onb2jEd0Q71GI8q1688PGQU3EFHkRtKLB/DYFPCZzZDezhmpQo6iHqSW2yVGgb5nt9x6NcccFOhK7jRl7QEmEkTmVn1AbtmJOL7ya5U+CZDbMKebCJnRdWgRlrtbE06TaklPnv0REHavXJ4c3fPdkDWc8mBiOhRX6+aAVII9D9Zt7zQLl6ROI8xH6RzIe0ZOy7gv9pF3YycAnrjX3ibD+5+7hvFKZPvgnhDansm++MjHa/mON5L08VxTY9lEFiTlQv2L7bS6XihwhWpmk6uQHQWpdURMdZsL2l2WRUNR+IROhvEQqg==\",\n" + + " \"timestamp\": 1685340395498,\n" + + " \"topicArn\": \"arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM\"\n" + + " },\n" + + " \"eventVersion\": \"1.0\",\n" + + " \"eventSource\": \"aws:sns\",\n" + + " \"eventSubscriptionArn\": \"arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM:740325aa-8302-42e6-ab5c-70c2c38633d3\"\n" + + " }\n" + + " ]\n" + + "}"; + + @Mock + DynamoDBUpdater ddbUpdater; + + @Test + @ExtendWith(MockitoExtension.class) + void invokeTest() { + ObjectMapper om = new ObjectMapper().registerModule(new JodaModule()); + SNSEvent event = null; + try { + event = om.readValue(snsEventJson, SNSEvent.class); + } catch (JsonMappingException e) { + e.printStackTrace(); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + Context context = new TestContext(); + //PutItemOutcome putItemOutcome = mock(PutItemOutcome.class); + DynamoDBUpdater dbUpdater = mock(DynamoDBUpdater.class); + HandlerSNS handler = new HandlerSNS(); + handler.ddbUpdater = dbUpdater; + String result = handler.handleRequest(event, context); + assertEquals(result, "200-OK"); + } + +} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestContext.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestContext.java new file mode 100755 index 0000000000..891d393d51 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestContext.java @@ -0,0 +1,45 @@ +package com.amazonaws.services.lambda.samples.events.sns; + +import com.amazonaws.services.lambda.runtime.Context; +import com.amazonaws.services.lambda.runtime.CognitoIdentity; +import com.amazonaws.services.lambda.runtime.ClientContext; +import com.amazonaws.services.lambda.runtime.LambdaLogger; + +public class TestContext implements Context{ + + public TestContext() {} + public String getAwsRequestId(){ + return new String("495b12a8-xmpl-4eca-8168-160484189f99"); + } + public String getLogGroupName(){ + return new String("/aws/lambda/my-function"); + } + public String getLogStreamName(){ + return new String("2020/02/26/[$LATEST]704f8dxmpla04097b9134246b8438f1a"); + } + public String getFunctionName(){ + return new String("my-function"); + } + public String getFunctionVersion(){ + return new String("$LATEST"); + } + public String getInvokedFunctionArn(){ + return new String("arn:aws:lambda:us-east-2:123456789012:function:my-function"); + } + public CognitoIdentity getIdentity(){ + return null; + } + public ClientContext getClientContext(){ + return null; + } + public int getRemainingTimeInMillis(){ + return 300000; + } + public int getMemoryLimitInMB(){ + return 512; + } + public LambdaLogger getLogger(){ + return new TestLogger(); + } + +} \ No newline at end of file diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestLogger.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestLogger.java new file mode 100755 index 0000000000..2740b026c2 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestLogger.java @@ -0,0 +1,14 @@ +package com.amazonaws.services.lambda.samples.events.sns; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.amazonaws.services.lambda.runtime.LambdaLogger; + +public class TestLogger implements LambdaLogger { + private static final Logger logger = LoggerFactory.getLogger(TestLogger.class); + public void log(String message){ + logger.info(message); + } + public void log(byte[] message){ + logger.info(new String(message)); + } +} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/template.yaml b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/template.yaml new file mode 100755 index 0000000000..105e3f9088 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/template.yaml @@ -0,0 +1,78 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Description: > + sns_event_consumer_function + + Sample SAM Template for sns-consumer-with-sam + +# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst +Globals: + Function: + Timeout: 15 + +Resources: + LambdaSNSConsumerJavaFunction: + Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction + Properties: + FunctionName: java-sns-consumer-dynamodb-sam + CodeUri: sns_event_consumer_function + Handler: com.amazonaws.services.lambda.samples.events.sns.HandlerSNS::handleRequest + Runtime: java11 + Architectures: + - x86_64 + MemorySize: 512 + Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object + Variables: + DYNAMO_DB_TABLE: !Ref SNSDynamoDBTable + JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1 # More info about tiered compilation https://aws.amazon.com/blogs/compute/optimizing-aws-lambda-function-performance-for-java/ + Events: + SNSEvent: + Type: SNS + Properties: + Topic: !Ref LambdaSNSTopic + Policies: + - Statement: + - Sid: DynamoDBPermissionsPolicy + Effect: Allow + Action: + - dynamodb:GetItem + - dynamodb:DeleteItem + - dynamodb:PutItem + - dynamodb:Scan + - dynamodb:Query + - dynamodb:UpdateItem + - dynamodb:BatchWriteItem + - dynamodb:BatchGetItem + - dynamodb:DescribeTable + - dynamodb:ConditionCheckItem + Resource: + - !Join ['', ["arn:", "aws:", "dynamodb:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":", "table/", !Ref SNSDynamoDBTable]] + - !Join ['', ["arn:", "aws:", "dynamodb:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":", "table/", !Ref SNSDynamoDBTable, "/index/*"]] + TopicConsumerFunction1Permission: + Type: 'AWS::Lambda::Permission' + Properties: + Action: 'lambda:InvokeFunction' + FunctionName: !Ref LambdaSNSConsumerJavaFunction + Principal: sns.amazonaws.com + SNSDynamoDBTable: + Type: AWS::Serverless::SimpleTable + Properties: + TableName: SNSDynamoDBTableJava + PrimaryKey: + Name: MessageID + Type: String + LambdaSNSTopic: + Type: AWS::SNS::Topic + Properties: + TopicName: !Ref SNSTopicName + Subscription: + - Protocol: lambda + Endpoint: !GetAtt LambdaSNSConsumerJavaFunction.Arn +Parameters: + SNSTopicName: + Type: String + Description: Enter the name of the SNS Topic +Outputs: + LambdaSNSConsumerJavaFunction: + Description: "Topic Consumer Lambda Function ARN" + Value: !GetAtt LambdaSNSConsumerJavaFunction.Arn diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.classpath b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.classpath new file mode 100755 index 0000000000..002ad570e2 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.classpath @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.gitignore b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.gitignore new file mode 100755 index 0000000000..b83d22266a --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.project b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.project new file mode 100755 index 0000000000..4ba90c9971 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.project @@ -0,0 +1,23 @@ + + + sns_message_sender + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.core.resources.prefs b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.core.resources.prefs new file mode 100755 index 0000000000..29abf99956 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.jdt.core.prefs b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.jdt.core.prefs new file mode 100755 index 0000000000..2f5cc74c3a --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/Commands b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/Commands new file mode 100755 index 0000000000..d9dac1ebe5 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/Commands @@ -0,0 +1,4 @@ +ava -classpath /JavaExamples/sns_message_sender_json/target/json-sns-producer-0.0.1-SNAPSHOT.jar sns.producer.JsonSNSProducer + +Example: +java -classpath ~/environment/JavaExamples/sns_message_sender_json/target/json-sns-producer-0.0.1-SNAPSHOT.jar sns.producer.JsonSNSProducer LambdaSNSTopic Message01 100 \ No newline at end of file diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/pom.xml b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/pom.xml new file mode 100755 index 0000000000..b3c982ac66 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/pom.xml @@ -0,0 +1,73 @@ + + 4.0.0 + com.amazonaws.services.lambda.samples.events.sns + json-sns-producer + 0.0.1-SNAPSHOT + + UTF-8 + 11 + 11 + + + + com.amazonaws + aws-lambda-java-core + 1.2.1 + + + com.amazonaws + aws-lambda-java-events + 3.11.0 + + + com.google.code.gson + gson + 2.8.9 + + + org.junit.jupiter + junit-jupiter-api + 5.6.0 + test + + + + software.amazon.awssdk + sns + 2.20.73 + + + + + + maven-surefire-plugin + 2.22.2 + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.2 + + false + + + + package + + shade + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 1.8 + 1.8 + + + + + \ No newline at end of file diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/JsonSNSProducer.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/JsonSNSProducer.java new file mode 100755 index 0000000000..d58ae36efe --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/JsonSNSProducer.java @@ -0,0 +1,143 @@ +package sns.producer; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +import software.amazon.awssdk.services.sns.SnsClient; +import software.amazon.awssdk.services.sns.model.ListTopicsRequest; +import software.amazon.awssdk.services.sns.model.ListTopicsResponse; +import software.amazon.awssdk.services.sns.model.PublishRequest; +import software.amazon.awssdk.services.sns.model.PublishResponse; +import software.amazon.awssdk.services.sns.model.SnsException; +import software.amazon.awssdk.services.sns.model.Topic; +import software.amazon.awssdk.services.sns.model.MessageAttributeValue; + +public class JsonSNSProducer { + + public static void main(String[] args) { + try { + JsonSNSProducer.snsSender(args[0], args[1].concat("-").concat(JsonSNSProducer.getTodayDate()), Integer.parseInt(args[2])); + } catch (NumberFormatException e) { + System.out.println("Pass three parameters in that order - 1 - The Topic Name, 2 - A String representing this batch of messages, 3 - Total number of messages in this batch"); + e.printStackTrace(); + } + } + + public static void snsSender(String snsTopic, String messageKey, int numberOfMessages) { + SnsClient snsClient = SnsClient.builder().build(); + String snsTopicARN = JsonSNSProducer.getTopicARNFromTopicName(snsClient, snsTopic); + List people = JsonSNSProducer.readDataFile(); + int numberOfMessagesToSend=0; + if (people.size() > numberOfMessages) { + numberOfMessagesToSend = numberOfMessages; + } else { + numberOfMessagesToSend = people.size(); + } + for (int i=1;i<= numberOfMessagesToSend; i++) { + Person thisPerson = JsonSNSProducer.getPersonFromLine(people.get(i)); + JsonSNSProducer.sendMessage(snsClient, snsTopicARN, thisPerson.toJson(), messageKey, i); + } + } + + public static String getTopicARNFromTopicName(SnsClient snsClient, String topicName) { + String topicARN = ""; + try { + ListTopicsRequest request = ListTopicsRequest.builder() + .build(); + + ListTopicsResponse result = snsClient.listTopics(request); + List topics = result.topics(); + for (Topic topic: topics) { + String currentTopicARN = topic.topicArn(); + if (currentTopicARN.endsWith(topicName)) { + topicARN = currentTopicARN; + System.out.println("Matching TopicARN = " + topicARN); + break; + } + } + + } catch (SnsException e) { + System.err.println("Incorrect Topic Name Specified"); + System.err.println(e.awsErrorDetails().errorMessage()); + System.exit(1); + } + return topicARN; + } + + public static void sendMessage(SnsClient snsClient, String topicARN, String message, String messageKey, int messageNumber) { + try { + Map attributes = new HashMap(); + attributes.put("MessageKey", MessageAttributeValue.builder().dataType("String").stringValue(messageKey).build()); + attributes.put("MessageNumber", MessageAttributeValue.builder().dataType("String").stringValue(Integer.toString(messageNumber)).build()); + PublishRequest request = PublishRequest.builder() + .message(message) + .topicArn(topicARN) + .messageAttributes(attributes) + .subject("Sending Message with Key = " + messageKey + " and message number = " + Integer.toString(messageNumber)) + .build(); + System.out.println("**********************************************************"); + System.out.println("Now going to send one SNS message to topic - " + topicARN); + System.out.println("Message Key = " + messageKey + " and Message Number = " + Integer.toString(messageNumber)); + System.out.println("Message Body = " + message); + PublishResponse result = snsClient.publish(request); + System.out.println(result.messageId() + " Message sent. Status is " + result.sdkHttpResponse().statusCode()); + System.out.println("Now done sending one SNS message"); + System.out.println("**********************************************************"); + + } catch (SnsException e) { + System.err.println(e.awsErrorDetails().errorMessage()); + System.exit(1); + } + } + + public static List readDataFile() { + List personList = new ArrayList(); + InputStream is = JsonSNSProducer.class.getClassLoader().getResourceAsStream("us-500.csv"); + BufferedReader bf = new BufferedReader(new InputStreamReader(is)); + String thisLine = null; + try { + thisLine = bf.readLine(); + while (null != thisLine) { + personList.add(thisLine); + thisLine = bf.readLine(); + } + } catch (IOException e) { + e.printStackTrace(); + } + return personList; + } + + public static Person getPersonFromLine(String line) { + String[] fields = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1); + Person thisPerson = new Person(); + thisPerson.setFirstname(fields[0]); + thisPerson.setLastname(fields[1]); + thisPerson.setCompany(fields[2]); + thisPerson.setStreet(fields[3]); + thisPerson.setCity(fields[4]); + thisPerson.setCounty(fields[5]); + thisPerson.setState(fields[6]); + thisPerson.setZip(fields[7]); + thisPerson.setHomePhone(fields[8]); + thisPerson.setCellPhone(fields[9]); + thisPerson.setEmail(fields[10]); + thisPerson.setWebsite(fields[11]); + return thisPerson; + } + + public static String getTodayDate() { + + LocalDateTime ldt = LocalDateTime.now(); + String formattedDateStr = DateTimeFormatter.ofPattern("MM-dd-YYYY-HH-MM-SS").format(ldt); + return formattedDateStr; + } + +} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/Person.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/Person.java new file mode 100755 index 0000000000..732af6bc7b --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/Person.java @@ -0,0 +1,133 @@ +package sns.producer; + +import java.util.Objects; + +import com.google.gson.Gson; + +public class Person { + + String firstname; + String lastname; + String company; + String street; + String city; + String county; + String state; + String zip; + String homePhone; + String cellPhone; + String email; + String website; + public Person() { + super(); + } + public String getFirstname() { + return firstname; + } + public void setFirstname(String firstname) { + this.firstname = firstname; + } + public String getLastname() { + return lastname; + } + public void setLastname(String lastname) { + this.lastname = lastname; + } + public String getCompany() { + return company; + } + public void setCompany(String company) { + this.company = company; + } + public String getStreet() { + return street; + } + public void setStreet(String street) { + this.street = street; + } + public String getCity() { + return city; + } + public void setCity(String city) { + this.city = city; + } + public String getCounty() { + return county; + } + public void setCounty(String county) { + this.county = county; + } + public String getState() { + return state; + } + public void setState(String state) { + this.state = state; + } + public String getZip() { + return zip; + } + public void setZip(String zip) { + this.zip = zip; + } + public String getHomePhone() { + return homePhone; + } + public void setHomePhone(String homePhone) { + this.homePhone = homePhone; + } + public String getCellPhone() { + return cellPhone; + } + public void setCellPhone(String cellPhone) { + this.cellPhone = cellPhone; + } + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + public String getWebsite() { + return website; + } + public void setWebsite(String website) { + this.website = website; + } + + + + @Override + public int hashCode() { + return Objects.hash(cellPhone, city, company, county, email, firstname, homePhone, lastname, state, street, + website, zip); + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Person other = (Person) obj; + return Objects.equals(cellPhone, other.cellPhone) && Objects.equals(city, other.city) + && Objects.equals(company, other.company) && Objects.equals(county, other.county) + && Objects.equals(email, other.email) && Objects.equals(firstname, other.firstname) + && Objects.equals(homePhone, other.homePhone) && Objects.equals(lastname, other.lastname) + && Objects.equals(state, other.state) && Objects.equals(street, other.street) + && Objects.equals(website, other.website) && Objects.equals(zip, other.zip); + } + @Override + public String toString() { + return "Person [firstname=" + firstname + ", lastname=" + lastname + ", company=" + company + ", street=" + + street + ", city=" + city + ", county=" + county + ", state=" + state + ", zip=" + zip + + ", homePhone=" + homePhone + ", cellPhone=" + cellPhone + ", email=" + email + ", website=" + website + + "]"; + } + + public String toJson() { + Gson gson = new Gson(); + return gson.toJson(this); + } + +} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/resources/us-500.csv b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/resources/us-500.csv new file mode 100755 index 0000000000..20c58066e5 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/resources/us-500.csv @@ -0,0 +1,500 @@ +James,Butt,"Benton, John B Jr",6649 N Blue Gum St,New Orleans,Orleans,LA,70116,504-621-8927,504-845-1427,jbutt@gmail.com,http://www.bentonjohnbjr.com +Josephine,Darakjy,"Chanay, Jeffrey A Esq",4 B Blue Ridge Blvd,Brighton,Livingston,MI,48116,810-292-9388,810-374-9840,josephine_darakjy@darakjy.org,http://www.chanayjeffreyaesq.com +Art,Venere,"Chemel, James L Cpa",8 W Cerritos Ave #54,Bridgeport,Gloucester,NJ,8014,856-636-8749,856-264-4130,art@venere.org,http://www.chemeljameslcpa.com +Lenna,Paprocki,Feltz Printing Service,639 Main St,Anchorage,Anchorage,AK,99501,907-385-4412,907-921-2010,lpaprocki@hotmail.com,http://www.feltzprintingservice.com +Donette,Foller,Printing Dimensions,34 Center St,Hamilton,Butler,OH,45011,513-570-1893,513-549-4561,donette.foller@cox.net,http://www.printingdimensions.com +Simona,Morasca,"Chapman, Ross E Esq",3 Mcauley Dr,Ashland,Ashland,OH,44805,419-503-2484,419-800-6759,simona@morasca.com,http://www.chapmanrosseesq.com +Mitsue,Tollner,Morlong Associates,7 Eads St,Chicago,Cook,IL,60632,773-573-6914,773-924-8565,mitsue_tollner@yahoo.com,http://www.morlongassociates.com +Leota,Dilliard,Commercial Press,7 W Jackson Blvd,San Jose,Santa Clara,CA,95111,408-752-3500,408-813-1105,leota@hotmail.com,http://www.commercialpress.com +Sage,Wieser,Truhlar And Truhlar Attys,5 Boston Ave #88,Sioux Falls,Minnehaha,SD,57105,605-414-2147,605-794-4895,sage_wieser@cox.net,http://www.truhlarandtruhlarattys.com +Kris,Marrier,"King, Christopher A Esq",228 Runamuck Pl #2808,Baltimore,Baltimore City,MD,21224,410-655-8723,410-804-4694,kris@gmail.com,http://www.kingchristopheraesq.com +Minna,Amigon,"Dorl, James J Esq",2371 Jerrold Ave,Kulpsville,Montgomery,PA,19443,215-874-1229,215-422-8694,minna_amigon@yahoo.com,http://www.dorljamesjesq.com +Abel,Maclead,Rangoni Of Florence,37275 St Rt 17m M,Middle Island,Suffolk,NY,11953,631-335-3414,631-677-3675,amaclead@gmail.com,http://www.rangoniofflorence.com +Kiley,Caldarera,Feiner Bros,25 E 75th St #69,Los Angeles,Los Angeles,CA,90034,310-498-5651,310-254-3084,kiley.caldarera@aol.com,http://www.feinerbros.com +Graciela,Ruta,Buckley Miller & Wright,98 Connecticut Ave Nw,Chagrin Falls,Geauga,OH,44023,440-780-8425,440-579-7763,gruta@cox.net,http://www.buckleymillerwright.com +Cammy,Albares,"Rousseaux, Michael Esq",56 E Morehead St,Laredo,Webb,TX,78045,956-537-6195,956-841-7216,calbares@gmail.com,http://www.rousseauxmichaelesq.com +Mattie,Poquette,Century Communications,73 State Road 434 E,Phoenix,Maricopa,AZ,85013,602-277-4385,602-953-6360,mattie@aol.com,http://www.centurycommunications.com +Meaghan,Garufi,"Bolton, Wilbur Esq",69734 E Carrillo St,Mc Minnville,Warren,TN,37110,931-313-9635,931-235-7959,meaghan@hotmail.com,http://www.boltonwilburesq.com +Gladys,Rim,T M Byxbee Company Pc,322 New Horizon Blvd,Milwaukee,Milwaukee,WI,53207,414-661-9598,414-377-2880,gladys.rim@rim.org,http://www.tmbyxbeecompanypc.com +Yuki,Whobrey,Farmers Insurance Group,1 State Route 27,Taylor,Wayne,MI,48180,313-288-7937,313-341-4470,yuki_whobrey@aol.com,http://www.farmersinsurancegroup.com +Fletcher,Flosi,Post Box Services Plus,394 Manchester Blvd,Rockford,Winnebago,IL,61109,815-828-2147,815-426-5657,fletcher.flosi@yahoo.com,http://www.postboxservicesplus.com +Bette,Nicka,Sport En Art,6 S 33rd St,Aston,Delaware,PA,19014,610-545-3615,610-492-4643,bette_nicka@cox.net,http://www.sportenart.com +Veronika,Inouye,C 4 Network Inc,6 Greenleaf Ave,San Jose,Santa Clara,CA,95111,408-540-1785,408-813-4592,vinouye@aol.com,http://www.cnetworkinc.com +Willard,Kolmetz,"Ingalls, Donald R Esq",618 W Yakima Ave,Irving,Dallas,TX,75062,972-303-9197,972-896-4882,willard@hotmail.com,http://www.ingallsdonaldresq.com +Maryann,Royster,"Franklin, Peter L Esq",74 S Westgate St,Albany,Albany,NY,12204,518-966-7987,518-448-8982,mroyster@royster.com,http://www.franklinpeterlesq.com +Alisha,Slusarski,Wtlz Power 107 Fm,3273 State St,Middlesex,Middlesex,NJ,8846,732-658-3154,732-635-3453,alisha@slusarski.com,http://www.wtlzpowerfm.com +Allene,Iturbide,"Ledecky, David Esq",1 Central Ave,Stevens Point,Portage,WI,54481,715-662-6764,715-530-9863,allene_iturbide@cox.net,http://www.ledeckydavidesq.com +Chanel,Caudy,Professional Image Inc,86 Nw 66th St #8673,Shawnee,Johnson,KS,66218,913-388-2079,913-899-1103,chanel.caudy@caudy.org,http://www.professionalimageinc.com +Ezekiel,Chui,"Sider, Donald C Esq",2 Cedar Ave #84,Easton,Talbot,MD,21601,410-669-1642,410-235-8738,ezekiel@chui.com,http://www.siderdonaldcesq.com +Willow,Kusko,U Pull It,90991 Thorburn Ave,New York,New York,NY,10011,212-582-4976,212-934-5167,wkusko@yahoo.com,http://www.upullit.com +Bernardo,Figeroa,"Clark, Richard Cpa",386 9th Ave N,Conroe,Montgomery,TX,77301,936-336-3951,936-597-3614,bfigeroa@aol.com,http://www.clarkrichardcpa.com +Ammie,Corrio,"Moskowitz, Barry S",74874 Atlantic Ave,Columbus,Franklin,OH,43215,614-801-9788,614-648-3265,ammie@corrio.com,http://www.moskowitzbarrys.com +Francine,Vocelka,Cascade Realty Advisors Inc,366 South Dr,Las Cruces,Dona Ana,NM,88011,505-977-3911,505-335-5293,francine_vocelka@vocelka.com,http://www.cascaderealtyadvisorsinc.com +Ernie,Stenseth,Knwz Newsradio,45 E Liberty St,Ridgefield Park,Bergen,NJ,7660,201-709-6245,201-387-9093,ernie_stenseth@aol.com,http://www.knwznewsradio.com +Albina,Glick,"Giampetro, Anthony D",4 Ralph Ct,Dunellen,Middlesex,NJ,8812,732-924-7882,732-782-6701,albina@glick.com,http://www.giampetroanthonyd.com +Alishia,Sergi,Milford Enterprises Inc,2742 Distribution Way,New York,New York,NY,10025,212-860-1579,212-753-2740,asergi@gmail.com,http://www.milfordenterprisesinc.com +Solange,Shinko,"Mosocco, Ronald A",426 Wolf St,Metairie,Jefferson,LA,70002,504-979-9175,504-265-8174,solange@shinko.com,http://www.mosoccoronalda.com +Jose,Stockham,Tri State Refueler Co,128 Bransten Rd,New York,New York,NY,10011,212-675-8570,212-569-4233,jose@yahoo.com,http://www.tristaterefuelerco.com +Rozella,Ostrosky,Parkway Company,17 Morena Blvd,Camarillo,Ventura,CA,93012,805-832-6163,805-609-1531,rozella.ostrosky@ostrosky.com,http://www.parkwaycompany.com +Valentine,Gillian,Fbs Business Finance,775 W 17th St,San Antonio,Bexar,TX,78204,210-812-9597,210-300-6244,valentine_gillian@gmail.com,http://www.fbsbusinessfinance.com +Kati,Rulapaugh,Eder Assocs Consltng Engrs Pc,6980 Dorsett Rd,Abilene,Dickinson,KS,67410,785-463-7829,785-219-7724,kati.rulapaugh@hotmail.com,http://www.ederassocsconsltngengrspc.com +Youlanda,Schemmer,Tri M Tool Inc,2881 Lewis Rd,Prineville,Crook,OR,97754,541-548-8197,541-993-2611,youlanda@aol.com,http://www.trimtoolinc.com +Dyan,Oldroyd,International Eyelets Inc,7219 Woodfield Rd,Overland Park,Johnson,KS,66204,913-413-4604,913-645-8918,doldroyd@aol.com,http://www.internationaleyeletsinc.com +Roxane,Campain,Rapid Trading Intl,1048 Main St,Fairbanks,Fairbanks North Star,AK,99708,907-231-4722,907-335-6568,roxane@hotmail.com,http://www.rapidtradingintl.com +Lavera,Perin,Abc Enterprises Inc,678 3rd Ave,Miami,Miami-Dade,FL,33196,305-606-7291,305-995-2078,lperin@perin.org,http://www.abcenterprisesinc.com +Erick,Ferencz,Cindy Turner Associates,20 S Babcock St,Fairbanks,Fairbanks North Star,AK,99712,907-741-1044,907-227-6777,erick.ferencz@aol.com,http://www.cindyturnerassociates.com +Fatima,Saylors,"Stanton, James D Esq",2 Lighthouse Ave,Hopkins,Hennepin,MN,55343,952-768-2416,952-479-2375,fsaylors@saylors.org,http://www.stantonjamesdesq.com +Jina,Briddick,Grace Pastries Inc,38938 Park Blvd,Boston,Suffolk,MA,2128,617-399-5124,617-997-5771,jina_briddick@briddick.com,http://www.gracepastriesinc.com +Kanisha,Waycott,"Schroer, Gene E Esq",5 Tomahawk Dr,Los Angeles,Los Angeles,CA,90006,323-453-2780,323-315-7314,kanisha_waycott@yahoo.com,http://www.schroergeneeesq.com +Emerson,Bowley,Knights Inn,762 S Main St,Madison,Dane,WI,53711,608-336-7444,608-658-7940,emerson.bowley@bowley.org,http://www.knightsinn.com +Blair,Malet,Bollinger Mach Shp & Shipyard,209 Decker Dr,Philadelphia,Philadelphia,PA,19132,215-907-9111,215-794-4519,bmalet@yahoo.com,http://www.bollingermachshpshipyard.com +Brock,Bolognia,Orinda News,4486 W O St #1,New York,New York,NY,10003,212-402-9216,212-617-5063,bbolognia@yahoo.com,http://www.orindanews.com +Lorrie,Nestle,Ballard Spahr Andrews,39 S 7th St,Tullahoma,Coffee,TN,37388,931-875-6644,931-303-6041,lnestle@hotmail.com,http://www.ballardspahrandrews.com +Sabra,Uyetake,Lowy Limousine Service,98839 Hawthorne Blvd #6101,Columbia,Richland,SC,29201,803-925-5213,803-681-3678,sabra@uyetake.org,http://www.lowylimousineservice.com +Marjory,Mastella,Vicon Corporation,71 San Mateo Ave,Wayne,Delaware,PA,19087,610-814-5533,610-379-7125,mmastella@mastella.com,http://www.viconcorporation.com +Karl,Klonowski,"Rossi, Michael M",76 Brooks St #9,Flemington,Hunterdon,NJ,8822,908-877-6135,908-470-4661,karl_klonowski@yahoo.com,http://www.rossimichaelm.com +Tonette,Wenner,Northwest Publishing,4545 Courthouse Rd,Westbury,Nassau,NY,11590,516-968-6051,516-333-4861,twenner@aol.com,http://www.northwestpublishing.com +Amber,Monarrez,Branford Wire & Mfg Co,14288 Foster Ave #4121,Jenkintown,Montgomery,PA,19046,215-934-8655,215-329-6386,amber_monarrez@monarrez.org,http://www.branfordwiremfgco.com +Shenika,Seewald,East Coast Marketing,4 Otis St,Van Nuys,Los Angeles,CA,91405,818-423-4007,818-749-8650,shenika@gmail.com,http://www.eastcoastmarketing.com +Delmy,Ahle,Wye Technologies Inc,65895 S 16th St,Providence,Providence,RI,2909,401-458-2547,401-559-8961,delmy.ahle@hotmail.com,http://www.wyetechnologiesinc.com +Deeanna,Juhas,"Healy, George W Iv",14302 Pennsylvania Ave,Huntingdon Valley,Montgomery,PA,19006,215-211-9589,215-417-9563,deeanna_juhas@gmail.com,http://www.healygeorgewiv.com +Blondell,Pugh,Alpenlite Inc,201 Hawk Ct,Providence,Providence,RI,2904,401-960-8259,401-300-8122,bpugh@aol.com,http://www.alpenliteinc.com +Jamal,Vanausdal,"Hubbard, Bruce Esq",53075 Sw 152nd Ter #615,Monroe Township,Middlesex,NJ,8831,732-234-1546,732-904-2931,jamal@vanausdal.org,http://www.hubbardbruceesq.com +Cecily,Hollack,Arthur A Oliver & Son Inc,59 N Groesbeck Hwy,Austin,Travis,TX,78731,512-486-3817,512-861-3814,cecily@hollack.org,http://www.arthuraoliversoninc.com +Carmelina,Lindall,George Jessop Carter Jewelers,2664 Lewis Rd,Littleton,Douglas,CO,80126,303-724-7371,303-874-5160,carmelina_lindall@lindall.com,http://www.georgejessopcarterjewelers.com +Maurine,Yglesias,"Schultz, Thomas C Md",59 Shady Ln #53,Milwaukee,Milwaukee,WI,53214,414-748-1374,414-573-7719,maurine_yglesias@yglesias.com,http://www.schultzthomascmd.com +Tawna,Buvens,H H H Enterprises Inc,3305 Nabell Ave #679,New York,New York,NY,10009,212-674-9610,212-462-9157,tawna@gmail.com,http://www.hhhenterprisesinc.com +Penney,Weight,Hawaiian King Hotel,18 Fountain St,Anchorage,Anchorage,AK,99515,907-797-9628,907-873-2882,penney_weight@aol.com,http://www.hawaiiankinghotel.com +Elly,Morocco,Killion Industries,7 W 32nd St,Erie,Erie,PA,16502,814-393-5571,814-420-3553,elly_morocco@gmail.com,http://www.killionindustries.com +Ilene,Eroman,"Robinson, William J Esq",2853 S Central Expy,Glen Burnie,Anne Arundel,MD,21061,410-914-9018,410-937-4543,ilene.eroman@hotmail.com,http://www.robinsonwilliamjesq.com +Vallie,Mondella,Private Properties,74 W College St,Boise,Ada,ID,83707,208-862-5339,208-737-8439,vmondella@mondella.com,http://www.privateproperties.com +Kallie,Blackwood,Rowley Schlimgen Inc,701 S Harrison Rd,San Francisco,San Francisco,CA,94104,415-315-2761,415-604-7609,kallie.blackwood@gmail.com,http://www.rowleyschlimgeninc.com +Johnetta,Abdallah,Forging Specialties,1088 Pinehurst St,Chapel Hill,Orange,NC,27514,919-225-9345,919-715-3791,johnetta_abdallah@aol.com,http://www.forgingspecialties.com +Bobbye,Rhym,"Smits, Patricia Garity",30 W 80th St #1995,San Carlos,San Mateo,CA,94070,650-528-5783,650-811-9032,brhym@rhym.com,http://www.smitspatriciagarity.com +Micaela,Rhymes,H Lee Leonard Attorney At Law,20932 Hedley St,Concord,Contra Costa,CA,94520,925-647-3298,925-522-7798,micaela_rhymes@gmail.com,http://www.hleeleonardattorneyatlaw.com +Tamar,Hoogland,A K Construction Co,2737 Pistorio Rd #9230,London,Madison,OH,43140,740-343-8575,740-526-5410,tamar@hotmail.com,http://www.akconstructionco.com +Moon,Parlato,"Ambelang, Jessica M Md",74989 Brandon St,Wellsville,Allegany,NY,14895,585-866-8313,585-498-4278,moon@yahoo.com,http://www.ambelangjessicammd.com +Laurel,Reitler,Q A Service,6 Kains Ave,Baltimore,Baltimore City,MD,21215,410-520-4832,410-957-6903,laurel_reitler@reitler.com,http://www.qaservice.com +Delisa,Crupi,Wood & Whitacre Contractors,47565 W Grand Ave,Newark,Essex,NJ,7105,973-354-2040,973-847-9611,delisa.crupi@crupi.com,http://www.woodwhitacrecontractors.com +Viva,Toelkes,Mark Iv Press Ltd,4284 Dorigo Ln,Chicago,Cook,IL,60647,773-446-5569,773-352-3437,viva.toelkes@gmail.com,http://www.markivpressltd.com +Elza,Lipke,Museum Of Science & Industry,6794 Lake Dr E,Newark,Essex,NJ,7104,973-927-3447,973-796-3667,elza@yahoo.com,http://www.museumofscienceindustry.com +Devorah,Chickering,Garrison Ind,31 Douglas Blvd #950,Clovis,Curry,NM,88101,505-975-8559,505-950-1763,devorah@hotmail.com,http://www.garrisonind.com +Timothy,Mulqueen,Saronix Nymph Products,44 W 4th St,Staten Island,Richmond,NY,10309,718-332-6527,718-654-7063,timothy_mulqueen@mulqueen.org,http://www.saronixnymphproducts.com +Arlette,Honeywell,Smc Inc,11279 Loytan St,Jacksonville,Duval,FL,32254,904-775-4480,904-514-9918,ahoneywell@honeywell.com,http://www.smcinc.com +Dominque,Dickerson,E A I Electronic Assocs Inc,69 Marquette Ave,Hayward,Alameda,CA,94545,510-993-3758,510-901-7640,dominque.dickerson@dickerson.org,http://www.eaielectronicassocsinc.com +Lettie,Isenhower,"Conte, Christopher A Esq",70 W Main St,Beachwood,Cuyahoga,OH,44122,216-657-7668,216-733-8494,lettie_isenhower@yahoo.com,http://www.contechristopheraesq.com +Myra,Munns,Anker Law Office,461 Prospect Pl #316,Euless,Tarrant,TX,76040,817-914-7518,817-451-3518,mmunns@cox.net,http://www.ankerlawoffice.com +Stephaine,Barfield,Beutelschies & Company,47154 Whipple Ave Nw,Gardena,Los Angeles,CA,90247,310-774-7643,310-968-1219,stephaine@barfield.com,http://www.beutelschiescompany.com +Lai,Gato,"Fligg, Kenneth I Jr",37 Alabama Ave,Evanston,Cook,IL,60201,847-728-7286,847-957-4614,lai.gato@gato.org,http://www.fliggkennethijr.com +Stephen,Emigh,"Sharp, J Daniel Esq",3777 E Richmond St #900,Akron,Summit,OH,44302,330-537-5358,330-700-2312,stephen_emigh@hotmail.com,http://www.sharpjdanielesq.com +Tyra,Shields,"Assink, Anne H Esq",3 Fort Worth Ave,Philadelphia,Philadelphia,PA,19106,215-255-1641,215-228-8264,tshields@gmail.com,http://www.assinkannehesq.com +Tammara,Wardrip,Jewel My Shop Inc,4800 Black Horse Pike,Burlingame,San Mateo,CA,94010,650-803-1936,650-216-5075,twardrip@cox.net,http://www.jewelmyshopinc.com +Cory,Gibes,Chinese Translation Resources,83649 W Belmont Ave,San Gabriel,Los Angeles,CA,91776,626-572-1096,626-696-2777,cory.gibes@gmail.com,http://www.chinesetranslationresources.com +Danica,Bruschke,"Stevens, Charles T",840 15th Ave,Waco,McLennan,TX,76708,254-782-8569,254-205-1422,danica_bruschke@gmail.com,http://www.stevenscharlest.com +Wilda,Giguere,"Mclaughlin, Luther W Cpa",1747 Calle Amanecer #2,Anchorage,Anchorage,AK,99501,907-870-5536,907-914-9482,wilda@cox.net,http://www.mclaughlinlutherwcpa.com +Elvera,Benimadho,Tree Musketeers,99385 Charity St #840,San Jose,Santa Clara,CA,95110,408-703-8505,408-440-8447,elvera.benimadho@cox.net,http://www.treemusketeers.com +Carma,Vanheusen,Springfield Div Oh Edison Co,68556 Central Hwy,San Leandro,Alameda,CA,94577,510-503-7169,510-452-4835,carma@cox.net,http://www.springfielddivohedisonco.com +Malinda,Hochard,Logan Memorial Hospital,55 Riverside Ave,Indianapolis,Marion,IN,46202,317-722-5066,317-472-2412,malinda.hochard@yahoo.com,http://www.loganmemorialhospital.com +Natalie,Fern,"Kelly, Charles G Esq",7140 University Ave,Rock Springs,Sweetwater,WY,82901,307-704-8713,307-279-3793,natalie.fern@hotmail.com,http://www.kellycharlesgesq.com +Lisha,Centini,Industrial Paper Shredders Inc,64 5th Ave #1153,Mc Lean,Fairfax,VA,22102,703-235-3937,703-475-7568,lisha@centini.org,http://www.industrialpapershreddersinc.com +Arlene,Klusman,Beck Horizon Builders,3 Secor Rd,New Orleans,Orleans,LA,70112,504-710-5840,504-946-1807,arlene_klusman@gmail.com,http://www.beckhorizonbuilders.com +Alease,Buemi,Porto Cayo At Hawks Cay,4 Webbs Chapel Rd,Boulder,Boulder,CO,80303,303-301-4946,303-521-9860,alease@buemi.com,http://www.portocayoathawkscay.com +Louisa,Cronauer,Pacific Grove Museum Ntrl Hist,524 Louisiana Ave Nw,San Leandro,Alameda,CA,94577,510-828-7047,510-472-7758,louisa@cronauer.com,http://www.pacificgrovemuseumntrlhist.com +Angella,Cetta,Bender & Hatley Pc,185 Blackstone Bldge,Honolulu,Honolulu,HI,96817,808-892-7943,808-475-2310,angella.cetta@hotmail.com,http://www.benderhatleypc.com +Cyndy,Goldammer,Di Cristina J & Son,170 Wyoming Ave,Burnsville,Dakota,MN,55337,952-334-9408,952-938-9457,cgoldammer@cox.net,http://www.dicristinajson.com +Rosio,Cork,Green Goddess,4 10th St W,High Point,Guilford,NC,27263,336-243-5659,336-497-4407,rosio.cork@gmail.com,http://www.greengoddess.com +Celeste,Korando,American Arts & Graphics,7 W Pinhook Rd,Lynbrook,Nassau,NY,11563,516-509-2347,516-365-7266,ckorando@hotmail.com,http://www.americanartsgraphics.com +Twana,Felger,Opryland Hotel,1 Commerce Way,Portland,Washington,OR,97224,503-939-3153,503-909-7167,twana.felger@felger.org,http://www.oprylandhotel.com +Estrella,Samu,Marking Devices Pubg Co,64 Lakeview Ave,Beloit,Rock,WI,53511,608-976-7199,608-942-8836,estrella@aol.com,http://www.markingdevicespubgco.com +Donte,Kines,W Tc Industries Inc,3 Aspen St,Worcester,Worcester,MA,1602,508-429-8576,508-843-1426,dkines@hotmail.com,http://www.wtcindustriesinc.com +Tiffiny,Steffensmeier,Whitehall Robbins Labs Divsn,32860 Sierra Rd,Miami,Miami-Dade,FL,33133,305-385-9695,305-304-6573,tiffiny_steffensmeier@cox.net,http://www.whitehallrobbinslabsdivsn.com +Edna,Miceli,Sampler,555 Main St,Erie,Erie,PA,16502,814-460-2655,814-299-2877,emiceli@miceli.org,http://www.sampler.com +Sue,Kownacki,Juno Chefs Incorporated,2 Se 3rd Ave,Mesquite,Dallas,TX,75149,972-666-3413,972-742-4000,sue@aol.com,http://www.junochefsincorporated.com +Jesusa,Shin,"Carroccio, A Thomas Esq",2239 Shawnee Mission Pky,Tullahoma,Coffee,TN,37388,931-273-8709,931-739-1551,jshin@shin.com,http://www.carroccioathomasesq.com +Rolland,Francescon,"Stanley, Richard L Esq",2726 Charcot Ave,Paterson,Passaic,NJ,7501,973-649-2922,973-284-4048,rolland@cox.net,http://www.stanleyrichardlesq.com +Pamella,Schmierer,K Cs Cstm Mouldings Windows,5161 Dorsett Rd,Homestead,Miami-Dade,FL,33030,305-420-8970,305-575-8481,pamella.schmierer@schmierer.org,http://www.kcscstmmouldingswindows.com +Glory,Kulzer,Comfort Inn,55892 Jacksonville Rd,Owings Mills,Baltimore,MD,21117,410-224-9462,410-916-8015,gkulzer@kulzer.org,http://www.comfortinn.com +Shawna,Palaspas,"Windsor, James L Esq",5 N Cleveland Massillon Rd,Thousand Oaks,Ventura,CA,91362,805-275-3566,805-638-6617,shawna_palaspas@palaspas.org,http://www.windsorjameslesq.com +Brandon,Callaro,Jackson Shields Yeiser,7 Benton Dr,Honolulu,Honolulu,HI,96819,808-215-6832,808-240-5168,brandon_callaro@hotmail.com,http://www.jacksonshieldsyeiser.com +Scarlet,Cartan,"Box, J Calvin Esq",9390 S Howell Ave,Albany,Dougherty,GA,31701,229-735-3378,229-365-9658,scarlet.cartan@yahoo.com,http://www.boxjcalvinesq.com +Oretha,Menter,Custom Engineering Inc,8 County Center Dr #647,Boston,Suffolk,MA,2210,617-418-5043,617-697-6024,oretha_menter@yahoo.com,http://www.customengineeringinc.com +Ty,Smith,Bresler Eitel Framg Gllry Ltd,4646 Kaahumanu St,Hackensack,Bergen,NJ,7601,201-672-1553,201-995-3149,tsmith@aol.com,http://www.breslereitelframggllryltd.com +Xuan,Rochin,"Carol, Drake Sparks Esq",2 Monroe St,San Mateo,San Mateo,CA,94403,650-933-5072,650-247-2625,xuan@gmail.com,http://www.caroldrakesparksesq.com +Lindsey,Dilello,Biltmore Investors Bank,52777 Leaders Heights Rd,Ontario,San Bernardino,CA,91761,909-639-9887,909-589-1693,lindsey.dilello@hotmail.com,http://www.biltmoreinvestorsbank.com +Devora,Perez,Desco Equipment Corp,72868 Blackington Ave,Oakland,Alameda,CA,94606,510-955-3016,510-755-9274,devora_perez@perez.org,http://www.descoequipmentcorp.com +Herman,Demesa,Merlin Electric Co,9 Norristown Rd,Troy,Rensselaer,NY,12180,518-497-2940,518-931-7852,hdemesa@cox.net,http://www.merlinelectricco.com +Rory,Papasergi,Bailey Cntl Co Div Babcock,83 County Road 437 #8581,Clarks Summit,Lackawanna,PA,18411,570-867-7489,570-469-8401,rpapasergi@cox.net,http://www.baileycntlcodivbabcock.com +Talia,Riopelle,Ford Brothers Wholesale Inc,1 N Harlem Ave #9,Orange,Essex,NJ,7050,973-245-2133,973-818-9788,talia_riopelle@aol.com,http://www.fordbrotherswholesaleinc.com +Van,Shire,Cambridge Inn,90131 J St,Pittstown,Hunterdon,NJ,8867,908-409-2890,908-448-1209,van.shire@shire.com,http://www.cambridgeinn.com +Lucina,Lary,"Matricciani, Albert J Jr",8597 W National Ave,Cocoa,Brevard,FL,32922,321-749-4981,321-632-4668,lucina_lary@cox.net,http://www.matriccianialbertjjr.com +Bok,Isaacs,Nelson Hawaiian Ltd,6 Gilson St,Bronx,Bronx,NY,10468,718-809-3762,718-478-8568,bok.isaacs@aol.com,http://www.nelsonhawaiianltd.com +Rolande,Spickerman,Neland Travel Agency,65 W Maple Ave,Pearl City,Honolulu,HI,96782,808-315-3077,808-526-5863,rolande.spickerman@spickerman.com,http://www.nelandtravelagency.com +Howard,Paulas,"Asendorf, J Alan Esq",866 34th Ave,Denver,Denver,CO,80231,303-623-4241,303-692-3118,hpaulas@gmail.com,http://www.asendorfjalanesq.com +Kimbery,Madarang,"Silberman, Arthur L Esq",798 Lund Farm Way,Rockaway,Morris,NJ,7866,973-310-1634,973-225-6259,kimbery_madarang@cox.net,http://www.silbermanarthurlesq.com +Thurman,Manno,Honey Bee Breeding Genetics &,9387 Charcot Ave,Absecon,Atlantic,NJ,8201,609-524-3586,609-234-8376,thurman.manno@yahoo.com,http://www.honeybeebreedinggenetics.com +Becky,Mirafuentes,Wells Kravitz Schnitzer,30553 Washington Rd,Plainfield,Union,NJ,7062,908-877-8409,908-426-8272,becky.mirafuentes@mirafuentes.com,http://www.wellskravitzschnitzer.com +Beatriz,Corrington,Prohab Rehabilitation Servs,481 W Lemon St,Middleboro,Plymouth,MA,2346,508-584-4279,508-315-3867,beatriz@yahoo.com,http://www.prohabrehabilitationservs.com +Marti,Maybury,"Eldridge, Kristin K Esq",4 Warehouse Point Rd #7,Chicago,Cook,IL,60638,773-775-4522,773-539-1058,marti.maybury@yahoo.com,http://www.eldridgekristinkesq.com +Nieves,Gotter,"Vlahos, John J Esq",4940 Pulaski Park Dr,Portland,Multnomah,OR,97202,503-527-5274,503-455-3094,nieves_gotter@gmail.com,http://www.vlahosjohnjesq.com +Leatha,Hagele,Ninas Indian Grs & Videos,627 Walford Ave,Dallas,Dallas,TX,75227,214-339-1809,214-225-5850,lhagele@cox.net,http://www.ninasindiangrsvideos.com +Valentin,Klimek,"Schmid, Gayanne K Esq",137 Pioneer Way,Chicago,Cook,IL,60604,312-303-5453,312-512-2338,vklimek@klimek.org,http://www.schmidgayannekesq.com +Melissa,Wiklund,Moapa Valley Federal Credit Un,61 13 Stoneridge #835,Findlay,Hancock,OH,45840,419-939-3613,419-254-4591,melissa@cox.net,http://www.moapavalleyfederalcreditun.com +Sheridan,Zane,Kentucky Tennessee Clay Co,2409 Alabama Rd,Riverside,Riverside,CA,92501,951-645-3605,951-248-6822,sheridan.zane@zane.com,http://www.kentuckytennesseeclayco.com +Bulah,Padilla,Admiral Party Rentals & Sales,8927 Vandever Ave,Waco,McLennan,TX,76707,254-463-4368,254-816-8417,bulah_padilla@hotmail.com,http://www.admiralpartyrentalssales.com +Audra,Kohnert,"Nelson, Karolyn King Esq",134 Lewis Rd,Nashville,Davidson,TN,37211,615-406-7854,615-448-9249,audra@kohnert.com,http://www.nelsonkarolynkingesq.com +Daren,Weirather,Panasystems,9 N College Ave #3,Milwaukee,Milwaukee,WI,53216,414-959-2540,414-838-3151,dweirather@aol.com,http://www.panasystems.com +Fernanda,Jillson,"Shank, Edward L Esq",60480 Old Us Highway 51,Preston,Caroline,MD,21655,410-387-5260,410-724-6472,fjillson@aol.com,http://www.shankedwardlesq.com +Gearldine,Gellinger,Megibow & Edwards,4 Bloomfield Ave,Irving,Dallas,TX,75061,972-934-6914,972-821-7118,gearldine_gellinger@gellinger.com,http://www.megibowedwards.com +Chau,Kitzman,"Benoff, Edward Esq",429 Tiger Ln,Beverly Hills,Los Angeles,CA,90212,310-560-8022,310-969-7230,chau@gmail.com,http://www.benoffedwardesq.com +Theola,Frey,Woodbridge Free Public Library,54169 N Main St,Massapequa,Nassau,NY,11758,516-948-5768,516-357-3362,theola_frey@frey.com,http://www.woodbridgefreepubliclibrary.com +Cheryl,Haroldson,New York Life John Thune,92 Main St,Atlantic City,Atlantic,NJ,8401,609-518-7697,609-263-9243,cheryl@haroldson.org,http://www.newyorklifejohnthune.com +Laticia,Merced,Alinabal Inc,72 Mannix Dr,Cincinnati,Hamilton,OH,45203,513-508-7371,513-418-1566,lmerced@gmail.com,http://www.alinabalinc.com +Carissa,Batman,"Poletto, Kim David Esq",12270 Caton Center Dr,Eugene,Lane,OR,97401,541-326-4074,541-801-5717,carissa.batman@yahoo.com,http://www.polettokimdavidesq.com +Lezlie,Craghead,"Chang, Carolyn Esq",749 W 18th St #45,Smithfield,Johnston,NC,27577,919-533-3762,919-885-2453,lezlie.craghead@craghead.org,http://www.changcarolynesq.com +Ozell,Shealy,Silver Bros Inc,8 Industry Ln,New York,New York,NY,10002,212-332-8435,212-880-8865,oshealy@hotmail.com,http://www.silverbrosinc.com +Arminda,Parvis,Newtec Inc,1 Huntwood Ave,Phoenix,Maricopa,AZ,85017,602-906-9419,602-277-3025,arminda@parvis.com,http://www.newtecinc.com +Reita,Leto,Creative Business Systems,55262 N French Rd,Indianapolis,Marion,IN,46240,317-234-1135,317-787-5514,reita.leto@gmail.com,http://www.creativebusinesssystems.com +Yolando,Luczki,Dal Tile Corporation,422 E 21st St,Syracuse,Onondaga,NY,13214,315-304-4759,315-640-6357,yolando@cox.net,http://www.daltilecorporation.com +Lizette,Stem,Edward S Katz,501 N 19th Ave,Cherry Hill,Camden,NJ,8002,856-487-5412,856-702-3676,lizette.stem@aol.com,http://www.edwardskatz.com +Gregoria,Pawlowicz,Oh My Goodknits Inc,455 N Main Ave,Garden City,Nassau,NY,11530,516-212-1915,516-376-4230,gpawlowicz@yahoo.com,http://www.ohmygoodknitsinc.com +Carin,Deleo,"Redeker, Debbie",1844 Southern Blvd,Little Rock,Pulaski,AR,72202,501-308-1040,501-409-6072,cdeleo@deleo.com,http://www.redekerdebbie.com +Chantell,Maynerich,Desert Sands Motel,2023 Greg St,Saint Paul,Ramsey,MN,55101,651-591-2583,651-776-9688,chantell@yahoo.com,http://www.desertsandsmotel.com +Dierdre,Yum,Cummins Southern Plains Inc,63381 Jenks Ave,Philadelphia,Philadelphia,PA,19134,215-325-3042,215-346-4666,dyum@yahoo.com,http://www.cumminssouthernplainsinc.com +Larae,Gudroe,Lehigh Furn Divsn Lehigh,6651 Municipal Rd,Houma,Terrebonne,LA,70360,985-890-7262,985-261-5783,larae_gudroe@gmail.com,http://www.lehighfurndivsnlehigh.com +Latrice,Tolfree,United Van Lines Agent,81 Norris Ave #525,Ronkonkoma,Suffolk,NY,11779,631-957-7624,631-998-2102,latrice.tolfree@hotmail.com,http://www.unitedvanlinesagent.com +Kerry,Theodorov,Capitol Reporters,6916 W Main St,Sacramento,Sacramento,CA,95827,916-591-3277,916-770-7448,kerry.theodorov@gmail.com,http://www.capitolreporters.com +Dorthy,Hidvegi,Kwik Kopy Printing,9635 S Main St,Boise,Ada,ID,83704,208-649-2373,208-690-3315,dhidvegi@yahoo.com,http://www.kwikkopyprinting.com +Fannie,Lungren,Centro Inc,17 Us Highway 111,Round Rock,Williamson,TX,78664,512-587-5746,512-528-9933,fannie.lungren@yahoo.com,http://www.centroinc.com +Evangelina,Radde,"Campbell, Jan Esq",992 Civic Center Dr,Philadelphia,Philadelphia,PA,19123,215-964-3284,215-417-5612,evangelina@aol.com,http://www.campbelljanesq.com +Novella,Degroot,"Evans, C Kelly Esq",303 N Radcliffe St,Hilo,Hawaii,HI,96720,808-477-4775,808-746-1865,novella_degroot@degroot.org,http://www.evansckellyesq.com +Clay,Hoa,Scat Enterprises,73 Saint Ann St #86,Reno,Washoe,NV,89502,775-501-8109,775-848-9135,choa@hoa.org,http://www.scatenterprises.com +Jennifer,Fallick,"Nagle, Daniel J Esq",44 58th St,Wheeling,Cook,IL,60090,847-979-9545,847-800-3054,jfallick@yahoo.com,http://www.nagledanieljesq.com +Irma,Wolfgramm,Serendiquity Bed & Breakfast,9745 W Main St,Randolph,Morris,NJ,7869,973-545-7355,973-868-8660,irma.wolfgramm@hotmail.com,http://www.serendiquitybedbreakfast.com +Eun,Coody,Ray Carolyne Realty,84 Bloomfield Ave,Spartanburg,Spartanburg,SC,29301,864-256-3620,864-594-4578,eun@yahoo.com,http://www.raycarolynerealty.com +Sylvia,Cousey,"Berg, Charles E",287 Youngstown Warren Rd,Hampstead,Carroll,MD,21074,410-209-9545,410-863-8263,sylvia_cousey@cousey.org,http://www.bergcharlese.com +Nana,Wrinkles,"Ray, Milbern D",6 Van Buren St,Mount Vernon,Westchester,NY,10553,914-855-2115,914-796-3775,nana@aol.com,http://www.raymilbernd.com +Layla,Springe,Chadds Ford Winery,229 N Forty Driv,New York,New York,NY,10011,212-260-3151,212-253-7448,layla.springe@cox.net,http://www.chaddsfordwinery.com +Joesph,Degonia,A R Packaging,2887 Knowlton St #5435,Berkeley,Alameda,CA,94710,510-677-9785,510-942-5916,joesph_degonia@degonia.org,http://www.arpackaging.com +Annabelle,Boord,Corn Popper,523 Marquette Ave,Concord,Middlesex,MA,1742,978-697-6263,978-289-7717,annabelle.boord@cox.net,http://www.cornpopper.com +Stephaine,Vinning,Birite Foodservice Distr,3717 Hamann Industrial Pky,San Francisco,San Francisco,CA,94104,415-767-6596,415-712-9530,stephaine@cox.net,http://www.biritefoodservicedistr.com +Nelida,Sawchuk,Anchorage Museum Of Hist & Art,3 State Route 35 S,Paramus,Bergen,NJ,7652,201-971-1638,201-247-8925,nelida@gmail.com,http://www.anchoragemuseumofhistart.com +Marguerita,Hiatt,"Haber, George D Md",82 N Highway 67,Oakley,Contra Costa,CA,94561,925-634-7158,925-541-8521,marguerita.hiatt@gmail.com,http://www.habergeorgedmd.com +Carmela,Cookey,Royal Pontiac Olds Inc,9 Murfreesboro Rd,Chicago,Cook,IL,60623,773-494-4195,773-297-9391,ccookey@cookey.org,http://www.royalpontiacoldsinc.com +Junita,Brideau,Leonards Antiques Inc,6 S Broadway St,Cedar Grove,Essex,NJ,7009,973-943-3423,973-582-5469,jbrideau@aol.com,http://www.leonardsantiquesinc.com +Claribel,Varriano,Meca,6 Harry L Dr #6327,Perrysburg,Wood,OH,43551,419-544-4900,419-573-2033,claribel_varriano@cox.net,http://www.meca.com +Benton,Skursky,Nercon Engineering & Mfg Inc,47939 Porter Ave,Gardena,Los Angeles,CA,90248,310-579-2907,310-694-8466,benton.skursky@aol.com,http://www.nerconengineeringmfginc.com +Hillary,Skulski,Replica I,9 Wales Rd Ne #914,Homosassa,Citrus,FL,34448,352-242-2570,352-990-5946,hillary.skulski@aol.com,http://www.replicai.com +Merilyn,Bayless,20 20 Printing Inc,195 13n N,Santa Clara,Santa Clara,CA,95054,408-758-5015,408-346-2180,merilyn_bayless@cox.net,http://www.printinginc.com +Teri,Ennaco,Publishers Group West,99 Tank Farm Rd,Hazleton,Luzerne,PA,18201,570-889-5187,570-355-1665,tennaco@gmail.com,http://www.publishersgroupwest.com +Merlyn,Lawler,"Nischwitz, Jeffrey L Esq",4671 Alemany Blvd,Jersey City,Hudson,NJ,7304,201-588-7810,201-858-9960,merlyn_lawler@hotmail.com,http://www.nischwitzjeffreylesq.com +Georgene,Montezuma,Payne Blades & Wellborn Pa,98 University Dr,San Ramon,Contra Costa,CA,94583,925-615-5185,925-943-3449,gmontezuma@cox.net,http://www.paynebladeswellbornpa.com +Jettie,Mconnell,Coldwell Bnkr Wright Real Est,50 E Wacker Dr,Bridgewater,Somerset,NJ,8807,908-802-3564,908-602-5258,jmconnell@hotmail.com,http://www.coldwellbnkrwrightrealest.com +Lemuel,Latzke,Computer Repair Service,70 Euclid Ave #722,Bohemia,Suffolk,NY,11716,631-748-6479,631-291-4976,lemuel.latzke@gmail.com,http://www.computerrepairservice.com +Melodie,Knipp,Fleetwood Building Block Inc,326 E Main St #6496,Thousand Oaks,Ventura,CA,91362,805-690-1682,805-810-8964,mknipp@gmail.com,http://www.fleetwoodbuildingblockinc.com +Candida,Corbley,Colts Neck Medical Assocs Inc,406 Main St,Somerville,Somerset,NJ,8876,908-275-8357,908-943-6103,candida_corbley@hotmail.com,http://www.coltsneckmedicalassocsinc.com +Karan,Karpin,New England Taxidermy,3 Elmwood Dr,Beaverton,Washington,OR,97005,503-940-8327,503-707-5812,karan_karpin@gmail.com,http://www.newenglandtaxidermy.com +Andra,Scheyer,"Ludcke, George O Esq",9 Church St,Salem,Marion,OR,97302,503-516-2189,503-950-3068,andra@gmail.com,http://www.ludckegeorgeoesq.com +Felicidad,Poullion,"Mccorkle, Tom S Esq",9939 N 14th St,Riverton,Burlington,NJ,8077,856-305-9731,856-828-6021,fpoullion@poullion.com,http://www.mccorkletomsesq.com +Belen,Strassner,Eagle Software Inc,5384 Southwyck Blvd,Douglasville,Douglas,GA,30135,770-507-8791,770-802-4003,belen_strassner@aol.com,http://www.eaglesoftwareinc.com +Gracia,Melnyk,Juvenile & Adult Super,97 Airport Loop Dr,Jacksonville,Duval,FL,32216,904-235-3633,904-627-4341,gracia@melnyk.com,http://www.juvenileadultsuper.com +Jolanda,Hanafan,"Perez, Joseph J Esq",37855 Nolan Rd,Bangor,Penobscot,ME,4401,207-458-9196,207-233-6185,jhanafan@gmail.com,http://www.perezjosephjesq.com +Barrett,Toyama,Case Foundation Co,4252 N Washington Ave #9,Kennedale,Tarrant,TX,76060,817-765-5781,817-577-6151,barrett.toyama@toyama.org,http://www.casefoundationco.com +Helga,Fredicks,Eis Environmental Engrs Inc,42754 S Ash Ave,Buffalo,Erie,NY,14228,716-752-4114,716-854-9845,helga_fredicks@yahoo.com,http://www.eisenvironmentalengrsinc.com +Ashlyn,Pinilla,Art Crafters,703 Beville Rd,Opa Locka,Miami-Dade,FL,33054,305-670-9628,305-857-5489,apinilla@cox.net,http://www.artcrafters.com +Fausto,Agramonte,Marriott Hotels Resorts Suites,5 Harrison Rd,New York,New York,NY,10038,212-313-1783,212-778-3063,fausto_agramonte@yahoo.com,http://www.marriotthotelsresortssuites.com +Ronny,Caiafa,Remaco Inc,73 Southern Blvd,Philadelphia,Philadelphia,PA,19103,215-605-7570,215-511-3531,ronny.caiafa@caiafa.org,http://www.remacoinc.com +Marge,Limmel,"Bjork, Robert D Jr",189 Village Park Rd,Crestview,Okaloosa,FL,32536,850-430-1663,850-330-8079,marge@gmail.com,http://www.bjorkrobertdjr.com +Norah,Waymire,"Carmichael, Jeffery L Esq",6 Middlegate Rd #106,San Francisco,San Francisco,CA,94107,415-306-7897,415-874-2984,norah.waymire@gmail.com,http://www.carmichaeljefferylesq.com +Aliza,Baltimore,"Andrews, J Robert Esq",1128 Delaware St,San Jose,Santa Clara,CA,95132,408-504-3552,408-425-1994,aliza@aol.com,http://www.andrewsjrobertesq.com +Mozell,Pelkowski,Winship & Byrne,577 Parade St,South San Francisco,San Mateo,CA,94080,650-947-1215,650-960-1069,mpelkowski@pelkowski.org,http://www.winshipbyrne.com +Viola,Bitsuie,Burton & Davis,70 Mechanic St,Northridge,Los Angeles,CA,91325,818-864-4875,818-481-5787,viola@gmail.com,http://www.burtondavis.com +Franklyn,Emard,Olympic Graphic Arts,4379 Highway 116,Philadelphia,Philadelphia,PA,19103,215-558-8189,215-483-3003,femard@emard.com,http://www.olympicgraphicarts.com +Willodean,Konopacki,Magnuson,55 Hawthorne Blvd,Lafayette,Lafayette,LA,70506,337-253-8384,337-774-7564,willodean_konopacki@konopacki.org,http://www.magnuson.com +Beckie,Silvestrini,A All American Travel Inc,7116 Western Ave,Dearborn,Wayne,MI,48126,313-533-4884,313-390-7855,beckie.silvestrini@silvestrini.com,http://www.aallamericantravelinc.com +Rebecka,Gesick,Polykote Inc,2026 N Plankinton Ave #3,Austin,Travis,TX,78754,512-213-8574,512-693-8345,rgesick@gesick.org,http://www.polykoteinc.com +Frederica,Blunk,Jets Cybernetics,99586 Main St,Dallas,Dallas,TX,75207,214-428-2285,214-529-1949,frederica_blunk@gmail.com,http://www.jetscybernetics.com +Glen,Bartolet,Metlab Testing Services,8739 Hudson St,Vashon,King,WA,98070,206-697-5796,206-389-1482,glen_bartolet@hotmail.com,http://www.metlabtestingservices.com +Freeman,Gochal,"Kellermann, William T Esq",383 Gunderman Rd #197,Coatesville,Chester,PA,19320,610-476-3501,610-752-2683,freeman_gochal@aol.com,http://www.kellermannwilliamtesq.com +Vincent,Meinerding,"Arturi, Peter D Esq",4441 Point Term Mkt,Philadelphia,Philadelphia,PA,19143,215-372-1718,215-829-4221,vincent.meinerding@hotmail.com,http://www.arturipeterdesq.com +Rima,Bevelacqua,Mcauley Mfg Co,2972 Lafayette Ave,Gardena,Los Angeles,CA,90248,310-858-5079,310-499-4200,rima@cox.net,http://www.mcauleymfgco.com +Glendora,Sarbacher,Defur Voran Hanley Radcliff,2140 Diamond Blvd,Rohnert Park,Sonoma,CA,94928,707-653-8214,707-881-3154,gsarbacher@gmail.com,http://www.defurvoranhanleyradcliff.com +Avery,Steier,Dill Dill Carr & Stonbraker Pc,93 Redmond Rd #492,Orlando,Orange,FL,32803,407-808-9439,407-945-8566,avery@cox.net,http://www.dilldillcarrstonbrakerpc.com +Cristy,Lother,Kleensteel,3989 Portage Tr,Escondido,San Diego,CA,92025,760-971-4322,760-465-4762,cristy@lother.com,http://www.kleensteel.com +Nicolette,Brossart,Goulds Pumps Inc Slurry Pump,1 Midway Rd,Westborough,Worcester,MA,1581,508-837-9230,508-504-6388,nicolette_brossart@brossart.com,http://www.gouldspumpsincslurrypump.com +Tracey,Modzelewski,Kansas City Insurance Report,77132 Coon Rapids Blvd Nw,Conroe,Montgomery,TX,77301,936-264-9294,936-988-8171,tracey@hotmail.com,http://www.kansascityinsurancereport.com +Virgina,Tegarden,Berhanu International Foods,755 Harbor Way,Milwaukee,Milwaukee,WI,53226,414-214-8697,414-411-5744,virgina_tegarden@tegarden.com,http://www.berhanuinternationalfoods.com +Tiera,Frankel,Roland Ashcroft,87 Sierra Rd,El Monte,Los Angeles,CA,91731,626-636-4117,626-638-4241,tfrankel@aol.com,http://www.rolandashcroft.com +Alaine,Bergesen,Hispanic Magazine,7667 S Hulen St #42,Yonkers,Westchester,NY,10701,914-300-9193,914-654-1426,alaine_bergesen@cox.net,http://www.hispanicmagazine.com +Earleen,Mai,Little Sheet Metal Co,75684 S Withlapopka Dr #32,Dallas,Dallas,TX,75227,214-289-1973,214-785-6750,earleen_mai@cox.net,http://www.littlesheetmetalco.com +Leonida,Gobern,"Holmes, Armstead J Esq",5 Elmwood Park Blvd,Biloxi,Harrison,MS,39530,228-235-5615,228-432-4635,leonida@gobern.org,http://www.holmesarmsteadjesq.com +Ressie,Auffrey,"Faw, James C Cpa",23 Palo Alto Sq,Miami,Miami-Dade,FL,33134,305-604-8981,305-287-4743,ressie.auffrey@yahoo.com,http://www.fawjamesccpa.com +Justine,Mugnolo,Evans Rule Company,38062 E Main St,New York,New York,NY,10048,212-304-9225,212-311-6377,jmugnolo@yahoo.com,http://www.evansrulecompany.com +Eladia,Saulter,Tyee Productions Inc,3958 S Dupont Hwy #7,Ramsey,Bergen,NJ,7446,201-474-4924,201-365-8698,eladia@saulter.com,http://www.tyeeproductionsinc.com +Chaya,Malvin,Dunnells & Duvall,560 Civic Center Dr,Ann Arbor,Washtenaw,MI,48103,734-928-5182,734-408-8174,chaya@malvin.com,http://www.dunnellsduvall.com +Gwenn,Suffield,Deltam Systems Inc,3270 Dequindre Rd,Deer Park,Suffolk,NY,11729,631-258-6558,631-295-9879,gwenn_suffield@suffield.org,http://www.deltamsystemsinc.com +Salena,Karpel,Hammill Mfg Co,1 Garfield Ave #7,Canton,Stark,OH,44707,330-791-8557,330-618-2579,skarpel@cox.net,http://www.hammillmfgco.com +Yoko,Fishburne,Sams Corner Store,9122 Carpenter Ave,New Haven,New Haven,CT,6511,203-506-4706,203-840-8634,yoko@fishburne.com,http://www.samscornerstore.com +Taryn,Moyd,"Siskin, Mark J Esq",48 Lenox St,Fairfax,Fairfax City,VA,22030,703-322-4041,703-938-7939,taryn.moyd@hotmail.com,http://www.siskinmarkjesq.com +Katina,Polidori,Cape & Associates Real Estate,5 Little River Tpke,Wilmington,Middlesex,MA,1887,978-626-2978,978-679-7429,katina_polidori@aol.com,http://www.capeassociatesrealestate.com +Rickie,Plumer,Merrill Lynch,3 N Groesbeck Hwy,Toledo,Lucas,OH,43613,419-693-1334,419-313-5571,rickie.plumer@aol.com,http://www.merrilllynch.com +Alex,Loader,"Sublett, Scott Esq",37 N Elm St #916,Tacoma,Pierce,WA,98409,253-660-7821,253-875-9222,alex@loader.com,http://www.sublettscottesq.com +Lashon,Vizarro,Sentry Signs,433 Westminster Blvd #590,Roseville,Placer,CA,95661,916-741-7884,916-289-4526,lashon@aol.com,http://www.sentrysigns.com +Lauran,Burnard,Professionals Unlimited,66697 Park Pl #3224,Riverton,Fremont,WY,82501,307-342-7795,307-453-7589,lburnard@burnard.com,http://www.professionalsunlimited.com +Ceola,Setter,Southern Steel Shelving Co,96263 Greenwood Pl,Warren,Knox,ME,4864,207-627-7565,207-297-5029,ceola.setter@setter.org,http://www.southernsteelshelvingco.com +My,Rantanen,"Bosco, Paul J",8 Mcarthur Ln,Richboro,Bucks,PA,18954,215-491-5633,215-647-2158,my@hotmail.com,http://www.boscopaulj.com +Lorrine,Worlds,"Longo, Nicholas J Esq",8 Fair Lawn Ave,Tampa,Hillsborough,FL,33614,813-769-2939,813-863-6467,lorrine.worlds@worlds.com,http://www.longonicholasjesq.com +Peggie,Sturiale,Henry County Middle School,9 N 14th St,El Cajon,San Diego,CA,92020,619-608-1763,619-695-8086,peggie@cox.net,http://www.henrycountymiddleschool.com +Marvel,Raymo,Edison Supply & Equipment Co,9 Vanowen St,College Station,Brazos,TX,77840,979-718-8968,979-809-5770,mraymo@yahoo.com,http://www.edisonsupplyequipmentco.com +Daron,Dinos,"Wolf, Warren R Esq",18 Waterloo Geneva Rd,Highland Park,Lake,IL,60035,847-233-3075,847-265-6609,daron_dinos@cox.net,http://www.wolfwarrenresq.com +An,Fritz,Linguistic Systems Inc,506 S Hacienda Dr,Atlantic City,Atlantic,NJ,8401,609-228-5265,609-854-7156,an_fritz@hotmail.com,http://www.linguisticsystemsinc.com +Portia,Stimmel,Peace Christian Center,3732 Sherman Ave,Bridgewater,Somerset,NJ,8807,908-722-7128,908-670-4712,portia.stimmel@aol.com,http://www.peacechristiancenter.com +Rhea,Aredondo,Double B Foods Inc,25657 Live Oak St,Brooklyn,Kings,NY,11226,718-560-9537,718-280-4183,rhea_aredondo@cox.net,http://www.doublebfoodsinc.com +Benedict,Sama,Alexander & Alexander Inc,4923 Carey Ave,Saint Louis,Saint Louis City,MO,63104,314-787-1588,314-858-4832,bsama@cox.net,http://www.alexanderalexanderinc.com +Alyce,Arias,Fairbanks Scales,3196 S Rider Trl,Stockton,San Joaquin,CA,95207,209-317-1801,209-242-7022,alyce@arias.org,http://www.fairbanksscales.com +Heike,Berganza,Cali Sportswear Cutting Dept,3 Railway Ave #75,Little Falls,Passaic,NJ,7424,973-936-5095,973-822-8827,heike@gmail.com,http://www.calisportswearcuttingdept.com +Carey,Dopico,"Garofani, John Esq",87393 E Highland Rd,Indianapolis,Marion,IN,46220,317-578-2453,317-441-5848,carey_dopico@dopico.org,http://www.garofanijohnesq.com +Dottie,Hellickson,Thompson Fabricating Co,67 E Chestnut Hill Rd,Seattle,King,WA,98133,206-540-6076,206-295-5631,dottie@hellickson.org,http://www.thompsonfabricatingco.com +Deandrea,Hughey,Century 21 Krall Real Estate,33 Lewis Rd #46,Burlington,Alamance,NC,27215,336-822-7652,336-467-3095,deandrea@yahoo.com,http://www.centurykrallrealestate.com +Kimberlie,Duenas,Mid Contntl Rlty & Prop Mgmt,8100 Jacksonville Rd #7,Hays,Ellis,KS,67601,785-629-8542,785-616-1685,kimberlie_duenas@yahoo.com,http://www.midcontntlrltypropmgmt.com +Martina,Staback,Ace Signs Inc,7 W Wabansia Ave #227,Orlando,Orange,FL,32822,407-471-6908,407-429-2145,martina_staback@staback.com,http://www.acesignsinc.com +Skye,Fillingim,Rodeway Inn,25 Minters Chapel Rd #9,Minneapolis,Hennepin,MN,55401,612-508-2655,612-664-6304,skye_fillingim@yahoo.com,http://www.rodewayinn.com +Jade,Farrar,Bonnet & Daughter,6882 Torresdale Ave,Columbia,Richland,SC,29201,803-352-5387,803-975-3405,jade.farrar@yahoo.com,http://www.bonnetdaughter.com +Charlene,Hamilton,Oshins & Gibbons,985 E 6th Ave,Santa Rosa,Sonoma,CA,95407,707-300-1771,707-821-8037,charlene.hamilton@hotmail.com,http://www.oshinsgibbons.com +Geoffrey,Acey,Price Business Services,7 West Ave #1,Palatine,Cook,IL,60067,847-222-1734,847-556-2909,geoffrey@gmail.com,http://www.pricebusinessservices.com +Stevie,Westerbeck,"Wise, Dennis W Md",26659 N 13th St,Costa Mesa,Orange,CA,92626,949-867-4077,949-903-3898,stevie.westerbeck@yahoo.com,http://www.wisedenniswmd.com +Pamella,Fortino,Super 8 Motel,669 Packerland Dr #1438,Denver,Denver,CO,80212,303-404-2210,303-794-1341,pamella@fortino.com,http://www.supermotel.com +Harrison,Haufler,John Wagner Associates,759 Eldora St,New Haven,New Haven,CT,6515,203-801-6193,203-801-8497,hhaufler@hotmail.com,http://www.johnwagnerassociates.com +Johnna,Engelberg,Thrifty Oil Co,5 S Colorado Blvd #449,Bothell,Snohomish,WA,98021,425-986-7573,425-700-3751,jengelberg@engelberg.org,http://www.thriftyoilco.com +Buddy,Cloney,Larkfield Photo,944 Gaither Dr,Strongsville,Cuyahoga,OH,44136,440-989-5826,440-327-2093,buddy.cloney@yahoo.com,http://www.larkfieldphoto.com +Dalene,Riden,Silverman Planetarium,66552 Malone Rd,Plaistow,Rockingham,NH,3865,603-315-6839,603-745-7497,dalene.riden@aol.com,http://www.silvermanplanetarium.com +Jerry,Zurcher,J & F Lumber,77 Massillon Rd #822,Satellite Beach,Brevard,FL,32937,321-518-5938,321-597-2159,jzurcher@zurcher.org,http://www.jflumber.com +Haydee,Denooyer,Cleaning Station Inc,25346 New Rd,New York,New York,NY,10016,212-792-8658,212-782-3493,hdenooyer@denooyer.org,http://www.cleaningstationinc.com +Joseph,Cryer,Ames Stationers,60 Fillmore Ave,Huntington Beach,Orange,CA,92647,714-584-2237,714-698-2170,joseph_cryer@cox.net,http://www.amesstationers.com +Deonna,Kippley,Midas Muffler Shops,57 Haven Ave #90,Southfield,Oakland,MI,48075,248-913-4677,248-793-4966,deonna_kippley@hotmail.com,http://www.midasmufflershops.com +Raymon,Calvaresi,Seaboard Securities Inc,6538 E Pomona St #60,Indianapolis,Marion,IN,46222,317-825-4724,317-342-1532,raymon.calvaresi@gmail.com,http://www.seaboardsecuritiesinc.com +Alecia,Bubash,"Petersen, James E Esq",6535 Joyce St,Wichita Falls,Wichita,TX,76301,940-276-7922,940-302-3036,alecia@aol.com,http://www.petersenjameseesq.com +Ma,Layous,Development Authority,78112 Morris Ave,North Haven,New Haven,CT,6473,203-721-3388,203-564-1543,mlayous@hotmail.com,http://www.developmentauthority.com +Detra,Coyier,Schott Fiber Optics Inc,96950 Hidden Ln,Aberdeen,Harford,MD,21001,410-739-9277,410-259-2118,detra@aol.com,http://www.schottfiberopticsinc.com +Terrilyn,Rodeigues,Stuart J Agins,3718 S Main St,New Orleans,Orleans,LA,70130,504-463-4384,504-635-8518,terrilyn.rodeigues@cox.net,http://www.stuartjagins.com +Salome,Lacovara,Mitsumi Electronics Corp,9677 Commerce Dr,Richmond,Richmond City,VA,23219,804-550-5097,804-858-1011,slacovara@gmail.com,http://www.mitsumielectronicscorp.com +Garry,Keetch,Italian Express Franchise Corp,5 Green Pond Rd #4,Southampton,Bucks,PA,18966,215-979-8776,215-846-9046,garry_keetch@hotmail.com,http://www.italianexpressfranchisecorp.com +Matthew,Neither,American Council On Sci & Hlth,636 Commerce Dr #42,Shakopee,Scott,MN,55379,952-651-7597,952-906-4597,mneither@yahoo.com,http://www.americancouncilonscihlth.com +Theodora,Restrepo,"Kleri, Patricia S Esq",42744 Hamann Industrial Pky #82,Miami,Miami-Dade,FL,33136,305-936-8226,305-573-1085,theodora.restrepo@restrepo.com,http://www.kleripatriciasesq.com +Noah,Kalafatis,Twiggs Abrams Blanchard,1950 5th Ave,Milwaukee,Milwaukee,WI,53209,414-263-5287,414-660-9766,noah.kalafatis@aol.com,http://www.twiggsabramsblanchard.com +Carmen,Sweigard,Maui Research & Technology Pk,61304 N French Rd,Somerset,Somerset,NJ,8873,732-941-2621,732-445-6940,csweigard@sweigard.com,http://www.mauiresearchtechnologypk.com +Lavonda,Hengel,Bradley Nameplate Corp,87 Imperial Ct #79,Fargo,Cass,ND,58102,701-898-2154,701-421-7080,lavonda@cox.net,http://www.bradleynameplatecorp.com +Junita,Stoltzman,Geonex Martel Inc,94 W Dodge Rd,Carson City,Carson City,NV,89701,775-638-9963,775-578-1214,junita@aol.com,http://www.geonexmartelinc.com +Herminia,Nicolozakes,Sea Island Div Of Fstr Ind Inc,4 58th St #3519,Scottsdale,Maricopa,AZ,85254,602-954-5141,602-304-6433,herminia@nicolozakes.org,http://www.seaislanddivoffstrindinc.com +Casie,Good,"Papay, Debbie J Esq",5221 Bear Valley Rd,Nashville,Davidson,TN,37211,615-390-2251,615-825-4297,casie.good@aol.com,http://www.papaydebbiejesq.com +Reena,Maisto,Lane Promotions,9648 S Main,Salisbury,Wicomico,MD,21801,410-351-1863,410-951-2667,reena@hotmail.com,http://www.lanepromotions.com +Mirta,Mallett,Stephen Kennerly Archts Inc Pc,7 S San Marcos Rd,New York,New York,NY,10004,212-870-1286,212-745-6948,mirta_mallett@gmail.com,http://www.stephenkennerlyarchtsincpc.com +Cathrine,Pontoriero,Business Systems Of Wis Inc,812 S Haven St,Amarillo,Randall,TX,79109,806-703-1435,806-558-5848,cathrine.pontoriero@pontoriero.com,http://www.businesssystemsofwisinc.com +Filiberto,Tawil,"Flash, Elena Salerno Esq",3882 W Congress St #799,Los Angeles,Los Angeles,CA,90016,323-765-2528,323-842-8226,ftawil@hotmail.com,http://www.flashelenasalernoesq.com +Raul,Upthegrove,"Neeley, Gregory W Esq",4 E Colonial Dr,La Mesa,San Diego,CA,91942,619-509-5282,619-666-4765,rupthegrove@yahoo.com,http://www.neeleygregorywesq.com +Sarah,Candlish,Alabama Educational Tv Comm,45 2nd Ave #9759,Atlanta,Fulton,GA,30328,770-732-1194,770-531-2842,sarah.candlish@gmail.com,http://www.alabamaeducationaltvcomm.com +Lucy,Treston,Franz Inc,57254 Brickell Ave #372,Worcester,Worcester,MA,1602,508-769-5250,508-502-5634,lucy@cox.net,http://www.franzinc.com +Judy,Aquas,Plantation Restaurant,8977 Connecticut Ave Nw #3,Niles,Berrien,MI,49120,269-756-7222,269-431-9464,jaquas@aquas.com,http://www.plantationrestaurant.com +Yvonne,Tjepkema,Radio Communications Co,9 Waydell St,Fairfield,Essex,NJ,7004,973-714-1721,973-976-8627,yvonne.tjepkema@hotmail.com,http://www.radiocommunicationsco.com +Kayleigh,Lace,Dentalaw Divsn Hlth Care,43 Huey P Long Ave,Lafayette,Lafayette,LA,70508,337-740-9323,337-751-2326,kayleigh.lace@yahoo.com,http://www.dentalawdivsnhlthcare.com +Felix,Hirpara,American Speedy Printing Ctrs,7563 Cornwall Rd #4462,Denver,Lancaster,PA,17517,717-491-5643,717-583-1497,felix_hirpara@cox.net,http://www.americanspeedyprintingctrs.com +Tresa,Sweely,"Grayson, Grant S Esq",22 Bridle Ln,Valley Park,Saint Louis,MO,63088,314-359-9566,314-231-3514,tresa_sweely@hotmail.com,http://www.graysongrantsesq.com +Kristeen,Turinetti,Jeanerette Middle School,70099 E North Ave,Arlington,Tarrant,TX,76013,817-213-8851,817-947-9480,kristeen@gmail.com,http://www.jeanerettemiddleschool.com +Jenelle,Regusters,"Haavisto, Brian F Esq",3211 E Northeast Loop,Tampa,Hillsborough,FL,33619,813-932-8715,813-357-7296,jregusters@regusters.com,http://www.haavistobrianfesq.com +Renea,Monterrubio,Wmmt Radio Station,26 Montgomery St,Atlanta,Fulton,GA,30328,770-679-4752,770-930-9967,renea@hotmail.com,http://www.wmmtradiostation.com +Olive,Matuszak,Colony Paints Sales Ofc & Plnt,13252 Lighthouse Ave,Cathedral City,Riverside,CA,92234,760-938-6069,760-745-2649,olive@aol.com,http://www.colonypaintssalesofcplnt.com +Ligia,Reiber,Floral Expressions,206 Main St #2804,Lansing,Ingham,MI,48933,517-906-1108,517-747-7664,lreiber@cox.net,http://www.floralexpressions.com +Christiane,Eschberger,Casco Services Inc,96541 W Central Blvd,Phoenix,Maricopa,AZ,85034,602-390-4944,602-330-6894,christiane.eschberger@yahoo.com,http://www.cascoservicesinc.com +Goldie,Schirpke,"Reuter, Arthur C Jr",34 Saint George Ave #2,Bangor,Penobscot,ME,4401,207-295-7569,207-748-3722,goldie.schirpke@yahoo.com,http://www.reuterarthurcjr.com +Loreta,Timenez,"Kaminski, Katherine Andritsaki",47857 Coney Island Ave,Clinton,Prince Georges,MD,20735,301-696-6420,301-392-6698,loreta.timenez@hotmail.com,http://www.kaminskikatherineandritsaki.com +Fabiola,Hauenstein,Sidewinder Products Corp,8573 Lincoln Blvd,York,York,PA,17404,717-809-3119,717-344-2804,fabiola.hauenstein@hauenstein.org,http://www.sidewinderproductscorp.com +Amie,Perigo,General Foam Corporation,596 Santa Maria Ave #7913,Mesquite,Dallas,TX,75150,972-419-7946,972-898-1033,amie.perigo@yahoo.com,http://www.generalfoamcorporation.com +Raina,Brachle,Ikg Borden Divsn Harsco Corp,3829 Ventura Blvd,Butte,Silver Bow,MT,59701,406-318-1515,406-374-7752,raina.brachle@brachle.org,http://www.ikgbordendivsnharscocorp.com +Erinn,Canlas,Anchor Computer Inc,13 S Hacienda Dr,Livingston,Essex,NJ,7039,973-767-3008,973-563-9502,erinn.canlas@canlas.com,http://www.anchorcomputerinc.com +Cherry,Lietz,Sebring & Co,40 9th Ave Sw #91,Waterford,Oakland,MI,48329,248-980-6904,248-697-7722,cherry@lietz.com,http://www.sebringco.com +Kattie,Vonasek,H A C Farm Lines Co Optv Assoc,2845 Boulder Crescent St,Cleveland,Cuyahoga,OH,44103,216-923-3715,216-270-9653,kattie@vonasek.org,http://www.hacfarmlinescooptvassoc.com +Lilli,Scriven,"Hunter, John J Esq",33 State St,Abilene,Taylor,TX,79601,325-631-1560,325-667-7868,lilli@aol.com,http://www.hunterjohnjesq.com +Whitley,Tomasulo,Freehold Fence Co,2 S 15th St,Fort Worth,Tarrant,TX,76107,817-526-4408,817-819-7799,whitley.tomasulo@aol.com,http://www.freeholdfenceco.com +Barbra,Adkin,Binswanger,4 Kohler Memorial Dr,Brooklyn,Kings,NY,11230,718-201-3751,718-732-9475,badkin@hotmail.com,http://www.binswanger.com +Hermila,Thyberg,Chilton Malting Co,1 Rancho Del Mar Shopping C,Providence,Providence,RI,2903,401-893-4882,401-885-7681,hermila_thyberg@hotmail.com,http://www.chiltonmaltingco.com +Jesusita,Flister,"Schoen, Edward J Jr",3943 N Highland Ave,Lancaster,Lancaster,PA,17601,717-885-9118,717-686-7564,jesusita.flister@hotmail.com,http://www.schoenedwardjjr.com +Caitlin,Julia,"Helderman, Seymour Cpa",5 Williams St,Johnston,Providence,RI,2919,401-948-4982,401-552-9059,caitlin.julia@julia.org,http://www.heldermanseymourcpa.com +Roosevelt,Hoffis,"Denbrook, Myron",60 Old Dover Rd,Hialeah,Miami-Dade,FL,33014,305-622-4739,305-302-1135,roosevelt.hoffis@aol.com,http://www.denbrookmyron.com +Helaine,Halter,"Lippitt, Mike",8 Sheridan Rd,Jersey City,Hudson,NJ,7304,201-832-4168,201-412-3040,hhalter@yahoo.com,http://www.lippittmike.com +Lorean,Martabano,"Hiram, Hogg P Esq",85092 Southern Blvd,San Antonio,Bexar,TX,78204,210-856-4979,210-634-2447,lorean.martabano@hotmail.com,http://www.hiramhoggpesq.com +France,Buzick,In Travel Agency,64 Newman Springs Rd E,Brooklyn,Kings,NY,11219,718-478-8504,718-853-3740,france.buzick@yahoo.com,http://www.intravelagency.com +Justine,Ferrario,Newhart Foods Inc,48 Stratford Ave,Pomona,Los Angeles,CA,91768,909-993-3242,909-631-5703,jferrario@hotmail.com,http://www.newhartfoodsinc.com +Adelina,Nabours,Courtyard By Marriott,80 Pittsford Victor Rd #9,Cleveland,Cuyahoga,OH,44103,216-230-4892,216-937-5320,adelina_nabours@gmail.com,http://www.courtyardbymarriott.com +Derick,Dhamer,"Studer, Eugene A Esq",87163 N Main Ave,New York,New York,NY,10013,212-304-4515,212-225-9676,ddhamer@cox.net,http://www.studereugeneaesq.com +Jerry,Dallen,Seashore Supply Co Waretown,393 Lafayette Ave,Richmond,Richmond City,VA,23219,804-762-9576,804-808-9574,jerry.dallen@yahoo.com,http://www.seashoresupplycowaretown.com +Leota,Ragel,Mayar Silk Inc,99 5th Ave #33,Trion,Chattooga,GA,30753,706-221-4243,706-616-5131,leota.ragel@gmail.com,http://www.mayarsilkinc.com +Jutta,Amyot,National Medical Excess Corp,49 N Mays St,Broussard,Lafayette,LA,70518,337-515-1438,337-991-8070,jamyot@hotmail.com,http://www.nationalmedicalexcesscorp.com +Aja,Gehrett,Stero Company,993 Washington Ave,Nutley,Essex,NJ,7110,973-544-2677,973-986-4456,aja_gehrett@hotmail.com,http://www.sterocompany.com +Kirk,Herritt,"Hasting, H Duane Esq",88 15th Ave Ne,Vestal,Broome,NY,13850,607-407-3716,607-350-7690,kirk.herritt@aol.com,http://www.hastinghduaneesq.com +Leonora,Mauson,Insty Prints,3381 E 40th Ave,Passaic,Passaic,NJ,7055,973-412-2995,973-355-2120,leonora@yahoo.com,http://www.instyprints.com +Winfred,Brucato,Glenridge Manor Mobile Home Pk,201 Ridgewood Rd,Moscow,Latah,ID,83843,208-252-4552,208-793-4108,winfred_brucato@hotmail.com,http://www.glenridgemanormobilehomepk.com +Tarra,Nachor,Circuit Solution Inc,39 Moccasin Dr,San Francisco,San Francisco,CA,94104,415-411-1775,415-284-2730,tarra.nachor@cox.net,http://www.circuitsolutioninc.com +Corinne,Loder,Local Office,4 Carroll St,North Attleboro,Bristol,MA,2760,508-942-4186,508-618-7826,corinne@loder.org,http://www.localoffice.com +Dulce,Labreche,Lee Kilkelly Paulson & Kabaker,9581 E Arapahoe Rd,Rochester,Oakland,MI,48307,248-357-8718,248-811-5696,dulce_labreche@yahoo.com,http://www.leekilkellypaulsonkabaker.com +Kate,Keneipp,"Davis, Maxon R Esq",33 N Michigan Ave,Green Bay,Brown,WI,54301,920-353-6377,920-355-1610,kate_keneipp@yahoo.com,http://www.davismaxonresq.com +Kaitlyn,Ogg,"Garrison, Paul E Esq",2 S Biscayne Blvd,Baltimore,Baltimore City,MD,21230,410-665-4903,410-773-3862,kaitlyn.ogg@gmail.com,http://www.garrisonpauleesq.com +Sherita,Saras,Black History Resource Center,8 Us Highway 22,Colorado Springs,El Paso,CO,80937,719-669-1664,719-547-9543,sherita.saras@cox.net,http://www.blackhistoryresourcecenter.com +Lashawnda,Stuer,"Rodriguez, J Christopher Esq",7422 Martin Ave #8,Toledo,Lucas,OH,43607,419-588-8719,419-399-1744,lstuer@cox.net,http://www.rodriguezjchristopheresq.com +Ernest,Syrop,Grant Family Health Center,94 Chase Rd,Hyattsville,Prince Georges,MD,20785,301-998-9644,301-257-4883,ernest@cox.net,http://www.grantfamilyhealthcenter.com +Nobuko,Halsey,Goeman Wood Products Inc,8139 I Hwy 10 #92,New Bedford,Bristol,MA,2745,508-855-9887,508-897-7916,nobuko.halsey@yahoo.com,http://www.goemanwoodproductsinc.com +Lavonna,Wolny,"Linhares, Kenneth A Esq",5 Cabot Rd,Mc Lean,Fairfax,VA,22102,703-483-1970,703-892-2914,lavonna.wolny@hotmail.com,http://www.linhareskennethaesq.com +Lashaunda,Lizama,Earnhardt Printing,3387 Ryan Dr,Hanover,Anne Arundel,MD,21076,410-678-2473,410-912-6032,llizama@cox.net,http://www.earnhardtprinting.com +Mariann,Bilden,H P G Industrys Inc,3125 Packer Ave #9851,Austin,Travis,TX,78753,512-223-4791,512-742-1149,mariann.bilden@aol.com,http://www.hpgindustrysinc.com +Helene,Rodenberger,Bailey Transportation Prod Inc,347 Chestnut St,Peoria,Maricopa,AZ,85381,623-461-8551,623-426-4907,helene@aol.com,http://www.baileytransportationprodinc.com +Roselle,Estell,Mcglynn Bliss Pc,8116 Mount Vernon Ave,Bucyrus,Crawford,OH,44820,419-571-5920,419-488-6648,roselle.estell@hotmail.com,http://www.mcglynnblisspc.com +Samira,Heintzman,Mutual Fish Co,8772 Old County Rd #5410,Kent,King,WA,98032,206-311-4137,206-923-6042,sheintzman@hotmail.com,http://www.mutualfishco.com +Margart,Meisel,"Yeates, Arthur L Aia",868 State St #38,Cincinnati,Hamilton,OH,45251,513-617-2362,513-747-9603,margart_meisel@yahoo.com,http://www.yeatesarthurlaia.com +Kristofer,Bennick,"Logan, Ronald J Esq",772 W River Dr,Bloomington,Monroe,IN,47404,812-368-1511,812-442-8544,kristofer.bennick@yahoo.com,http://www.loganronaldjesq.com +Weldon,Acuff,Advantage Martgage Company,73 W Barstow Ave,Arlington Heights,Cook,IL,60004,847-353-2156,847-613-5866,wacuff@gmail.com,http://www.advantagemartgagecompany.com +Shalon,Shadrick,Germer And Gertz Llp,61047 Mayfield Ave,Brooklyn,Kings,NY,11223,718-232-2337,718-394-4974,shalon@cox.net,http://www.germerandgertzllp.com +Denise,Patak,Spence Law Offices,2139 Santa Rosa Ave,Orlando,Orange,FL,32801,407-446-4358,407-808-3254,denise@patak.org,http://www.spencelawoffices.com +Louvenia,Beech,John Ortiz Nts Therapy Center,598 43rd St,Beverly Hills,Los Angeles,CA,90210,310-820-2117,310-652-2379,louvenia.beech@beech.com,http://www.johnortizntstherapycenter.com +Audry,Yaw,Mike Uchrin Htg & Air Cond Inc,70295 Pioneer Ct,Brandon,Hillsborough,FL,33511,813-797-4816,813-744-7100,audry.yaw@yaw.org,http://www.mikeuchrinhtgaircondinc.com +Kristel,Ehmann,"Mccoy, Joy Reynolds Esq",92899 Kalakaua Ave,El Paso,El Paso,TX,79925,915-452-1290,915-300-6100,kristel.ehmann@aol.com,http://www.mccoyjoyreynoldsesq.com +Vincenza,Zepp,Kbor 1600 Am,395 S 6th St #2,El Cajon,San Diego,CA,92020,619-603-5125,619-935-6661,vzepp@gmail.com,http://www.kboram.com +Elouise,Gwalthney,Quality Inn Northwest,9506 Edgemore Ave,Bladensburg,Prince Georges,MD,20710,301-841-5012,301-591-3034,egwalthney@yahoo.com,http://www.qualityinnnorthwest.com +Venita,Maillard,Wallace Church Assoc Inc,72119 S Walker Ave #63,Anaheim,Orange,CA,92801,714-523-6653,714-663-9740,venita_maillard@gmail.com,http://www.wallacechurchassocinc.com +Kasandra,Semidey,Can Tron,369 Latham St #500,Saint Louis,Saint Louis City,MO,63102,314-732-9131,314-697-3652,kasandra_semidey@semidey.com,http://www.cantron.com +Xochitl,Discipio,Ravaal Enterprises Inc,3158 Runamuck Pl,Round Rock,Williamson,TX,78664,512-233-1831,512-942-3411,xdiscipio@gmail.com,http://www.ravaalenterprisesinc.com +Maile,Linahan,Thompson Steel Company Inc,9 Plainsboro Rd #598,Greensboro,Guilford,NC,27409,336-670-2640,336-364-6037,mlinahan@yahoo.com,http://www.thompsonsteelcompanyinc.com +Krissy,Rauser,"Anderson, Mark A Esq",8728 S Broad St,Coram,Suffolk,NY,11727,631-443-4710,631-288-2866,krauser@cox.net,http://www.andersonmarkaesq.com +Pete,Dubaldi,Womack & Galich,2215 Prosperity Dr,Lyndhurst,Bergen,NJ,7071,201-825-2514,201-749-8866,pdubaldi@hotmail.com,http://www.womackgalich.com +Linn,Paa,Valerie & Company,1 S Pine St,Memphis,Shelby,TN,38112,901-412-4381,901-573-9024,linn_paa@paa.com,http://www.valeriecompany.com +Paris,Wide,Gehring Pumps Inc,187 Market St,Atlanta,Fulton,GA,30342,404-505-4445,404-607-8435,paris@hotmail.com,http://www.gehringpumpsinc.com +Wynell,Dorshorst,"Haehnel, Craig W Esq",94290 S Buchanan St,Pacifica,San Mateo,CA,94044,650-473-1262,650-749-9879,wynell_dorshorst@dorshorst.org,http://www.haehnelcraigwesq.com +Quentin,Birkner,Spoor Behrins Campbell & Young,7061 N 2nd St,Burnsville,Dakota,MN,55337,952-702-7993,952-314-5871,qbirkner@aol.com,http://www.spoorbehrinscampbellyoung.com +Regenia,Kannady,Ken Jeter Store Equipment Inc,10759 Main St,Scottsdale,Maricopa,AZ,85260,480-726-1280,480-205-5121,regenia.kannady@cox.net,http://www.kenjeterstoreequipmentinc.com +Sheron,Louissant,"Potter, Brenda J Cpa",97 E 3rd St #9,Long Island City,Queens,NY,11101,718-976-8610,718-613-9994,sheron@aol.com,http://www.potterbrendajcpa.com +Izetta,Funnell,Baird Kurtz & Dobson,82 Winsor St #54,Atlanta,Dekalb,GA,30340,770-844-3447,770-584-4119,izetta.funnell@hotmail.com,http://www.bairdkurtzdobson.com +Rodolfo,Butzen,"Minor, Cynthia A Esq",41 Steel Ct,Northfield,Rice,MN,55057,507-210-3510,507-590-5237,rodolfo@hotmail.com,http://www.minorcynthiaaesq.com +Zona,Colla,"Solove, Robert A Esq",49440 Dearborn St,Norwalk,Fairfield,CT,6854,203-461-1949,203-938-2557,zona@hotmail.com,http://www.soloverobertaesq.com +Serina,Zagen,Mark Ii Imports Inc,7 S Beverly Dr,Fort Wayne,Allen,IN,46802,260-273-3725,260-382-4869,szagen@aol.com,http://www.markiiimportsinc.com +Paz,Sahagun,White Sign Div Ctrl Equip Co,919 Wall Blvd,Meridian,Lauderdale,MS,39307,601-927-8287,601-249-4511,paz_sahagun@cox.net,http://www.whitesigndivctrlequipco.com +Markus,Lukasik,M & M Store Fixtures Co Inc,89 20th St E #779,Sterling Heights,Macomb,MI,48310,586-970-7380,586-247-1614,markus@yahoo.com,http://www.mmstorefixturescoinc.com +Jaclyn,Bachman,Judah Caster & Wheel Co,721 Interstate 45 S,Colorado Springs,El Paso,CO,80919,719-853-3600,719-223-2074,jaclyn@aol.com,http://www.judahcasterwheelco.com +Cyril,Daufeldt,Galaxy International Inc,3 Lawton St,New York,New York,NY,10013,212-745-8484,212-422-5427,cyril_daufeldt@daufeldt.com,http://www.galaxyinternationalinc.com +Gayla,Schnitzler,Sigma Corp Of America,38 Pleasant Hill Rd,Hayward,Alameda,CA,94545,510-686-3407,510-441-4055,gschnitzler@gmail.com,http://www.sigmacorpofamerica.com +Erick,Nievas,"Soward, Anne Esq",45 E Acacia Ct,Chicago,Cook,IL,60624,773-704-9903,773-359-6109,erick_nievas@aol.com,http://www.sowardanneesq.com +Jennie,Drymon,"Osborne, Michelle M Esq",63728 Poway Rd #1,Scranton,Lackawanna,PA,18509,570-218-4831,570-868-8688,jennie@cox.net,http://www.osbornemichellemesq.com +Mitsue,Scipione,Students In Free Entrprs Natl,77 222 Dr,Oroville,Butte,CA,95965,530-986-9272,530-399-3254,mscipione@scipione.com,http://www.studentsinfreeentrprsnatl.com +Ciara,Ventura,"Johnson, Robert M Esq",53 W Carey St,Port Jervis,Orange,NY,12771,845-823-8877,845-694-7919,cventura@yahoo.com,http://www.johnsonrobertmesq.com +Galen,Cantres,Del Charro Apartments,617 Nw 36th Ave,Brook Park,Cuyahoga,OH,44142,216-600-6111,216-871-6876,galen@yahoo.com,http://www.delcharroapartments.com +Truman,Feichtner,Legal Search Inc,539 Coldwater Canyon Ave,Bloomfield,Essex,NJ,7003,973-852-2736,973-473-5108,tfeichtner@yahoo.com,http://www.legalsearchinc.com +Gail,Kitty,Service Supply Co Inc,735 Crawford Dr,Anchorage,Anchorage,AK,99501,907-435-9166,907-770-3542,gail@kitty.com,http://www.servicesupplycoinc.com +Dalene,Schoeneck,"Sameshima, Douglas J Esq",910 Rahway Ave,Philadelphia,Philadelphia,PA,19102,215-268-1275,215-380-8820,dalene@schoeneck.org,http://www.sameshimadouglasjesq.com +Gertude,Witten,"Thompson, John Randolph Jr",7 Tarrytown Rd,Cincinnati,Hamilton,OH,45217,513-977-7043,513-863-9471,gertude.witten@gmail.com,http://www.thompsonjohnrandolphjr.com +Lizbeth,Kohl,E T Balancing Co Inc,35433 Blake St #588,Gardena,Los Angeles,CA,90248,310-699-1222,310-955-5788,lizbeth@yahoo.com,http://www.etbalancingcoinc.com +Glenn,Berray,"Griswold, John E Esq",29 Cherry St #7073,Des Moines,Polk,IA,50315,515-370-7348,515-372-1738,gberray@gmail.com,http://www.griswoldjohneesq.com +Lashandra,Klang,Acqua Group,810 N La Brea Ave,King of Prussia,Montgomery,PA,19406,610-809-1818,610-378-7332,lashandra@yahoo.com,http://www.acquagroup.com +Lenna,Newville,"Brooks, Morris J Jr",987 Main St,Raleigh,Wake,NC,27601,919-623-2524,919-254-5987,lnewville@newville.com,http://www.brooksmorrisjjr.com +Laurel,Pagliuca,Printing Images Corp,36 Enterprise St Se,Richland,Benton,WA,99352,509-695-5199,509-595-6485,laurel@yahoo.com,http://www.printingimagescorp.com +Mireya,Frerking,Roberts Supply Co Inc,8429 Miller Rd,Pelham,Westchester,NY,10803,914-868-5965,914-883-3061,mireya.frerking@hotmail.com,http://www.robertssupplycoinc.com +Annelle,Tagala,Vico Products Mfg Co,5 W 7th St,Parkville,Baltimore,MD,21234,410-757-1035,410-234-2267,annelle@yahoo.com,http://www.vicoproductsmfgco.com +Dean,Ketelsen,J M Custom Design Millwork,2 Flynn Rd,Hicksville,Nassau,NY,11801,516-847-4418,516-732-6649,dean_ketelsen@gmail.com,http://www.jmcustomdesignmillwork.com +Levi,Munis,Farrell & Johnson Office Equip,2094 Ne 36th Ave,Worcester,Worcester,MA,1603,508-456-4907,508-658-7802,levi.munis@gmail.com,http://www.farrelljohnsonofficeequip.com +Sylvie,Ryser,Millers Market & Deli,649 Tulane Ave,Tulsa,Tulsa,OK,74105,918-644-9555,918-565-1706,sylvie@aol.com,http://www.millersmarketdeli.com +Sharee,Maile,Holiday Inn Naperville,2094 Montour Blvd,Muskegon,Muskegon,MI,49442,231-467-9978,231-265-6940,sharee_maile@aol.com,http://www.holidayinnnaperville.com +Cordelia,Storment,"Burrows, Jon H Esq",393 Hammond Dr,Lafayette,Lafayette,LA,70506,337-566-6001,337-255-3427,cordelia_storment@aol.com,http://www.burrowsjonhesq.com +Mollie,Mcdoniel,Dock Seal Specialty,8590 Lake Lizzie Dr,Bowling Green,Wood,OH,43402,419-975-3182,419-417-4674,mollie_mcdoniel@yahoo.com,http://www.docksealspecialty.com +Brett,Mccullan,Five Star Limousines Of Tx Inc,87895 Concord Rd,La Mesa,San Diego,CA,91942,619-461-9984,619-727-3892,brett.mccullan@mccullan.com,http://www.fivestarlimousinesoftxinc.com +Teddy,Pedrozo,"Barkan, Neal J Esq",46314 Route 130,Bridgeport,Fairfield,CT,6610,203-892-3863,203-918-3939,teddy_pedrozo@aol.com,http://www.barkannealjesq.com +Tasia,Andreason,"Campbell, Robert A",4 Cowesett Ave,Kearny,Hudson,NJ,7032,201-920-9002,201-969-7063,tasia_andreason@yahoo.com,http://www.campbellroberta.com +Hubert,Walthall,"Dee, Deanna",95 Main Ave #2,Barberton,Summit,OH,44203,330-903-1345,330-566-8898,hubert@walthall.org,http://www.deedeanna.com +Arthur,Farrow,"Young, Timothy L Esq",28 S 7th St #2824,Englewood,Bergen,NJ,7631,201-238-5688,201-772-4377,arthur.farrow@yahoo.com,http://www.youngtimothylesq.com +Vilma,Berlanga,"Wells, D Fred Esq",79 S Howell Ave,Grand Rapids,Kent,MI,49546,616-737-3085,616-568-4113,vberlanga@berlanga.com,http://www.wellsdfredesq.com +Billye,Miro,"Gray, Francine H Esq",36 Lancaster Dr Se,Pearl,Rankin,MS,39208,601-567-5386,601-637-5479,billye_miro@cox.net,http://www.grayfrancinehesq.com +Glenna,Slayton,Toledo Iv Care,2759 Livingston Ave,Memphis,Shelby,TN,38118,901-640-9178,901-869-4314,glenna_slayton@cox.net,http://www.toledoivcare.com +Mitzie,Hudnall,Cangro Transmission Co,17 Jersey Ave,Englewood,Arapahoe,CO,80110,303-402-1940,303-997-7760,mitzie_hudnall@yahoo.com,http://www.cangrotransmissionco.com +Bernardine,Rodefer,Sat Poly Inc,2 W Grand Ave,Memphis,Shelby,TN,38112,901-901-4726,901-739-5892,bernardine_rodefer@yahoo.com,http://www.satpolyinc.com +Staci,Schmaltz,Midwest Contracting & Mfg Inc,18 Coronado Ave #563,Pasadena,Los Angeles,CA,91106,626-866-2339,626-293-7678,staci_schmaltz@aol.com,http://www.midwestcontractingmfginc.com +Nichelle,Meteer,Print Doctor,72 Beechwood Ter,Chicago,Cook,IL,60657,773-225-9985,773-857-2231,nichelle_meteer@meteer.com,http://www.printdoctor.com +Janine,Rhoden,Nordic Group Inc,92 Broadway,Astoria,Queens,NY,11103,718-228-5894,718-728-5051,jrhoden@yahoo.com,http://www.nordicgroupinc.com +Ettie,Hoopengardner,Jackson Millwork Co,39 Franklin Ave,Richland,Benton,WA,99352,509-755-5393,509-847-3352,ettie.hoopengardner@hotmail.com,http://www.jacksonmillworkco.com +Eden,Jayson,Harris Corporation,4 Iwaena St,Baltimore,Baltimore City,MD,21202,410-890-7866,410-429-4888,eden_jayson@yahoo.com,http://www.harriscorporation.com +Lynelle,Auber,United Cerebral Palsy Of Ne Pa,32820 Corkwood Rd,Newark,Essex,NJ,7104,973-860-8610,973-605-6492,lynelle_auber@gmail.com,http://www.unitedcerebralpalsyofnepa.com +Merissa,Tomblin,One Day Surgery Center Inc,34 Raritan Center Pky,Bellflower,Los Angeles,CA,90706,562-579-6900,562-719-7922,merissa.tomblin@gmail.com,http://www.onedaysurgerycenterinc.com +Golda,Kaniecki,Calaveras Prospect,6201 S Nevada Ave,Toms River,Ocean,NJ,8755,732-628-9909,732-617-5310,golda_kaniecki@yahoo.com,http://www.calaverasprospect.com +Catarina,Gleich,"Terk, Robert E Esq",78 Maryland Dr #146,Denville,Morris,NJ,7834,973-210-3994,973-491-8723,catarina_gleich@hotmail.com,http://www.terkroberteesq.com +Virgie,Kiel,"Cullen, Terrence P Esq",76598 Rd I 95 #1,Denver,Denver,CO,80216,303-776-7548,303-845-5408,vkiel@hotmail.com,http://www.cullenterrencepesq.com +Jolene,Ostolaza,Central Die Casting Mfg Co Inc,1610 14th St Nw,Newport News,Newport News City,VA,23608,757-682-7116,757-940-1741,jolene@yahoo.com,http://www.centraldiecastingmfgcoinc.com +Keneth,Borgman,Centerline Engineering,86350 Roszel Rd,Phoenix,Maricopa,AZ,85012,602-919-4211,602-442-3092,keneth@yahoo.com,http://www.centerlineengineering.com +Rikki,Nayar,Targan & Kievit Pa,1644 Clove Rd,Miami,Miami-Dade,FL,33155,305-968-9487,305-978-2069,rikki@nayar.com,http://www.targankievitpa.com +Elke,Sengbusch,Riley Riper Hollin & Colagreco,9 W Central Ave,Phoenix,Maricopa,AZ,85013,602-896-2993,602-575-3457,elke_sengbusch@yahoo.com,http://www.rileyriperhollincolagreco.com +Hoa,Sarao,"Kaplan, Joel S Esq",27846 Lafayette Ave,Oak Hill,Volusia,FL,32759,386-526-7800,386-599-7296,hoa@sarao.org,http://www.kaplanjoelsesq.com +Trinidad,Mcrae,Water Office,10276 Brooks St,San Francisco,San Francisco,CA,94105,415-331-9634,415-419-1597,trinidad_mcrae@yahoo.com,http://www.wateroffice.com +Mari,Lueckenbach,"Westbrooks, Nelson E Jr",1 Century Park E,San Diego,San Diego,CA,92110,858-793-9684,858-228-5683,mari_lueckenbach@yahoo.com,http://www.westbrooksnelsonejr.com +Selma,Husser,Armon Communications,9 State Highway 57 #22,Jersey City,Hudson,NJ,7306,201-991-8369,201-772-7699,selma.husser@cox.net,http://www.armoncommunications.com +Antione,Onofrio,Jacobs & Gerber Inc,4 S Washington Ave,San Bernardino,San Bernardino,CA,92410,909-430-7765,909-665-3223,aonofrio@onofrio.com,http://www.jacobsgerberinc.com +Luisa,Jurney,Forest Fire Laboratory,25 Se 176th Pl,Cambridge,Middlesex,MA,2138,617-365-2134,617-544-2541,ljurney@hotmail.com,http://www.forestfirelaboratory.com +Clorinda,Heimann,"Haughey, Charles Jr",105 Richmond Valley Rd,Escondido,San Diego,CA,92025,760-291-5497,760-261-4786,clorinda.heimann@hotmail.com,http://www.haugheycharlesjr.com +Dick,Wenzinger,Wheaton Plastic Products,22 Spruce St #595,Gardena,Los Angeles,CA,90248,310-510-9713,310-936-2258,dick@yahoo.com,http://www.wheatonplasticproducts.com +Ahmed,Angalich,Reese Plastics,2 W Beverly Blvd,Harrisburg,Dauphin,PA,17110,717-528-8996,717-632-5831,ahmed.angalich@angalich.com,http://www.reeseplastics.com +Iluminada,Ohms,Nazette Marner Good Wendt,72 Southern Blvd,Mesa,Maricopa,AZ,85204,480-293-2882,480-866-6544,iluminada.ohms@yahoo.com,http://www.nazettemarnergoodwendt.com +Joanna,Leinenbach,Levinson Axelrod Wheaton,1 Washington St,Lake Worth,Palm Beach,FL,33461,561-470-4574,561-951-9734,joanna_leinenbach@hotmail.com,http://www.levinsonaxelrodwheaton.com +Caprice,Suell,"Egnor, W Dan Esq",90177 N 55th Ave,Nashville,Davidson,TN,37211,615-246-1824,615-726-4537,caprice@aol.com,http://www.egnorwdanesq.com +Stephane,Myricks,Portland Central Thriftlodge,9 Tower Ave,Burlington,Boone,KY,41005,859-717-7638,859-308-4286,stephane_myricks@cox.net,http://www.portlandcentralthriftlodge.com +Quentin,Swayze,Ulbrich Trucking,278 Bayview Ave,Milan,Monroe,MI,48160,734-561-6170,734-851-8571,quentin_swayze@yahoo.com,http://www.ulbrichtrucking.com +Annmarie,Castros,Tipiak Inc,80312 W 32nd St,Conroe,Montgomery,TX,77301,936-751-7961,936-937-2334,annmarie_castros@gmail.com,http://www.tipiakinc.com +Shonda,Greenbush,Saint George Well Drilling,82 Us Highway 46,Clifton,Passaic,NJ,7011,973-482-2430,973-644-2974,shonda_greenbush@cox.net,http://www.saintgeorgewelldrilling.com +Cecil,Lapage,"Hawkes, Douglas D",4 Stovall St #72,Union City,Hudson,NJ,7087,201-693-3967,201-856-2720,clapage@lapage.com,http://www.hawkesdouglasd.com +Jeanice,Claucherty,Accurel Systems Intrntl Corp,19 Amboy Ave,Miami,Miami-Dade,FL,33142,305-988-4162,305-306-7834,jeanice.claucherty@yahoo.com,http://www.accurelsystemsintrntlcorp.com +Josphine,Villanueva,Santa Cruz Community Internet,63 Smith Ln #8343,Moss,Clay,TN,38575,931-553-9774,931-486-6946,josphine_villanueva@villanueva.com,http://www.santacruzcommunityinternet.com +Daniel,Perruzza,Gersh & Danielson,11360 S Halsted St,Santa Ana,Orange,CA,92705,714-771-3880,714-531-1391,dperruzza@perruzza.com,http://www.gershdanielson.com +Cassi,Wildfong,"Cobb, James O Esq",26849 Jefferson Hwy,Rolling Meadows,Cook,IL,60008,847-633-3216,847-755-9041,cassi.wildfong@aol.com,http://www.cobbjamesoesq.com +Britt,Galam,Wheatley Trucking Company,2500 Pringle Rd Se #508,Hatfield,Montgomery,PA,19440,215-888-3304,215-351-8523,britt@galam.org,http://www.wheatleytruckingcompany.com +Adell,Lipkin,Systems Graph Inc Ab Dick Dlr,65 Mountain View Dr,Whippany,Morris,NJ,7981,973-654-1561,973-662-8988,adell.lipkin@lipkin.com,http://www.systemsgraphincabdickdlr.com +Jacqueline,Rowling,John Hancock Mutl Life Ins Co,1 N San Saba,Erie,Erie,PA,16501,814-865-8113,814-481-1700,jacqueline.rowling@yahoo.com,http://www.johnhancockmutllifeinsco.com +Lonny,Weglarz,History Division Of State,51120 State Route 18,Salt Lake City,Salt Lake,UT,84115,801-293-9853,801-892-8781,lonny_weglarz@gmail.com,http://www.historydivisionofstate.com +Lonna,Diestel,"Dimmock, Thomas J Esq",1482 College Ave,Fayetteville,Cumberland,NC,28301,910-922-3672,910-200-7912,lonna_diestel@gmail.com,http://www.dimmockthomasjesq.com +Cristal,Samara,Intermed Inc,4119 Metropolitan Dr,Los Angeles,Los Angeles,CA,90021,213-975-8026,213-696-8004,cristal@cox.net,http://www.intermedinc.com +Kenneth,Grenet,Bank Of New York,2167 Sierra Rd,East Lansing,Ingham,MI,48823,517-499-2322,517-867-8077,kenneth.grenet@grenet.org,http://www.bankofnewyork.com +Elli,Mclaird,Sportmaster Intrnatl,6 Sunrise Ave,Utica,Oneida,NY,13501,315-818-2638,315-474-5570,emclaird@mclaird.com,http://www.sportmasterintrnatl.com +Alline,Jeanty,W W John Holden Inc,55713 Lake City Hwy,South Bend,St Joseph,IN,46601,574-656-2800,574-405-1983,ajeanty@gmail.com,http://www.wwjohnholdeninc.com +Sharika,Eanes,Maccani & Delp,75698 N Fiesta Blvd,Orlando,Orange,FL,32806,407-312-1691,407-472-1332,sharika.eanes@aol.com,http://www.maccanidelp.com +Nu,Mcnease,Amazonia Film Project,88 Sw 28th Ter,Harrison,Hudson,NJ,7029,973-751-9003,973-903-4175,nu@gmail.com,http://www.amazoniafilmproject.com +Daniela,Comnick,Water & Sewer Department,7 Flowers Rd #403,Trenton,Mercer,NJ,8611,609-200-8577,609-398-2805,dcomnick@cox.net,http://www.watersewerdepartment.com +Cecilia,Colaizzo,Switchcraft Inc,4 Nw 12th St #3849,Madison,Dane,WI,53717,608-382-4541,608-302-3387,cecilia_colaizzo@colaizzo.com,http://www.switchcraftinc.com +Leslie,Threets,C W D C Metal Fabricators,2 A Kelley Dr,Katonah,Westchester,NY,10536,914-861-9748,914-396-2615,leslie@cox.net,http://www.cwdcmetalfabricators.com +Nan,Koppinger,"Shimotani, Grace T",88827 Frankford Ave,Greensboro,Guilford,NC,27401,336-370-5333,336-564-1492,nan@koppinger.com,http://www.shimotanigracet.com +Izetta,Dewar,"Lisatoni, Jean Esq",2 W Scyene Rd #3,Baltimore,Baltimore City,MD,21217,410-473-1708,410-522-7621,idewar@dewar.com,http://www.lisatonijeanesq.com +Tegan,Arceo,Ceramic Tile Sales Inc,62260 Park Stre,Monroe Township,Middlesex,NJ,8831,732-730-2692,732-705-6719,tegan.arceo@arceo.org,http://www.ceramictilesalesinc.com +Ruthann,Keener,Maiden Craft Inc,3424 29th St Se,Kerrville,Kerr,TX,78028,830-258-2769,830-919-5991,ruthann@hotmail.com,http://www.maidencraftinc.com +Joni,Breland,Carriage House Cllsn Rpr Inc,35 E Main St #43,Elk Grove Village,Cook,IL,60007,847-519-5906,847-740-5304,joni_breland@cox.net,http://www.carriagehousecllsnrprinc.com +Vi,Rentfro,Video Workshop,7163 W Clark Rd,Freehold,Monmouth,NJ,7728,732-605-4781,732-724-7251,vrentfro@cox.net,http://www.videoworkshop.com +Colette,Kardas,Fresno Tile Center Inc,21575 S Apple Creek Rd,Omaha,Douglas,NE,68124,402-896-5943,402-707-1602,colette.kardas@yahoo.com,http://www.fresnotilecenterinc.com +Malcolm,Tromblay,Versatile Sash & Woodwork,747 Leonis Blvd,Annandale,Fairfax,VA,22003,703-221-5602,703-874-4248,malcolm_tromblay@cox.net,http://www.versatilesashwoodwork.com +Ryan,Harnos,Warner Electric Brk & Cltch Co,13 Gunnison St,Plano,Collin,TX,75075,972-558-1665,972-961-4968,ryan@cox.net,http://www.warnerelectricbrkcltchco.com +Jess,Chaffins,New York Public Library,18 3rd Ave,New York,New York,NY,10016,212-510-4633,212-428-9538,jess.chaffins@chaffins.org,http://www.newyorkpubliclibrary.com +Sharen,Bourbon,"Mccaleb, John A Esq",62 W Austin St,Syosset,Nassau,NY,11791,516-816-1541,516-749-3188,sbourbon@yahoo.com,http://www.mccalebjohnaesq.com +Nickolas,Juvera,United Oil Co Inc,177 S Rider Trl #52,Crystal River,Citrus,FL,34429,352-598-8301,352-947-6152,nickolas_juvera@cox.net,http://www.unitedoilcoinc.com +Gary,Nunlee,Irving Foot Center,2 W Mount Royal Ave,Fortville,Hancock,IN,46040,317-542-6023,317-887-8486,gary_nunlee@nunlee.org,http://www.irvingfootcenter.com +Diane,Devreese,Acme Supply Co,1953 Telegraph Rd,Saint Joseph,Buchanan,MO,64504,816-557-9673,816-329-5565,diane@cox.net,http://www.acmesupplyco.com +Roslyn,Chavous,"Mcrae, James L",63517 Dupont St,Jackson,Hinds,MS,39211,601-234-9632,601-973-5754,roslyn.chavous@chavous.org,http://www.mcraejamesl.com +Glory,Schieler,Mcgraths Seafood,5 E Truman Rd,Abilene,Taylor,TX,79602,325-869-2649,325-740-3778,glory@yahoo.com,http://www.mcgrathsseafood.com +Rasheeda,Sayaphon,"Kummerer, J Michael Esq",251 Park Ave #979,Saratoga,Santa Clara,CA,95070,408-805-4309,408-997-7490,rasheeda@aol.com,http://www.kummererjmichaelesq.com +Alpha,Palaia,"Stoffer, James M Jr",43496 Commercial Dr #29,Cherry Hill,Camden,NJ,8003,856-312-2629,856-513-7024,alpha@yahoo.com,http://www.stofferjamesmjr.com +Refugia,Jacobos,North Central Fl Sfty Cncl,2184 Worth St,Hayward,Alameda,CA,94545,510-974-8671,510-509-3496,refugia.jacobos@jacobos.com,http://www.northcentralflsftycncl.com +Shawnda,Yori,Fiorucci Foods Usa Inc,50126 N Plankinton Ave,Longwood,Seminole,FL,32750,407-538-5106,407-564-8113,shawnda.yori@yahoo.com,http://www.fioruccifoodsusainc.com +Mona,Delasancha,Sign All,38773 Gravois Ave,Cheyenne,Laramie,WY,82001,307-403-1488,307-816-7115,mdelasancha@hotmail.com,http://www.signall.com +Gilma,Liukko,Sammys Steak Den,16452 Greenwich St,Garden City,Nassau,NY,11530,516-393-9967,516-407-9573,gilma_liukko@gmail.com,http://www.sammyssteakden.com +Janey,Gabisi,"Dobscha, Stephen F Esq",40 Cambridge Ave,Madison,Dane,WI,53715,608-967-7194,608-586-6912,jgabisi@hotmail.com,http://www.dobschastephenfesq.com +Lili,Paskin,Morgan Custom Homes,20113 4th Ave E,Kearny,Hudson,NJ,7032,201-431-2989,201-478-8540,lili.paskin@cox.net,http://www.morgancustomhomes.com +Loren,Asar,Olsen Payne & Company,6 Ridgewood Center Dr,Old Forge,Lackawanna,PA,18518,570-648-3035,570-569-2356,loren.asar@aol.com,http://www.olsenpaynecompany.com +Dorothy,Chesterfield,Cowan & Kelly,469 Outwater Ln,San Diego,San Diego,CA,92126,858-617-7834,858-732-1884,dorothy@cox.net,http://www.cowankelly.com +Gail,Similton,"Johnson, Wes Esq",62 Monroe St,Thousand Palms,Riverside,CA,92276,760-616-5388,760-493-9208,gail_similton@similton.com,http://www.johnsonwesesq.com +Catalina,Tillotson,Icn Pharmaceuticals Inc,3338 A Lockport Pl #6,Margate City,Atlantic,NJ,8402,609-373-3332,609-826-4990,catalina@hotmail.com,http://www.icnpharmaceuticalsinc.com +Lawrence,Lorens,New England Sec Equip Co Inc,9 Hwy,Providence,Providence,RI,2906,401-465-6432,401-893-1820,lawrence.lorens@hotmail.com,http://www.newenglandsecequipcoinc.com +Carlee,Boulter,"Tippett, Troy M Ii",8284 Hart St,Abilene,Dickinson,KS,67410,785-347-1805,785-253-7049,carlee.boulter@hotmail.com,http://www.tippetttroymii.com +Thaddeus,Ankeny,Atc Contracting,5 Washington St #1,Roseville,Placer,CA,95678,916-920-3571,916-459-2433,tankeny@ankeny.org,http://www.atccontracting.com +Jovita,Oles,"Pagano, Philip G Esq",8 S Haven St,Daytona Beach,Volusia,FL,32114,386-248-4118,386-208-6976,joles@gmail.com,http://www.paganophilipgesq.com +Alesia,Hixenbaugh,Kwikprint,9 Front St,Washington,District of Columbia,DC,20001,202-646-7516,202-276-6826,alesia_hixenbaugh@hixenbaugh.org,http://www.kwikprint.com +Lai,Harabedian,Buergi & Madden Scale,1933 Packer Ave #2,Novato,Marin,CA,94945,415-423-3294,415-926-6089,lai@gmail.com,http://www.buergimaddenscale.com +Brittni,Gillaspie,Inner Label,67 Rv Cent,Boise,Ada,ID,83709,208-709-1235,208-206-9848,bgillaspie@gillaspie.com,http://www.innerlabel.com +Raylene,Kampa,Hermar Inc,2 Sw Nyberg Rd,Elkhart,Elkhart,IN,46514,574-499-1454,574-330-1884,rkampa@kampa.org,http://www.hermarinc.com +Flo,Bookamer,Simonton Howe & Schneider Pc,89992 E 15th St,Alliance,Box Butte,NE,69301,308-726-2182,308-250-6987,flo.bookamer@cox.net,http://www.simontonhoweschneiderpc.com +Jani,Biddy,Warehouse Office & Paper Prod,61556 W 20th Ave,Seattle,King,WA,98104,206-711-6498,206-395-6284,jbiddy@yahoo.com,http://www.warehouseofficepaperprod.com +Chauncey,Motley,Affiliated With Travelodge,63 E Aurora Dr,Orlando,Orange,FL,32804,407-413-4842,407-557-8857,chauncey_motley@aol.com,http://www.affiliatedwithtravelodge.com \ No newline at end of file diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/README.md b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/README.md new file mode 100755 index 0000000000..960fbc1bc1 --- /dev/null +++ b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/README.md @@ -0,0 +1,2 @@ +# javaSNSLambdaDynamoDB +Java samples for SNS --> Lambda --> DynamoDB From 537ae873e657e65787ecbb8754e96d85c02c5a54 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Sat, 11 Jul 2026 17:13:30 -0700 Subject: [PATCH 02/20] Added pattern lambda-durable-java-sam --- .../DEVELOPER_GUIDE.md | 0 .../JavaLambdaDurableFunctions/.gitignore | 13 - .../README.md | 107 ++-- .../USER_GUIDE.md | 2 +- .../build-and-deploy.sh | 0 .../durable-functions/Dockerfile | 0 .../durable-functions/pom.xml | 0 .../chaining/OrderProcessingHandler.java | 0 .../ResilientPaymentHandler.java | 0 .../fanout/ParallelProcessingHandler.java | 0 .../ApprovalWorkflowHandler.java | 0 .../BatchDataProcessorHandler.java | 0 .../samples/durable/models/OrderItem.java | 0 .../samples/durable/models/OrderRequest.java | 0 .../durable/models/ProcessingResult.java | 0 .../durable/monitoring/JobMonitorHandler.java | 0 .../OrderFulfillmentHandler.java | 0 .../timer/ScheduledReminderHandler.java | 0 .../events/approval-event.json | 0 .../events/chaining-event.json | 0 .../events/errorhandling-event.json | 0 .../events/fanout-event.json | 0 .../events/mapprocessing-event.json | 0 .../events/monitoring-event.json | 0 .../events/suborchestration-event.json | 0 .../events/timer-event.json | 0 .../durable-functions-sam/template.yaml | 0 .../infrastructure/ec2-client-instance.yaml | 2 +- .../javaSNSLambdaDynamoDB/.gitignore | 24 - .../sns_consumer_dynamo_sam/.gitignore | 25 - .../sns_consumer_dynamo_sam/README.md | 95 ---- .../sns_consumer_dynamo_sam/events/event.json | 31 -- .../sns_event_consumer_function/.gitignore | 1 - .../.settings/org.eclipse.jdt.core.prefs | 8 - .../sns_event_consumer_function/pom.xml | 89 ---- .../samples/events/sns/DynamoDBUpdater.java | 79 --- .../lambda/samples/events/sns/HandlerSNS.java | 84 --- .../lambda/samples/events/sns/Person.java | 138 ----- .../events/sns/DynamoDBUpdaterTest.java | 105 ---- .../samples/events/sns/HandlerSNSTest.java | 73 --- .../samples/events/sns/TestContext.java | 45 -- .../lambda/samples/events/sns/TestLogger.java | 14 - .../sns_consumer_dynamo_sam/template.yaml | 78 --- .../sns_message_sender_json/.classpath | 38 -- .../sns_message_sender_json/.gitignore | 1 - .../sns_message_sender_json/.project | 23 - .../org.eclipse.core.resources.prefs | 6 - .../.settings/org.eclipse.jdt.core.prefs | 8 - .../sns_message_sender_json/Commands | 4 - .../sns_message_sender_json/pom.xml | 73 --- .../java/sns/producer/JsonSNSProducer.java | 143 ----- .../src/main/java/sns/producer/Person.java | 133 ----- .../src/main/resources/us-500.csv | 500 ------------------ .../javaSNSLambdaDynamoDB/README.md | 2 - .../sns-message-sender/pom.xml | 0 .../sns/producer/DurableFunctionsTrigger.java | 0 56 files changed, 78 insertions(+), 1866 deletions(-) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/DEVELOPER_GUIDE.md (100%) delete mode 100644 lambda-durable-java-sam/JavaLambdaDurableFunctions/.gitignore rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/README.md (69%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/USER_GUIDE.md (99%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/build-and-deploy.sh (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/Dockerfile (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/pom.xml (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderItem.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderRequest.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/ProcessingResult.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/events/approval-event.json (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/events/chaining-event.json (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/events/errorhandling-event.json (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/events/fanout-event.json (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/events/mapprocessing-event.json (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/events/monitoring-event.json (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/events/suborchestration-event.json (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/events/timer-event.json (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/durable-functions-sam/template.yaml (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/infrastructure/ec2-client-instance.yaml (99%) delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/.gitignore delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/.gitignore delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/README.md delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/events/event.json delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.gitignore delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.settings/org.eclipse.jdt.core.prefs delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/pom.xml delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdater.java delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNS.java delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/Person.java delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdaterTest.java delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNSTest.java delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestContext.java delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestLogger.java delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/template.yaml delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.classpath delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.gitignore delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.project delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.core.resources.prefs delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.jdt.core.prefs delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/Commands delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/pom.xml delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/JsonSNSProducer.java delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/Person.java delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/resources/us-500.csv delete mode 100755 lambda-durable-java-sam/javaSNSLambdaDynamoDB/README.md rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/sns-message-sender/pom.xml (100%) rename lambda-durable-java-sam/{JavaLambdaDurableFunctions => }/sns-message-sender/src/main/java/sns/producer/DurableFunctionsTrigger.java (100%) diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/DEVELOPER_GUIDE.md b/lambda-durable-java-sam/DEVELOPER_GUIDE.md similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/DEVELOPER_GUIDE.md rename to lambda-durable-java-sam/DEVELOPER_GUIDE.md diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/.gitignore b/lambda-durable-java-sam/JavaLambdaDurableFunctions/.gitignore deleted file mode 100644 index 03d0710633..0000000000 --- a/lambda-durable-java-sam/JavaLambdaDurableFunctions/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -target/ -build/ -.aws-sam/ -*.class -*.jar -*.log -.idea/ -*.iml -.classpath -.project -.settings/ -.DS_Store -dependency-reduced-pom.xml diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/README.md b/lambda-durable-java-sam/README.md similarity index 69% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/README.md rename to lambda-durable-java-sam/README.md index 3944209944..6937fb4ac7 100644 --- a/lambda-durable-java-sam/JavaLambdaDurableFunctions/README.md +++ b/lambda-durable-java-sam/README.md @@ -36,7 +36,13 @@ SNS Topic (Producer) --> Lambda Durable Functions (Consumers) --> DynamoDB (Resu ## Quick Start -### 1. Deploy Infrastructure (Optional - for EC2 dev environment) +You can run this project either from an EC2 instance (Option A) or from your local machine (Option B). + +### Option A: Using the EC2 Dev Environment + +The CloudFormation template deploys a VPC with a public subnet and an EC2 instance pre-configured with Java 21, Maven, Docker, AWS CLI v2, and SAM CLI. The project code is automatically cloned onto the instance. + +**1. Deploy the infrastructure stack:** ```bash aws cloudformation create-stack \ @@ -45,7 +51,44 @@ aws cloudformation create-stack \ --capabilities CAPABILITY_NAMED_IAM ``` -### 2. Build the Durable Functions Container Image +Wait for the stack to complete (~5 minutes): +```bash +aws cloudformation wait stack-create-complete --stack-name durable-functions-infra +``` + +**2. Connect to the instance via EC2 Instance Connect:** + +```bash +INSTANCE_ID=$(aws cloudformation describe-stacks --stack-name durable-functions-infra \ + --query 'Stacks[0].Outputs[?OutputKey==`EC2InstanceId`].OutputValue' --output text) +aws ec2-instance-connect ssh --instance-id $INSTANCE_ID +``` + +**3. Navigate to the project directory:** + +```bash +cd /home/ec2-user/serverless-patterns/lambda-durable-java-sam +``` + +Then continue from [Build and Deploy](#build-and-deploy) below. + +### Option B: Local Development + +Ensure you have Java 21+, Maven 3.8+, Docker, AWS CLI v2, and SAM CLI installed. + +Clone the project: +```bash +git clone https://github.com/aws-samples/serverless-patterns.git +cd serverless-patterns/lambda-durable-java-sam +``` + +Then continue from [Build and Deploy](#build-and-deploy) below. + +--- + +## Build and Deploy + +### 1. Build the Durable Functions Container Image ```bash cd durable-functions-sam/durable-functions @@ -53,7 +96,7 @@ mvn clean package -DskipTests docker build -t durable-functions-java-examples . ``` -### 3. Push to ECR +### 2. Push to ECR ```bash AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) @@ -73,21 +116,21 @@ docker push \ $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/durable-functions-java-examples:latest ``` -### 4. Deploy with SAM +### 3. Deploy with SAM ```bash -cd durable-functions-sam +cd .. sam deploy --guided ``` -### 5. Build the SNS Message Sender +### 4. Build the SNS Message Sender ```bash -cd sns-message-sender +cd ../sns-message-sender mvn clean package ``` -### 6. Trigger a Durable Function +### 5. Trigger a Durable Function ```bash java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ @@ -182,27 +225,29 @@ aws lambda get-durable-execution --function-name durable-chaining-example:1 --ex ``` lambda-durable-java-sam/ -└── JavaLambdaDurableFunctions/ - ├── README.md - ├── infrastructure/ - │ └── ec2-client-instance.yaml # VPC + EC2 CloudFormation template - ├── durable-functions-sam/ - │ ├── template.yaml # SAM template for all Lambda functions - │ └── durable-functions/ - │ ├── pom.xml - │ ├── Dockerfile - │ └── src/main/java/com/amazonaws/samples/durable/ - │ ├── models/ # Shared model classes - │ ├── chaining/ # Pattern 1: Sequential steps - │ ├── fanout/ # Pattern 2: Parallel execution - │ ├── humaninteraction/ # Pattern 3: Callbacks - │ ├── monitoring/ # Pattern 4: Polling - │ ├── timer/ # Pattern 5: Scheduled delays - │ ├── errorhandling/ # Pattern 6: Retries & compensation - │ ├── mapprocessing/ # Pattern 7: Collection processing - │ └── suborchestration/ # Pattern 8: Child contexts - └── sns-message-sender/ - ├── pom.xml - └── src/main/java/sns/producer/ - └── DurableFunctionsTrigger.java +├── README.md +├── USER_GUIDE.md +├── DEVELOPER_GUIDE.md +├── build-and-deploy.sh +├── infrastructure/ +│ └── ec2-client-instance.yaml # VPC + EC2 CloudFormation template +├── durable-functions-sam/ +│ ├── template.yaml # SAM template for all Lambda functions +│ └── durable-functions/ +│ ├── pom.xml +│ ├── Dockerfile +│ └── src/main/java/com/amazonaws/samples/durable/ +│ ├── models/ # Shared model classes +│ ├── chaining/ # Pattern 1: Sequential steps +│ ├── fanout/ # Pattern 2: Parallel execution +│ ├── humaninteraction/ # Pattern 3: Callbacks +│ ├── monitoring/ # Pattern 4: Polling +│ ├── timer/ # Pattern 5: Scheduled delays +│ ├── errorhandling/ # Pattern 6: Retries & compensation +│ ├── mapprocessing/ # Pattern 7: Collection processing +│ └── suborchestration/ # Pattern 8: Child contexts +└── sns-message-sender/ + ├── pom.xml + └── src/main/java/sns/producer/ + └── DurableFunctionsTrigger.java ``` diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/USER_GUIDE.md b/lambda-durable-java-sam/USER_GUIDE.md similarity index 99% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/USER_GUIDE.md rename to lambda-durable-java-sam/USER_GUIDE.md index 3d663f89bd..e53d37c483 100644 --- a/lambda-durable-java-sam/JavaLambdaDurableFunctions/USER_GUIDE.md +++ b/lambda-durable-java-sam/USER_GUIDE.md @@ -76,7 +76,7 @@ sam --version Clone the project: ```bash git clone https://github.com/aws-samples/serverless-patterns.git -cd serverless-patterns/lambda-durable-java-sam/JavaLambdaDurableFunctions +cd serverless-patterns/lambda-durable-java-sam ``` --- diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/build-and-deploy.sh b/lambda-durable-java-sam/build-and-deploy.sh similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/build-and-deploy.sh rename to lambda-durable-java-sam/build-and-deploy.sh diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/Dockerfile b/lambda-durable-java-sam/durable-functions-sam/durable-functions/Dockerfile similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/Dockerfile rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/Dockerfile diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/pom.xml b/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/pom.xml rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderItem.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderItem.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderItem.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderItem.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderRequest.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderRequest.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderRequest.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/OrderRequest.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/ProcessingResult.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/ProcessingResult.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/ProcessingResult.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/ProcessingResult.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java rename to lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/approval-event.json b/lambda-durable-java-sam/durable-functions-sam/events/approval-event.json similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/approval-event.json rename to lambda-durable-java-sam/durable-functions-sam/events/approval-event.json diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/chaining-event.json b/lambda-durable-java-sam/durable-functions-sam/events/chaining-event.json similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/chaining-event.json rename to lambda-durable-java-sam/durable-functions-sam/events/chaining-event.json diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/errorhandling-event.json b/lambda-durable-java-sam/durable-functions-sam/events/errorhandling-event.json similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/errorhandling-event.json rename to lambda-durable-java-sam/durable-functions-sam/events/errorhandling-event.json diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/fanout-event.json b/lambda-durable-java-sam/durable-functions-sam/events/fanout-event.json similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/fanout-event.json rename to lambda-durable-java-sam/durable-functions-sam/events/fanout-event.json diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/mapprocessing-event.json b/lambda-durable-java-sam/durable-functions-sam/events/mapprocessing-event.json similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/mapprocessing-event.json rename to lambda-durable-java-sam/durable-functions-sam/events/mapprocessing-event.json diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/monitoring-event.json b/lambda-durable-java-sam/durable-functions-sam/events/monitoring-event.json similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/monitoring-event.json rename to lambda-durable-java-sam/durable-functions-sam/events/monitoring-event.json diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/suborchestration-event.json b/lambda-durable-java-sam/durable-functions-sam/events/suborchestration-event.json similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/suborchestration-event.json rename to lambda-durable-java-sam/durable-functions-sam/events/suborchestration-event.json diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/timer-event.json b/lambda-durable-java-sam/durable-functions-sam/events/timer-event.json similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/events/timer-event.json rename to lambda-durable-java-sam/durable-functions-sam/events/timer-event.json diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/template.yaml b/lambda-durable-java-sam/durable-functions-sam/template.yaml similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/durable-functions-sam/template.yaml rename to lambda-durable-java-sam/durable-functions-sam/template.yaml diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/infrastructure/ec2-client-instance.yaml b/lambda-durable-java-sam/infrastructure/ec2-client-instance.yaml similarity index 99% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/infrastructure/ec2-client-instance.yaml rename to lambda-durable-java-sam/infrastructure/ec2-client-instance.yaml index 8bfc12fcde..f196ec398d 100644 --- a/lambda-durable-java-sam/JavaLambdaDurableFunctions/infrastructure/ec2-client-instance.yaml +++ b/lambda-durable-java-sam/infrastructure/ec2-client-instance.yaml @@ -234,7 +234,7 @@ Resources: cd ./serverless-patterns git sparse-checkout set --no-cone /lambda-durable-java-sam git checkout - cd lambda-durable-java-sam/JavaLambdaDurableFunctions + cd lambda-durable-java-sam sudo chown -R ec2-user . # Get IP CIDR range for EC2 Instance Connect diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/.gitignore b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/.gitignore deleted file mode 100755 index 524f0963bd..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* -replay_pid* diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/.gitignore b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/.gitignore deleted file mode 100755 index c90d3bd6ee..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/.gitignore +++ /dev/null @@ -1,25 +0,0 @@ -node_modules -npm-debug.log -package-lock.json -package -*out.yml -out.json -bucket-name.txt -target -build -.gradle -*.zip -bin -obj -Gemfile.lock -lib -__pycache__ -*.pyc -.classpath -.factorypath -.project -.settings/* -.aws -.sam -.aws-sam -*.toml diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/README.md b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/README.md deleted file mode 100755 index 5d37d8fa60..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# sns-consumer-dynamo-sam - -This project contains source code and supporting files for a serverless application that you can deploy with the SAM CLI. It includes the following files and folders. - -- sns_event_consumer_function/src/main/java - Code for the application's Lambda function. -- events - Invocation events that you can use to invoke the function. -- sns_event_consumer_function/src/test/java - Unit tests for the application code. -- template.yaml - A template that defines the application's AWS resources. - -The application uses several AWS resources, including a Lambda function, an SNS event source and a DynamoDB table to which the lambda function will write. These resources are defined in the `template.yaml` file in this project. You can update the template to add AWS resources through the same deployment process that updates your application code. - - -## Use the SAM CLI to build and test locally - -Build your application with the `sam build` command. - -```bash -sam build -``` - -The SAM CLI installs dependencies defined in `sns_event_consumer_function/pom.xml`, creates a deployment package, and saves it in the `.aws-sam/build` folder. - -Test a single function by invoking it directly with a test event. An event is a JSON document that represents the input that the function receives from the event source. Test events are included in the `events` folder in this project. - -Run functions locally and invoke them with the `sam local invoke` command. - -```bash -sam local invoke --event events/event.json -``` - -## Deploy the sample application - -The Serverless Application Model Command Line Interface (SAM CLI) is an extension of the AWS CLI that adds functionality for building and testing Lambda applications. It uses Docker to run your functions in an Amazon Linux environment that matches Lambda. It can also emulate your application's build environment and API. - -To use the SAM CLI, you need the following tools. - -* SAM CLI - [Install the SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) -* Docker - [Install Docker community edition](https://hub.docker.com/search/?type=edition&offering=community) - -To build and deploy your application for the first time, run the following in your shell: - -```bash -sam build -sam deploy --guided -``` - -The first command will build the source of your application. The second command will package and deploy your application to AWS, with a series of prompts: - -* **Stack Name**: The name of the stack to deploy to CloudFormation. This should be unique to your account and region, and a good starting point would be something matching your project name. -* **AWS Region**: The AWS region you want to deploy your app to. -* **Parameter SNSTopicName**: The name of the SNS Topic -* **Confirm changes before deploy**: If set to yes, any change sets will be shown to you before execution for manual review. If set to no, the AWS SAM CLI will automatically deploy application changes. -* **Allow SAM CLI IAM role creation**: Many AWS SAM templates, including this example, create AWS IAM roles required for the AWS Lambda function(s) included to access AWS services. By default, these are scoped down to minimum required permissions. To deploy an AWS CloudFormation stack which creates or modifies IAM roles, the `CAPABILITY_IAM` value for `capabilities` must be provided. If permission isn't provided through this prompt, to deploy this example you must explicitly pass `--capabilities CAPABILITY_IAM` to the `sam deploy` command. -* **Disable rollback**: Defaults to No and it preserves the state of previously provisioned resources when an operation fails -* **Save arguments to configuration file**: If set to yes, your choices will be saved to a configuration file inside the project, so that in the future you can just re-run `sam deploy` without parameters to deploy changes to your application. -* **SAM configuration file [samconfig.toml]**: Name of the configuration file to store configuration information locally -* **SAM configuration environment [default]**: Environment for storing deployment information locally - -You should get a message "Successfully created/updated stack - in " if all goes well - - -## Test the sample application - -Once the lambda function is deployed, send some SNS messages on the queue that the lambda function is listening on. - -Use the project ../sns_message_sender_json. - -Look at the Readme of that project to determine how to build that project and run the command that will send SNS messages with a Json payload to the lambda function built using this project. The lambda function will receive the SNS messages with a JSON payload and input fields from the SNS message into a DynamoDB table. - -The value field of each SNS message that will be sent out will be a Json element of the format - -"person": { - "firstname": "Myra", - "lastname": "Munns", - "company": "Anker Law Office", - "street": "461 Prospect Pl #316", - "city": "Euless", - "county": "Tarrant", - "state": "TX", - "zip": "76040", - "homePhone": "817-914-7518", - "cellPhone": "817-451-3518", - "email": "mmunns@cox.net", - "website": "http://www.ankerlawoffice.com" -} - -Then check Cloudwatch logs and you should see messages for the Cloudwatch Log Group with the name of the deployed Lambda function. - -The lambda code parses the SNS messages and outputs the fields in the SNS messages to Cloudwatch logs - -Unlike SQS, a single invocation of the lambda function receives a single message. - -The code in this example prints out the fields in the SNS message and logs them in Cloudwatch logs. - -Apart from outputting to Cloudwatch logs, the lambda function also inputs fields from the SNS message (both message metadata fields as well as payload fields from the JSON payload) into a DynamoDB table created by the SAM template. You can log into the AWS console and look at the DynamoDB table and run a scan to see data getting input from the SNS message into the DynamoDB table diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/events/event.json b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/events/event.json deleted file mode 100755 index 39f3c5ce76..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/events/event.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "Records": [ - { - "EventVersion": "1.0", - "EventSubscriptionArn": "arn:aws:sns:us-east-1:123456789012:sns-lambda:21be56ed-a058-49f5-8c98-aedd2564c486", - "EventSource": "aws:sns", - "Sns": { - "SignatureVersion": "1", - "Timestamp": "2019-01-02T12:45:07.000Z", - "Signature": "tcc6faL2yUC6dgZdmrwh1Y4cGa/ebXEkAi6RibDsvpi+tE/1+82j...65r==", - "SigningCertUrl": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-ac565b8b1a6c5d002d285f9598aa1d9b.pem", - "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e", - "Message": "{\"firstname\":\"Mitsue\",\"lastname\":\"Tollner\",\"company\":\"Morlong Associates\",\"street\":\"7 Eads St\",\"city\":\"Chicago\",\"county\":\"Cook\",\"state\":\"IL\",\"zip\":\"60632\",\"homePhone\":\"773-573-6914\",\"cellPhone\":\"773-924-8565\",\"email\":\"mitsue_tollner@yahoo.com\",\"website\":\"http://www.morlongassociates.com\"}", - "MessageAttributes": { - "MessageKey": { - "Type": "String", - "Value": "TestKey07-05-29-2023-10-05-75" - }, - "MessageNumber": { - "Type": "String", - "Value": "6" - } - }, - "Type": "Notification", - "UnsubscribeUrl": "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:123456789012:test-lambda:21be56ed-a058-49f5-8c98-aedd2564c486", - "TopicArn":"arn:aws:sns:us-east-1:123456789012:sns-lambda", - "Subject": "TestInvoke" - } - } - ] -} \ No newline at end of file diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.gitignore b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.gitignore deleted file mode 100755 index b83d22266a..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.settings/org.eclipse.jdt.core.prefs b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.settings/org.eclipse.jdt.core.prefs deleted file mode 100755 index 2af1e7b99c..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 -org.eclipse.jdt.core.compiler.compliance=11 -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=11 diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/pom.xml b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/pom.xml deleted file mode 100755 index 584edecdfc..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/pom.xml +++ /dev/null @@ -1,89 +0,0 @@ - - 4.0.0 - com.amazonaws.services.lambda.samples.events.sns - SNSConsumer - 1.0 - jar - A sample Lambda SNS consumer - - 11 - 11 - - - - com.amazonaws - aws-lambda-java-core - 1.2.1 - - - com.amazonaws - aws-lambda-java-events - 3.11.0 - - - - com.amazonaws - aws-java-sdk-dynamodb - 1.12.445 - - - org.junit.jupiter - junit-jupiter-api - 5.6.0 - test - - - org.junit.jupiter - junit-jupiter-engine - 5.6.0 - test - - - org.mockito - mockito-core - 3.7.7 - test - - - org.mockito - mockito-junit-jupiter - 3.8.0 - test - - - software.amazon.awssdk - sns - 2.20.73 - - - - com.fasterxml.jackson.core - jackson-core - 2.15.1 - - - com.fasterxml.jackson.datatype - jackson-datatype-joda - 2.15.1 - - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.4 - - - - package - - shade - - - - - - - diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdater.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdater.java deleted file mode 100755 index 7a44f73ece..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdater.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.amazonaws.services.lambda.samples.events.sns; - - -import java.util.Map; -import com.amazonaws.client.builder.AwsClientBuilder.EndpointConfiguration; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; -import com.amazonaws.services.dynamodbv2.document.DynamoDB; -import com.amazonaws.services.dynamodbv2.document.Item; -import com.amazonaws.services.dynamodbv2.document.PutItemOutcome; -import com.amazonaws.services.dynamodbv2.document.Table; -import com.amazonaws.services.lambda.runtime.LambdaLogger; -import com.amazonaws.services.lambda.runtime.events.SNSEvent; -import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord; - -public class DynamoDBUpdater { - - String dynamoDBTableName; - AmazonDynamoDB client; - DynamoDB dynamoDB; - Table dynamoTable; - - - public DynamoDBUpdater(String dynamoDBTableName) { - super(); - if (null == dynamoDBTableName) { - this.dynamoDBTableName = "SNS_LAMBDA_DYNAMO_TABLE"; - } else { - this.dynamoDBTableName = dynamoDBTableName; - } - String AWS_SAM_LOCAL = System.getenv("AWS_SAM_LOCAL"); - if (null == AWS_SAM_LOCAL) { - this.client = AmazonDynamoDBClientBuilder.standard().build(); - } else { - this.client = AmazonDynamoDBClientBuilder.standard().withEndpointConfiguration(new EndpointConfiguration("http://127.0.0.1:8000", "")).build(); - this.dynamoDBTableName = "SQS_LAMBDA_DYNAMO_TABLE"; - } - //this.client = AmazonDynamoDBClientBuilder.standard().build(); - this.dynamoDB = new DynamoDB(client); - this.dynamoTable = dynamoDB.getTable(this.dynamoDBTableName); - } - - public PutItemOutcome insertIntoDynamoDB(SNSRecord record, Person thisPerson, LambdaLogger logger) { - logger.log("Now inserting a row in DynamoDB for messageID = " + record.getSNS().getMessageId()); - Item item = new Item(); - item.withPrimaryKey("MessageID", record.getSNS().getMessageId()); - item.withString("EventSource", record.getEventSource()); - item.withString("EventSubscriptionARN", record.getEventSubscriptionArn()); - item.withString("EventVersion", record.getEventVersion()); - item.withString("SigningCertURL", record.getSNS().getSigningCertUrl()); - item.withString("MessageID", record.getSNS().getMessageId()); - item.withString("Subject", record.getSNS().getSubject()); - item.withString("UnsubscribeURL", record.getSNS().getUnsubscribeUrl()); - item.withString("SignatureURL", record.getSNS().getSignatureVersion()); - item.withString("Signature", record.getSNS().getSignature()); - item.withString("Type", record.getSNS().getType()); - item.withString("TopicARN", record.getSNS().getTopicArn()); - item.withString("Timestamp", record.getSNS().getTimestamp().toString()); - item.withString("Firstname", thisPerson.getFirstname()); - item.withString("Lastname", thisPerson.getLastname()); - item.withString("Company", thisPerson.getCompany()); - item.withString("Address_Street", thisPerson.getStreet()); - item.withString("City", thisPerson.getCity()); - item.withString("County", thisPerson.getCounty()); - item.withString("State", thisPerson.getState()); - item.withString("Zip", thisPerson.getZip()); - item.withString("Home_Phone", thisPerson.getHomePhone()); - item.withString("Cell_Phone", thisPerson.getCellPhone()); - item.withString("Email", thisPerson.getEmail()); - item.withString("Website", thisPerson.getWebsite()); - Map attributes = record.getSNS().getMessageAttributes(); - attributes.forEach((k,v) -> { - item.withString(k, v.getValue()); - }); - logger.log("Now done inserting a row in DynamoDB for messageID = " + record.getSNS().getMessageId()); - return dynamoTable.putItem(item); - } - -} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNS.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNS.java deleted file mode 100755 index 694b453689..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNS.java +++ /dev/null @@ -1,84 +0,0 @@ -//Lambda Runtime delivers a batch of messages to the lambda function -//Each batch of messages has two fields EventSource and EventSourceARN -//Each batch of messages also has a field called Records -//The Records is a map with multiple keys and values -//Each key is a combination of the Topic Name and the Partition Number -//One batch of messages can contain messages from multiple partitions - -/* -To simplify representing a batch of Kafka messages as a list of messages -We have created a Java class called KafkaMessage under the models package -Here we are mapping the structure of an incoming Kafka event to a list of -objects of the KafkaMessage class - */ - -package com.amazonaws.services.lambda.samples.events.sns; - -import java.util.List; -import java.util.Map; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.LambdaLogger; -import com.amazonaws.services.lambda.runtime.RequestHandler; -import com.amazonaws.services.lambda.runtime.events.SNSEvent; -import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.joda.JodaModule; - -public class HandlerSNS implements RequestHandler{ - //Gson gson = new GsonBuilder().setPrettyPrinting().create(); - String dynamoDBTableName = System.getenv("DYNAMO_DB_TABLE"); - DynamoDBUpdater ddbUpdater = new DynamoDBUpdater(dynamoDBTableName); - boolean addToDynamoDB=true; - ObjectMapper objectMapper = new ObjectMapper().registerModule(new JodaModule()); - @Override - public String handleRequest(SNSEvent event, Context context) - { - LambdaLogger logger = context.getLogger(); - try { - logger.log("Begin Event *************"); - try { - logger.log(objectMapper.writeValueAsString(event)); - } catch (JsonProcessingException e1) { - logger.log("An exception occurred " + e1.getMessage()); - throw new RuntimeException(e1); - } - logger.log("End Event ***************"); - List records = event.getRecords(); - for (SNSRecord record : records) { - logger.log("Event Source = " + record.getEventSource()); - logger.log("Event Subscription ARN = " + record.getEventSubscriptionArn()); - logger.log("Event Version = " + record.getEventVersion()); - logger.log("Signing Cert URL = " + record.getSNS().getSigningCertUrl()); - logger.log("Message ID = " + record.getSNS().getMessageId()); - logger.log("Subject = " + record.getSNS().getSubject()); - logger.log("Unsubscribe URL = " + record.getSNS().getUnsubscribeUrl()); - logger.log("Signature URL = " + record.getSNS().getSignatureVersion()); - logger.log("Signature = " + record.getSNS().getSignature()); - logger.log("Type = " + record.getSNS().getType()); - logger.log("Topic ARN = " + record.getSNS().getTopicArn()); - logger.log("Timestamp = " + record.getSNS().getTimestamp().toString()); - String message = record.getSNS().getMessage(); - Person person = objectMapper.readValue(message, Person.class); - logger.log("This person = " + person.toString()); - Map attributes = record.getSNS().getMessageAttributes(); - attributes.forEach((k,v) -> { - logger.log("Attribute: " + k + ", Value: " + v.getValue()); - }); - logger.log(record.getSNS().getSignatureVersion()); - String AWS_SAM_LOCAL = System.getenv("AWS_SAM_LOCAL"); - if ((null == AWS_SAM_LOCAL) && (addToDynamoDB)) { - ddbUpdater.insertIntoDynamoDB(record, person, logger); - } - } - } catch (Exception e) { - logger.log("An exception occurred " + e.getMessage()); - throw new RuntimeException(e); - } - return new String("200-OK"); - } - - public void throwit(String message) throws Exception{ - throw new Exception(message); - } -} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/Person.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/Person.java deleted file mode 100755 index 08ff03c7aa..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/main/java/com/amazonaws/services/lambda/samples/events/sns/Person.java +++ /dev/null @@ -1,138 +0,0 @@ -package com.amazonaws.services.lambda.samples.events.sns; - -import java.util.Objects; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - - -public class Person { - - String firstname; - String lastname; - String company; - String street; - String city; - String county; - String state; - String zip; - String homePhone; - String cellPhone; - String email; - String website; - public Person() { - super(); - } - public String getFirstname() { - return firstname; - } - public void setFirstname(String firstname) { - this.firstname = firstname; - } - public String getLastname() { - return lastname; - } - public void setLastname(String lastname) { - this.lastname = lastname; - } - public String getCompany() { - return company; - } - public void setCompany(String company) { - this.company = company; - } - public String getStreet() { - return street; - } - public void setStreet(String street) { - this.street = street; - } - public String getCity() { - return city; - } - public void setCity(String city) { - this.city = city; - } - public String getCounty() { - return county; - } - public void setCounty(String county) { - this.county = county; - } - public String getState() { - return state; - } - public void setState(String state) { - this.state = state; - } - public String getZip() { - return zip; - } - public void setZip(String zip) { - this.zip = zip; - } - public String getHomePhone() { - return homePhone; - } - public void setHomePhone(String homePhone) { - this.homePhone = homePhone; - } - public String getCellPhone() { - return cellPhone; - } - public void setCellPhone(String cellPhone) { - this.cellPhone = cellPhone; - } - public String getEmail() { - return email; - } - public void setEmail(String email) { - this.email = email; - } - public String getWebsite() { - return website; - } - public void setWebsite(String website) { - this.website = website; - } - @Override - public String toString() { - return "Person [firstname=" + firstname + ", lastname=" + lastname + ", company=" + company + ", street=" - + street + ", city=" + city + ", county=" + county + ", state=" + state + ", zip=" + zip - + ", homePhone=" + homePhone + ", cellPhone=" + cellPhone + ", email=" + email + ", website=" + website - + "]"; - } - - public String toJson() { - ObjectMapper om = new ObjectMapper(); - String personJson = ""; - try { - personJson = om.writeValueAsString(this); - } catch (JsonProcessingException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return personJson; - } - @Override - public int hashCode() { - return Objects.hash(cellPhone, city, company, county, email, firstname, homePhone, lastname, state, street, - website, zip); - } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Person other = (Person) obj; - return Objects.equals(cellPhone, other.cellPhone) && Objects.equals(city, other.city) - && Objects.equals(company, other.company) && Objects.equals(county, other.county) - && Objects.equals(email, other.email) && Objects.equals(firstname, other.firstname) - && Objects.equals(homePhone, other.homePhone) && Objects.equals(lastname, other.lastname) - && Objects.equals(state, other.state) && Objects.equals(street, other.street) - && Objects.equals(website, other.website) && Objects.equals(zip, other.zip); - } - -} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdaterTest.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdaterTest.java deleted file mode 100755 index 360953ed6a..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/DynamoDBUpdaterTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.amazonaws.services.lambda.samples.events.sns; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.util.List; - -import org.junit.jupiter.api.Test; -import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; -import com.amazonaws.services.dynamodbv2.document.DynamoDB; -import com.amazonaws.services.dynamodbv2.document.Item; -import com.amazonaws.services.dynamodbv2.document.PutItemOutcome; -import com.amazonaws.services.dynamodbv2.document.Table; -import com.amazonaws.services.lambda.runtime.LambdaLogger; -import com.amazonaws.services.lambda.runtime.events.SNSEvent; -import com.amazonaws.services.lambda.runtime.events.SNSEvent.SNSRecord; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.joda.JodaModule; - - -import org.mockito.ArgumentMatchers; - -class DynamoDBUpdaterTest { - - private static final String snsEventJson = "{\n" - + " \"records\": [\n" - + " {\n" - + " \"sns\": {\n" - + " \"messageAttributes\": {\n" - + " \"MessageKey\": {\n" - + " \"type\": \"String\",\n" - + " \"value\": \"TestKey03-05-29-2023-06-05-49\"\n" - + " },\n" - + " \"MessageNumber\": {\n" - + " \"type\": \"String\",\n" - + " \"value\": \"89\"\n" - + " }\n" - + " },\n" - + " \"signingCertUrl\": \"https://sns.us-west-2.amazonaws.com/SimpleNotificationService-01d088a6f77103d0fe307c0069e40ed6.pem\",\n" - + " \"messageId\": \"e31e34d1-7349-539d-9b0e-683f306298ac\",\n" - + " \"message\": \"{\\\"firstname\\\":\\\"Tyra\\\",\\\"lastname\\\":\\\"Shields\\\",\\\"company\\\":\\\"\\\\\\\"Assink, Anne H Esq\\\\\\\"\\\",\\\"street\\\":\\\"3 Fort Worth Ave\\\",\\\"city\\\":\\\"Philadelphia\\\",\\\"county\\\":\\\"Philadelphia\\\",\\\"state\\\":\\\"PA\\\",\\\"zip\\\":\\\"19106\\\",\\\"homePhone\\\":\\\"215-255-1641\\\",\\\"cellPhone\\\":\\\"215-228-8264\\\",\\\"email\\\":\\\"tshields@gmail.com\\\",\\\"website\\\":\\\"http://www.assinkannehesq.com\\\"}\",\n" - + " \"subject\": \"Sending Message with Key = TestKey03-05-29-2023-06-05-49 and message number = 89\",\n" - + " \"unsubscribeUrl\": \"https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM:740325aa-8302-42e6-ab5c-70c2c38633d3\",\n" - + " \"type\": \"Notification\",\n" - + " \"signatureVersion\": \"1\",\n" - + " \"signature\": \"VzYoZ8lESJ+s9sMsy1Xlb8CfV8Y7M8Qk/w18onb2jEd0Q71GI8q1688PGQU3EFHkRtKLB/DYFPCZzZDezhmpQo6iHqSW2yVGgb5nt9x6NcccFOhK7jRl7QEmEkTmVn1AbtmJOL7ya5U+CZDbMKebCJnRdWgRlrtbE06TaklPnv0REHavXJ4c3fPdkDWc8mBiOhRX6+aAVII9D9Zt7zQLl6ROI8xH6RzIe0ZOy7gv9pF3YycAnrjX3ibD+5+7hvFKZPvgnhDansm++MjHa/mON5L08VxTY9lEFiTlQv2L7bS6XihwhWpmk6uQHQWpdURMdZsL2l2WRUNR+IROhvEQqg==\",\n" - + " \"timestamp\": 1685340395498,\n" - + " \"topicArn\": \"arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM\"\n" - + " },\n" - + " \"eventVersion\": \"1.0\",\n" - + " \"eventSource\": \"aws:sns\",\n" - + " \"eventSubscriptionArn\": \"arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM:740325aa-8302-42e6-ab5c-70c2c38633d3\"\n" - + " }\n" - + " ]\n" - + "}"; - - @Test - void testDynamoDBUpdater() { - DynamoDBUpdater ddbUpdater = new DynamoDBUpdater("DBTable"); - assertNotNull(ddbUpdater); - assertEquals(ddbUpdater.dynamoDBTableName, "DBTable"); - assertNotNull(ddbUpdater.client); - assertNotNull(ddbUpdater.dynamoDB); - assertNotNull(ddbUpdater.dynamoTable); - } - - @Test - void testInsertIntoDynamoDB() { - ObjectMapper om = new ObjectMapper().registerModule(new JodaModule()); - SNSEvent event = null; - try { - event = om.readValue(snsEventJson, SNSEvent.class); - } catch (JsonMappingException e) { - e.printStackTrace(); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - List records = event.getRecords(); - for(SNSRecord msg : records){ - Table dynamoDbTable = mock(Table.class); - AmazonDynamoDB client = mock(AmazonDynamoDB.class); - DynamoDB dynamoDB = mock(DynamoDB.class); - PutItemOutcome putoutcome = mock(PutItemOutcome.class); - LambdaLogger logger = mock(LambdaLogger.class); - DynamoDBUpdater ddbUpdater = new DynamoDBUpdater("DBTable"); - ddbUpdater.client = client; - ddbUpdater.dynamoDB = dynamoDB; - ddbUpdater.dynamoTable = dynamoDbTable; - Person person = new Person(); - try { - person = om.readValue(msg.getSNS().getMessage(), Person.class); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - when(ddbUpdater.dynamoTable.putItem(ArgumentMatchers.any(Item.class))).thenReturn(putoutcome); - PutItemOutcome putOutcome = ddbUpdater.insertIntoDynamoDB(msg, person, logger); - assertNotNull(putOutcome); - } - - } -} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNSTest.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNSTest.java deleted file mode 100755 index 1f43a52ef3..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/HandlerSNSTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.amazonaws.services.lambda.samples.events.sns; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.events.SNSEvent; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonMappingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.joda.JodaModule; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -class HandlerSNSTest { - private static final String snsEventJson = "{\n" - + " \"records\": [\n" - + " {\n" - + " \"sns\": {\n" - + " \"messageAttributes\": {\n" - + " \"MessageKey\": {\n" - + " \"type\": \"String\",\n" - + " \"value\": \"TestKey03-05-29-2023-06-05-49\"\n" - + " },\n" - + " \"MessageNumber\": {\n" - + " \"type\": \"String\",\n" - + " \"value\": \"89\"\n" - + " }\n" - + " },\n" - + " \"signingCertUrl\": \"https://sns.us-west-2.amazonaws.com/SimpleNotificationService-01d088a6f77103d0fe307c0069e40ed6.pem\",\n" - + " \"messageId\": \"e31e34d1-7349-539d-9b0e-683f306298ac\",\n" - + " \"message\": \"{\\\"firstname\\\":\\\"Tyra\\\",\\\"lastname\\\":\\\"Shields\\\",\\\"company\\\":\\\"\\\\\\\"Assink, Anne H Esq\\\\\\\"\\\",\\\"street\\\":\\\"3 Fort Worth Ave\\\",\\\"city\\\":\\\"Philadelphia\\\",\\\"county\\\":\\\"Philadelphia\\\",\\\"state\\\":\\\"PA\\\",\\\"zip\\\":\\\"19106\\\",\\\"homePhone\\\":\\\"215-255-1641\\\",\\\"cellPhone\\\":\\\"215-228-8264\\\",\\\"email\\\":\\\"tshields@gmail.com\\\",\\\"website\\\":\\\"http://www.assinkannehesq.com\\\"}\",\n" - + " \"subject\": \"Sending Message with Key = TestKey03-05-29-2023-06-05-49 and message number = 89\",\n" - + " \"unsubscribeUrl\": \"https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM:740325aa-8302-42e6-ab5c-70c2c38633d3\",\n" - + " \"type\": \"Notification\",\n" - + " \"signatureVersion\": \"1\",\n" - + " \"signature\": \"VzYoZ8lESJ+s9sMsy1Xlb8CfV8Y7M8Qk/w18onb2jEd0Q71GI8q1688PGQU3EFHkRtKLB/DYFPCZzZDezhmpQo6iHqSW2yVGgb5nt9x6NcccFOhK7jRl7QEmEkTmVn1AbtmJOL7ya5U+CZDbMKebCJnRdWgRlrtbE06TaklPnv0REHavXJ4c3fPdkDWc8mBiOhRX6+aAVII9D9Zt7zQLl6ROI8xH6RzIe0ZOy7gv9pF3YycAnrjX3ibD+5+7hvFKZPvgnhDansm++MjHa/mON5L08VxTY9lEFiTlQv2L7bS6XihwhWpmk6uQHQWpdURMdZsL2l2WRUNR+IROhvEQqg==\",\n" - + " \"timestamp\": 1685340395498,\n" - + " \"topicArn\": \"arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM\"\n" - + " },\n" - + " \"eventVersion\": \"1.0\",\n" - + " \"eventSource\": \"aws:sns\",\n" - + " \"eventSubscriptionArn\": \"arn:aws:sns:us-west-2:664251831272:LambdaSNSTopicDynamoJavaSAM:740325aa-8302-42e6-ab5c-70c2c38633d3\"\n" - + " }\n" - + " ]\n" - + "}"; - - @Mock - DynamoDBUpdater ddbUpdater; - - @Test - @ExtendWith(MockitoExtension.class) - void invokeTest() { - ObjectMapper om = new ObjectMapper().registerModule(new JodaModule()); - SNSEvent event = null; - try { - event = om.readValue(snsEventJson, SNSEvent.class); - } catch (JsonMappingException e) { - e.printStackTrace(); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - Context context = new TestContext(); - //PutItemOutcome putItemOutcome = mock(PutItemOutcome.class); - DynamoDBUpdater dbUpdater = mock(DynamoDBUpdater.class); - HandlerSNS handler = new HandlerSNS(); - handler.ddbUpdater = dbUpdater; - String result = handler.handleRequest(event, context); - assertEquals(result, "200-OK"); - } - -} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestContext.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestContext.java deleted file mode 100755 index 891d393d51..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestContext.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.amazonaws.services.lambda.samples.events.sns; - -import com.amazonaws.services.lambda.runtime.Context; -import com.amazonaws.services.lambda.runtime.CognitoIdentity; -import com.amazonaws.services.lambda.runtime.ClientContext; -import com.amazonaws.services.lambda.runtime.LambdaLogger; - -public class TestContext implements Context{ - - public TestContext() {} - public String getAwsRequestId(){ - return new String("495b12a8-xmpl-4eca-8168-160484189f99"); - } - public String getLogGroupName(){ - return new String("/aws/lambda/my-function"); - } - public String getLogStreamName(){ - return new String("2020/02/26/[$LATEST]704f8dxmpla04097b9134246b8438f1a"); - } - public String getFunctionName(){ - return new String("my-function"); - } - public String getFunctionVersion(){ - return new String("$LATEST"); - } - public String getInvokedFunctionArn(){ - return new String("arn:aws:lambda:us-east-2:123456789012:function:my-function"); - } - public CognitoIdentity getIdentity(){ - return null; - } - public ClientContext getClientContext(){ - return null; - } - public int getRemainingTimeInMillis(){ - return 300000; - } - public int getMemoryLimitInMB(){ - return 512; - } - public LambdaLogger getLogger(){ - return new TestLogger(); - } - -} \ No newline at end of file diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestLogger.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestLogger.java deleted file mode 100755 index 2740b026c2..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/sns_event_consumer_function/src/test/java/com/amazonaws/services/lambda/samples/events/sns/TestLogger.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.amazonaws.services.lambda.samples.events.sns; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.amazonaws.services.lambda.runtime.LambdaLogger; - -public class TestLogger implements LambdaLogger { - private static final Logger logger = LoggerFactory.getLogger(TestLogger.class); - public void log(String message){ - logger.info(message); - } - public void log(byte[] message){ - logger.info(new String(message)); - } -} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/template.yaml b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/template.yaml deleted file mode 100755 index 105e3f9088..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_consumer_dynamo_sam/template.yaml +++ /dev/null @@ -1,78 +0,0 @@ -AWSTemplateFormatVersion: '2010-09-09' -Transform: AWS::Serverless-2016-10-31 -Description: > - sns_event_consumer_function - - Sample SAM Template for sns-consumer-with-sam - -# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst -Globals: - Function: - Timeout: 15 - -Resources: - LambdaSNSConsumerJavaFunction: - Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction - Properties: - FunctionName: java-sns-consumer-dynamodb-sam - CodeUri: sns_event_consumer_function - Handler: com.amazonaws.services.lambda.samples.events.sns.HandlerSNS::handleRequest - Runtime: java11 - Architectures: - - x86_64 - MemorySize: 512 - Environment: # More info about Env Vars: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#environment-object - Variables: - DYNAMO_DB_TABLE: !Ref SNSDynamoDBTable - JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1 # More info about tiered compilation https://aws.amazon.com/blogs/compute/optimizing-aws-lambda-function-performance-for-java/ - Events: - SNSEvent: - Type: SNS - Properties: - Topic: !Ref LambdaSNSTopic - Policies: - - Statement: - - Sid: DynamoDBPermissionsPolicy - Effect: Allow - Action: - - dynamodb:GetItem - - dynamodb:DeleteItem - - dynamodb:PutItem - - dynamodb:Scan - - dynamodb:Query - - dynamodb:UpdateItem - - dynamodb:BatchWriteItem - - dynamodb:BatchGetItem - - dynamodb:DescribeTable - - dynamodb:ConditionCheckItem - Resource: - - !Join ['', ["arn:", "aws:", "dynamodb:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":", "table/", !Ref SNSDynamoDBTable]] - - !Join ['', ["arn:", "aws:", "dynamodb:", !Ref "AWS::Region", ":", !Ref "AWS::AccountId", ":", "table/", !Ref SNSDynamoDBTable, "/index/*"]] - TopicConsumerFunction1Permission: - Type: 'AWS::Lambda::Permission' - Properties: - Action: 'lambda:InvokeFunction' - FunctionName: !Ref LambdaSNSConsumerJavaFunction - Principal: sns.amazonaws.com - SNSDynamoDBTable: - Type: AWS::Serverless::SimpleTable - Properties: - TableName: SNSDynamoDBTableJava - PrimaryKey: - Name: MessageID - Type: String - LambdaSNSTopic: - Type: AWS::SNS::Topic - Properties: - TopicName: !Ref SNSTopicName - Subscription: - - Protocol: lambda - Endpoint: !GetAtt LambdaSNSConsumerJavaFunction.Arn -Parameters: - SNSTopicName: - Type: String - Description: Enter the name of the SNS Topic -Outputs: - LambdaSNSConsumerJavaFunction: - Description: "Topic Consumer Lambda Function ARN" - Value: !GetAtt LambdaSNSConsumerJavaFunction.Arn diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.classpath b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.classpath deleted file mode 100755 index 002ad570e2..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.classpath +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.gitignore b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.gitignore deleted file mode 100755 index b83d22266a..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/target/ diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.project b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.project deleted file mode 100755 index 4ba90c9971..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - sns_message_sender - - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.m2e.core.maven2Builder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.m2e.core.maven2Nature - - diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.core.resources.prefs b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.core.resources.prefs deleted file mode 100755 index 29abf99956..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,6 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/main/java=UTF-8 -encoding//src/main/resources=UTF-8 -encoding//src/test/java=UTF-8 -encoding//src/test/resources=UTF-8 -encoding/=UTF-8 diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.jdt.core.prefs b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.jdt.core.prefs deleted file mode 100755 index 2f5cc74c3a..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,8 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 -org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=1.8 diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/Commands b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/Commands deleted file mode 100755 index d9dac1ebe5..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/Commands +++ /dev/null @@ -1,4 +0,0 @@ -ava -classpath /JavaExamples/sns_message_sender_json/target/json-sns-producer-0.0.1-SNAPSHOT.jar sns.producer.JsonSNSProducer - -Example: -java -classpath ~/environment/JavaExamples/sns_message_sender_json/target/json-sns-producer-0.0.1-SNAPSHOT.jar sns.producer.JsonSNSProducer LambdaSNSTopic Message01 100 \ No newline at end of file diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/pom.xml b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/pom.xml deleted file mode 100755 index b3c982ac66..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/pom.xml +++ /dev/null @@ -1,73 +0,0 @@ - - 4.0.0 - com.amazonaws.services.lambda.samples.events.sns - json-sns-producer - 0.0.1-SNAPSHOT - - UTF-8 - 11 - 11 - - - - com.amazonaws - aws-lambda-java-core - 1.2.1 - - - com.amazonaws - aws-lambda-java-events - 3.11.0 - - - com.google.code.gson - gson - 2.8.9 - - - org.junit.jupiter - junit-jupiter-api - 5.6.0 - test - - - - software.amazon.awssdk - sns - 2.20.73 - - - - - - maven-surefire-plugin - 2.22.2 - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.2 - - false - - - - package - - shade - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - 1.8 - 1.8 - - - - - \ No newline at end of file diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/JsonSNSProducer.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/JsonSNSProducer.java deleted file mode 100755 index d58ae36efe..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/JsonSNSProducer.java +++ /dev/null @@ -1,143 +0,0 @@ -package sns.producer; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; - -import software.amazon.awssdk.services.sns.SnsClient; -import software.amazon.awssdk.services.sns.model.ListTopicsRequest; -import software.amazon.awssdk.services.sns.model.ListTopicsResponse; -import software.amazon.awssdk.services.sns.model.PublishRequest; -import software.amazon.awssdk.services.sns.model.PublishResponse; -import software.amazon.awssdk.services.sns.model.SnsException; -import software.amazon.awssdk.services.sns.model.Topic; -import software.amazon.awssdk.services.sns.model.MessageAttributeValue; - -public class JsonSNSProducer { - - public static void main(String[] args) { - try { - JsonSNSProducer.snsSender(args[0], args[1].concat("-").concat(JsonSNSProducer.getTodayDate()), Integer.parseInt(args[2])); - } catch (NumberFormatException e) { - System.out.println("Pass three parameters in that order - 1 - The Topic Name, 2 - A String representing this batch of messages, 3 - Total number of messages in this batch"); - e.printStackTrace(); - } - } - - public static void snsSender(String snsTopic, String messageKey, int numberOfMessages) { - SnsClient snsClient = SnsClient.builder().build(); - String snsTopicARN = JsonSNSProducer.getTopicARNFromTopicName(snsClient, snsTopic); - List people = JsonSNSProducer.readDataFile(); - int numberOfMessagesToSend=0; - if (people.size() > numberOfMessages) { - numberOfMessagesToSend = numberOfMessages; - } else { - numberOfMessagesToSend = people.size(); - } - for (int i=1;i<= numberOfMessagesToSend; i++) { - Person thisPerson = JsonSNSProducer.getPersonFromLine(people.get(i)); - JsonSNSProducer.sendMessage(snsClient, snsTopicARN, thisPerson.toJson(), messageKey, i); - } - } - - public static String getTopicARNFromTopicName(SnsClient snsClient, String topicName) { - String topicARN = ""; - try { - ListTopicsRequest request = ListTopicsRequest.builder() - .build(); - - ListTopicsResponse result = snsClient.listTopics(request); - List topics = result.topics(); - for (Topic topic: topics) { - String currentTopicARN = topic.topicArn(); - if (currentTopicARN.endsWith(topicName)) { - topicARN = currentTopicARN; - System.out.println("Matching TopicARN = " + topicARN); - break; - } - } - - } catch (SnsException e) { - System.err.println("Incorrect Topic Name Specified"); - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - return topicARN; - } - - public static void sendMessage(SnsClient snsClient, String topicARN, String message, String messageKey, int messageNumber) { - try { - Map attributes = new HashMap(); - attributes.put("MessageKey", MessageAttributeValue.builder().dataType("String").stringValue(messageKey).build()); - attributes.put("MessageNumber", MessageAttributeValue.builder().dataType("String").stringValue(Integer.toString(messageNumber)).build()); - PublishRequest request = PublishRequest.builder() - .message(message) - .topicArn(topicARN) - .messageAttributes(attributes) - .subject("Sending Message with Key = " + messageKey + " and message number = " + Integer.toString(messageNumber)) - .build(); - System.out.println("**********************************************************"); - System.out.println("Now going to send one SNS message to topic - " + topicARN); - System.out.println("Message Key = " + messageKey + " and Message Number = " + Integer.toString(messageNumber)); - System.out.println("Message Body = " + message); - PublishResponse result = snsClient.publish(request); - System.out.println(result.messageId() + " Message sent. Status is " + result.sdkHttpResponse().statusCode()); - System.out.println("Now done sending one SNS message"); - System.out.println("**********************************************************"); - - } catch (SnsException e) { - System.err.println(e.awsErrorDetails().errorMessage()); - System.exit(1); - } - } - - public static List readDataFile() { - List personList = new ArrayList(); - InputStream is = JsonSNSProducer.class.getClassLoader().getResourceAsStream("us-500.csv"); - BufferedReader bf = new BufferedReader(new InputStreamReader(is)); - String thisLine = null; - try { - thisLine = bf.readLine(); - while (null != thisLine) { - personList.add(thisLine); - thisLine = bf.readLine(); - } - } catch (IOException e) { - e.printStackTrace(); - } - return personList; - } - - public static Person getPersonFromLine(String line) { - String[] fields = line.split(",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", -1); - Person thisPerson = new Person(); - thisPerson.setFirstname(fields[0]); - thisPerson.setLastname(fields[1]); - thisPerson.setCompany(fields[2]); - thisPerson.setStreet(fields[3]); - thisPerson.setCity(fields[4]); - thisPerson.setCounty(fields[5]); - thisPerson.setState(fields[6]); - thisPerson.setZip(fields[7]); - thisPerson.setHomePhone(fields[8]); - thisPerson.setCellPhone(fields[9]); - thisPerson.setEmail(fields[10]); - thisPerson.setWebsite(fields[11]); - return thisPerson; - } - - public static String getTodayDate() { - - LocalDateTime ldt = LocalDateTime.now(); - String formattedDateStr = DateTimeFormatter.ofPattern("MM-dd-YYYY-HH-MM-SS").format(ldt); - return formattedDateStr; - } - -} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/Person.java b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/Person.java deleted file mode 100755 index 732af6bc7b..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/java/sns/producer/Person.java +++ /dev/null @@ -1,133 +0,0 @@ -package sns.producer; - -import java.util.Objects; - -import com.google.gson.Gson; - -public class Person { - - String firstname; - String lastname; - String company; - String street; - String city; - String county; - String state; - String zip; - String homePhone; - String cellPhone; - String email; - String website; - public Person() { - super(); - } - public String getFirstname() { - return firstname; - } - public void setFirstname(String firstname) { - this.firstname = firstname; - } - public String getLastname() { - return lastname; - } - public void setLastname(String lastname) { - this.lastname = lastname; - } - public String getCompany() { - return company; - } - public void setCompany(String company) { - this.company = company; - } - public String getStreet() { - return street; - } - public void setStreet(String street) { - this.street = street; - } - public String getCity() { - return city; - } - public void setCity(String city) { - this.city = city; - } - public String getCounty() { - return county; - } - public void setCounty(String county) { - this.county = county; - } - public String getState() { - return state; - } - public void setState(String state) { - this.state = state; - } - public String getZip() { - return zip; - } - public void setZip(String zip) { - this.zip = zip; - } - public String getHomePhone() { - return homePhone; - } - public void setHomePhone(String homePhone) { - this.homePhone = homePhone; - } - public String getCellPhone() { - return cellPhone; - } - public void setCellPhone(String cellPhone) { - this.cellPhone = cellPhone; - } - public String getEmail() { - return email; - } - public void setEmail(String email) { - this.email = email; - } - public String getWebsite() { - return website; - } - public void setWebsite(String website) { - this.website = website; - } - - - - @Override - public int hashCode() { - return Objects.hash(cellPhone, city, company, county, email, firstname, homePhone, lastname, state, street, - website, zip); - } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Person other = (Person) obj; - return Objects.equals(cellPhone, other.cellPhone) && Objects.equals(city, other.city) - && Objects.equals(company, other.company) && Objects.equals(county, other.county) - && Objects.equals(email, other.email) && Objects.equals(firstname, other.firstname) - && Objects.equals(homePhone, other.homePhone) && Objects.equals(lastname, other.lastname) - && Objects.equals(state, other.state) && Objects.equals(street, other.street) - && Objects.equals(website, other.website) && Objects.equals(zip, other.zip); - } - @Override - public String toString() { - return "Person [firstname=" + firstname + ", lastname=" + lastname + ", company=" + company + ", street=" - + street + ", city=" + city + ", county=" + county + ", state=" + state + ", zip=" + zip - + ", homePhone=" + homePhone + ", cellPhone=" + cellPhone + ", email=" + email + ", website=" + website - + "]"; - } - - public String toJson() { - Gson gson = new Gson(); - return gson.toJson(this); - } - -} diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/resources/us-500.csv b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/resources/us-500.csv deleted file mode 100755 index 20c58066e5..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/JSONMessage/sns_message_sender_json/src/main/resources/us-500.csv +++ /dev/null @@ -1,500 +0,0 @@ -James,Butt,"Benton, John B Jr",6649 N Blue Gum St,New Orleans,Orleans,LA,70116,504-621-8927,504-845-1427,jbutt@gmail.com,http://www.bentonjohnbjr.com -Josephine,Darakjy,"Chanay, Jeffrey A Esq",4 B Blue Ridge Blvd,Brighton,Livingston,MI,48116,810-292-9388,810-374-9840,josephine_darakjy@darakjy.org,http://www.chanayjeffreyaesq.com -Art,Venere,"Chemel, James L Cpa",8 W Cerritos Ave #54,Bridgeport,Gloucester,NJ,8014,856-636-8749,856-264-4130,art@venere.org,http://www.chemeljameslcpa.com -Lenna,Paprocki,Feltz Printing Service,639 Main St,Anchorage,Anchorage,AK,99501,907-385-4412,907-921-2010,lpaprocki@hotmail.com,http://www.feltzprintingservice.com -Donette,Foller,Printing Dimensions,34 Center St,Hamilton,Butler,OH,45011,513-570-1893,513-549-4561,donette.foller@cox.net,http://www.printingdimensions.com -Simona,Morasca,"Chapman, Ross E Esq",3 Mcauley Dr,Ashland,Ashland,OH,44805,419-503-2484,419-800-6759,simona@morasca.com,http://www.chapmanrosseesq.com -Mitsue,Tollner,Morlong Associates,7 Eads St,Chicago,Cook,IL,60632,773-573-6914,773-924-8565,mitsue_tollner@yahoo.com,http://www.morlongassociates.com -Leota,Dilliard,Commercial Press,7 W Jackson Blvd,San Jose,Santa Clara,CA,95111,408-752-3500,408-813-1105,leota@hotmail.com,http://www.commercialpress.com -Sage,Wieser,Truhlar And Truhlar Attys,5 Boston Ave #88,Sioux Falls,Minnehaha,SD,57105,605-414-2147,605-794-4895,sage_wieser@cox.net,http://www.truhlarandtruhlarattys.com -Kris,Marrier,"King, Christopher A Esq",228 Runamuck Pl #2808,Baltimore,Baltimore City,MD,21224,410-655-8723,410-804-4694,kris@gmail.com,http://www.kingchristopheraesq.com -Minna,Amigon,"Dorl, James J Esq",2371 Jerrold Ave,Kulpsville,Montgomery,PA,19443,215-874-1229,215-422-8694,minna_amigon@yahoo.com,http://www.dorljamesjesq.com -Abel,Maclead,Rangoni Of Florence,37275 St Rt 17m M,Middle Island,Suffolk,NY,11953,631-335-3414,631-677-3675,amaclead@gmail.com,http://www.rangoniofflorence.com -Kiley,Caldarera,Feiner Bros,25 E 75th St #69,Los Angeles,Los Angeles,CA,90034,310-498-5651,310-254-3084,kiley.caldarera@aol.com,http://www.feinerbros.com -Graciela,Ruta,Buckley Miller & Wright,98 Connecticut Ave Nw,Chagrin Falls,Geauga,OH,44023,440-780-8425,440-579-7763,gruta@cox.net,http://www.buckleymillerwright.com -Cammy,Albares,"Rousseaux, Michael Esq",56 E Morehead St,Laredo,Webb,TX,78045,956-537-6195,956-841-7216,calbares@gmail.com,http://www.rousseauxmichaelesq.com -Mattie,Poquette,Century Communications,73 State Road 434 E,Phoenix,Maricopa,AZ,85013,602-277-4385,602-953-6360,mattie@aol.com,http://www.centurycommunications.com -Meaghan,Garufi,"Bolton, Wilbur Esq",69734 E Carrillo St,Mc Minnville,Warren,TN,37110,931-313-9635,931-235-7959,meaghan@hotmail.com,http://www.boltonwilburesq.com -Gladys,Rim,T M Byxbee Company Pc,322 New Horizon Blvd,Milwaukee,Milwaukee,WI,53207,414-661-9598,414-377-2880,gladys.rim@rim.org,http://www.tmbyxbeecompanypc.com -Yuki,Whobrey,Farmers Insurance Group,1 State Route 27,Taylor,Wayne,MI,48180,313-288-7937,313-341-4470,yuki_whobrey@aol.com,http://www.farmersinsurancegroup.com -Fletcher,Flosi,Post Box Services Plus,394 Manchester Blvd,Rockford,Winnebago,IL,61109,815-828-2147,815-426-5657,fletcher.flosi@yahoo.com,http://www.postboxservicesplus.com -Bette,Nicka,Sport En Art,6 S 33rd St,Aston,Delaware,PA,19014,610-545-3615,610-492-4643,bette_nicka@cox.net,http://www.sportenart.com -Veronika,Inouye,C 4 Network Inc,6 Greenleaf Ave,San Jose,Santa Clara,CA,95111,408-540-1785,408-813-4592,vinouye@aol.com,http://www.cnetworkinc.com -Willard,Kolmetz,"Ingalls, Donald R Esq",618 W Yakima Ave,Irving,Dallas,TX,75062,972-303-9197,972-896-4882,willard@hotmail.com,http://www.ingallsdonaldresq.com -Maryann,Royster,"Franklin, Peter L Esq",74 S Westgate St,Albany,Albany,NY,12204,518-966-7987,518-448-8982,mroyster@royster.com,http://www.franklinpeterlesq.com -Alisha,Slusarski,Wtlz Power 107 Fm,3273 State St,Middlesex,Middlesex,NJ,8846,732-658-3154,732-635-3453,alisha@slusarski.com,http://www.wtlzpowerfm.com -Allene,Iturbide,"Ledecky, David Esq",1 Central Ave,Stevens Point,Portage,WI,54481,715-662-6764,715-530-9863,allene_iturbide@cox.net,http://www.ledeckydavidesq.com -Chanel,Caudy,Professional Image Inc,86 Nw 66th St #8673,Shawnee,Johnson,KS,66218,913-388-2079,913-899-1103,chanel.caudy@caudy.org,http://www.professionalimageinc.com -Ezekiel,Chui,"Sider, Donald C Esq",2 Cedar Ave #84,Easton,Talbot,MD,21601,410-669-1642,410-235-8738,ezekiel@chui.com,http://www.siderdonaldcesq.com -Willow,Kusko,U Pull It,90991 Thorburn Ave,New York,New York,NY,10011,212-582-4976,212-934-5167,wkusko@yahoo.com,http://www.upullit.com -Bernardo,Figeroa,"Clark, Richard Cpa",386 9th Ave N,Conroe,Montgomery,TX,77301,936-336-3951,936-597-3614,bfigeroa@aol.com,http://www.clarkrichardcpa.com -Ammie,Corrio,"Moskowitz, Barry S",74874 Atlantic Ave,Columbus,Franklin,OH,43215,614-801-9788,614-648-3265,ammie@corrio.com,http://www.moskowitzbarrys.com -Francine,Vocelka,Cascade Realty Advisors Inc,366 South Dr,Las Cruces,Dona Ana,NM,88011,505-977-3911,505-335-5293,francine_vocelka@vocelka.com,http://www.cascaderealtyadvisorsinc.com -Ernie,Stenseth,Knwz Newsradio,45 E Liberty St,Ridgefield Park,Bergen,NJ,7660,201-709-6245,201-387-9093,ernie_stenseth@aol.com,http://www.knwznewsradio.com -Albina,Glick,"Giampetro, Anthony D",4 Ralph Ct,Dunellen,Middlesex,NJ,8812,732-924-7882,732-782-6701,albina@glick.com,http://www.giampetroanthonyd.com -Alishia,Sergi,Milford Enterprises Inc,2742 Distribution Way,New York,New York,NY,10025,212-860-1579,212-753-2740,asergi@gmail.com,http://www.milfordenterprisesinc.com -Solange,Shinko,"Mosocco, Ronald A",426 Wolf St,Metairie,Jefferson,LA,70002,504-979-9175,504-265-8174,solange@shinko.com,http://www.mosoccoronalda.com -Jose,Stockham,Tri State Refueler Co,128 Bransten Rd,New York,New York,NY,10011,212-675-8570,212-569-4233,jose@yahoo.com,http://www.tristaterefuelerco.com -Rozella,Ostrosky,Parkway Company,17 Morena Blvd,Camarillo,Ventura,CA,93012,805-832-6163,805-609-1531,rozella.ostrosky@ostrosky.com,http://www.parkwaycompany.com -Valentine,Gillian,Fbs Business Finance,775 W 17th St,San Antonio,Bexar,TX,78204,210-812-9597,210-300-6244,valentine_gillian@gmail.com,http://www.fbsbusinessfinance.com -Kati,Rulapaugh,Eder Assocs Consltng Engrs Pc,6980 Dorsett Rd,Abilene,Dickinson,KS,67410,785-463-7829,785-219-7724,kati.rulapaugh@hotmail.com,http://www.ederassocsconsltngengrspc.com -Youlanda,Schemmer,Tri M Tool Inc,2881 Lewis Rd,Prineville,Crook,OR,97754,541-548-8197,541-993-2611,youlanda@aol.com,http://www.trimtoolinc.com -Dyan,Oldroyd,International Eyelets Inc,7219 Woodfield Rd,Overland Park,Johnson,KS,66204,913-413-4604,913-645-8918,doldroyd@aol.com,http://www.internationaleyeletsinc.com -Roxane,Campain,Rapid Trading Intl,1048 Main St,Fairbanks,Fairbanks North Star,AK,99708,907-231-4722,907-335-6568,roxane@hotmail.com,http://www.rapidtradingintl.com -Lavera,Perin,Abc Enterprises Inc,678 3rd Ave,Miami,Miami-Dade,FL,33196,305-606-7291,305-995-2078,lperin@perin.org,http://www.abcenterprisesinc.com -Erick,Ferencz,Cindy Turner Associates,20 S Babcock St,Fairbanks,Fairbanks North Star,AK,99712,907-741-1044,907-227-6777,erick.ferencz@aol.com,http://www.cindyturnerassociates.com -Fatima,Saylors,"Stanton, James D Esq",2 Lighthouse Ave,Hopkins,Hennepin,MN,55343,952-768-2416,952-479-2375,fsaylors@saylors.org,http://www.stantonjamesdesq.com -Jina,Briddick,Grace Pastries Inc,38938 Park Blvd,Boston,Suffolk,MA,2128,617-399-5124,617-997-5771,jina_briddick@briddick.com,http://www.gracepastriesinc.com -Kanisha,Waycott,"Schroer, Gene E Esq",5 Tomahawk Dr,Los Angeles,Los Angeles,CA,90006,323-453-2780,323-315-7314,kanisha_waycott@yahoo.com,http://www.schroergeneeesq.com -Emerson,Bowley,Knights Inn,762 S Main St,Madison,Dane,WI,53711,608-336-7444,608-658-7940,emerson.bowley@bowley.org,http://www.knightsinn.com -Blair,Malet,Bollinger Mach Shp & Shipyard,209 Decker Dr,Philadelphia,Philadelphia,PA,19132,215-907-9111,215-794-4519,bmalet@yahoo.com,http://www.bollingermachshpshipyard.com -Brock,Bolognia,Orinda News,4486 W O St #1,New York,New York,NY,10003,212-402-9216,212-617-5063,bbolognia@yahoo.com,http://www.orindanews.com -Lorrie,Nestle,Ballard Spahr Andrews,39 S 7th St,Tullahoma,Coffee,TN,37388,931-875-6644,931-303-6041,lnestle@hotmail.com,http://www.ballardspahrandrews.com -Sabra,Uyetake,Lowy Limousine Service,98839 Hawthorne Blvd #6101,Columbia,Richland,SC,29201,803-925-5213,803-681-3678,sabra@uyetake.org,http://www.lowylimousineservice.com -Marjory,Mastella,Vicon Corporation,71 San Mateo Ave,Wayne,Delaware,PA,19087,610-814-5533,610-379-7125,mmastella@mastella.com,http://www.viconcorporation.com -Karl,Klonowski,"Rossi, Michael M",76 Brooks St #9,Flemington,Hunterdon,NJ,8822,908-877-6135,908-470-4661,karl_klonowski@yahoo.com,http://www.rossimichaelm.com -Tonette,Wenner,Northwest Publishing,4545 Courthouse Rd,Westbury,Nassau,NY,11590,516-968-6051,516-333-4861,twenner@aol.com,http://www.northwestpublishing.com -Amber,Monarrez,Branford Wire & Mfg Co,14288 Foster Ave #4121,Jenkintown,Montgomery,PA,19046,215-934-8655,215-329-6386,amber_monarrez@monarrez.org,http://www.branfordwiremfgco.com -Shenika,Seewald,East Coast Marketing,4 Otis St,Van Nuys,Los Angeles,CA,91405,818-423-4007,818-749-8650,shenika@gmail.com,http://www.eastcoastmarketing.com -Delmy,Ahle,Wye Technologies Inc,65895 S 16th St,Providence,Providence,RI,2909,401-458-2547,401-559-8961,delmy.ahle@hotmail.com,http://www.wyetechnologiesinc.com -Deeanna,Juhas,"Healy, George W Iv",14302 Pennsylvania Ave,Huntingdon Valley,Montgomery,PA,19006,215-211-9589,215-417-9563,deeanna_juhas@gmail.com,http://www.healygeorgewiv.com -Blondell,Pugh,Alpenlite Inc,201 Hawk Ct,Providence,Providence,RI,2904,401-960-8259,401-300-8122,bpugh@aol.com,http://www.alpenliteinc.com -Jamal,Vanausdal,"Hubbard, Bruce Esq",53075 Sw 152nd Ter #615,Monroe Township,Middlesex,NJ,8831,732-234-1546,732-904-2931,jamal@vanausdal.org,http://www.hubbardbruceesq.com -Cecily,Hollack,Arthur A Oliver & Son Inc,59 N Groesbeck Hwy,Austin,Travis,TX,78731,512-486-3817,512-861-3814,cecily@hollack.org,http://www.arthuraoliversoninc.com -Carmelina,Lindall,George Jessop Carter Jewelers,2664 Lewis Rd,Littleton,Douglas,CO,80126,303-724-7371,303-874-5160,carmelina_lindall@lindall.com,http://www.georgejessopcarterjewelers.com -Maurine,Yglesias,"Schultz, Thomas C Md",59 Shady Ln #53,Milwaukee,Milwaukee,WI,53214,414-748-1374,414-573-7719,maurine_yglesias@yglesias.com,http://www.schultzthomascmd.com -Tawna,Buvens,H H H Enterprises Inc,3305 Nabell Ave #679,New York,New York,NY,10009,212-674-9610,212-462-9157,tawna@gmail.com,http://www.hhhenterprisesinc.com -Penney,Weight,Hawaiian King Hotel,18 Fountain St,Anchorage,Anchorage,AK,99515,907-797-9628,907-873-2882,penney_weight@aol.com,http://www.hawaiiankinghotel.com -Elly,Morocco,Killion Industries,7 W 32nd St,Erie,Erie,PA,16502,814-393-5571,814-420-3553,elly_morocco@gmail.com,http://www.killionindustries.com -Ilene,Eroman,"Robinson, William J Esq",2853 S Central Expy,Glen Burnie,Anne Arundel,MD,21061,410-914-9018,410-937-4543,ilene.eroman@hotmail.com,http://www.robinsonwilliamjesq.com -Vallie,Mondella,Private Properties,74 W College St,Boise,Ada,ID,83707,208-862-5339,208-737-8439,vmondella@mondella.com,http://www.privateproperties.com -Kallie,Blackwood,Rowley Schlimgen Inc,701 S Harrison Rd,San Francisco,San Francisco,CA,94104,415-315-2761,415-604-7609,kallie.blackwood@gmail.com,http://www.rowleyschlimgeninc.com -Johnetta,Abdallah,Forging Specialties,1088 Pinehurst St,Chapel Hill,Orange,NC,27514,919-225-9345,919-715-3791,johnetta_abdallah@aol.com,http://www.forgingspecialties.com -Bobbye,Rhym,"Smits, Patricia Garity",30 W 80th St #1995,San Carlos,San Mateo,CA,94070,650-528-5783,650-811-9032,brhym@rhym.com,http://www.smitspatriciagarity.com -Micaela,Rhymes,H Lee Leonard Attorney At Law,20932 Hedley St,Concord,Contra Costa,CA,94520,925-647-3298,925-522-7798,micaela_rhymes@gmail.com,http://www.hleeleonardattorneyatlaw.com -Tamar,Hoogland,A K Construction Co,2737 Pistorio Rd #9230,London,Madison,OH,43140,740-343-8575,740-526-5410,tamar@hotmail.com,http://www.akconstructionco.com -Moon,Parlato,"Ambelang, Jessica M Md",74989 Brandon St,Wellsville,Allegany,NY,14895,585-866-8313,585-498-4278,moon@yahoo.com,http://www.ambelangjessicammd.com -Laurel,Reitler,Q A Service,6 Kains Ave,Baltimore,Baltimore City,MD,21215,410-520-4832,410-957-6903,laurel_reitler@reitler.com,http://www.qaservice.com -Delisa,Crupi,Wood & Whitacre Contractors,47565 W Grand Ave,Newark,Essex,NJ,7105,973-354-2040,973-847-9611,delisa.crupi@crupi.com,http://www.woodwhitacrecontractors.com -Viva,Toelkes,Mark Iv Press Ltd,4284 Dorigo Ln,Chicago,Cook,IL,60647,773-446-5569,773-352-3437,viva.toelkes@gmail.com,http://www.markivpressltd.com -Elza,Lipke,Museum Of Science & Industry,6794 Lake Dr E,Newark,Essex,NJ,7104,973-927-3447,973-796-3667,elza@yahoo.com,http://www.museumofscienceindustry.com -Devorah,Chickering,Garrison Ind,31 Douglas Blvd #950,Clovis,Curry,NM,88101,505-975-8559,505-950-1763,devorah@hotmail.com,http://www.garrisonind.com -Timothy,Mulqueen,Saronix Nymph Products,44 W 4th St,Staten Island,Richmond,NY,10309,718-332-6527,718-654-7063,timothy_mulqueen@mulqueen.org,http://www.saronixnymphproducts.com -Arlette,Honeywell,Smc Inc,11279 Loytan St,Jacksonville,Duval,FL,32254,904-775-4480,904-514-9918,ahoneywell@honeywell.com,http://www.smcinc.com -Dominque,Dickerson,E A I Electronic Assocs Inc,69 Marquette Ave,Hayward,Alameda,CA,94545,510-993-3758,510-901-7640,dominque.dickerson@dickerson.org,http://www.eaielectronicassocsinc.com -Lettie,Isenhower,"Conte, Christopher A Esq",70 W Main St,Beachwood,Cuyahoga,OH,44122,216-657-7668,216-733-8494,lettie_isenhower@yahoo.com,http://www.contechristopheraesq.com -Myra,Munns,Anker Law Office,461 Prospect Pl #316,Euless,Tarrant,TX,76040,817-914-7518,817-451-3518,mmunns@cox.net,http://www.ankerlawoffice.com -Stephaine,Barfield,Beutelschies & Company,47154 Whipple Ave Nw,Gardena,Los Angeles,CA,90247,310-774-7643,310-968-1219,stephaine@barfield.com,http://www.beutelschiescompany.com -Lai,Gato,"Fligg, Kenneth I Jr",37 Alabama Ave,Evanston,Cook,IL,60201,847-728-7286,847-957-4614,lai.gato@gato.org,http://www.fliggkennethijr.com -Stephen,Emigh,"Sharp, J Daniel Esq",3777 E Richmond St #900,Akron,Summit,OH,44302,330-537-5358,330-700-2312,stephen_emigh@hotmail.com,http://www.sharpjdanielesq.com -Tyra,Shields,"Assink, Anne H Esq",3 Fort Worth Ave,Philadelphia,Philadelphia,PA,19106,215-255-1641,215-228-8264,tshields@gmail.com,http://www.assinkannehesq.com -Tammara,Wardrip,Jewel My Shop Inc,4800 Black Horse Pike,Burlingame,San Mateo,CA,94010,650-803-1936,650-216-5075,twardrip@cox.net,http://www.jewelmyshopinc.com -Cory,Gibes,Chinese Translation Resources,83649 W Belmont Ave,San Gabriel,Los Angeles,CA,91776,626-572-1096,626-696-2777,cory.gibes@gmail.com,http://www.chinesetranslationresources.com -Danica,Bruschke,"Stevens, Charles T",840 15th Ave,Waco,McLennan,TX,76708,254-782-8569,254-205-1422,danica_bruschke@gmail.com,http://www.stevenscharlest.com -Wilda,Giguere,"Mclaughlin, Luther W Cpa",1747 Calle Amanecer #2,Anchorage,Anchorage,AK,99501,907-870-5536,907-914-9482,wilda@cox.net,http://www.mclaughlinlutherwcpa.com -Elvera,Benimadho,Tree Musketeers,99385 Charity St #840,San Jose,Santa Clara,CA,95110,408-703-8505,408-440-8447,elvera.benimadho@cox.net,http://www.treemusketeers.com -Carma,Vanheusen,Springfield Div Oh Edison Co,68556 Central Hwy,San Leandro,Alameda,CA,94577,510-503-7169,510-452-4835,carma@cox.net,http://www.springfielddivohedisonco.com -Malinda,Hochard,Logan Memorial Hospital,55 Riverside Ave,Indianapolis,Marion,IN,46202,317-722-5066,317-472-2412,malinda.hochard@yahoo.com,http://www.loganmemorialhospital.com -Natalie,Fern,"Kelly, Charles G Esq",7140 University Ave,Rock Springs,Sweetwater,WY,82901,307-704-8713,307-279-3793,natalie.fern@hotmail.com,http://www.kellycharlesgesq.com -Lisha,Centini,Industrial Paper Shredders Inc,64 5th Ave #1153,Mc Lean,Fairfax,VA,22102,703-235-3937,703-475-7568,lisha@centini.org,http://www.industrialpapershreddersinc.com -Arlene,Klusman,Beck Horizon Builders,3 Secor Rd,New Orleans,Orleans,LA,70112,504-710-5840,504-946-1807,arlene_klusman@gmail.com,http://www.beckhorizonbuilders.com -Alease,Buemi,Porto Cayo At Hawks Cay,4 Webbs Chapel Rd,Boulder,Boulder,CO,80303,303-301-4946,303-521-9860,alease@buemi.com,http://www.portocayoathawkscay.com -Louisa,Cronauer,Pacific Grove Museum Ntrl Hist,524 Louisiana Ave Nw,San Leandro,Alameda,CA,94577,510-828-7047,510-472-7758,louisa@cronauer.com,http://www.pacificgrovemuseumntrlhist.com -Angella,Cetta,Bender & Hatley Pc,185 Blackstone Bldge,Honolulu,Honolulu,HI,96817,808-892-7943,808-475-2310,angella.cetta@hotmail.com,http://www.benderhatleypc.com -Cyndy,Goldammer,Di Cristina J & Son,170 Wyoming Ave,Burnsville,Dakota,MN,55337,952-334-9408,952-938-9457,cgoldammer@cox.net,http://www.dicristinajson.com -Rosio,Cork,Green Goddess,4 10th St W,High Point,Guilford,NC,27263,336-243-5659,336-497-4407,rosio.cork@gmail.com,http://www.greengoddess.com -Celeste,Korando,American Arts & Graphics,7 W Pinhook Rd,Lynbrook,Nassau,NY,11563,516-509-2347,516-365-7266,ckorando@hotmail.com,http://www.americanartsgraphics.com -Twana,Felger,Opryland Hotel,1 Commerce Way,Portland,Washington,OR,97224,503-939-3153,503-909-7167,twana.felger@felger.org,http://www.oprylandhotel.com -Estrella,Samu,Marking Devices Pubg Co,64 Lakeview Ave,Beloit,Rock,WI,53511,608-976-7199,608-942-8836,estrella@aol.com,http://www.markingdevicespubgco.com -Donte,Kines,W Tc Industries Inc,3 Aspen St,Worcester,Worcester,MA,1602,508-429-8576,508-843-1426,dkines@hotmail.com,http://www.wtcindustriesinc.com -Tiffiny,Steffensmeier,Whitehall Robbins Labs Divsn,32860 Sierra Rd,Miami,Miami-Dade,FL,33133,305-385-9695,305-304-6573,tiffiny_steffensmeier@cox.net,http://www.whitehallrobbinslabsdivsn.com -Edna,Miceli,Sampler,555 Main St,Erie,Erie,PA,16502,814-460-2655,814-299-2877,emiceli@miceli.org,http://www.sampler.com -Sue,Kownacki,Juno Chefs Incorporated,2 Se 3rd Ave,Mesquite,Dallas,TX,75149,972-666-3413,972-742-4000,sue@aol.com,http://www.junochefsincorporated.com -Jesusa,Shin,"Carroccio, A Thomas Esq",2239 Shawnee Mission Pky,Tullahoma,Coffee,TN,37388,931-273-8709,931-739-1551,jshin@shin.com,http://www.carroccioathomasesq.com -Rolland,Francescon,"Stanley, Richard L Esq",2726 Charcot Ave,Paterson,Passaic,NJ,7501,973-649-2922,973-284-4048,rolland@cox.net,http://www.stanleyrichardlesq.com -Pamella,Schmierer,K Cs Cstm Mouldings Windows,5161 Dorsett Rd,Homestead,Miami-Dade,FL,33030,305-420-8970,305-575-8481,pamella.schmierer@schmierer.org,http://www.kcscstmmouldingswindows.com -Glory,Kulzer,Comfort Inn,55892 Jacksonville Rd,Owings Mills,Baltimore,MD,21117,410-224-9462,410-916-8015,gkulzer@kulzer.org,http://www.comfortinn.com -Shawna,Palaspas,"Windsor, James L Esq",5 N Cleveland Massillon Rd,Thousand Oaks,Ventura,CA,91362,805-275-3566,805-638-6617,shawna_palaspas@palaspas.org,http://www.windsorjameslesq.com -Brandon,Callaro,Jackson Shields Yeiser,7 Benton Dr,Honolulu,Honolulu,HI,96819,808-215-6832,808-240-5168,brandon_callaro@hotmail.com,http://www.jacksonshieldsyeiser.com -Scarlet,Cartan,"Box, J Calvin Esq",9390 S Howell Ave,Albany,Dougherty,GA,31701,229-735-3378,229-365-9658,scarlet.cartan@yahoo.com,http://www.boxjcalvinesq.com -Oretha,Menter,Custom Engineering Inc,8 County Center Dr #647,Boston,Suffolk,MA,2210,617-418-5043,617-697-6024,oretha_menter@yahoo.com,http://www.customengineeringinc.com -Ty,Smith,Bresler Eitel Framg Gllry Ltd,4646 Kaahumanu St,Hackensack,Bergen,NJ,7601,201-672-1553,201-995-3149,tsmith@aol.com,http://www.breslereitelframggllryltd.com -Xuan,Rochin,"Carol, Drake Sparks Esq",2 Monroe St,San Mateo,San Mateo,CA,94403,650-933-5072,650-247-2625,xuan@gmail.com,http://www.caroldrakesparksesq.com -Lindsey,Dilello,Biltmore Investors Bank,52777 Leaders Heights Rd,Ontario,San Bernardino,CA,91761,909-639-9887,909-589-1693,lindsey.dilello@hotmail.com,http://www.biltmoreinvestorsbank.com -Devora,Perez,Desco Equipment Corp,72868 Blackington Ave,Oakland,Alameda,CA,94606,510-955-3016,510-755-9274,devora_perez@perez.org,http://www.descoequipmentcorp.com -Herman,Demesa,Merlin Electric Co,9 Norristown Rd,Troy,Rensselaer,NY,12180,518-497-2940,518-931-7852,hdemesa@cox.net,http://www.merlinelectricco.com -Rory,Papasergi,Bailey Cntl Co Div Babcock,83 County Road 437 #8581,Clarks Summit,Lackawanna,PA,18411,570-867-7489,570-469-8401,rpapasergi@cox.net,http://www.baileycntlcodivbabcock.com -Talia,Riopelle,Ford Brothers Wholesale Inc,1 N Harlem Ave #9,Orange,Essex,NJ,7050,973-245-2133,973-818-9788,talia_riopelle@aol.com,http://www.fordbrotherswholesaleinc.com -Van,Shire,Cambridge Inn,90131 J St,Pittstown,Hunterdon,NJ,8867,908-409-2890,908-448-1209,van.shire@shire.com,http://www.cambridgeinn.com -Lucina,Lary,"Matricciani, Albert J Jr",8597 W National Ave,Cocoa,Brevard,FL,32922,321-749-4981,321-632-4668,lucina_lary@cox.net,http://www.matriccianialbertjjr.com -Bok,Isaacs,Nelson Hawaiian Ltd,6 Gilson St,Bronx,Bronx,NY,10468,718-809-3762,718-478-8568,bok.isaacs@aol.com,http://www.nelsonhawaiianltd.com -Rolande,Spickerman,Neland Travel Agency,65 W Maple Ave,Pearl City,Honolulu,HI,96782,808-315-3077,808-526-5863,rolande.spickerman@spickerman.com,http://www.nelandtravelagency.com -Howard,Paulas,"Asendorf, J Alan Esq",866 34th Ave,Denver,Denver,CO,80231,303-623-4241,303-692-3118,hpaulas@gmail.com,http://www.asendorfjalanesq.com -Kimbery,Madarang,"Silberman, Arthur L Esq",798 Lund Farm Way,Rockaway,Morris,NJ,7866,973-310-1634,973-225-6259,kimbery_madarang@cox.net,http://www.silbermanarthurlesq.com -Thurman,Manno,Honey Bee Breeding Genetics &,9387 Charcot Ave,Absecon,Atlantic,NJ,8201,609-524-3586,609-234-8376,thurman.manno@yahoo.com,http://www.honeybeebreedinggenetics.com -Becky,Mirafuentes,Wells Kravitz Schnitzer,30553 Washington Rd,Plainfield,Union,NJ,7062,908-877-8409,908-426-8272,becky.mirafuentes@mirafuentes.com,http://www.wellskravitzschnitzer.com -Beatriz,Corrington,Prohab Rehabilitation Servs,481 W Lemon St,Middleboro,Plymouth,MA,2346,508-584-4279,508-315-3867,beatriz@yahoo.com,http://www.prohabrehabilitationservs.com -Marti,Maybury,"Eldridge, Kristin K Esq",4 Warehouse Point Rd #7,Chicago,Cook,IL,60638,773-775-4522,773-539-1058,marti.maybury@yahoo.com,http://www.eldridgekristinkesq.com -Nieves,Gotter,"Vlahos, John J Esq",4940 Pulaski Park Dr,Portland,Multnomah,OR,97202,503-527-5274,503-455-3094,nieves_gotter@gmail.com,http://www.vlahosjohnjesq.com -Leatha,Hagele,Ninas Indian Grs & Videos,627 Walford Ave,Dallas,Dallas,TX,75227,214-339-1809,214-225-5850,lhagele@cox.net,http://www.ninasindiangrsvideos.com -Valentin,Klimek,"Schmid, Gayanne K Esq",137 Pioneer Way,Chicago,Cook,IL,60604,312-303-5453,312-512-2338,vklimek@klimek.org,http://www.schmidgayannekesq.com -Melissa,Wiklund,Moapa Valley Federal Credit Un,61 13 Stoneridge #835,Findlay,Hancock,OH,45840,419-939-3613,419-254-4591,melissa@cox.net,http://www.moapavalleyfederalcreditun.com -Sheridan,Zane,Kentucky Tennessee Clay Co,2409 Alabama Rd,Riverside,Riverside,CA,92501,951-645-3605,951-248-6822,sheridan.zane@zane.com,http://www.kentuckytennesseeclayco.com -Bulah,Padilla,Admiral Party Rentals & Sales,8927 Vandever Ave,Waco,McLennan,TX,76707,254-463-4368,254-816-8417,bulah_padilla@hotmail.com,http://www.admiralpartyrentalssales.com -Audra,Kohnert,"Nelson, Karolyn King Esq",134 Lewis Rd,Nashville,Davidson,TN,37211,615-406-7854,615-448-9249,audra@kohnert.com,http://www.nelsonkarolynkingesq.com -Daren,Weirather,Panasystems,9 N College Ave #3,Milwaukee,Milwaukee,WI,53216,414-959-2540,414-838-3151,dweirather@aol.com,http://www.panasystems.com -Fernanda,Jillson,"Shank, Edward L Esq",60480 Old Us Highway 51,Preston,Caroline,MD,21655,410-387-5260,410-724-6472,fjillson@aol.com,http://www.shankedwardlesq.com -Gearldine,Gellinger,Megibow & Edwards,4 Bloomfield Ave,Irving,Dallas,TX,75061,972-934-6914,972-821-7118,gearldine_gellinger@gellinger.com,http://www.megibowedwards.com -Chau,Kitzman,"Benoff, Edward Esq",429 Tiger Ln,Beverly Hills,Los Angeles,CA,90212,310-560-8022,310-969-7230,chau@gmail.com,http://www.benoffedwardesq.com -Theola,Frey,Woodbridge Free Public Library,54169 N Main St,Massapequa,Nassau,NY,11758,516-948-5768,516-357-3362,theola_frey@frey.com,http://www.woodbridgefreepubliclibrary.com -Cheryl,Haroldson,New York Life John Thune,92 Main St,Atlantic City,Atlantic,NJ,8401,609-518-7697,609-263-9243,cheryl@haroldson.org,http://www.newyorklifejohnthune.com -Laticia,Merced,Alinabal Inc,72 Mannix Dr,Cincinnati,Hamilton,OH,45203,513-508-7371,513-418-1566,lmerced@gmail.com,http://www.alinabalinc.com -Carissa,Batman,"Poletto, Kim David Esq",12270 Caton Center Dr,Eugene,Lane,OR,97401,541-326-4074,541-801-5717,carissa.batman@yahoo.com,http://www.polettokimdavidesq.com -Lezlie,Craghead,"Chang, Carolyn Esq",749 W 18th St #45,Smithfield,Johnston,NC,27577,919-533-3762,919-885-2453,lezlie.craghead@craghead.org,http://www.changcarolynesq.com -Ozell,Shealy,Silver Bros Inc,8 Industry Ln,New York,New York,NY,10002,212-332-8435,212-880-8865,oshealy@hotmail.com,http://www.silverbrosinc.com -Arminda,Parvis,Newtec Inc,1 Huntwood Ave,Phoenix,Maricopa,AZ,85017,602-906-9419,602-277-3025,arminda@parvis.com,http://www.newtecinc.com -Reita,Leto,Creative Business Systems,55262 N French Rd,Indianapolis,Marion,IN,46240,317-234-1135,317-787-5514,reita.leto@gmail.com,http://www.creativebusinesssystems.com -Yolando,Luczki,Dal Tile Corporation,422 E 21st St,Syracuse,Onondaga,NY,13214,315-304-4759,315-640-6357,yolando@cox.net,http://www.daltilecorporation.com -Lizette,Stem,Edward S Katz,501 N 19th Ave,Cherry Hill,Camden,NJ,8002,856-487-5412,856-702-3676,lizette.stem@aol.com,http://www.edwardskatz.com -Gregoria,Pawlowicz,Oh My Goodknits Inc,455 N Main Ave,Garden City,Nassau,NY,11530,516-212-1915,516-376-4230,gpawlowicz@yahoo.com,http://www.ohmygoodknitsinc.com -Carin,Deleo,"Redeker, Debbie",1844 Southern Blvd,Little Rock,Pulaski,AR,72202,501-308-1040,501-409-6072,cdeleo@deleo.com,http://www.redekerdebbie.com -Chantell,Maynerich,Desert Sands Motel,2023 Greg St,Saint Paul,Ramsey,MN,55101,651-591-2583,651-776-9688,chantell@yahoo.com,http://www.desertsandsmotel.com -Dierdre,Yum,Cummins Southern Plains Inc,63381 Jenks Ave,Philadelphia,Philadelphia,PA,19134,215-325-3042,215-346-4666,dyum@yahoo.com,http://www.cumminssouthernplainsinc.com -Larae,Gudroe,Lehigh Furn Divsn Lehigh,6651 Municipal Rd,Houma,Terrebonne,LA,70360,985-890-7262,985-261-5783,larae_gudroe@gmail.com,http://www.lehighfurndivsnlehigh.com -Latrice,Tolfree,United Van Lines Agent,81 Norris Ave #525,Ronkonkoma,Suffolk,NY,11779,631-957-7624,631-998-2102,latrice.tolfree@hotmail.com,http://www.unitedvanlinesagent.com -Kerry,Theodorov,Capitol Reporters,6916 W Main St,Sacramento,Sacramento,CA,95827,916-591-3277,916-770-7448,kerry.theodorov@gmail.com,http://www.capitolreporters.com -Dorthy,Hidvegi,Kwik Kopy Printing,9635 S Main St,Boise,Ada,ID,83704,208-649-2373,208-690-3315,dhidvegi@yahoo.com,http://www.kwikkopyprinting.com -Fannie,Lungren,Centro Inc,17 Us Highway 111,Round Rock,Williamson,TX,78664,512-587-5746,512-528-9933,fannie.lungren@yahoo.com,http://www.centroinc.com -Evangelina,Radde,"Campbell, Jan Esq",992 Civic Center Dr,Philadelphia,Philadelphia,PA,19123,215-964-3284,215-417-5612,evangelina@aol.com,http://www.campbelljanesq.com -Novella,Degroot,"Evans, C Kelly Esq",303 N Radcliffe St,Hilo,Hawaii,HI,96720,808-477-4775,808-746-1865,novella_degroot@degroot.org,http://www.evansckellyesq.com -Clay,Hoa,Scat Enterprises,73 Saint Ann St #86,Reno,Washoe,NV,89502,775-501-8109,775-848-9135,choa@hoa.org,http://www.scatenterprises.com -Jennifer,Fallick,"Nagle, Daniel J Esq",44 58th St,Wheeling,Cook,IL,60090,847-979-9545,847-800-3054,jfallick@yahoo.com,http://www.nagledanieljesq.com -Irma,Wolfgramm,Serendiquity Bed & Breakfast,9745 W Main St,Randolph,Morris,NJ,7869,973-545-7355,973-868-8660,irma.wolfgramm@hotmail.com,http://www.serendiquitybedbreakfast.com -Eun,Coody,Ray Carolyne Realty,84 Bloomfield Ave,Spartanburg,Spartanburg,SC,29301,864-256-3620,864-594-4578,eun@yahoo.com,http://www.raycarolynerealty.com -Sylvia,Cousey,"Berg, Charles E",287 Youngstown Warren Rd,Hampstead,Carroll,MD,21074,410-209-9545,410-863-8263,sylvia_cousey@cousey.org,http://www.bergcharlese.com -Nana,Wrinkles,"Ray, Milbern D",6 Van Buren St,Mount Vernon,Westchester,NY,10553,914-855-2115,914-796-3775,nana@aol.com,http://www.raymilbernd.com -Layla,Springe,Chadds Ford Winery,229 N Forty Driv,New York,New York,NY,10011,212-260-3151,212-253-7448,layla.springe@cox.net,http://www.chaddsfordwinery.com -Joesph,Degonia,A R Packaging,2887 Knowlton St #5435,Berkeley,Alameda,CA,94710,510-677-9785,510-942-5916,joesph_degonia@degonia.org,http://www.arpackaging.com -Annabelle,Boord,Corn Popper,523 Marquette Ave,Concord,Middlesex,MA,1742,978-697-6263,978-289-7717,annabelle.boord@cox.net,http://www.cornpopper.com -Stephaine,Vinning,Birite Foodservice Distr,3717 Hamann Industrial Pky,San Francisco,San Francisco,CA,94104,415-767-6596,415-712-9530,stephaine@cox.net,http://www.biritefoodservicedistr.com -Nelida,Sawchuk,Anchorage Museum Of Hist & Art,3 State Route 35 S,Paramus,Bergen,NJ,7652,201-971-1638,201-247-8925,nelida@gmail.com,http://www.anchoragemuseumofhistart.com -Marguerita,Hiatt,"Haber, George D Md",82 N Highway 67,Oakley,Contra Costa,CA,94561,925-634-7158,925-541-8521,marguerita.hiatt@gmail.com,http://www.habergeorgedmd.com -Carmela,Cookey,Royal Pontiac Olds Inc,9 Murfreesboro Rd,Chicago,Cook,IL,60623,773-494-4195,773-297-9391,ccookey@cookey.org,http://www.royalpontiacoldsinc.com -Junita,Brideau,Leonards Antiques Inc,6 S Broadway St,Cedar Grove,Essex,NJ,7009,973-943-3423,973-582-5469,jbrideau@aol.com,http://www.leonardsantiquesinc.com -Claribel,Varriano,Meca,6 Harry L Dr #6327,Perrysburg,Wood,OH,43551,419-544-4900,419-573-2033,claribel_varriano@cox.net,http://www.meca.com -Benton,Skursky,Nercon Engineering & Mfg Inc,47939 Porter Ave,Gardena,Los Angeles,CA,90248,310-579-2907,310-694-8466,benton.skursky@aol.com,http://www.nerconengineeringmfginc.com -Hillary,Skulski,Replica I,9 Wales Rd Ne #914,Homosassa,Citrus,FL,34448,352-242-2570,352-990-5946,hillary.skulski@aol.com,http://www.replicai.com -Merilyn,Bayless,20 20 Printing Inc,195 13n N,Santa Clara,Santa Clara,CA,95054,408-758-5015,408-346-2180,merilyn_bayless@cox.net,http://www.printinginc.com -Teri,Ennaco,Publishers Group West,99 Tank Farm Rd,Hazleton,Luzerne,PA,18201,570-889-5187,570-355-1665,tennaco@gmail.com,http://www.publishersgroupwest.com -Merlyn,Lawler,"Nischwitz, Jeffrey L Esq",4671 Alemany Blvd,Jersey City,Hudson,NJ,7304,201-588-7810,201-858-9960,merlyn_lawler@hotmail.com,http://www.nischwitzjeffreylesq.com -Georgene,Montezuma,Payne Blades & Wellborn Pa,98 University Dr,San Ramon,Contra Costa,CA,94583,925-615-5185,925-943-3449,gmontezuma@cox.net,http://www.paynebladeswellbornpa.com -Jettie,Mconnell,Coldwell Bnkr Wright Real Est,50 E Wacker Dr,Bridgewater,Somerset,NJ,8807,908-802-3564,908-602-5258,jmconnell@hotmail.com,http://www.coldwellbnkrwrightrealest.com -Lemuel,Latzke,Computer Repair Service,70 Euclid Ave #722,Bohemia,Suffolk,NY,11716,631-748-6479,631-291-4976,lemuel.latzke@gmail.com,http://www.computerrepairservice.com -Melodie,Knipp,Fleetwood Building Block Inc,326 E Main St #6496,Thousand Oaks,Ventura,CA,91362,805-690-1682,805-810-8964,mknipp@gmail.com,http://www.fleetwoodbuildingblockinc.com -Candida,Corbley,Colts Neck Medical Assocs Inc,406 Main St,Somerville,Somerset,NJ,8876,908-275-8357,908-943-6103,candida_corbley@hotmail.com,http://www.coltsneckmedicalassocsinc.com -Karan,Karpin,New England Taxidermy,3 Elmwood Dr,Beaverton,Washington,OR,97005,503-940-8327,503-707-5812,karan_karpin@gmail.com,http://www.newenglandtaxidermy.com -Andra,Scheyer,"Ludcke, George O Esq",9 Church St,Salem,Marion,OR,97302,503-516-2189,503-950-3068,andra@gmail.com,http://www.ludckegeorgeoesq.com -Felicidad,Poullion,"Mccorkle, Tom S Esq",9939 N 14th St,Riverton,Burlington,NJ,8077,856-305-9731,856-828-6021,fpoullion@poullion.com,http://www.mccorkletomsesq.com -Belen,Strassner,Eagle Software Inc,5384 Southwyck Blvd,Douglasville,Douglas,GA,30135,770-507-8791,770-802-4003,belen_strassner@aol.com,http://www.eaglesoftwareinc.com -Gracia,Melnyk,Juvenile & Adult Super,97 Airport Loop Dr,Jacksonville,Duval,FL,32216,904-235-3633,904-627-4341,gracia@melnyk.com,http://www.juvenileadultsuper.com -Jolanda,Hanafan,"Perez, Joseph J Esq",37855 Nolan Rd,Bangor,Penobscot,ME,4401,207-458-9196,207-233-6185,jhanafan@gmail.com,http://www.perezjosephjesq.com -Barrett,Toyama,Case Foundation Co,4252 N Washington Ave #9,Kennedale,Tarrant,TX,76060,817-765-5781,817-577-6151,barrett.toyama@toyama.org,http://www.casefoundationco.com -Helga,Fredicks,Eis Environmental Engrs Inc,42754 S Ash Ave,Buffalo,Erie,NY,14228,716-752-4114,716-854-9845,helga_fredicks@yahoo.com,http://www.eisenvironmentalengrsinc.com -Ashlyn,Pinilla,Art Crafters,703 Beville Rd,Opa Locka,Miami-Dade,FL,33054,305-670-9628,305-857-5489,apinilla@cox.net,http://www.artcrafters.com -Fausto,Agramonte,Marriott Hotels Resorts Suites,5 Harrison Rd,New York,New York,NY,10038,212-313-1783,212-778-3063,fausto_agramonte@yahoo.com,http://www.marriotthotelsresortssuites.com -Ronny,Caiafa,Remaco Inc,73 Southern Blvd,Philadelphia,Philadelphia,PA,19103,215-605-7570,215-511-3531,ronny.caiafa@caiafa.org,http://www.remacoinc.com -Marge,Limmel,"Bjork, Robert D Jr",189 Village Park Rd,Crestview,Okaloosa,FL,32536,850-430-1663,850-330-8079,marge@gmail.com,http://www.bjorkrobertdjr.com -Norah,Waymire,"Carmichael, Jeffery L Esq",6 Middlegate Rd #106,San Francisco,San Francisco,CA,94107,415-306-7897,415-874-2984,norah.waymire@gmail.com,http://www.carmichaeljefferylesq.com -Aliza,Baltimore,"Andrews, J Robert Esq",1128 Delaware St,San Jose,Santa Clara,CA,95132,408-504-3552,408-425-1994,aliza@aol.com,http://www.andrewsjrobertesq.com -Mozell,Pelkowski,Winship & Byrne,577 Parade St,South San Francisco,San Mateo,CA,94080,650-947-1215,650-960-1069,mpelkowski@pelkowski.org,http://www.winshipbyrne.com -Viola,Bitsuie,Burton & Davis,70 Mechanic St,Northridge,Los Angeles,CA,91325,818-864-4875,818-481-5787,viola@gmail.com,http://www.burtondavis.com -Franklyn,Emard,Olympic Graphic Arts,4379 Highway 116,Philadelphia,Philadelphia,PA,19103,215-558-8189,215-483-3003,femard@emard.com,http://www.olympicgraphicarts.com -Willodean,Konopacki,Magnuson,55 Hawthorne Blvd,Lafayette,Lafayette,LA,70506,337-253-8384,337-774-7564,willodean_konopacki@konopacki.org,http://www.magnuson.com -Beckie,Silvestrini,A All American Travel Inc,7116 Western Ave,Dearborn,Wayne,MI,48126,313-533-4884,313-390-7855,beckie.silvestrini@silvestrini.com,http://www.aallamericantravelinc.com -Rebecka,Gesick,Polykote Inc,2026 N Plankinton Ave #3,Austin,Travis,TX,78754,512-213-8574,512-693-8345,rgesick@gesick.org,http://www.polykoteinc.com -Frederica,Blunk,Jets Cybernetics,99586 Main St,Dallas,Dallas,TX,75207,214-428-2285,214-529-1949,frederica_blunk@gmail.com,http://www.jetscybernetics.com -Glen,Bartolet,Metlab Testing Services,8739 Hudson St,Vashon,King,WA,98070,206-697-5796,206-389-1482,glen_bartolet@hotmail.com,http://www.metlabtestingservices.com -Freeman,Gochal,"Kellermann, William T Esq",383 Gunderman Rd #197,Coatesville,Chester,PA,19320,610-476-3501,610-752-2683,freeman_gochal@aol.com,http://www.kellermannwilliamtesq.com -Vincent,Meinerding,"Arturi, Peter D Esq",4441 Point Term Mkt,Philadelphia,Philadelphia,PA,19143,215-372-1718,215-829-4221,vincent.meinerding@hotmail.com,http://www.arturipeterdesq.com -Rima,Bevelacqua,Mcauley Mfg Co,2972 Lafayette Ave,Gardena,Los Angeles,CA,90248,310-858-5079,310-499-4200,rima@cox.net,http://www.mcauleymfgco.com -Glendora,Sarbacher,Defur Voran Hanley Radcliff,2140 Diamond Blvd,Rohnert Park,Sonoma,CA,94928,707-653-8214,707-881-3154,gsarbacher@gmail.com,http://www.defurvoranhanleyradcliff.com -Avery,Steier,Dill Dill Carr & Stonbraker Pc,93 Redmond Rd #492,Orlando,Orange,FL,32803,407-808-9439,407-945-8566,avery@cox.net,http://www.dilldillcarrstonbrakerpc.com -Cristy,Lother,Kleensteel,3989 Portage Tr,Escondido,San Diego,CA,92025,760-971-4322,760-465-4762,cristy@lother.com,http://www.kleensteel.com -Nicolette,Brossart,Goulds Pumps Inc Slurry Pump,1 Midway Rd,Westborough,Worcester,MA,1581,508-837-9230,508-504-6388,nicolette_brossart@brossart.com,http://www.gouldspumpsincslurrypump.com -Tracey,Modzelewski,Kansas City Insurance Report,77132 Coon Rapids Blvd Nw,Conroe,Montgomery,TX,77301,936-264-9294,936-988-8171,tracey@hotmail.com,http://www.kansascityinsurancereport.com -Virgina,Tegarden,Berhanu International Foods,755 Harbor Way,Milwaukee,Milwaukee,WI,53226,414-214-8697,414-411-5744,virgina_tegarden@tegarden.com,http://www.berhanuinternationalfoods.com -Tiera,Frankel,Roland Ashcroft,87 Sierra Rd,El Monte,Los Angeles,CA,91731,626-636-4117,626-638-4241,tfrankel@aol.com,http://www.rolandashcroft.com -Alaine,Bergesen,Hispanic Magazine,7667 S Hulen St #42,Yonkers,Westchester,NY,10701,914-300-9193,914-654-1426,alaine_bergesen@cox.net,http://www.hispanicmagazine.com -Earleen,Mai,Little Sheet Metal Co,75684 S Withlapopka Dr #32,Dallas,Dallas,TX,75227,214-289-1973,214-785-6750,earleen_mai@cox.net,http://www.littlesheetmetalco.com -Leonida,Gobern,"Holmes, Armstead J Esq",5 Elmwood Park Blvd,Biloxi,Harrison,MS,39530,228-235-5615,228-432-4635,leonida@gobern.org,http://www.holmesarmsteadjesq.com -Ressie,Auffrey,"Faw, James C Cpa",23 Palo Alto Sq,Miami,Miami-Dade,FL,33134,305-604-8981,305-287-4743,ressie.auffrey@yahoo.com,http://www.fawjamesccpa.com -Justine,Mugnolo,Evans Rule Company,38062 E Main St,New York,New York,NY,10048,212-304-9225,212-311-6377,jmugnolo@yahoo.com,http://www.evansrulecompany.com -Eladia,Saulter,Tyee Productions Inc,3958 S Dupont Hwy #7,Ramsey,Bergen,NJ,7446,201-474-4924,201-365-8698,eladia@saulter.com,http://www.tyeeproductionsinc.com -Chaya,Malvin,Dunnells & Duvall,560 Civic Center Dr,Ann Arbor,Washtenaw,MI,48103,734-928-5182,734-408-8174,chaya@malvin.com,http://www.dunnellsduvall.com -Gwenn,Suffield,Deltam Systems Inc,3270 Dequindre Rd,Deer Park,Suffolk,NY,11729,631-258-6558,631-295-9879,gwenn_suffield@suffield.org,http://www.deltamsystemsinc.com -Salena,Karpel,Hammill Mfg Co,1 Garfield Ave #7,Canton,Stark,OH,44707,330-791-8557,330-618-2579,skarpel@cox.net,http://www.hammillmfgco.com -Yoko,Fishburne,Sams Corner Store,9122 Carpenter Ave,New Haven,New Haven,CT,6511,203-506-4706,203-840-8634,yoko@fishburne.com,http://www.samscornerstore.com -Taryn,Moyd,"Siskin, Mark J Esq",48 Lenox St,Fairfax,Fairfax City,VA,22030,703-322-4041,703-938-7939,taryn.moyd@hotmail.com,http://www.siskinmarkjesq.com -Katina,Polidori,Cape & Associates Real Estate,5 Little River Tpke,Wilmington,Middlesex,MA,1887,978-626-2978,978-679-7429,katina_polidori@aol.com,http://www.capeassociatesrealestate.com -Rickie,Plumer,Merrill Lynch,3 N Groesbeck Hwy,Toledo,Lucas,OH,43613,419-693-1334,419-313-5571,rickie.plumer@aol.com,http://www.merrilllynch.com -Alex,Loader,"Sublett, Scott Esq",37 N Elm St #916,Tacoma,Pierce,WA,98409,253-660-7821,253-875-9222,alex@loader.com,http://www.sublettscottesq.com -Lashon,Vizarro,Sentry Signs,433 Westminster Blvd #590,Roseville,Placer,CA,95661,916-741-7884,916-289-4526,lashon@aol.com,http://www.sentrysigns.com -Lauran,Burnard,Professionals Unlimited,66697 Park Pl #3224,Riverton,Fremont,WY,82501,307-342-7795,307-453-7589,lburnard@burnard.com,http://www.professionalsunlimited.com -Ceola,Setter,Southern Steel Shelving Co,96263 Greenwood Pl,Warren,Knox,ME,4864,207-627-7565,207-297-5029,ceola.setter@setter.org,http://www.southernsteelshelvingco.com -My,Rantanen,"Bosco, Paul J",8 Mcarthur Ln,Richboro,Bucks,PA,18954,215-491-5633,215-647-2158,my@hotmail.com,http://www.boscopaulj.com -Lorrine,Worlds,"Longo, Nicholas J Esq",8 Fair Lawn Ave,Tampa,Hillsborough,FL,33614,813-769-2939,813-863-6467,lorrine.worlds@worlds.com,http://www.longonicholasjesq.com -Peggie,Sturiale,Henry County Middle School,9 N 14th St,El Cajon,San Diego,CA,92020,619-608-1763,619-695-8086,peggie@cox.net,http://www.henrycountymiddleschool.com -Marvel,Raymo,Edison Supply & Equipment Co,9 Vanowen St,College Station,Brazos,TX,77840,979-718-8968,979-809-5770,mraymo@yahoo.com,http://www.edisonsupplyequipmentco.com -Daron,Dinos,"Wolf, Warren R Esq",18 Waterloo Geneva Rd,Highland Park,Lake,IL,60035,847-233-3075,847-265-6609,daron_dinos@cox.net,http://www.wolfwarrenresq.com -An,Fritz,Linguistic Systems Inc,506 S Hacienda Dr,Atlantic City,Atlantic,NJ,8401,609-228-5265,609-854-7156,an_fritz@hotmail.com,http://www.linguisticsystemsinc.com -Portia,Stimmel,Peace Christian Center,3732 Sherman Ave,Bridgewater,Somerset,NJ,8807,908-722-7128,908-670-4712,portia.stimmel@aol.com,http://www.peacechristiancenter.com -Rhea,Aredondo,Double B Foods Inc,25657 Live Oak St,Brooklyn,Kings,NY,11226,718-560-9537,718-280-4183,rhea_aredondo@cox.net,http://www.doublebfoodsinc.com -Benedict,Sama,Alexander & Alexander Inc,4923 Carey Ave,Saint Louis,Saint Louis City,MO,63104,314-787-1588,314-858-4832,bsama@cox.net,http://www.alexanderalexanderinc.com -Alyce,Arias,Fairbanks Scales,3196 S Rider Trl,Stockton,San Joaquin,CA,95207,209-317-1801,209-242-7022,alyce@arias.org,http://www.fairbanksscales.com -Heike,Berganza,Cali Sportswear Cutting Dept,3 Railway Ave #75,Little Falls,Passaic,NJ,7424,973-936-5095,973-822-8827,heike@gmail.com,http://www.calisportswearcuttingdept.com -Carey,Dopico,"Garofani, John Esq",87393 E Highland Rd,Indianapolis,Marion,IN,46220,317-578-2453,317-441-5848,carey_dopico@dopico.org,http://www.garofanijohnesq.com -Dottie,Hellickson,Thompson Fabricating Co,67 E Chestnut Hill Rd,Seattle,King,WA,98133,206-540-6076,206-295-5631,dottie@hellickson.org,http://www.thompsonfabricatingco.com -Deandrea,Hughey,Century 21 Krall Real Estate,33 Lewis Rd #46,Burlington,Alamance,NC,27215,336-822-7652,336-467-3095,deandrea@yahoo.com,http://www.centurykrallrealestate.com -Kimberlie,Duenas,Mid Contntl Rlty & Prop Mgmt,8100 Jacksonville Rd #7,Hays,Ellis,KS,67601,785-629-8542,785-616-1685,kimberlie_duenas@yahoo.com,http://www.midcontntlrltypropmgmt.com -Martina,Staback,Ace Signs Inc,7 W Wabansia Ave #227,Orlando,Orange,FL,32822,407-471-6908,407-429-2145,martina_staback@staback.com,http://www.acesignsinc.com -Skye,Fillingim,Rodeway Inn,25 Minters Chapel Rd #9,Minneapolis,Hennepin,MN,55401,612-508-2655,612-664-6304,skye_fillingim@yahoo.com,http://www.rodewayinn.com -Jade,Farrar,Bonnet & Daughter,6882 Torresdale Ave,Columbia,Richland,SC,29201,803-352-5387,803-975-3405,jade.farrar@yahoo.com,http://www.bonnetdaughter.com -Charlene,Hamilton,Oshins & Gibbons,985 E 6th Ave,Santa Rosa,Sonoma,CA,95407,707-300-1771,707-821-8037,charlene.hamilton@hotmail.com,http://www.oshinsgibbons.com -Geoffrey,Acey,Price Business Services,7 West Ave #1,Palatine,Cook,IL,60067,847-222-1734,847-556-2909,geoffrey@gmail.com,http://www.pricebusinessservices.com -Stevie,Westerbeck,"Wise, Dennis W Md",26659 N 13th St,Costa Mesa,Orange,CA,92626,949-867-4077,949-903-3898,stevie.westerbeck@yahoo.com,http://www.wisedenniswmd.com -Pamella,Fortino,Super 8 Motel,669 Packerland Dr #1438,Denver,Denver,CO,80212,303-404-2210,303-794-1341,pamella@fortino.com,http://www.supermotel.com -Harrison,Haufler,John Wagner Associates,759 Eldora St,New Haven,New Haven,CT,6515,203-801-6193,203-801-8497,hhaufler@hotmail.com,http://www.johnwagnerassociates.com -Johnna,Engelberg,Thrifty Oil Co,5 S Colorado Blvd #449,Bothell,Snohomish,WA,98021,425-986-7573,425-700-3751,jengelberg@engelberg.org,http://www.thriftyoilco.com -Buddy,Cloney,Larkfield Photo,944 Gaither Dr,Strongsville,Cuyahoga,OH,44136,440-989-5826,440-327-2093,buddy.cloney@yahoo.com,http://www.larkfieldphoto.com -Dalene,Riden,Silverman Planetarium,66552 Malone Rd,Plaistow,Rockingham,NH,3865,603-315-6839,603-745-7497,dalene.riden@aol.com,http://www.silvermanplanetarium.com -Jerry,Zurcher,J & F Lumber,77 Massillon Rd #822,Satellite Beach,Brevard,FL,32937,321-518-5938,321-597-2159,jzurcher@zurcher.org,http://www.jflumber.com -Haydee,Denooyer,Cleaning Station Inc,25346 New Rd,New York,New York,NY,10016,212-792-8658,212-782-3493,hdenooyer@denooyer.org,http://www.cleaningstationinc.com -Joseph,Cryer,Ames Stationers,60 Fillmore Ave,Huntington Beach,Orange,CA,92647,714-584-2237,714-698-2170,joseph_cryer@cox.net,http://www.amesstationers.com -Deonna,Kippley,Midas Muffler Shops,57 Haven Ave #90,Southfield,Oakland,MI,48075,248-913-4677,248-793-4966,deonna_kippley@hotmail.com,http://www.midasmufflershops.com -Raymon,Calvaresi,Seaboard Securities Inc,6538 E Pomona St #60,Indianapolis,Marion,IN,46222,317-825-4724,317-342-1532,raymon.calvaresi@gmail.com,http://www.seaboardsecuritiesinc.com -Alecia,Bubash,"Petersen, James E Esq",6535 Joyce St,Wichita Falls,Wichita,TX,76301,940-276-7922,940-302-3036,alecia@aol.com,http://www.petersenjameseesq.com -Ma,Layous,Development Authority,78112 Morris Ave,North Haven,New Haven,CT,6473,203-721-3388,203-564-1543,mlayous@hotmail.com,http://www.developmentauthority.com -Detra,Coyier,Schott Fiber Optics Inc,96950 Hidden Ln,Aberdeen,Harford,MD,21001,410-739-9277,410-259-2118,detra@aol.com,http://www.schottfiberopticsinc.com -Terrilyn,Rodeigues,Stuart J Agins,3718 S Main St,New Orleans,Orleans,LA,70130,504-463-4384,504-635-8518,terrilyn.rodeigues@cox.net,http://www.stuartjagins.com -Salome,Lacovara,Mitsumi Electronics Corp,9677 Commerce Dr,Richmond,Richmond City,VA,23219,804-550-5097,804-858-1011,slacovara@gmail.com,http://www.mitsumielectronicscorp.com -Garry,Keetch,Italian Express Franchise Corp,5 Green Pond Rd #4,Southampton,Bucks,PA,18966,215-979-8776,215-846-9046,garry_keetch@hotmail.com,http://www.italianexpressfranchisecorp.com -Matthew,Neither,American Council On Sci & Hlth,636 Commerce Dr #42,Shakopee,Scott,MN,55379,952-651-7597,952-906-4597,mneither@yahoo.com,http://www.americancouncilonscihlth.com -Theodora,Restrepo,"Kleri, Patricia S Esq",42744 Hamann Industrial Pky #82,Miami,Miami-Dade,FL,33136,305-936-8226,305-573-1085,theodora.restrepo@restrepo.com,http://www.kleripatriciasesq.com -Noah,Kalafatis,Twiggs Abrams Blanchard,1950 5th Ave,Milwaukee,Milwaukee,WI,53209,414-263-5287,414-660-9766,noah.kalafatis@aol.com,http://www.twiggsabramsblanchard.com -Carmen,Sweigard,Maui Research & Technology Pk,61304 N French Rd,Somerset,Somerset,NJ,8873,732-941-2621,732-445-6940,csweigard@sweigard.com,http://www.mauiresearchtechnologypk.com -Lavonda,Hengel,Bradley Nameplate Corp,87 Imperial Ct #79,Fargo,Cass,ND,58102,701-898-2154,701-421-7080,lavonda@cox.net,http://www.bradleynameplatecorp.com -Junita,Stoltzman,Geonex Martel Inc,94 W Dodge Rd,Carson City,Carson City,NV,89701,775-638-9963,775-578-1214,junita@aol.com,http://www.geonexmartelinc.com -Herminia,Nicolozakes,Sea Island Div Of Fstr Ind Inc,4 58th St #3519,Scottsdale,Maricopa,AZ,85254,602-954-5141,602-304-6433,herminia@nicolozakes.org,http://www.seaislanddivoffstrindinc.com -Casie,Good,"Papay, Debbie J Esq",5221 Bear Valley Rd,Nashville,Davidson,TN,37211,615-390-2251,615-825-4297,casie.good@aol.com,http://www.papaydebbiejesq.com -Reena,Maisto,Lane Promotions,9648 S Main,Salisbury,Wicomico,MD,21801,410-351-1863,410-951-2667,reena@hotmail.com,http://www.lanepromotions.com -Mirta,Mallett,Stephen Kennerly Archts Inc Pc,7 S San Marcos Rd,New York,New York,NY,10004,212-870-1286,212-745-6948,mirta_mallett@gmail.com,http://www.stephenkennerlyarchtsincpc.com -Cathrine,Pontoriero,Business Systems Of Wis Inc,812 S Haven St,Amarillo,Randall,TX,79109,806-703-1435,806-558-5848,cathrine.pontoriero@pontoriero.com,http://www.businesssystemsofwisinc.com -Filiberto,Tawil,"Flash, Elena Salerno Esq",3882 W Congress St #799,Los Angeles,Los Angeles,CA,90016,323-765-2528,323-842-8226,ftawil@hotmail.com,http://www.flashelenasalernoesq.com -Raul,Upthegrove,"Neeley, Gregory W Esq",4 E Colonial Dr,La Mesa,San Diego,CA,91942,619-509-5282,619-666-4765,rupthegrove@yahoo.com,http://www.neeleygregorywesq.com -Sarah,Candlish,Alabama Educational Tv Comm,45 2nd Ave #9759,Atlanta,Fulton,GA,30328,770-732-1194,770-531-2842,sarah.candlish@gmail.com,http://www.alabamaeducationaltvcomm.com -Lucy,Treston,Franz Inc,57254 Brickell Ave #372,Worcester,Worcester,MA,1602,508-769-5250,508-502-5634,lucy@cox.net,http://www.franzinc.com -Judy,Aquas,Plantation Restaurant,8977 Connecticut Ave Nw #3,Niles,Berrien,MI,49120,269-756-7222,269-431-9464,jaquas@aquas.com,http://www.plantationrestaurant.com -Yvonne,Tjepkema,Radio Communications Co,9 Waydell St,Fairfield,Essex,NJ,7004,973-714-1721,973-976-8627,yvonne.tjepkema@hotmail.com,http://www.radiocommunicationsco.com -Kayleigh,Lace,Dentalaw Divsn Hlth Care,43 Huey P Long Ave,Lafayette,Lafayette,LA,70508,337-740-9323,337-751-2326,kayleigh.lace@yahoo.com,http://www.dentalawdivsnhlthcare.com -Felix,Hirpara,American Speedy Printing Ctrs,7563 Cornwall Rd #4462,Denver,Lancaster,PA,17517,717-491-5643,717-583-1497,felix_hirpara@cox.net,http://www.americanspeedyprintingctrs.com -Tresa,Sweely,"Grayson, Grant S Esq",22 Bridle Ln,Valley Park,Saint Louis,MO,63088,314-359-9566,314-231-3514,tresa_sweely@hotmail.com,http://www.graysongrantsesq.com -Kristeen,Turinetti,Jeanerette Middle School,70099 E North Ave,Arlington,Tarrant,TX,76013,817-213-8851,817-947-9480,kristeen@gmail.com,http://www.jeanerettemiddleschool.com -Jenelle,Regusters,"Haavisto, Brian F Esq",3211 E Northeast Loop,Tampa,Hillsborough,FL,33619,813-932-8715,813-357-7296,jregusters@regusters.com,http://www.haavistobrianfesq.com -Renea,Monterrubio,Wmmt Radio Station,26 Montgomery St,Atlanta,Fulton,GA,30328,770-679-4752,770-930-9967,renea@hotmail.com,http://www.wmmtradiostation.com -Olive,Matuszak,Colony Paints Sales Ofc & Plnt,13252 Lighthouse Ave,Cathedral City,Riverside,CA,92234,760-938-6069,760-745-2649,olive@aol.com,http://www.colonypaintssalesofcplnt.com -Ligia,Reiber,Floral Expressions,206 Main St #2804,Lansing,Ingham,MI,48933,517-906-1108,517-747-7664,lreiber@cox.net,http://www.floralexpressions.com -Christiane,Eschberger,Casco Services Inc,96541 W Central Blvd,Phoenix,Maricopa,AZ,85034,602-390-4944,602-330-6894,christiane.eschberger@yahoo.com,http://www.cascoservicesinc.com -Goldie,Schirpke,"Reuter, Arthur C Jr",34 Saint George Ave #2,Bangor,Penobscot,ME,4401,207-295-7569,207-748-3722,goldie.schirpke@yahoo.com,http://www.reuterarthurcjr.com -Loreta,Timenez,"Kaminski, Katherine Andritsaki",47857 Coney Island Ave,Clinton,Prince Georges,MD,20735,301-696-6420,301-392-6698,loreta.timenez@hotmail.com,http://www.kaminskikatherineandritsaki.com -Fabiola,Hauenstein,Sidewinder Products Corp,8573 Lincoln Blvd,York,York,PA,17404,717-809-3119,717-344-2804,fabiola.hauenstein@hauenstein.org,http://www.sidewinderproductscorp.com -Amie,Perigo,General Foam Corporation,596 Santa Maria Ave #7913,Mesquite,Dallas,TX,75150,972-419-7946,972-898-1033,amie.perigo@yahoo.com,http://www.generalfoamcorporation.com -Raina,Brachle,Ikg Borden Divsn Harsco Corp,3829 Ventura Blvd,Butte,Silver Bow,MT,59701,406-318-1515,406-374-7752,raina.brachle@brachle.org,http://www.ikgbordendivsnharscocorp.com -Erinn,Canlas,Anchor Computer Inc,13 S Hacienda Dr,Livingston,Essex,NJ,7039,973-767-3008,973-563-9502,erinn.canlas@canlas.com,http://www.anchorcomputerinc.com -Cherry,Lietz,Sebring & Co,40 9th Ave Sw #91,Waterford,Oakland,MI,48329,248-980-6904,248-697-7722,cherry@lietz.com,http://www.sebringco.com -Kattie,Vonasek,H A C Farm Lines Co Optv Assoc,2845 Boulder Crescent St,Cleveland,Cuyahoga,OH,44103,216-923-3715,216-270-9653,kattie@vonasek.org,http://www.hacfarmlinescooptvassoc.com -Lilli,Scriven,"Hunter, John J Esq",33 State St,Abilene,Taylor,TX,79601,325-631-1560,325-667-7868,lilli@aol.com,http://www.hunterjohnjesq.com -Whitley,Tomasulo,Freehold Fence Co,2 S 15th St,Fort Worth,Tarrant,TX,76107,817-526-4408,817-819-7799,whitley.tomasulo@aol.com,http://www.freeholdfenceco.com -Barbra,Adkin,Binswanger,4 Kohler Memorial Dr,Brooklyn,Kings,NY,11230,718-201-3751,718-732-9475,badkin@hotmail.com,http://www.binswanger.com -Hermila,Thyberg,Chilton Malting Co,1 Rancho Del Mar Shopping C,Providence,Providence,RI,2903,401-893-4882,401-885-7681,hermila_thyberg@hotmail.com,http://www.chiltonmaltingco.com -Jesusita,Flister,"Schoen, Edward J Jr",3943 N Highland Ave,Lancaster,Lancaster,PA,17601,717-885-9118,717-686-7564,jesusita.flister@hotmail.com,http://www.schoenedwardjjr.com -Caitlin,Julia,"Helderman, Seymour Cpa",5 Williams St,Johnston,Providence,RI,2919,401-948-4982,401-552-9059,caitlin.julia@julia.org,http://www.heldermanseymourcpa.com -Roosevelt,Hoffis,"Denbrook, Myron",60 Old Dover Rd,Hialeah,Miami-Dade,FL,33014,305-622-4739,305-302-1135,roosevelt.hoffis@aol.com,http://www.denbrookmyron.com -Helaine,Halter,"Lippitt, Mike",8 Sheridan Rd,Jersey City,Hudson,NJ,7304,201-832-4168,201-412-3040,hhalter@yahoo.com,http://www.lippittmike.com -Lorean,Martabano,"Hiram, Hogg P Esq",85092 Southern Blvd,San Antonio,Bexar,TX,78204,210-856-4979,210-634-2447,lorean.martabano@hotmail.com,http://www.hiramhoggpesq.com -France,Buzick,In Travel Agency,64 Newman Springs Rd E,Brooklyn,Kings,NY,11219,718-478-8504,718-853-3740,france.buzick@yahoo.com,http://www.intravelagency.com -Justine,Ferrario,Newhart Foods Inc,48 Stratford Ave,Pomona,Los Angeles,CA,91768,909-993-3242,909-631-5703,jferrario@hotmail.com,http://www.newhartfoodsinc.com -Adelina,Nabours,Courtyard By Marriott,80 Pittsford Victor Rd #9,Cleveland,Cuyahoga,OH,44103,216-230-4892,216-937-5320,adelina_nabours@gmail.com,http://www.courtyardbymarriott.com -Derick,Dhamer,"Studer, Eugene A Esq",87163 N Main Ave,New York,New York,NY,10013,212-304-4515,212-225-9676,ddhamer@cox.net,http://www.studereugeneaesq.com -Jerry,Dallen,Seashore Supply Co Waretown,393 Lafayette Ave,Richmond,Richmond City,VA,23219,804-762-9576,804-808-9574,jerry.dallen@yahoo.com,http://www.seashoresupplycowaretown.com -Leota,Ragel,Mayar Silk Inc,99 5th Ave #33,Trion,Chattooga,GA,30753,706-221-4243,706-616-5131,leota.ragel@gmail.com,http://www.mayarsilkinc.com -Jutta,Amyot,National Medical Excess Corp,49 N Mays St,Broussard,Lafayette,LA,70518,337-515-1438,337-991-8070,jamyot@hotmail.com,http://www.nationalmedicalexcesscorp.com -Aja,Gehrett,Stero Company,993 Washington Ave,Nutley,Essex,NJ,7110,973-544-2677,973-986-4456,aja_gehrett@hotmail.com,http://www.sterocompany.com -Kirk,Herritt,"Hasting, H Duane Esq",88 15th Ave Ne,Vestal,Broome,NY,13850,607-407-3716,607-350-7690,kirk.herritt@aol.com,http://www.hastinghduaneesq.com -Leonora,Mauson,Insty Prints,3381 E 40th Ave,Passaic,Passaic,NJ,7055,973-412-2995,973-355-2120,leonora@yahoo.com,http://www.instyprints.com -Winfred,Brucato,Glenridge Manor Mobile Home Pk,201 Ridgewood Rd,Moscow,Latah,ID,83843,208-252-4552,208-793-4108,winfred_brucato@hotmail.com,http://www.glenridgemanormobilehomepk.com -Tarra,Nachor,Circuit Solution Inc,39 Moccasin Dr,San Francisco,San Francisco,CA,94104,415-411-1775,415-284-2730,tarra.nachor@cox.net,http://www.circuitsolutioninc.com -Corinne,Loder,Local Office,4 Carroll St,North Attleboro,Bristol,MA,2760,508-942-4186,508-618-7826,corinne@loder.org,http://www.localoffice.com -Dulce,Labreche,Lee Kilkelly Paulson & Kabaker,9581 E Arapahoe Rd,Rochester,Oakland,MI,48307,248-357-8718,248-811-5696,dulce_labreche@yahoo.com,http://www.leekilkellypaulsonkabaker.com -Kate,Keneipp,"Davis, Maxon R Esq",33 N Michigan Ave,Green Bay,Brown,WI,54301,920-353-6377,920-355-1610,kate_keneipp@yahoo.com,http://www.davismaxonresq.com -Kaitlyn,Ogg,"Garrison, Paul E Esq",2 S Biscayne Blvd,Baltimore,Baltimore City,MD,21230,410-665-4903,410-773-3862,kaitlyn.ogg@gmail.com,http://www.garrisonpauleesq.com -Sherita,Saras,Black History Resource Center,8 Us Highway 22,Colorado Springs,El Paso,CO,80937,719-669-1664,719-547-9543,sherita.saras@cox.net,http://www.blackhistoryresourcecenter.com -Lashawnda,Stuer,"Rodriguez, J Christopher Esq",7422 Martin Ave #8,Toledo,Lucas,OH,43607,419-588-8719,419-399-1744,lstuer@cox.net,http://www.rodriguezjchristopheresq.com -Ernest,Syrop,Grant Family Health Center,94 Chase Rd,Hyattsville,Prince Georges,MD,20785,301-998-9644,301-257-4883,ernest@cox.net,http://www.grantfamilyhealthcenter.com -Nobuko,Halsey,Goeman Wood Products Inc,8139 I Hwy 10 #92,New Bedford,Bristol,MA,2745,508-855-9887,508-897-7916,nobuko.halsey@yahoo.com,http://www.goemanwoodproductsinc.com -Lavonna,Wolny,"Linhares, Kenneth A Esq",5 Cabot Rd,Mc Lean,Fairfax,VA,22102,703-483-1970,703-892-2914,lavonna.wolny@hotmail.com,http://www.linhareskennethaesq.com -Lashaunda,Lizama,Earnhardt Printing,3387 Ryan Dr,Hanover,Anne Arundel,MD,21076,410-678-2473,410-912-6032,llizama@cox.net,http://www.earnhardtprinting.com -Mariann,Bilden,H P G Industrys Inc,3125 Packer Ave #9851,Austin,Travis,TX,78753,512-223-4791,512-742-1149,mariann.bilden@aol.com,http://www.hpgindustrysinc.com -Helene,Rodenberger,Bailey Transportation Prod Inc,347 Chestnut St,Peoria,Maricopa,AZ,85381,623-461-8551,623-426-4907,helene@aol.com,http://www.baileytransportationprodinc.com -Roselle,Estell,Mcglynn Bliss Pc,8116 Mount Vernon Ave,Bucyrus,Crawford,OH,44820,419-571-5920,419-488-6648,roselle.estell@hotmail.com,http://www.mcglynnblisspc.com -Samira,Heintzman,Mutual Fish Co,8772 Old County Rd #5410,Kent,King,WA,98032,206-311-4137,206-923-6042,sheintzman@hotmail.com,http://www.mutualfishco.com -Margart,Meisel,"Yeates, Arthur L Aia",868 State St #38,Cincinnati,Hamilton,OH,45251,513-617-2362,513-747-9603,margart_meisel@yahoo.com,http://www.yeatesarthurlaia.com -Kristofer,Bennick,"Logan, Ronald J Esq",772 W River Dr,Bloomington,Monroe,IN,47404,812-368-1511,812-442-8544,kristofer.bennick@yahoo.com,http://www.loganronaldjesq.com -Weldon,Acuff,Advantage Martgage Company,73 W Barstow Ave,Arlington Heights,Cook,IL,60004,847-353-2156,847-613-5866,wacuff@gmail.com,http://www.advantagemartgagecompany.com -Shalon,Shadrick,Germer And Gertz Llp,61047 Mayfield Ave,Brooklyn,Kings,NY,11223,718-232-2337,718-394-4974,shalon@cox.net,http://www.germerandgertzllp.com -Denise,Patak,Spence Law Offices,2139 Santa Rosa Ave,Orlando,Orange,FL,32801,407-446-4358,407-808-3254,denise@patak.org,http://www.spencelawoffices.com -Louvenia,Beech,John Ortiz Nts Therapy Center,598 43rd St,Beverly Hills,Los Angeles,CA,90210,310-820-2117,310-652-2379,louvenia.beech@beech.com,http://www.johnortizntstherapycenter.com -Audry,Yaw,Mike Uchrin Htg & Air Cond Inc,70295 Pioneer Ct,Brandon,Hillsborough,FL,33511,813-797-4816,813-744-7100,audry.yaw@yaw.org,http://www.mikeuchrinhtgaircondinc.com -Kristel,Ehmann,"Mccoy, Joy Reynolds Esq",92899 Kalakaua Ave,El Paso,El Paso,TX,79925,915-452-1290,915-300-6100,kristel.ehmann@aol.com,http://www.mccoyjoyreynoldsesq.com -Vincenza,Zepp,Kbor 1600 Am,395 S 6th St #2,El Cajon,San Diego,CA,92020,619-603-5125,619-935-6661,vzepp@gmail.com,http://www.kboram.com -Elouise,Gwalthney,Quality Inn Northwest,9506 Edgemore Ave,Bladensburg,Prince Georges,MD,20710,301-841-5012,301-591-3034,egwalthney@yahoo.com,http://www.qualityinnnorthwest.com -Venita,Maillard,Wallace Church Assoc Inc,72119 S Walker Ave #63,Anaheim,Orange,CA,92801,714-523-6653,714-663-9740,venita_maillard@gmail.com,http://www.wallacechurchassocinc.com -Kasandra,Semidey,Can Tron,369 Latham St #500,Saint Louis,Saint Louis City,MO,63102,314-732-9131,314-697-3652,kasandra_semidey@semidey.com,http://www.cantron.com -Xochitl,Discipio,Ravaal Enterprises Inc,3158 Runamuck Pl,Round Rock,Williamson,TX,78664,512-233-1831,512-942-3411,xdiscipio@gmail.com,http://www.ravaalenterprisesinc.com -Maile,Linahan,Thompson Steel Company Inc,9 Plainsboro Rd #598,Greensboro,Guilford,NC,27409,336-670-2640,336-364-6037,mlinahan@yahoo.com,http://www.thompsonsteelcompanyinc.com -Krissy,Rauser,"Anderson, Mark A Esq",8728 S Broad St,Coram,Suffolk,NY,11727,631-443-4710,631-288-2866,krauser@cox.net,http://www.andersonmarkaesq.com -Pete,Dubaldi,Womack & Galich,2215 Prosperity Dr,Lyndhurst,Bergen,NJ,7071,201-825-2514,201-749-8866,pdubaldi@hotmail.com,http://www.womackgalich.com -Linn,Paa,Valerie & Company,1 S Pine St,Memphis,Shelby,TN,38112,901-412-4381,901-573-9024,linn_paa@paa.com,http://www.valeriecompany.com -Paris,Wide,Gehring Pumps Inc,187 Market St,Atlanta,Fulton,GA,30342,404-505-4445,404-607-8435,paris@hotmail.com,http://www.gehringpumpsinc.com -Wynell,Dorshorst,"Haehnel, Craig W Esq",94290 S Buchanan St,Pacifica,San Mateo,CA,94044,650-473-1262,650-749-9879,wynell_dorshorst@dorshorst.org,http://www.haehnelcraigwesq.com -Quentin,Birkner,Spoor Behrins Campbell & Young,7061 N 2nd St,Burnsville,Dakota,MN,55337,952-702-7993,952-314-5871,qbirkner@aol.com,http://www.spoorbehrinscampbellyoung.com -Regenia,Kannady,Ken Jeter Store Equipment Inc,10759 Main St,Scottsdale,Maricopa,AZ,85260,480-726-1280,480-205-5121,regenia.kannady@cox.net,http://www.kenjeterstoreequipmentinc.com -Sheron,Louissant,"Potter, Brenda J Cpa",97 E 3rd St #9,Long Island City,Queens,NY,11101,718-976-8610,718-613-9994,sheron@aol.com,http://www.potterbrendajcpa.com -Izetta,Funnell,Baird Kurtz & Dobson,82 Winsor St #54,Atlanta,Dekalb,GA,30340,770-844-3447,770-584-4119,izetta.funnell@hotmail.com,http://www.bairdkurtzdobson.com -Rodolfo,Butzen,"Minor, Cynthia A Esq",41 Steel Ct,Northfield,Rice,MN,55057,507-210-3510,507-590-5237,rodolfo@hotmail.com,http://www.minorcynthiaaesq.com -Zona,Colla,"Solove, Robert A Esq",49440 Dearborn St,Norwalk,Fairfield,CT,6854,203-461-1949,203-938-2557,zona@hotmail.com,http://www.soloverobertaesq.com -Serina,Zagen,Mark Ii Imports Inc,7 S Beverly Dr,Fort Wayne,Allen,IN,46802,260-273-3725,260-382-4869,szagen@aol.com,http://www.markiiimportsinc.com -Paz,Sahagun,White Sign Div Ctrl Equip Co,919 Wall Blvd,Meridian,Lauderdale,MS,39307,601-927-8287,601-249-4511,paz_sahagun@cox.net,http://www.whitesigndivctrlequipco.com -Markus,Lukasik,M & M Store Fixtures Co Inc,89 20th St E #779,Sterling Heights,Macomb,MI,48310,586-970-7380,586-247-1614,markus@yahoo.com,http://www.mmstorefixturescoinc.com -Jaclyn,Bachman,Judah Caster & Wheel Co,721 Interstate 45 S,Colorado Springs,El Paso,CO,80919,719-853-3600,719-223-2074,jaclyn@aol.com,http://www.judahcasterwheelco.com -Cyril,Daufeldt,Galaxy International Inc,3 Lawton St,New York,New York,NY,10013,212-745-8484,212-422-5427,cyril_daufeldt@daufeldt.com,http://www.galaxyinternationalinc.com -Gayla,Schnitzler,Sigma Corp Of America,38 Pleasant Hill Rd,Hayward,Alameda,CA,94545,510-686-3407,510-441-4055,gschnitzler@gmail.com,http://www.sigmacorpofamerica.com -Erick,Nievas,"Soward, Anne Esq",45 E Acacia Ct,Chicago,Cook,IL,60624,773-704-9903,773-359-6109,erick_nievas@aol.com,http://www.sowardanneesq.com -Jennie,Drymon,"Osborne, Michelle M Esq",63728 Poway Rd #1,Scranton,Lackawanna,PA,18509,570-218-4831,570-868-8688,jennie@cox.net,http://www.osbornemichellemesq.com -Mitsue,Scipione,Students In Free Entrprs Natl,77 222 Dr,Oroville,Butte,CA,95965,530-986-9272,530-399-3254,mscipione@scipione.com,http://www.studentsinfreeentrprsnatl.com -Ciara,Ventura,"Johnson, Robert M Esq",53 W Carey St,Port Jervis,Orange,NY,12771,845-823-8877,845-694-7919,cventura@yahoo.com,http://www.johnsonrobertmesq.com -Galen,Cantres,Del Charro Apartments,617 Nw 36th Ave,Brook Park,Cuyahoga,OH,44142,216-600-6111,216-871-6876,galen@yahoo.com,http://www.delcharroapartments.com -Truman,Feichtner,Legal Search Inc,539 Coldwater Canyon Ave,Bloomfield,Essex,NJ,7003,973-852-2736,973-473-5108,tfeichtner@yahoo.com,http://www.legalsearchinc.com -Gail,Kitty,Service Supply Co Inc,735 Crawford Dr,Anchorage,Anchorage,AK,99501,907-435-9166,907-770-3542,gail@kitty.com,http://www.servicesupplycoinc.com -Dalene,Schoeneck,"Sameshima, Douglas J Esq",910 Rahway Ave,Philadelphia,Philadelphia,PA,19102,215-268-1275,215-380-8820,dalene@schoeneck.org,http://www.sameshimadouglasjesq.com -Gertude,Witten,"Thompson, John Randolph Jr",7 Tarrytown Rd,Cincinnati,Hamilton,OH,45217,513-977-7043,513-863-9471,gertude.witten@gmail.com,http://www.thompsonjohnrandolphjr.com -Lizbeth,Kohl,E T Balancing Co Inc,35433 Blake St #588,Gardena,Los Angeles,CA,90248,310-699-1222,310-955-5788,lizbeth@yahoo.com,http://www.etbalancingcoinc.com -Glenn,Berray,"Griswold, John E Esq",29 Cherry St #7073,Des Moines,Polk,IA,50315,515-370-7348,515-372-1738,gberray@gmail.com,http://www.griswoldjohneesq.com -Lashandra,Klang,Acqua Group,810 N La Brea Ave,King of Prussia,Montgomery,PA,19406,610-809-1818,610-378-7332,lashandra@yahoo.com,http://www.acquagroup.com -Lenna,Newville,"Brooks, Morris J Jr",987 Main St,Raleigh,Wake,NC,27601,919-623-2524,919-254-5987,lnewville@newville.com,http://www.brooksmorrisjjr.com -Laurel,Pagliuca,Printing Images Corp,36 Enterprise St Se,Richland,Benton,WA,99352,509-695-5199,509-595-6485,laurel@yahoo.com,http://www.printingimagescorp.com -Mireya,Frerking,Roberts Supply Co Inc,8429 Miller Rd,Pelham,Westchester,NY,10803,914-868-5965,914-883-3061,mireya.frerking@hotmail.com,http://www.robertssupplycoinc.com -Annelle,Tagala,Vico Products Mfg Co,5 W 7th St,Parkville,Baltimore,MD,21234,410-757-1035,410-234-2267,annelle@yahoo.com,http://www.vicoproductsmfgco.com -Dean,Ketelsen,J M Custom Design Millwork,2 Flynn Rd,Hicksville,Nassau,NY,11801,516-847-4418,516-732-6649,dean_ketelsen@gmail.com,http://www.jmcustomdesignmillwork.com -Levi,Munis,Farrell & Johnson Office Equip,2094 Ne 36th Ave,Worcester,Worcester,MA,1603,508-456-4907,508-658-7802,levi.munis@gmail.com,http://www.farrelljohnsonofficeequip.com -Sylvie,Ryser,Millers Market & Deli,649 Tulane Ave,Tulsa,Tulsa,OK,74105,918-644-9555,918-565-1706,sylvie@aol.com,http://www.millersmarketdeli.com -Sharee,Maile,Holiday Inn Naperville,2094 Montour Blvd,Muskegon,Muskegon,MI,49442,231-467-9978,231-265-6940,sharee_maile@aol.com,http://www.holidayinnnaperville.com -Cordelia,Storment,"Burrows, Jon H Esq",393 Hammond Dr,Lafayette,Lafayette,LA,70506,337-566-6001,337-255-3427,cordelia_storment@aol.com,http://www.burrowsjonhesq.com -Mollie,Mcdoniel,Dock Seal Specialty,8590 Lake Lizzie Dr,Bowling Green,Wood,OH,43402,419-975-3182,419-417-4674,mollie_mcdoniel@yahoo.com,http://www.docksealspecialty.com -Brett,Mccullan,Five Star Limousines Of Tx Inc,87895 Concord Rd,La Mesa,San Diego,CA,91942,619-461-9984,619-727-3892,brett.mccullan@mccullan.com,http://www.fivestarlimousinesoftxinc.com -Teddy,Pedrozo,"Barkan, Neal J Esq",46314 Route 130,Bridgeport,Fairfield,CT,6610,203-892-3863,203-918-3939,teddy_pedrozo@aol.com,http://www.barkannealjesq.com -Tasia,Andreason,"Campbell, Robert A",4 Cowesett Ave,Kearny,Hudson,NJ,7032,201-920-9002,201-969-7063,tasia_andreason@yahoo.com,http://www.campbellroberta.com -Hubert,Walthall,"Dee, Deanna",95 Main Ave #2,Barberton,Summit,OH,44203,330-903-1345,330-566-8898,hubert@walthall.org,http://www.deedeanna.com -Arthur,Farrow,"Young, Timothy L Esq",28 S 7th St #2824,Englewood,Bergen,NJ,7631,201-238-5688,201-772-4377,arthur.farrow@yahoo.com,http://www.youngtimothylesq.com -Vilma,Berlanga,"Wells, D Fred Esq",79 S Howell Ave,Grand Rapids,Kent,MI,49546,616-737-3085,616-568-4113,vberlanga@berlanga.com,http://www.wellsdfredesq.com -Billye,Miro,"Gray, Francine H Esq",36 Lancaster Dr Se,Pearl,Rankin,MS,39208,601-567-5386,601-637-5479,billye_miro@cox.net,http://www.grayfrancinehesq.com -Glenna,Slayton,Toledo Iv Care,2759 Livingston Ave,Memphis,Shelby,TN,38118,901-640-9178,901-869-4314,glenna_slayton@cox.net,http://www.toledoivcare.com -Mitzie,Hudnall,Cangro Transmission Co,17 Jersey Ave,Englewood,Arapahoe,CO,80110,303-402-1940,303-997-7760,mitzie_hudnall@yahoo.com,http://www.cangrotransmissionco.com -Bernardine,Rodefer,Sat Poly Inc,2 W Grand Ave,Memphis,Shelby,TN,38112,901-901-4726,901-739-5892,bernardine_rodefer@yahoo.com,http://www.satpolyinc.com -Staci,Schmaltz,Midwest Contracting & Mfg Inc,18 Coronado Ave #563,Pasadena,Los Angeles,CA,91106,626-866-2339,626-293-7678,staci_schmaltz@aol.com,http://www.midwestcontractingmfginc.com -Nichelle,Meteer,Print Doctor,72 Beechwood Ter,Chicago,Cook,IL,60657,773-225-9985,773-857-2231,nichelle_meteer@meteer.com,http://www.printdoctor.com -Janine,Rhoden,Nordic Group Inc,92 Broadway,Astoria,Queens,NY,11103,718-228-5894,718-728-5051,jrhoden@yahoo.com,http://www.nordicgroupinc.com -Ettie,Hoopengardner,Jackson Millwork Co,39 Franklin Ave,Richland,Benton,WA,99352,509-755-5393,509-847-3352,ettie.hoopengardner@hotmail.com,http://www.jacksonmillworkco.com -Eden,Jayson,Harris Corporation,4 Iwaena St,Baltimore,Baltimore City,MD,21202,410-890-7866,410-429-4888,eden_jayson@yahoo.com,http://www.harriscorporation.com -Lynelle,Auber,United Cerebral Palsy Of Ne Pa,32820 Corkwood Rd,Newark,Essex,NJ,7104,973-860-8610,973-605-6492,lynelle_auber@gmail.com,http://www.unitedcerebralpalsyofnepa.com -Merissa,Tomblin,One Day Surgery Center Inc,34 Raritan Center Pky,Bellflower,Los Angeles,CA,90706,562-579-6900,562-719-7922,merissa.tomblin@gmail.com,http://www.onedaysurgerycenterinc.com -Golda,Kaniecki,Calaveras Prospect,6201 S Nevada Ave,Toms River,Ocean,NJ,8755,732-628-9909,732-617-5310,golda_kaniecki@yahoo.com,http://www.calaverasprospect.com -Catarina,Gleich,"Terk, Robert E Esq",78 Maryland Dr #146,Denville,Morris,NJ,7834,973-210-3994,973-491-8723,catarina_gleich@hotmail.com,http://www.terkroberteesq.com -Virgie,Kiel,"Cullen, Terrence P Esq",76598 Rd I 95 #1,Denver,Denver,CO,80216,303-776-7548,303-845-5408,vkiel@hotmail.com,http://www.cullenterrencepesq.com -Jolene,Ostolaza,Central Die Casting Mfg Co Inc,1610 14th St Nw,Newport News,Newport News City,VA,23608,757-682-7116,757-940-1741,jolene@yahoo.com,http://www.centraldiecastingmfgcoinc.com -Keneth,Borgman,Centerline Engineering,86350 Roszel Rd,Phoenix,Maricopa,AZ,85012,602-919-4211,602-442-3092,keneth@yahoo.com,http://www.centerlineengineering.com -Rikki,Nayar,Targan & Kievit Pa,1644 Clove Rd,Miami,Miami-Dade,FL,33155,305-968-9487,305-978-2069,rikki@nayar.com,http://www.targankievitpa.com -Elke,Sengbusch,Riley Riper Hollin & Colagreco,9 W Central Ave,Phoenix,Maricopa,AZ,85013,602-896-2993,602-575-3457,elke_sengbusch@yahoo.com,http://www.rileyriperhollincolagreco.com -Hoa,Sarao,"Kaplan, Joel S Esq",27846 Lafayette Ave,Oak Hill,Volusia,FL,32759,386-526-7800,386-599-7296,hoa@sarao.org,http://www.kaplanjoelsesq.com -Trinidad,Mcrae,Water Office,10276 Brooks St,San Francisco,San Francisco,CA,94105,415-331-9634,415-419-1597,trinidad_mcrae@yahoo.com,http://www.wateroffice.com -Mari,Lueckenbach,"Westbrooks, Nelson E Jr",1 Century Park E,San Diego,San Diego,CA,92110,858-793-9684,858-228-5683,mari_lueckenbach@yahoo.com,http://www.westbrooksnelsonejr.com -Selma,Husser,Armon Communications,9 State Highway 57 #22,Jersey City,Hudson,NJ,7306,201-991-8369,201-772-7699,selma.husser@cox.net,http://www.armoncommunications.com -Antione,Onofrio,Jacobs & Gerber Inc,4 S Washington Ave,San Bernardino,San Bernardino,CA,92410,909-430-7765,909-665-3223,aonofrio@onofrio.com,http://www.jacobsgerberinc.com -Luisa,Jurney,Forest Fire Laboratory,25 Se 176th Pl,Cambridge,Middlesex,MA,2138,617-365-2134,617-544-2541,ljurney@hotmail.com,http://www.forestfirelaboratory.com -Clorinda,Heimann,"Haughey, Charles Jr",105 Richmond Valley Rd,Escondido,San Diego,CA,92025,760-291-5497,760-261-4786,clorinda.heimann@hotmail.com,http://www.haugheycharlesjr.com -Dick,Wenzinger,Wheaton Plastic Products,22 Spruce St #595,Gardena,Los Angeles,CA,90248,310-510-9713,310-936-2258,dick@yahoo.com,http://www.wheatonplasticproducts.com -Ahmed,Angalich,Reese Plastics,2 W Beverly Blvd,Harrisburg,Dauphin,PA,17110,717-528-8996,717-632-5831,ahmed.angalich@angalich.com,http://www.reeseplastics.com -Iluminada,Ohms,Nazette Marner Good Wendt,72 Southern Blvd,Mesa,Maricopa,AZ,85204,480-293-2882,480-866-6544,iluminada.ohms@yahoo.com,http://www.nazettemarnergoodwendt.com -Joanna,Leinenbach,Levinson Axelrod Wheaton,1 Washington St,Lake Worth,Palm Beach,FL,33461,561-470-4574,561-951-9734,joanna_leinenbach@hotmail.com,http://www.levinsonaxelrodwheaton.com -Caprice,Suell,"Egnor, W Dan Esq",90177 N 55th Ave,Nashville,Davidson,TN,37211,615-246-1824,615-726-4537,caprice@aol.com,http://www.egnorwdanesq.com -Stephane,Myricks,Portland Central Thriftlodge,9 Tower Ave,Burlington,Boone,KY,41005,859-717-7638,859-308-4286,stephane_myricks@cox.net,http://www.portlandcentralthriftlodge.com -Quentin,Swayze,Ulbrich Trucking,278 Bayview Ave,Milan,Monroe,MI,48160,734-561-6170,734-851-8571,quentin_swayze@yahoo.com,http://www.ulbrichtrucking.com -Annmarie,Castros,Tipiak Inc,80312 W 32nd St,Conroe,Montgomery,TX,77301,936-751-7961,936-937-2334,annmarie_castros@gmail.com,http://www.tipiakinc.com -Shonda,Greenbush,Saint George Well Drilling,82 Us Highway 46,Clifton,Passaic,NJ,7011,973-482-2430,973-644-2974,shonda_greenbush@cox.net,http://www.saintgeorgewelldrilling.com -Cecil,Lapage,"Hawkes, Douglas D",4 Stovall St #72,Union City,Hudson,NJ,7087,201-693-3967,201-856-2720,clapage@lapage.com,http://www.hawkesdouglasd.com -Jeanice,Claucherty,Accurel Systems Intrntl Corp,19 Amboy Ave,Miami,Miami-Dade,FL,33142,305-988-4162,305-306-7834,jeanice.claucherty@yahoo.com,http://www.accurelsystemsintrntlcorp.com -Josphine,Villanueva,Santa Cruz Community Internet,63 Smith Ln #8343,Moss,Clay,TN,38575,931-553-9774,931-486-6946,josphine_villanueva@villanueva.com,http://www.santacruzcommunityinternet.com -Daniel,Perruzza,Gersh & Danielson,11360 S Halsted St,Santa Ana,Orange,CA,92705,714-771-3880,714-531-1391,dperruzza@perruzza.com,http://www.gershdanielson.com -Cassi,Wildfong,"Cobb, James O Esq",26849 Jefferson Hwy,Rolling Meadows,Cook,IL,60008,847-633-3216,847-755-9041,cassi.wildfong@aol.com,http://www.cobbjamesoesq.com -Britt,Galam,Wheatley Trucking Company,2500 Pringle Rd Se #508,Hatfield,Montgomery,PA,19440,215-888-3304,215-351-8523,britt@galam.org,http://www.wheatleytruckingcompany.com -Adell,Lipkin,Systems Graph Inc Ab Dick Dlr,65 Mountain View Dr,Whippany,Morris,NJ,7981,973-654-1561,973-662-8988,adell.lipkin@lipkin.com,http://www.systemsgraphincabdickdlr.com -Jacqueline,Rowling,John Hancock Mutl Life Ins Co,1 N San Saba,Erie,Erie,PA,16501,814-865-8113,814-481-1700,jacqueline.rowling@yahoo.com,http://www.johnhancockmutllifeinsco.com -Lonny,Weglarz,History Division Of State,51120 State Route 18,Salt Lake City,Salt Lake,UT,84115,801-293-9853,801-892-8781,lonny_weglarz@gmail.com,http://www.historydivisionofstate.com -Lonna,Diestel,"Dimmock, Thomas J Esq",1482 College Ave,Fayetteville,Cumberland,NC,28301,910-922-3672,910-200-7912,lonna_diestel@gmail.com,http://www.dimmockthomasjesq.com -Cristal,Samara,Intermed Inc,4119 Metropolitan Dr,Los Angeles,Los Angeles,CA,90021,213-975-8026,213-696-8004,cristal@cox.net,http://www.intermedinc.com -Kenneth,Grenet,Bank Of New York,2167 Sierra Rd,East Lansing,Ingham,MI,48823,517-499-2322,517-867-8077,kenneth.grenet@grenet.org,http://www.bankofnewyork.com -Elli,Mclaird,Sportmaster Intrnatl,6 Sunrise Ave,Utica,Oneida,NY,13501,315-818-2638,315-474-5570,emclaird@mclaird.com,http://www.sportmasterintrnatl.com -Alline,Jeanty,W W John Holden Inc,55713 Lake City Hwy,South Bend,St Joseph,IN,46601,574-656-2800,574-405-1983,ajeanty@gmail.com,http://www.wwjohnholdeninc.com -Sharika,Eanes,Maccani & Delp,75698 N Fiesta Blvd,Orlando,Orange,FL,32806,407-312-1691,407-472-1332,sharika.eanes@aol.com,http://www.maccanidelp.com -Nu,Mcnease,Amazonia Film Project,88 Sw 28th Ter,Harrison,Hudson,NJ,7029,973-751-9003,973-903-4175,nu@gmail.com,http://www.amazoniafilmproject.com -Daniela,Comnick,Water & Sewer Department,7 Flowers Rd #403,Trenton,Mercer,NJ,8611,609-200-8577,609-398-2805,dcomnick@cox.net,http://www.watersewerdepartment.com -Cecilia,Colaizzo,Switchcraft Inc,4 Nw 12th St #3849,Madison,Dane,WI,53717,608-382-4541,608-302-3387,cecilia_colaizzo@colaizzo.com,http://www.switchcraftinc.com -Leslie,Threets,C W D C Metal Fabricators,2 A Kelley Dr,Katonah,Westchester,NY,10536,914-861-9748,914-396-2615,leslie@cox.net,http://www.cwdcmetalfabricators.com -Nan,Koppinger,"Shimotani, Grace T",88827 Frankford Ave,Greensboro,Guilford,NC,27401,336-370-5333,336-564-1492,nan@koppinger.com,http://www.shimotanigracet.com -Izetta,Dewar,"Lisatoni, Jean Esq",2 W Scyene Rd #3,Baltimore,Baltimore City,MD,21217,410-473-1708,410-522-7621,idewar@dewar.com,http://www.lisatonijeanesq.com -Tegan,Arceo,Ceramic Tile Sales Inc,62260 Park Stre,Monroe Township,Middlesex,NJ,8831,732-730-2692,732-705-6719,tegan.arceo@arceo.org,http://www.ceramictilesalesinc.com -Ruthann,Keener,Maiden Craft Inc,3424 29th St Se,Kerrville,Kerr,TX,78028,830-258-2769,830-919-5991,ruthann@hotmail.com,http://www.maidencraftinc.com -Joni,Breland,Carriage House Cllsn Rpr Inc,35 E Main St #43,Elk Grove Village,Cook,IL,60007,847-519-5906,847-740-5304,joni_breland@cox.net,http://www.carriagehousecllsnrprinc.com -Vi,Rentfro,Video Workshop,7163 W Clark Rd,Freehold,Monmouth,NJ,7728,732-605-4781,732-724-7251,vrentfro@cox.net,http://www.videoworkshop.com -Colette,Kardas,Fresno Tile Center Inc,21575 S Apple Creek Rd,Omaha,Douglas,NE,68124,402-896-5943,402-707-1602,colette.kardas@yahoo.com,http://www.fresnotilecenterinc.com -Malcolm,Tromblay,Versatile Sash & Woodwork,747 Leonis Blvd,Annandale,Fairfax,VA,22003,703-221-5602,703-874-4248,malcolm_tromblay@cox.net,http://www.versatilesashwoodwork.com -Ryan,Harnos,Warner Electric Brk & Cltch Co,13 Gunnison St,Plano,Collin,TX,75075,972-558-1665,972-961-4968,ryan@cox.net,http://www.warnerelectricbrkcltchco.com -Jess,Chaffins,New York Public Library,18 3rd Ave,New York,New York,NY,10016,212-510-4633,212-428-9538,jess.chaffins@chaffins.org,http://www.newyorkpubliclibrary.com -Sharen,Bourbon,"Mccaleb, John A Esq",62 W Austin St,Syosset,Nassau,NY,11791,516-816-1541,516-749-3188,sbourbon@yahoo.com,http://www.mccalebjohnaesq.com -Nickolas,Juvera,United Oil Co Inc,177 S Rider Trl #52,Crystal River,Citrus,FL,34429,352-598-8301,352-947-6152,nickolas_juvera@cox.net,http://www.unitedoilcoinc.com -Gary,Nunlee,Irving Foot Center,2 W Mount Royal Ave,Fortville,Hancock,IN,46040,317-542-6023,317-887-8486,gary_nunlee@nunlee.org,http://www.irvingfootcenter.com -Diane,Devreese,Acme Supply Co,1953 Telegraph Rd,Saint Joseph,Buchanan,MO,64504,816-557-9673,816-329-5565,diane@cox.net,http://www.acmesupplyco.com -Roslyn,Chavous,"Mcrae, James L",63517 Dupont St,Jackson,Hinds,MS,39211,601-234-9632,601-973-5754,roslyn.chavous@chavous.org,http://www.mcraejamesl.com -Glory,Schieler,Mcgraths Seafood,5 E Truman Rd,Abilene,Taylor,TX,79602,325-869-2649,325-740-3778,glory@yahoo.com,http://www.mcgrathsseafood.com -Rasheeda,Sayaphon,"Kummerer, J Michael Esq",251 Park Ave #979,Saratoga,Santa Clara,CA,95070,408-805-4309,408-997-7490,rasheeda@aol.com,http://www.kummererjmichaelesq.com -Alpha,Palaia,"Stoffer, James M Jr",43496 Commercial Dr #29,Cherry Hill,Camden,NJ,8003,856-312-2629,856-513-7024,alpha@yahoo.com,http://www.stofferjamesmjr.com -Refugia,Jacobos,North Central Fl Sfty Cncl,2184 Worth St,Hayward,Alameda,CA,94545,510-974-8671,510-509-3496,refugia.jacobos@jacobos.com,http://www.northcentralflsftycncl.com -Shawnda,Yori,Fiorucci Foods Usa Inc,50126 N Plankinton Ave,Longwood,Seminole,FL,32750,407-538-5106,407-564-8113,shawnda.yori@yahoo.com,http://www.fioruccifoodsusainc.com -Mona,Delasancha,Sign All,38773 Gravois Ave,Cheyenne,Laramie,WY,82001,307-403-1488,307-816-7115,mdelasancha@hotmail.com,http://www.signall.com -Gilma,Liukko,Sammys Steak Den,16452 Greenwich St,Garden City,Nassau,NY,11530,516-393-9967,516-407-9573,gilma_liukko@gmail.com,http://www.sammyssteakden.com -Janey,Gabisi,"Dobscha, Stephen F Esq",40 Cambridge Ave,Madison,Dane,WI,53715,608-967-7194,608-586-6912,jgabisi@hotmail.com,http://www.dobschastephenfesq.com -Lili,Paskin,Morgan Custom Homes,20113 4th Ave E,Kearny,Hudson,NJ,7032,201-431-2989,201-478-8540,lili.paskin@cox.net,http://www.morgancustomhomes.com -Loren,Asar,Olsen Payne & Company,6 Ridgewood Center Dr,Old Forge,Lackawanna,PA,18518,570-648-3035,570-569-2356,loren.asar@aol.com,http://www.olsenpaynecompany.com -Dorothy,Chesterfield,Cowan & Kelly,469 Outwater Ln,San Diego,San Diego,CA,92126,858-617-7834,858-732-1884,dorothy@cox.net,http://www.cowankelly.com -Gail,Similton,"Johnson, Wes Esq",62 Monroe St,Thousand Palms,Riverside,CA,92276,760-616-5388,760-493-9208,gail_similton@similton.com,http://www.johnsonwesesq.com -Catalina,Tillotson,Icn Pharmaceuticals Inc,3338 A Lockport Pl #6,Margate City,Atlantic,NJ,8402,609-373-3332,609-826-4990,catalina@hotmail.com,http://www.icnpharmaceuticalsinc.com -Lawrence,Lorens,New England Sec Equip Co Inc,9 Hwy,Providence,Providence,RI,2906,401-465-6432,401-893-1820,lawrence.lorens@hotmail.com,http://www.newenglandsecequipcoinc.com -Carlee,Boulter,"Tippett, Troy M Ii",8284 Hart St,Abilene,Dickinson,KS,67410,785-347-1805,785-253-7049,carlee.boulter@hotmail.com,http://www.tippetttroymii.com -Thaddeus,Ankeny,Atc Contracting,5 Washington St #1,Roseville,Placer,CA,95678,916-920-3571,916-459-2433,tankeny@ankeny.org,http://www.atccontracting.com -Jovita,Oles,"Pagano, Philip G Esq",8 S Haven St,Daytona Beach,Volusia,FL,32114,386-248-4118,386-208-6976,joles@gmail.com,http://www.paganophilipgesq.com -Alesia,Hixenbaugh,Kwikprint,9 Front St,Washington,District of Columbia,DC,20001,202-646-7516,202-276-6826,alesia_hixenbaugh@hixenbaugh.org,http://www.kwikprint.com -Lai,Harabedian,Buergi & Madden Scale,1933 Packer Ave #2,Novato,Marin,CA,94945,415-423-3294,415-926-6089,lai@gmail.com,http://www.buergimaddenscale.com -Brittni,Gillaspie,Inner Label,67 Rv Cent,Boise,Ada,ID,83709,208-709-1235,208-206-9848,bgillaspie@gillaspie.com,http://www.innerlabel.com -Raylene,Kampa,Hermar Inc,2 Sw Nyberg Rd,Elkhart,Elkhart,IN,46514,574-499-1454,574-330-1884,rkampa@kampa.org,http://www.hermarinc.com -Flo,Bookamer,Simonton Howe & Schneider Pc,89992 E 15th St,Alliance,Box Butte,NE,69301,308-726-2182,308-250-6987,flo.bookamer@cox.net,http://www.simontonhoweschneiderpc.com -Jani,Biddy,Warehouse Office & Paper Prod,61556 W 20th Ave,Seattle,King,WA,98104,206-711-6498,206-395-6284,jbiddy@yahoo.com,http://www.warehouseofficepaperprod.com -Chauncey,Motley,Affiliated With Travelodge,63 E Aurora Dr,Orlando,Orange,FL,32804,407-413-4842,407-557-8857,chauncey_motley@aol.com,http://www.affiliatedwithtravelodge.com \ No newline at end of file diff --git a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/README.md b/lambda-durable-java-sam/javaSNSLambdaDynamoDB/README.md deleted file mode 100755 index 960fbc1bc1..0000000000 --- a/lambda-durable-java-sam/javaSNSLambdaDynamoDB/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# javaSNSLambdaDynamoDB -Java samples for SNS --> Lambda --> DynamoDB diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/pom.xml b/lambda-durable-java-sam/sns-message-sender/pom.xml similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/pom.xml rename to lambda-durable-java-sam/sns-message-sender/pom.xml diff --git a/lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/src/main/java/sns/producer/DurableFunctionsTrigger.java b/lambda-durable-java-sam/sns-message-sender/src/main/java/sns/producer/DurableFunctionsTrigger.java similarity index 100% rename from lambda-durable-java-sam/JavaLambdaDurableFunctions/sns-message-sender/src/main/java/sns/producer/DurableFunctionsTrigger.java rename to lambda-durable-java-sam/sns-message-sender/src/main/java/sns/producer/DurableFunctionsTrigger.java From 1c96849b9259d20b7bcdb6987a5f83eaa9b3ba08 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Sun, 12 Jul 2026 00:39:35 -0700 Subject: [PATCH 03/20] Added pattern lambda-durable-java-sam --- .../infrastructure/ec2-client-instance.yaml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lambda-durable-java-sam/infrastructure/ec2-client-instance.yaml b/lambda-durable-java-sam/infrastructure/ec2-client-instance.yaml index f196ec398d..c9bf2f85d0 100644 --- a/lambda-durable-java-sam/infrastructure/ec2-client-instance.yaml +++ b/lambda-durable-java-sam/infrastructure/ec2-client-instance.yaml @@ -139,6 +139,17 @@ Resources: fi done + # Set JAVA_HOME based on installed version + if [ "$JAVA_VERSION" == "java17" ]; then + JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto + else + JAVA_HOME=/usr/lib/jvm/java-21-amazon-corretto + fi + echo "export JAVA_HOME=$JAVA_HOME" >> /home/ec2-user/.bash_profile + echo "export PATH=$JAVA_HOME/bin:\$PATH" >> /home/ec2-user/.bash_profile + export JAVA_HOME + export PATH=$JAVA_HOME/bin:$PATH + max_attempts=5 attempt_num=1 success=false @@ -283,7 +294,7 @@ Resources: - arn:aws:iam::aws:policy/AWSLambda_FullAccess - arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess_v2 - arn:aws:iam::aws:policy/AmazonSNSFullAccess - - arn:aws:iam::aws:policy/AmazonECR_FullAccess + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess Policies: - PolicyName: SecurityGroupsPolicy PolicyDocument: !Sub '{ From fd76af4d5325ec4d8eaa56d56b09042d05127477 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Sun, 12 Jul 2026 00:59:06 -0700 Subject: [PATCH 04/20] Added pattern lambda-durable-java-sam --- .../durable/suborchestration/OrderFulfillmentHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java index c752e9cdd5..916189b8fd 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java @@ -58,7 +58,7 @@ public Map handleRequest(Map event, DurableConte ); // Wait for both concurrent sub-workflows to complete - List results = DurableFuture.allOf(paymentFuture, inventoryFuture); + DurableFuture.allOf(paymentFuture, inventoryFuture); Map paymentResult = paymentFuture.get(); Map inventoryResult = inventoryFuture.get(); From c3fabb3fce2d0736891ed52cc14e2075da8144c1 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Mon, 13 Jul 2026 23:03:34 -0700 Subject: [PATCH 05/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/README.md | 7 ++++--- .../durable-functions-sam/template.yaml | 8 -------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/lambda-durable-java-sam/README.md b/lambda-durable-java-sam/README.md index 6937fb4ac7..e1b16d214e 100644 --- a/lambda-durable-java-sam/README.md +++ b/lambda-durable-java-sam/README.md @@ -100,7 +100,7 @@ docker build -t durable-functions-java-examples . ```bash AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) -AWS_REGION=$(aws configure get region) +AWS_REGION=${AWS_REGION:-$(aws configure get region)} aws ecr get-login-password --region $AWS_REGION \ | docker login --username AWS --password-stdin \ @@ -119,8 +119,9 @@ docker push \ ### 3. Deploy with SAM ```bash -cd .. -sam deploy --guided +cd /home/ec2-user/serverless-patterns/lambda-durable-java-sam/durable-functions-sam +(adjust the folder path for local deployment) +sam deploy --guided --capabilities CAPABILITY_NAMED_IAM ``` ### 4. Build the SNS Message Sender diff --git a/lambda-durable-java-sam/durable-functions-sam/template.yaml b/lambda-durable-java-sam/durable-functions-sam/template.yaml index 9098460cc0..d0b8c329e9 100644 --- a/lambda-durable-java-sam/durable-functions-sam/template.yaml +++ b/lambda-durable-java-sam/durable-functions-sam/template.yaml @@ -19,14 +19,6 @@ Parameters: Default: DurableFunctionsSNSTopic Resources: - # ECR Repository for the container image - DurableFunctionsECRRepo: - Type: AWS::ECR::Repository - Properties: - RepositoryName: durable-functions-java-examples - ImageScanningConfiguration: - ScanOnPush: true - # SNS Topic for triggering the durable functions DurableFunctionsSNSTopic: Type: AWS::SNS::Topic From 70300f0ffc428d8df1f4e37976491b6059411033 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Tue, 14 Jul 2026 00:01:53 -0700 Subject: [PATCH 06/20] Added pattern lambda-durable-java-sam --- .../durable-functions/pom.xml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml b/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml index 16d7c83452..eb73c19c37 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml @@ -12,8 +12,21 @@ 21 21 UTF-8 + 2.31.3 + + + + software.amazon.awssdk + bom + ${aws.sdk.version} + pom + import + + + + software.amazon.lambda.durable @@ -33,12 +46,10 @@ software.amazon.awssdk dynamodb - 2.25.0 software.amazon.awssdk sns - 2.25.0 com.fasterxml.jackson.core From e263a32ed043b090f3aa4dc7f263a118fd7eecca Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Tue, 14 Jul 2026 00:21:32 -0700 Subject: [PATCH 07/20] Added pattern lambda-durable-java-sam --- .../durable-functions-sam/durable-functions/pom.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml b/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml index eb73c19c37..9c104104d9 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml @@ -12,7 +12,7 @@ 21 21 UTF-8 - 2.31.3 + 2.42.21 @@ -51,6 +51,10 @@ software.amazon.awssdk sns + + software.amazon.awssdk + lambda + com.fasterxml.jackson.core jackson-databind From 1758fff05b3a99d0092ad53903fe5d4557e1c18e Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Tue, 14 Jul 2026 11:12:03 -0700 Subject: [PATCH 08/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/README.md | 3 +- .../durable-functions-sam/template.yaml | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/lambda-durable-java-sam/README.md b/lambda-durable-java-sam/README.md index e1b16d214e..52d83ea273 100644 --- a/lambda-durable-java-sam/README.md +++ b/lambda-durable-java-sam/README.md @@ -106,7 +106,8 @@ aws ecr get-login-password --region $AWS_REGION \ | docker login --username AWS --password-stdin \ $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com -# Create the repository (first time only) +# Delete the repository if it already exists, then recreate it +aws ecr delete-repository --repository-name durable-functions-java-examples --force 2>/dev/null aws ecr create-repository --repository-name durable-functions-java-examples docker tag durable-functions-java-examples:latest \ diff --git a/lambda-durable-java-sam/durable-functions-sam/template.yaml b/lambda-durable-java-sam/durable-functions-sam/template.yaml index d0b8c329e9..b3a9aad808 100644 --- a/lambda-durable-java-sam/durable-functions-sam/template.yaml +++ b/lambda-durable-java-sam/durable-functions-sam/template.yaml @@ -102,6 +102,10 @@ Resources: ImageConfig: Command: ["com.amazonaws.samples.durable.chaining.OrderProcessingHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn + AutoPublishAlias: live + DurableExecution: + Enabled: true + MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -124,6 +128,10 @@ Resources: ImageConfig: Command: ["com.amazonaws.samples.durable.fanout.ParallelProcessingHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn + AutoPublishAlias: live + DurableExecution: + Enabled: true + MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -146,6 +154,10 @@ Resources: ImageConfig: Command: ["com.amazonaws.samples.durable.humaninteraction.ApprovalWorkflowHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn + AutoPublishAlias: live + DurableExecution: + Enabled: true + MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -169,6 +181,10 @@ Resources: ImageConfig: Command: ["com.amazonaws.samples.durable.monitoring.JobMonitorHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn + AutoPublishAlias: live + DurableExecution: + Enabled: true + MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -191,6 +207,10 @@ Resources: ImageConfig: Command: ["com.amazonaws.samples.durable.timer.ScheduledReminderHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn + AutoPublishAlias: live + DurableExecution: + Enabled: true + MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -214,6 +234,10 @@ Resources: ImageConfig: Command: ["com.amazonaws.samples.durable.errorhandling.ResilientPaymentHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn + AutoPublishAlias: live + DurableExecution: + Enabled: true + MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -236,6 +260,10 @@ Resources: ImageConfig: Command: ["com.amazonaws.samples.durable.mapprocessing.BatchDataProcessorHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn + AutoPublishAlias: live + DurableExecution: + Enabled: true + MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -258,6 +286,10 @@ Resources: ImageConfig: Command: ["com.amazonaws.samples.durable.suborchestration.OrderFulfillmentHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn + AutoPublishAlias: live + DurableExecution: + Enabled: true + MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable From 60b5e49f965531c0eca9e62c956d7a73ca75aa8b Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Tue, 14 Jul 2026 13:36:48 -0700 Subject: [PATCH 09/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/README.md | 29 ++++++++++++++++++- .../durable-functions-sam/template.yaml | 24 --------------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/lambda-durable-java-sam/README.md b/lambda-durable-java-sam/README.md index 52d83ea273..a09a4353c7 100644 --- a/lambda-durable-java-sam/README.md +++ b/lambda-durable-java-sam/README.md @@ -125,7 +125,34 @@ cd /home/ec2-user/serverless-patterns/lambda-durable-java-sam/durable-functions- sam deploy --guided --capabilities CAPABILITY_NAMED_IAM ``` -### 4. Build the SNS Message Sender +### 4. Enable Durable Execution on Each Function + +After SAM deploys the functions, enable durable execution on the published version: + +```bash +FUNCTIONS=( + durable-chaining-example + durable-fanout-example + durable-human-interaction-example + durable-monitoring-example + durable-timer-example + durable-error-handling-example + durable-map-processing-example + durable-sub-orchestration-example +) + +for FUNC in "${FUNCTIONS[@]}"; do + VERSION=$(aws lambda list-versions-by-function --function-name $FUNC \ + --query 'Versions[-1].Version' --output text) + aws lambda put-function-durable-execution-config \ + --function-name $FUNC \ + --qualifier $VERSION \ + --durable-execution-config '{"Enabled": true, "MaxConcurrency": 10}' + echo "Enabled durable execution on $FUNC:$VERSION" +done +``` + +### 5. Build the SNS Message Sender ```bash cd ../sns-message-sender diff --git a/lambda-durable-java-sam/durable-functions-sam/template.yaml b/lambda-durable-java-sam/durable-functions-sam/template.yaml index b3a9aad808..b3ba1361fa 100644 --- a/lambda-durable-java-sam/durable-functions-sam/template.yaml +++ b/lambda-durable-java-sam/durable-functions-sam/template.yaml @@ -103,9 +103,6 @@ Resources: Command: ["com.amazonaws.samples.durable.chaining.OrderProcessingHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn AutoPublishAlias: live - DurableExecution: - Enabled: true - MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -129,9 +126,6 @@ Resources: Command: ["com.amazonaws.samples.durable.fanout.ParallelProcessingHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn AutoPublishAlias: live - DurableExecution: - Enabled: true - MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -155,9 +149,6 @@ Resources: Command: ["com.amazonaws.samples.durable.humaninteraction.ApprovalWorkflowHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn AutoPublishAlias: live - DurableExecution: - Enabled: true - MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -182,9 +173,6 @@ Resources: Command: ["com.amazonaws.samples.durable.monitoring.JobMonitorHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn AutoPublishAlias: live - DurableExecution: - Enabled: true - MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -208,9 +196,6 @@ Resources: Command: ["com.amazonaws.samples.durable.timer.ScheduledReminderHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn AutoPublishAlias: live - DurableExecution: - Enabled: true - MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -235,9 +220,6 @@ Resources: Command: ["com.amazonaws.samples.durable.errorhandling.ResilientPaymentHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn AutoPublishAlias: live - DurableExecution: - Enabled: true - MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -261,9 +243,6 @@ Resources: Command: ["com.amazonaws.samples.durable.mapprocessing.BatchDataProcessorHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn AutoPublishAlias: live - DurableExecution: - Enabled: true - MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable @@ -287,9 +266,6 @@ Resources: Command: ["com.amazonaws.samples.durable.suborchestration.OrderFulfillmentHandler::handleRequest"] Role: !GetAtt DurableFunctionRole.Arn AutoPublishAlias: live - DurableExecution: - Enabled: true - MaxConcurrency: 10 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable From 60f704880d0ec4af1db5d4d338cdc58cf1f8a076 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Tue, 14 Jul 2026 14:45:15 -0700 Subject: [PATCH 10/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/README.md | 35 +- .../durable-functions-sam/template.yaml | 439 ++++++++++++++---- 2 files changed, 343 insertions(+), 131 deletions(-) diff --git a/lambda-durable-java-sam/README.md b/lambda-durable-java-sam/README.md index a09a4353c7..0636793dd2 100644 --- a/lambda-durable-java-sam/README.md +++ b/lambda-durable-java-sam/README.md @@ -119,40 +119,19 @@ docker push \ ### 3. Deploy with SAM +Delete any previously deployed stack first, then deploy: + ```bash -cd /home/ec2-user/serverless-patterns/lambda-durable-java-sam/durable-functions-sam +cd /home/ec2-user/serverless-patterns/lambda-durable-java-sam/durable-functions-sam (adjust the folder path for local deployment) -sam deploy --guided --capabilities CAPABILITY_NAMED_IAM -``` -### 4. Enable Durable Execution on Each Function +aws cloudformation delete-stack --stack-name lambda-durable-java-sam +aws cloudformation wait stack-delete-complete --stack-name lambda-durable-java-sam -After SAM deploys the functions, enable durable execution on the published version: - -```bash -FUNCTIONS=( - durable-chaining-example - durable-fanout-example - durable-human-interaction-example - durable-monitoring-example - durable-timer-example - durable-error-handling-example - durable-map-processing-example - durable-sub-orchestration-example -) - -for FUNC in "${FUNCTIONS[@]}"; do - VERSION=$(aws lambda list-versions-by-function --function-name $FUNC \ - --query 'Versions[-1].Version' --output text) - aws lambda put-function-durable-execution-config \ - --function-name $FUNC \ - --qualifier $VERSION \ - --durable-execution-config '{"Enabled": true, "MaxConcurrency": 10}' - echo "Enabled durable execution on $FUNC:$VERSION" -done +sam deploy --guided --capabilities CAPABILITY_NAMED_IAM ``` -### 5. Build the SNS Message Sender +### 4. Build the SNS Message Sender ```bash cd ../sns-message-sender diff --git a/lambda-durable-java-sam/durable-functions-sam/template.yaml b/lambda-durable-java-sam/durable-functions-sam/template.yaml index b3ba1361fa..e0cb570fb3 100644 --- a/lambda-durable-java-sam/durable-functions-sam/template.yaml +++ b/lambda-durable-java-sam/durable-functions-sam/template.yaml @@ -5,13 +5,6 @@ Description: > Demonstrates chaining, fan-out/fan-in, human interaction, monitoring, timers, error handling, map processing, and sub-orchestration patterns. -Globals: - Function: - Timeout: 60 - MemorySize: 512 - Architectures: - - x86_64 - Parameters: SNSTopicName: Type: String @@ -94,189 +87,429 @@ Resources: # Example 1: Chaining Pattern - Sequential steps with data passing ChainingFunction: - Type: AWS::Serverless::Function + Type: AWS::Lambda::Function Properties: FunctionName: durable-chaining-example PackageType: Image - ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + Code: + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" ImageConfig: - Command: ["com.amazonaws.samples.durable.chaining.OrderProcessingHandler::handleRequest"] + Command: + - com.amazonaws.samples.durable.chaining.OrderProcessingHandler::handleRequest Role: !GetAtt DurableFunctionRole.Arn - AutoPublishAlias: live + Timeout: 60 + MemorySize: 512 + Architectures: + - x86_64 + DurableConfig: + ExecutionTimeout: 3600 + RetentionPeriodInDays: 14 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable - Events: - SNSEvent: - Type: SNS - Properties: - Topic: !Ref DurableFunctionsSNSTopic - FilterPolicy: - pattern: - - chaining + + ChainingFunctionVersion: + Type: AWS::Lambda::Version + Properties: + FunctionName: !Ref ChainingFunction + + ChainingFunctionAlias: + Type: AWS::Lambda::Alias + Properties: + FunctionName: !Ref ChainingFunction + FunctionVersion: !GetAtt ChainingFunctionVersion.Version + Name: live + + ChainingFunctionSNSPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !Ref ChainingFunctionAlias + Action: lambda:InvokeFunction + Principal: sns.amazonaws.com + SourceArn: !Ref DurableFunctionsSNSTopic + + ChainingFunctionSNSSubscription: + Type: AWS::SNS::Subscription + Properties: + TopicArn: !Ref DurableFunctionsSNSTopic + Protocol: lambda + Endpoint: !Ref ChainingFunctionAlias + FilterPolicy: + pattern: + - chaining # Example 2: Fan-Out/Fan-In Pattern - Parallel processing FanOutFunction: - Type: AWS::Serverless::Function + Type: AWS::Lambda::Function Properties: FunctionName: durable-fanout-example PackageType: Image - ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + Code: + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" ImageConfig: - Command: ["com.amazonaws.samples.durable.fanout.ParallelProcessingHandler::handleRequest"] + Command: + - com.amazonaws.samples.durable.fanout.ParallelProcessingHandler::handleRequest Role: !GetAtt DurableFunctionRole.Arn - AutoPublishAlias: live + Timeout: 60 + MemorySize: 512 + Architectures: + - x86_64 + DurableConfig: + ExecutionTimeout: 3600 + RetentionPeriodInDays: 14 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable - Events: - SNSEvent: - Type: SNS - Properties: - Topic: !Ref DurableFunctionsSNSTopic - FilterPolicy: - pattern: - - fanout + + FanOutFunctionVersion: + Type: AWS::Lambda::Version + Properties: + FunctionName: !Ref FanOutFunction + + FanOutFunctionAlias: + Type: AWS::Lambda::Alias + Properties: + FunctionName: !Ref FanOutFunction + FunctionVersion: !GetAtt FanOutFunctionVersion.Version + Name: live + + FanOutFunctionSNSPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !Ref FanOutFunctionAlias + Action: lambda:InvokeFunction + Principal: sns.amazonaws.com + SourceArn: !Ref DurableFunctionsSNSTopic + + FanOutFunctionSNSSubscription: + Type: AWS::SNS::Subscription + Properties: + TopicArn: !Ref DurableFunctionsSNSTopic + Protocol: lambda + Endpoint: !Ref FanOutFunctionAlias + FilterPolicy: + pattern: + - fanout # Example 3: Human Interaction Pattern - Callbacks HumanInteractionFunction: - Type: AWS::Serverless::Function + Type: AWS::Lambda::Function Properties: FunctionName: durable-human-interaction-example PackageType: Image - ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + Code: + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" ImageConfig: - Command: ["com.amazonaws.samples.durable.humaninteraction.ApprovalWorkflowHandler::handleRequest"] + Command: + - com.amazonaws.samples.durable.humaninteraction.ApprovalWorkflowHandler::handleRequest Role: !GetAtt DurableFunctionRole.Arn - AutoPublishAlias: live + Timeout: 60 + MemorySize: 512 + Architectures: + - x86_64 + DurableConfig: + ExecutionTimeout: 3600 + RetentionPeriodInDays: 14 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable SNS_TOPIC_ARN: !Ref DurableFunctionsSNSTopic - Events: - SNSEvent: - Type: SNS - Properties: - Topic: !Ref DurableFunctionsSNSTopic - FilterPolicy: - pattern: - - approval + + HumanInteractionFunctionVersion: + Type: AWS::Lambda::Version + Properties: + FunctionName: !Ref HumanInteractionFunction + + HumanInteractionFunctionAlias: + Type: AWS::Lambda::Alias + Properties: + FunctionName: !Ref HumanInteractionFunction + FunctionVersion: !GetAtt HumanInteractionFunctionVersion.Version + Name: live + + HumanInteractionFunctionSNSPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !Ref HumanInteractionFunctionAlias + Action: lambda:InvokeFunction + Principal: sns.amazonaws.com + SourceArn: !Ref DurableFunctionsSNSTopic + + HumanInteractionFunctionSNSSubscription: + Type: AWS::SNS::Subscription + Properties: + TopicArn: !Ref DurableFunctionsSNSTopic + Protocol: lambda + Endpoint: !Ref HumanInteractionFunctionAlias + FilterPolicy: + pattern: + - approval # Example 4: Monitoring/Polling Pattern - Wait for condition MonitoringFunction: - Type: AWS::Serverless::Function + Type: AWS::Lambda::Function Properties: FunctionName: durable-monitoring-example PackageType: Image - ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + Code: + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" ImageConfig: - Command: ["com.amazonaws.samples.durable.monitoring.JobMonitorHandler::handleRequest"] + Command: + - com.amazonaws.samples.durable.monitoring.JobMonitorHandler::handleRequest Role: !GetAtt DurableFunctionRole.Arn - AutoPublishAlias: live + Timeout: 60 + MemorySize: 512 + Architectures: + - x86_64 + DurableConfig: + ExecutionTimeout: 3600 + RetentionPeriodInDays: 14 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable - Events: - SNSEvent: - Type: SNS - Properties: - Topic: !Ref DurableFunctionsSNSTopic - FilterPolicy: - pattern: - - monitoring + + MonitoringFunctionVersion: + Type: AWS::Lambda::Version + Properties: + FunctionName: !Ref MonitoringFunction + + MonitoringFunctionAlias: + Type: AWS::Lambda::Alias + Properties: + FunctionName: !Ref MonitoringFunction + FunctionVersion: !GetAtt MonitoringFunctionVersion.Version + Name: live + + MonitoringFunctionSNSPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !Ref MonitoringFunctionAlias + Action: lambda:InvokeFunction + Principal: sns.amazonaws.com + SourceArn: !Ref DurableFunctionsSNSTopic + + MonitoringFunctionSNSSubscription: + Type: AWS::SNS::Subscription + Properties: + TopicArn: !Ref DurableFunctionsSNSTopic + Protocol: lambda + Endpoint: !Ref MonitoringFunctionAlias + FilterPolicy: + pattern: + - monitoring # Example 5: Timer Pattern - Scheduled delays TimerFunction: - Type: AWS::Serverless::Function + Type: AWS::Lambda::Function Properties: FunctionName: durable-timer-example PackageType: Image - ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + Code: + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" ImageConfig: - Command: ["com.amazonaws.samples.durable.timer.ScheduledReminderHandler::handleRequest"] + Command: + - com.amazonaws.samples.durable.timer.ScheduledReminderHandler::handleRequest Role: !GetAtt DurableFunctionRole.Arn - AutoPublishAlias: live + Timeout: 60 + MemorySize: 512 + Architectures: + - x86_64 + DurableConfig: + ExecutionTimeout: 3600 + RetentionPeriodInDays: 14 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable SNS_TOPIC_ARN: !Ref DurableFunctionsSNSTopic - Events: - SNSEvent: - Type: SNS - Properties: - Topic: !Ref DurableFunctionsSNSTopic - FilterPolicy: - pattern: - - timer + + TimerFunctionVersion: + Type: AWS::Lambda::Version + Properties: + FunctionName: !Ref TimerFunction + + TimerFunctionAlias: + Type: AWS::Lambda::Alias + Properties: + FunctionName: !Ref TimerFunction + FunctionVersion: !GetAtt TimerFunctionVersion.Version + Name: live + + TimerFunctionSNSPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !Ref TimerFunctionAlias + Action: lambda:InvokeFunction + Principal: sns.amazonaws.com + SourceArn: !Ref DurableFunctionsSNSTopic + + TimerFunctionSNSSubscription: + Type: AWS::SNS::Subscription + Properties: + TopicArn: !Ref DurableFunctionsSNSTopic + Protocol: lambda + Endpoint: !Ref TimerFunctionAlias + FilterPolicy: + pattern: + - timer # Example 6: Error Handling Pattern - Retries and compensation ErrorHandlingFunction: - Type: AWS::Serverless::Function + Type: AWS::Lambda::Function Properties: FunctionName: durable-error-handling-example PackageType: Image - ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + Code: + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" ImageConfig: - Command: ["com.amazonaws.samples.durable.errorhandling.ResilientPaymentHandler::handleRequest"] + Command: + - com.amazonaws.samples.durable.errorhandling.ResilientPaymentHandler::handleRequest Role: !GetAtt DurableFunctionRole.Arn - AutoPublishAlias: live + Timeout: 60 + MemorySize: 512 + Architectures: + - x86_64 + DurableConfig: + ExecutionTimeout: 3600 + RetentionPeriodInDays: 14 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable - Events: - SNSEvent: - Type: SNS - Properties: - Topic: !Ref DurableFunctionsSNSTopic - FilterPolicy: - pattern: - - errorhandling + + ErrorHandlingFunctionVersion: + Type: AWS::Lambda::Version + Properties: + FunctionName: !Ref ErrorHandlingFunction + + ErrorHandlingFunctionAlias: + Type: AWS::Lambda::Alias + Properties: + FunctionName: !Ref ErrorHandlingFunction + FunctionVersion: !GetAtt ErrorHandlingFunctionVersion.Version + Name: live + + ErrorHandlingFunctionSNSPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !Ref ErrorHandlingFunctionAlias + Action: lambda:InvokeFunction + Principal: sns.amazonaws.com + SourceArn: !Ref DurableFunctionsSNSTopic + + ErrorHandlingFunctionSNSSubscription: + Type: AWS::SNS::Subscription + Properties: + TopicArn: !Ref DurableFunctionsSNSTopic + Protocol: lambda + Endpoint: !Ref ErrorHandlingFunctionAlias + FilterPolicy: + pattern: + - errorhandling # Example 7: Map Processing Pattern - Collection processing MapProcessingFunction: - Type: AWS::Serverless::Function + Type: AWS::Lambda::Function Properties: FunctionName: durable-map-processing-example PackageType: Image - ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + Code: + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" ImageConfig: - Command: ["com.amazonaws.samples.durable.mapprocessing.BatchDataProcessorHandler::handleRequest"] + Command: + - com.amazonaws.samples.durable.mapprocessing.BatchDataProcessorHandler::handleRequest Role: !GetAtt DurableFunctionRole.Arn - AutoPublishAlias: live + Timeout: 60 + MemorySize: 512 + Architectures: + - x86_64 + DurableConfig: + ExecutionTimeout: 3600 + RetentionPeriodInDays: 14 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable - Events: - SNSEvent: - Type: SNS - Properties: - Topic: !Ref DurableFunctionsSNSTopic - FilterPolicy: - pattern: - - mapprocessing + + MapProcessingFunctionVersion: + Type: AWS::Lambda::Version + Properties: + FunctionName: !Ref MapProcessingFunction + + MapProcessingFunctionAlias: + Type: AWS::Lambda::Alias + Properties: + FunctionName: !Ref MapProcessingFunction + FunctionVersion: !GetAtt MapProcessingFunctionVersion.Version + Name: live + + MapProcessingFunctionSNSPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !Ref MapProcessingFunctionAlias + Action: lambda:InvokeFunction + Principal: sns.amazonaws.com + SourceArn: !Ref DurableFunctionsSNSTopic + + MapProcessingFunctionSNSSubscription: + Type: AWS::SNS::Subscription + Properties: + TopicArn: !Ref DurableFunctionsSNSTopic + Protocol: lambda + Endpoint: !Ref MapProcessingFunctionAlias + FilterPolicy: + pattern: + - mapprocessing # Example 8: Sub-Orchestration Pattern - Child contexts SubOrchestrationFunction: - Type: AWS::Serverless::Function + Type: AWS::Lambda::Function Properties: FunctionName: durable-sub-orchestration-example PackageType: Image - ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" + Code: + ImageUri: !Sub "${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/durable-functions-java-examples:latest" ImageConfig: - Command: ["com.amazonaws.samples.durable.suborchestration.OrderFulfillmentHandler::handleRequest"] + Command: + - com.amazonaws.samples.durable.suborchestration.OrderFulfillmentHandler::handleRequest Role: !GetAtt DurableFunctionRole.Arn - AutoPublishAlias: live + Timeout: 60 + MemorySize: 512 + Architectures: + - x86_64 + DurableConfig: + ExecutionTimeout: 3600 + RetentionPeriodInDays: 14 Environment: Variables: DYNAMO_DB_TABLE: !Ref DurableFunctionsDynamoDBTable - Events: - SNSEvent: - Type: SNS - Properties: - Topic: !Ref DurableFunctionsSNSTopic - FilterPolicy: - pattern: - - suborchestration + + SubOrchestrationFunctionVersion: + Type: AWS::Lambda::Version + Properties: + FunctionName: !Ref SubOrchestrationFunction + + SubOrchestrationFunctionAlias: + Type: AWS::Lambda::Alias + Properties: + FunctionName: !Ref SubOrchestrationFunction + FunctionVersion: !GetAtt SubOrchestrationFunctionVersion.Version + Name: live + + SubOrchestrationFunctionSNSPermission: + Type: AWS::Lambda::Permission + Properties: + FunctionName: !Ref SubOrchestrationFunctionAlias + Action: lambda:InvokeFunction + Principal: sns.amazonaws.com + SourceArn: !Ref DurableFunctionsSNSTopic + + SubOrchestrationFunctionSNSSubscription: + Type: AWS::SNS::Subscription + Properties: + TopicArn: !Ref DurableFunctionsSNSTopic + Protocol: lambda + Endpoint: !Ref SubOrchestrationFunctionAlias + FilterPolicy: + pattern: + - suborchestration Outputs: SNSTopicArn: From c7fa711c396f21d63c65b8cebe61d9580fe342e9 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Tue, 14 Jul 2026 18:01:51 -0700 Subject: [PATCH 11/20] Added pattern lambda-durable-java-sam --- .../chaining/OrderProcessingHandler.java | 7 ++--- .../ResilientPaymentHandler.java | 4 ++- .../fanout/ParallelProcessingHandler.java | 4 ++- .../ApprovalWorkflowHandler.java | 4 ++- .../BatchDataProcessorHandler.java | 4 ++- .../durable/models/SnsEventParser.java | 27 +++++++++++++++++++ .../durable/monitoring/JobMonitorHandler.java | 4 ++- .../OrderFulfillmentHandler.java | 4 ++- .../timer/ScheduledReminderHandler.java | 4 ++- 9 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/SnsEventParser.java diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java index 5050382a3f..2d4431460c 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/chaining/OrderProcessingHandler.java @@ -1,15 +1,15 @@ package com.amazonaws.samples.durable.chaining; import java.util.Map; +import java.time.Duration; +import com.amazonaws.samples.durable.models.SnsEventParser; import software.amazon.lambda.durable.DurableContext; import software.amazon.lambda.durable.DurableHandler; import software.amazon.lambda.durable.config.StepConfig; import software.amazon.lambda.durable.retry.RetryStrategies; import software.amazon.lambda.durable.retry.JitterStrategy; -import java.time.Duration; - /** * PATTERN: Function Chaining * @@ -23,7 +23,8 @@ public class OrderProcessingHandler extends DurableHandler, Map> { @Override - public Map handleRequest(Map event, DurableContext context) { + public Map handleRequest(Map rawEvent, DurableContext context) { + Map event = SnsEventParser.extractMessage(rawEvent); context.getLogger().info("Starting order processing chain for: " + event.get("orderId")); StepConfig retryConfig = StepConfig.builder() diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java index 7aeb5cb43a..43b254d07a 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/errorhandling/ResilientPaymentHandler.java @@ -3,6 +3,7 @@ import java.time.Duration; import java.util.Map; +import com.amazonaws.samples.durable.models.SnsEventParser; import software.amazon.lambda.durable.DurableContext; import software.amazon.lambda.durable.DurableHandler; import software.amazon.lambda.durable.config.StepConfig; @@ -30,7 +31,8 @@ public class ResilientPaymentHandler extends DurableHandler, Map> { @Override - public Map handleRequest(Map event, DurableContext context) { + public Map handleRequest(Map rawEvent, DurableContext context) { + Map event = SnsEventParser.extractMessage(rawEvent); context.getLogger().info("Starting resilient payment workflow"); String orderId = (String) event.getOrDefault("orderId", "ORD-001"); diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java index 23193384d7..b83279c9f4 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/fanout/ParallelProcessingHandler.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Map; +import com.amazonaws.samples.durable.models.SnsEventParser; import software.amazon.lambda.durable.DurableContext; import software.amazon.lambda.durable.DurableFuture; import software.amazon.lambda.durable.DurableHandler; @@ -23,7 +24,8 @@ public class ParallelProcessingHandler extends DurableHandler, Map> { @Override - public Map handleRequest(Map event, DurableContext context) { + public Map handleRequest(Map rawEvent, DurableContext context) { + Map event = SnsEventParser.extractMessage(rawEvent); context.getLogger().info("Starting fan-out/fan-in processing"); String dataId = (String) event.getOrDefault("dataId", "DATA-001"); diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java index b61a174b08..3b9715d9f9 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/humaninteraction/ApprovalWorkflowHandler.java @@ -3,6 +3,7 @@ import java.time.Duration; import java.util.Map; +import com.amazonaws.samples.durable.models.SnsEventParser; import software.amazon.lambda.durable.DurableCallbackFuture; import software.amazon.lambda.durable.DurableContext; import software.amazon.lambda.durable.DurableHandler; @@ -34,7 +35,8 @@ public class ApprovalWorkflowHandler extends DurableHandler, Map> { @Override - public Map handleRequest(Map event, DurableContext context) { + public Map handleRequest(Map rawEvent, DurableContext context) { + Map event = SnsEventParser.extractMessage(rawEvent); context.getLogger().info("Starting approval workflow"); String requestId = (String) event.getOrDefault("requestId", "REQ-" + System.currentTimeMillis()); diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java index 69956729ec..c2f0aaa2a1 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/mapprocessing/BatchDataProcessorHandler.java @@ -5,6 +5,7 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import com.amazonaws.samples.durable.models.SnsEventParser; import software.amazon.lambda.durable.DurableContext; import software.amazon.lambda.durable.DurableHandler; import software.amazon.lambda.durable.config.CompletionConfig; @@ -29,7 +30,8 @@ public class BatchDataProcessorHandler extends DurableHandler, Map> { @Override - public Map handleRequest(Map event, DurableContext context) { + public Map handleRequest(Map rawEvent, DurableContext context) { + Map event = SnsEventParser.extractMessage(rawEvent); context.getLogger().info("Starting batch data processing"); int batchSize = ((Number) event.getOrDefault("batchSize", 10)).intValue(); diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/SnsEventParser.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/SnsEventParser.java new file mode 100644 index 0000000000..381e47418d --- /dev/null +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/models/SnsEventParser.java @@ -0,0 +1,27 @@ +package com.amazonaws.samples.durable.models; + +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class SnsEventParser { + + private static final ObjectMapper mapper = new ObjectMapper(); + + @SuppressWarnings("unchecked") + public static Map extractMessage(Map event) { + try { + List> records = (List>) event.get("Records"); + if (records != null && !records.isEmpty()) { + Map sns = (Map) records.get(0).get("Sns"); + String message = (String) sns.get("Message"); + return mapper.readValue(message, new TypeReference>() {}); + } + } catch (Exception e) { + // Not an SNS event envelope, return as-is + } + return event; + } +} diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java index a031c590c4..852b50b114 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/monitoring/JobMonitorHandler.java @@ -3,6 +3,7 @@ import java.time.Duration; import java.util.Map; +import com.amazonaws.samples.durable.models.SnsEventParser; import software.amazon.lambda.durable.DurableContext; import software.amazon.lambda.durable.DurableHandler; import software.amazon.lambda.durable.TypeToken; @@ -28,7 +29,8 @@ public class JobMonitorHandler extends DurableHandler, Map handleRequest(Map event, DurableContext context) { + public Map handleRequest(Map rawEvent, DurableContext context) { + Map event = SnsEventParser.extractMessage(rawEvent); context.getLogger().info("Starting job monitor"); String jobId = (String) event.getOrDefault("jobId", "JOB-" + System.currentTimeMillis()); diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java index 916189b8fd..f6114b737d 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/suborchestration/OrderFulfillmentHandler.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Map; +import com.amazonaws.samples.durable.models.SnsEventParser; import software.amazon.lambda.durable.DurableContext; import software.amazon.lambda.durable.DurableFuture; import software.amazon.lambda.durable.DurableHandler; @@ -27,7 +28,8 @@ public class OrderFulfillmentHandler extends DurableHandler, Map> { @Override - public Map handleRequest(Map event, DurableContext context) { + public Map handleRequest(Map rawEvent, DurableContext context) { + Map event = SnsEventParser.extractMessage(rawEvent); context.getLogger().info("Starting order fulfillment orchestration"); String orderId = (String) event.getOrDefault("orderId", "ORD-" + System.currentTimeMillis()); diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java index 46e2253476..1078902b31 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/main/java/com/amazonaws/samples/durable/timer/ScheduledReminderHandler.java @@ -3,6 +3,7 @@ import java.time.Duration; import java.util.Map; +import com.amazonaws.samples.durable.models.SnsEventParser; import software.amazon.lambda.durable.DurableContext; import software.amazon.lambda.durable.DurableFuture; import software.amazon.lambda.durable.DurableHandler; @@ -25,7 +26,8 @@ public class ScheduledReminderHandler extends DurableHandler, Map> { @Override - public Map handleRequest(Map event, DurableContext context) { + public Map handleRequest(Map rawEvent, DurableContext context) { + Map event = SnsEventParser.extractMessage(rawEvent); context.getLogger().info("Starting scheduled reminder workflow"); String taskId = (String) event.getOrDefault("taskId", "TASK-001"); From 7dc00521b92c3b8376d44fe32f77adacd43aaccd Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Tue, 14 Jul 2026 22:57:07 -0700 Subject: [PATCH 12/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/DIAGRAMS.md | 67 +++++++ .../images/pattern1-chaining.svg | 175 ++++++++++++++++++ .../images/pattern2-fanout.svg | 137 ++++++++++++++ .../images/pattern3-human-interaction.svg | 139 ++++++++++++++ .../images/pattern4-monitoring.svg | 144 ++++++++++++++ .../images/pattern5-timer.svg | 148 +++++++++++++++ .../images/pattern6-error-handling.svg | 139 ++++++++++++++ .../images/pattern7-map-processing.svg | 147 +++++++++++++++ .../images/pattern8-sub-orchestration.svg | 160 ++++++++++++++++ 9 files changed, 1256 insertions(+) create mode 100644 lambda-durable-java-sam/DIAGRAMS.md create mode 100644 lambda-durable-java-sam/images/pattern1-chaining.svg create mode 100644 lambda-durable-java-sam/images/pattern2-fanout.svg create mode 100644 lambda-durable-java-sam/images/pattern3-human-interaction.svg create mode 100644 lambda-durable-java-sam/images/pattern4-monitoring.svg create mode 100644 lambda-durable-java-sam/images/pattern5-timer.svg create mode 100644 lambda-durable-java-sam/images/pattern6-error-handling.svg create mode 100644 lambda-durable-java-sam/images/pattern7-map-processing.svg create mode 100644 lambda-durable-java-sam/images/pattern8-sub-orchestration.svg diff --git a/lambda-durable-java-sam/DIAGRAMS.md b/lambda-durable-java-sam/DIAGRAMS.md new file mode 100644 index 0000000000..9b0d41fea6 --- /dev/null +++ b/lambda-durable-java-sam/DIAGRAMS.md @@ -0,0 +1,67 @@ +# Lambda Durable Functions - Step Diagrams + +Visual step-by-step flow diagrams for each durable execution pattern. + +--- + +## Pattern 1: Function Chaining + +Sequential steps where each step's output feeds into the next. Completed steps are checkpointed and never re-executed on replay. + +![Pattern 1: Chaining](images/pattern1-chaining.svg) + +--- + +## Pattern 2: Fan-Out / Fan-In + +Parallel execution of independent operations with result aggregation. Uses `parallel()` for heterogeneous tasks and `map()` for homogeneous collection processing. + +![Pattern 2: Fan-Out/Fan-In](images/pattern2-fanout.svg) + +--- + +## Pattern 3: Human Interaction + +Execution suspends while waiting for an external human decision via callback. No compute charges during the wait. An external system calls `send-durable-execution-callback-success` or `send-durable-execution-callback-failure` to resume. + +![Pattern 3: Human Interaction](images/pattern3-human-interaction.svg) + +--- + +## Pattern 4: Monitoring / Polling + +Uses `waitForCondition` to poll an external system with exponential backoff. The function suspends between polls without consuming compute. + +![Pattern 4: Monitoring](images/pattern4-monitoring.svg) + +--- + +## Pattern 5: Timer / Scheduled Delays + +Uses `wait()` to suspend execution for specified durations. The function exits and is automatically resumed when the wait completes — zero compute charges during waits. + +![Pattern 5: Timer](images/pattern5-timer.svg) + +--- + +## Pattern 6: Error Handling & Saga Compensation + +Demonstrates retries with backoff, at-most-once semantics for non-idempotent operations, custom retry logic, and saga compensation when later steps fail. + +![Pattern 6: Error Handling](images/pattern6-error-handling.svg) + +--- + +## Pattern 7: Map Processing + +Processes a collection concurrently with configurable concurrency limits and failure tolerance. Each item gets its own child context with independent checkpoints. + +![Pattern 7: Map Processing](images/pattern7-map-processing.svg) + +--- + +## Pattern 8: Sub-Orchestration + +Uses `runInChildContext()` and `runInChildContextAsync()` to compose complex workflows from isolated, reusable sub-workflows. Each child context has its own operation namespace. + +![Pattern 8: Sub-Orchestration](images/pattern8-sub-orchestration.svg) diff --git a/lambda-durable-java-sam/images/pattern1-chaining.svg b/lambda-durable-java-sam/images/pattern1-chaining.svg new file mode 100644 index 0000000000..dfcfebf88a --- /dev/null +++ b/lambda-durable-java-sam/images/pattern1-chaining.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pattern 1: Function Chaining + | + Sequential steps with checkpointed results + + + + SNS Topic + + + + + + + + + Step 1: validate-order + Validate orderId exists + Verify amount > 0 + Retry: 3x, exp backoff + + + + checkpointed + + + + + + Step 2: reserve-inventory + Reserve stock in warehouse + Generate reservationId + Retry: 3x, exp backoff + + + + checkpointed + + + + + + Step 3: process-payment + Charge customer card + Generate transactionId + Retry: 3x, exp backoff + + + + checkpointed + + + + + + Step 4: ship-order + Create shipping label + Generate trackingNumber + Retry: 3x, exp backoff + + + + + + + + + Step 5: notify-customer + Send shipment email + Include tracking info + + + + + + Key Concept: Checkpointing & Replay + + Each step's result is durably checkpointed. If the function is interrupted (timeout, error, wait), it resumes from + the last checkpoint without re-executing completed steps. + + + + Step 1 + + + + + + Step 2 + + + + + + Step 3 + + + + + + Step 4 + + + + + Step 5 + + ← On replay: skips 1-2, resumes at 3 + + + + + + Data Flow Between Steps + + + + Input (SNS Message) + orderId: "ORD-123" + totalAmount: 299.99 + customerId: "CUST-001" + shippingAddress: "123 Main St" + + + + + Validate Output + orderId: "ORD-123" + status: "VALIDATED" + amount: 299.99 + customerId: "CUST-001" + + + + + Inventory Output + orderId: "ORD-123" + status: "INVENTORY_RESERVED" + reservationId: "RES-ORD-123" + warehouse: "WAREHOUSE-EAST-1" + + + + + Final Output + pattern: "CHAINING" + finalStatus: "COMPLETED" + trackingNumber: "TRACK-..." + transactionId: "TXN-..." + + → DynamoDB + diff --git a/lambda-durable-java-sam/images/pattern2-fanout.svg b/lambda-durable-java-sam/images/pattern2-fanout.svg new file mode 100644 index 0000000000..87d2ef14b4 --- /dev/null +++ b/lambda-durable-java-sam/images/pattern2-fanout.svg @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pattern 2: Fan-Out / Fan-In + | + Parallel execution with result aggregation + + + + SNS Topic + + + + + + + parallel("analyze-data") - 3 concurrent branches + + + + + + Branch: sentiment-analysis + Analyze document sentiment + Result: "POSITIVE (0.87)" + + + + + + Branch: entity-extraction + Extract named entities + Result: [AWS, Lambda, Java...] + + + + + + Branch: summarization + Generate document summary + Result: "Document discusses..." + + + + All branches execute concurrently - total time = slowest branch (~700ms) + + + + BARRIER + + + + + + + + + map("process-documents") - 5 items processed concurrently + + + + doc-1 + wordCount: 150 + PROCESSED ✓ + + + doc-2 + wordCount: 300 + PROCESSED ✓ + + + doc-3 + wordCount: 450 + PROCESSED ✓ + + + doc-4 + wordCount: 600 + PROCESSED ✓ + + + doc-5 + wordCount: 750 + PROCESSED ✓ + + + + Each item gets its own child context with independent checkpointing + + + + + + + + + Step: aggregate-results + Combines parallel analysis + map results + sentiment + entities + summary + docsProcessed + → Returns: FAN_OUT_FAN_IN COMPLETED + + + + Legend + + parallel() - heterogeneous + + map() - homogeneous + + Barrier (wait for all) + + Checkpointed step + parallel() runs different + tasks concurrently; map() + applies same logic to each + diff --git a/lambda-durable-java-sam/images/pattern3-human-interaction.svg b/lambda-durable-java-sam/images/pattern3-human-interaction.svg new file mode 100644 index 0000000000..3a30b2bde1 --- /dev/null +++ b/lambda-durable-java-sam/images/pattern3-human-interaction.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pattern 3: Human Interaction + | + Suspend execution awaiting external callback + + + + + + prepare-approval + Build approval request + Identify approver + Retry: 3x, exp backoff + + + + + + + + + notify-approver + Send email/SMS + Include callback URL + Retry: 3x, exp backoff + + + + + + + EXECUTION SUSPENDED + createCallback() + No compute charges during wait + Timeout: 72 hours + + $0.00 / hour billed + + + + Callback ID logged for external use: + send-durable-execution-callback-success + + + + + + + APPROVED + + + + + + + REJECTED + + + + + + process-request + Execute approved action + Update database record + + + + + + + + + send-confirmation + Notify requester + Include approval details + + + + + + + COMPLETED + + + + + + return-status + Return REJECTED status + + + + + + Key Concept: Callback-Based Suspension + + The execution is fully suspended during the wait. No Lambda compute is consumed. The function resumes only when an + external system calls back with the callback ID, or when the timeout (72 hours) expires. + + + + + Active (~200ms) + + SUSPENDED - Zero compute (minutes to 72 hours) + + Resumed (~100ms) + + External trigger: aws lambda invoke ... send-durable-execution-callback-success --payload '{"callbackId": "...", "result": "APPROVED"}' + diff --git a/lambda-durable-java-sam/images/pattern4-monitoring.svg b/lambda-durable-java-sam/images/pattern4-monitoring.svg new file mode 100644 index 0000000000..70ca1f4e5e --- /dev/null +++ b/lambda-durable-java-sam/images/pattern4-monitoring.svg @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pattern 4: Monitoring + | + Polling with exponential backoff and durable suspension + + + + + + acknowledge-job + Record job start time + Initialize attempt = 0 + + + + + + + + + waitForCondition() - Polling Loop with Exponential Backoff + + + + Poll #1 + check status + NOT READY + + + + + SUSPEND + wait 5s + + + + + Poll #2 + check status + NOT READY + + + + + SUSPEND + wait 10s + + + + + Poll #3 + check status + NOT READY + + + + + SUSPEND + wait 20s + + + ... + + + + Poll + #N + DONE! + + + + Backoff Formula: + delay = 5s × 2^(attempt-1), capped at 60s | Sequence: 5s, 10s, 20s, 40s, 60s, 60s, ... + + + + + + + + + Condition Check (stopPolling) + COMPLETED or FAILED → exit loop + Max attempts or timeout → FAILED + + + + + + + + + process-result + Format final status + Store job outcome + + + + + + + COMPLETED + + + + + + Key Concept: Durable Polling vs. Busy Waiting + + Unlike traditional polling (Lambda running continuously), each wait() call suspends the execution entirely. + The function resumes only when the timer fires. You pay only for the brief poll check (~50ms), not the wait time. + + + + Traditional: 10 polls × 15min timeout = 150min billed + + Durable: 10 polls × 50ms active = 500ms billed + diff --git a/lambda-durable-java-sam/images/pattern5-timer.svg b/lambda-durable-java-sam/images/pattern5-timer.svg new file mode 100644 index 0000000000..7fbc43b861 --- /dev/null +++ b/lambda-durable-java-sam/images/pattern5-timer.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pattern 5: Timer / Scheduled Delays + | + Durable waits with zero compute charges + + + + + + + create-task + Create escalation task + Record creation time + + + + + + + + + send-initial-notification + Notify assignee + Start escalation timer + + + + + + + SUSPENDED + wait(30s) + + + + + + + + + send-first-reminder + Remind assignee + Warning: escalation soon + + + + + + + SUSPENDED + wait(60s) + + + + + + + + + escalate-to-manager + Notify manager + Mark as escalated + + + + + + + + + Parallel: waitAsync(5s) + stepAsync(final-processing) + + + waitAsync(5s) + + + stepAsync: final-processing + + + + + + + ESCALATED + + + + + + Key Concept: Zero-Cost Durable Timers + + During wait() periods, the execution is fully suspended. No Lambda compute is consumed. + The function resumes precisely when the timer fires - whether 30 seconds or 30 days later. + + + Execution Timeline: + + + ~100ms + + + wait(30s) - $0 + + + ~100ms + + + wait(60s) - $0 + + + ~100ms + + + wait(5s) - $0 + + + ~100ms + + + Total billed compute: ~400ms | Total elapsed time: ~95 seconds | Cost savings vs continuous execution: 99.6% + + + + Zero compute charges during all wait() periods + diff --git a/lambda-durable-java-sam/images/pattern6-error-handling.svg b/lambda-durable-java-sam/images/pattern6-error-handling.svg new file mode 100644 index 0000000000..6e472324f8 --- /dev/null +++ b/lambda-durable-java-sam/images/pattern6-error-handling.svg @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pattern 6: Error Handling & Compensation + | + Retry policies, saga compensation, and interrupt handling + + + + + + validate-payment + Verify card details + Check fraud signals + Retry: default (3x, backoff) + + + + + + + + + charge-payment (AT_MOST_ONCE) + + Custom Retry Policy: + • Skip: IllegalArgumentException + • Retry transient errors: up to 4x + • Backoff: exponential + + + + Attempt 0: FAIL + + Attempt 1: OK ✓ + + + + + + StepInterruptedException + Check payment status externally + before retrying (idempotency) + + + + + + + + + reserve-inventory + Reserve stock + Lock quantity + Retry: 3x, exp backoff + + + + + SUCCESS + + + + COMPLETED + + + + + FAIL + + + + + + SAGA COMPENSATION + + + + + + refund-payment + Reverse charge + Notify customer + + + + + + + COMPENSATED + + + + + + Key Concepts: Retry Semantics & Saga Pattern + + + AT_MOST_ONCE Semantics: + If the function is interrupted during a step marked AT_MOST_ONCE, it will NOT automatically retry. + Instead, a StepInterruptedException is thrown so you can check the external state before deciding to retry. + + + Saga Compensation Pattern: + When a later step fails, previously completed steps are compensated (reversed) to maintain consistency. + Each step has an associated compensation action that undoes its effect. + + + Custom Retry Configuration: + + retryOn(RuntimeException.class).skipOn(IllegalArgumentException.class).maxRetries(4).backoff(exponential) | Non-retryable errors skip immediately + diff --git a/lambda-durable-java-sam/images/pattern7-map-processing.svg b/lambda-durable-java-sam/images/pattern7-map-processing.svg new file mode 100644 index 0000000000..97bbe8f01e --- /dev/null +++ b/lambda-durable-java-sam/images/pattern7-map-processing.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pattern 7: Map Processing + | + Bounded-concurrency batch processing with failure tolerance + + + + + + prepare-batch + Load 10 items from queue + Partition into work units + + + + + + + + + map("process-items") - maxConcurrency=3, toleratedFailures=2 + + + 3 Concurrent Slots: + + + + + + Slot 1 + + + validate + + + transform + + + store + + Items 1, 4, 7, 10 + item-5: ✗ fails validation + + + + + + Slot 2 + + + validate + + + transform + + + store + + Items 2, 5, 8 + item-10: ✗ fails validation + + + + + + Slot 3 + + + validate + + + transform + + + store + + Items 3, 6, 9 + All succeed ✓ + + + + Failure Tolerance: 2 failures tolerated + Every 5th item fails validation. 2 failures (items 5, 10) ≤ toleratedFailures=2 → map() continues and completes + + + + Progress: 10/10 processed | 8 succeeded | 2 failed (within tolerance) + + + + + + + + + summarize-results + Aggregate outcomes: + 8 succeeded ✓ + 2 failed ✗ + Success rate: 80% + Store summary in DDB + Total items: 10 + + + + + + Key Concept: Bounded Concurrency & Failure Tolerance + + map() processes items with bounded concurrency (maxConcurrency=3). Items are distributed across slots round-robin. + If failures ≤ toleratedFailures, the map completes successfully. If exceeded, it throws MapBatchFailedException. + + + + Configuration: + maxConcurrency=3 | toleratedFailures=2 | each item: validate → transform → store + Items assigned to slots: Slot1=[1,4,7,10] Slot2=[2,5,8] Slot3=[3,6,9] + + + + vs. Step Functions Map: + Same bounded concurrency concept, but runs within a single Lambda + No state machine transitions overhead - sub-steps are checkpointed within the function + diff --git a/lambda-durable-java-sam/images/pattern8-sub-orchestration.svg b/lambda-durable-java-sam/images/pattern8-sub-orchestration.svg new file mode 100644 index 0000000000..a3c92e7582 --- /dev/null +++ b/lambda-durable-java-sam/images/pattern8-sub-orchestration.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Pattern 8: Sub-Orchestration + | + Child workflow contexts with isolated operation namespaces + + + + Main Context + + + + + + validate-order + Verify order details + Check inventory exists + + + + + + + + + CONCURRENT: allOf() barrier - both must complete + + + + + + Payment Sub-Workflow (child context: "payment") + + + authorize-card + + + + + wait 2s + SUSPEND + + + + + fraud-check + + + + + capture-payment + + + Isolated namespace: payment.authorize-card, payment.fraud-check, ... + + + + + + Inventory Sub-Workflow ("inventory") + + + check-availability + + + + + reserve-stock + + + Isolated: inventory.check-availability, inventory.reserve-stock + + + + BARRIER + + + + sequential + + + + + + Shipping Sub-Workflow (child context: "shipping") + + + create-label + + + + + schedule-pickup + + + + + generate-tracking + + + Isolated: shipping.* + + + + + + + + + Notification Sub-Workflow (child context: "notification") + + + send-confirmation + + + + + send-shipping-notification + + + notification.* + + + + + + + FULFILLED + + + + + + Key Concept: Isolated Child Contexts + + Each child workflow runs in its own context with namespaced operations (e.g., "payment.authorize-card"). This prevents + step name collisions and enables independent checkpointing. allOf() waits for all concurrent children before proceeding. + From 9d13912c13e0f02fdae25e8c10acc350a43eb6d8 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Wed, 15 Jul 2026 10:35:11 -0700 Subject: [PATCH 13/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/DEVELOPER_GUIDE.md | 2 ++ lambda-durable-java-sam/README.md | 31 ++++++++++----------- lambda-durable-java-sam/USER_GUIDE.md | 21 ++++++++++---- lambda-durable-java-sam/build-and-deploy.sh | 10 ++++--- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/lambda-durable-java-sam/DEVELOPER_GUIDE.md b/lambda-durable-java-sam/DEVELOPER_GUIDE.md index ccff063d0f..4b31baf9e0 100644 --- a/lambda-durable-java-sam/DEVELOPER_GUIDE.md +++ b/lambda-durable-java-sam/DEVELOPER_GUIDE.md @@ -13,6 +13,8 @@ 9. [Testing](#testing) 10. [Common Pitfalls](#common-pitfalls) +> **Tip:** For visual step-by-step flow diagrams of each pattern, see [DIAGRAMS.md](DIAGRAMS.md). + --- ## Architecture Overview diff --git a/lambda-durable-java-sam/README.md b/lambda-durable-java-sam/README.md index 0636793dd2..914950ead3 100644 --- a/lambda-durable-java-sam/README.md +++ b/lambda-durable-java-sam/README.md @@ -44,25 +44,20 @@ The CloudFormation template deploys a VPC with a public subnet and an EC2 instan **1. Deploy the infrastructure stack:** -```bash -aws cloudformation create-stack \ - --stack-name durable-functions-infra \ - --template-body file://infrastructure/ec2-client-instance.yaml \ - --capabilities CAPABILITY_NAMED_IAM -``` - -Wait for the stack to complete (~5 minutes): -```bash -aws cloudformation wait stack-create-complete --stack-name durable-functions-infra -``` +1. Open the [AWS CloudFormation console](https://console.aws.amazon.com/cloudformation/) +2. Click **Create stack** > **With new resources (standard)** +3. Select **Upload a template file**, then upload `infrastructure/ec2-client-instance.yaml` +4. Enter stack name: `durable-functions-infra` +5. Click **Next** through the options, check **I acknowledge that AWS CloudFormation might create IAM resources with custom names**, then click **Submit** +6. Wait for the stack status to reach **CREATE_COMPLETE** (~5 minutes) **2. Connect to the instance via EC2 Instance Connect:** -```bash -INSTANCE_ID=$(aws cloudformation describe-stacks --stack-name durable-functions-infra \ - --query 'Stacks[0].Outputs[?OutputKey==`EC2InstanceId`].OutputValue' --output text) -aws ec2-instance-connect ssh --instance-id $INSTANCE_ID -``` +1. Open the [AWS EC2 console](https://console.aws.amazon.com/ec2/) +2. Click **Instances** in the left navigation +3. Select the instance named `DurableFunctionsDevInstance` (created by the stack) +4. Click **Connect** at the top +5. On the **EC2 Instance Connect** tab, click **Connect** **3. Navigate to the project directory:** @@ -198,6 +193,10 @@ aws lambda send-durable-execution-callback-failure \ --error ErrorType=Rejected,ErrorMessage="Budget exceeded policy limit" ``` +## Step Diagrams + +For visual step-by-step flow diagrams of each pattern, see [DIAGRAMS.md](DIAGRAMS.md). + ## Key Concepts ### DurableHandler diff --git a/lambda-durable-java-sam/USER_GUIDE.md b/lambda-durable-java-sam/USER_GUIDE.md index e53d37c483..3acc2ad0a1 100644 --- a/lambda-durable-java-sam/USER_GUIDE.md +++ b/lambda-durable-java-sam/USER_GUIDE.md @@ -4,6 +4,10 @@ Welcome to the **AWS Lambda Durable Functions in Java** workshop! In this workshop, you will learn how to build resilient, long-running workflows using Lambda Durable Functions. You'll deploy and run eight different patterns that demonstrate the full capability of durable execution in Java. +### Visual Step Diagrams + +To see the visual flow of each pattern, refer to [DIAGRAMS.md](DIAGRAMS.md). + ### What are Lambda Durable Functions? Lambda Durable Functions enable you to build multi-step applications that can execute for up to **one year** while maintaining reliable progress despite interruptions. Key capabilities: @@ -102,16 +106,17 @@ docker build -t durable-functions-java-examples . ```bash AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) -AWS_REGION=$(aws configure get region) - -# Create repository -aws ecr create-repository --repository-name durable-functions-java-examples +AWS_REGION=${AWS_REGION:-$(aws configure get region)} # Login to ECR aws ecr get-login-password --region $AWS_REGION \ | docker login --username AWS --password-stdin \ $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com +# Delete the repository if it already exists, then recreate it +aws ecr delete-repository --repository-name durable-functions-java-examples --force 2>/dev/null +aws ecr create-repository --repository-name durable-functions-java-examples + # Tag and push docker tag durable-functions-java-examples:latest \ $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/durable-functions-java-examples:latest @@ -124,7 +129,7 @@ docker push \ ```bash cd .. -sam deploy --guided +sam deploy --guided --capabilities CAPABILITY_NAMED_IAM ``` Accept the defaults or customize: @@ -133,6 +138,12 @@ Accept the defaults or customize: - Confirm changeset: Yes - Allow SAM CLI to create IAM roles: Yes +> **Note:** If redeploying, delete the existing stack first since durable execution config cannot be added to existing functions: +> ```bash +> aws cloudformation delete-stack --stack-name durable-functions-java-examples +> aws cloudformation wait stack-delete-complete --stack-name durable-functions-java-examples +> ``` + ### Step 5: Build the SNS message sender ```bash diff --git a/lambda-durable-java-sam/build-and-deploy.sh b/lambda-durable-java-sam/build-and-deploy.sh index 3cd997f708..435d8067ae 100755 --- a/lambda-durable-java-sam/build-and-deploy.sh +++ b/lambda-durable-java-sam/build-and-deploy.sh @@ -6,7 +6,7 @@ echo " Lambda Durable Functions Java - Build and Deploy" echo "============================================================" AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) -AWS_REGION=$(aws configure get region) +AWS_REGION=${AWS_REGION:-$(aws configure get region)} ECR_REPO="durable-functions-java-examples" IMAGE_URI="$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPO:latest" @@ -28,10 +28,12 @@ echo ">>> Step 2: Building Docker image..." docker build -t $ECR_REPO . echo " Docker image built." -# Step 3: Create ECR repository (ignore error if exists) +# Step 3: Delete and recreate ECR repository echo "" -echo ">>> Step 3: Ensuring ECR repository exists..." -aws ecr create-repository --repository-name $ECR_REPO 2>/dev/null || echo " Repository already exists." +echo ">>> Step 3: Recreating ECR repository..." +aws ecr delete-repository --repository-name $ECR_REPO --force 2>/dev/null || true +aws ecr create-repository --repository-name $ECR_REPO +echo " Repository created." # Step 4: Login to ECR and push echo "" From f9583d3db177d41d2310e07a6e47f11f2cc852b5 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Wed, 15 Jul 2026 15:02:40 -0700 Subject: [PATCH 14/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lambda-durable-java-sam/README.md b/lambda-durable-java-sam/README.md index 914950ead3..961ec06173 100644 --- a/lambda-durable-java-sam/README.md +++ b/lambda-durable-java-sam/README.md @@ -71,7 +71,28 @@ Then continue from [Build and Deploy](#build-and-deploy) below. Ensure you have Java 21+, Maven 3.8+, Docker, AWS CLI v2, and SAM CLI installed. -Clone the project: +**1. Configure your AWS credentials and region:** + +If you don't have an AWS CLI profile configured, create one pointing to the account where you want to deploy: + +```bash +aws configure +``` + +If you have multiple profiles, set your desired profile as the default for this shell session: + +```bash +export AWS_PROFILE=your-profile-name +``` + +Set the AWS region where you want to deploy the pattern: + +```bash +export AWS_REGION=us-east-1 # Change to your preferred region +``` + +**2. Clone the project:** + ```bash git clone https://github.com/aws-samples/serverless-patterns.git cd serverless-patterns/lambda-durable-java-sam From 868efde74dd451250503209e2503e130a6daa1c5 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Thu, 16 Jul 2026 09:34:24 -0700 Subject: [PATCH 15/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/README.md | 162 ++++++++++++++++++-- lambda-durable-java-sam/USER_GUIDE.md | 4 +- lambda-durable-java-sam/build-and-deploy.sh | 2 +- 3 files changed, 157 insertions(+), 11 deletions(-) diff --git a/lambda-durable-java-sam/README.md b/lambda-durable-java-sam/README.md index 961ec06173..23162dc97c 100644 --- a/lambda-durable-java-sam/README.md +++ b/lambda-durable-java-sam/README.md @@ -71,7 +71,39 @@ Then continue from [Build and Deploy](#build-and-deploy) below. Ensure you have Java 21+, Maven 3.8+, Docker, AWS CLI v2, and SAM CLI installed. -**1. Configure your AWS credentials and region:** +**1. Set JAVA_HOME:** + +Ensure `JAVA_HOME` points to your Java 21 installation directory (not the `bin` subdirectory): + +**macOS (zsh/bash):** +```bash +export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-21.jdk/Contents/Home +``` + +**Linux (bash):** +```bash +export JAVA_HOME=/usr/lib/jvm/java-21-amazon-corretto +``` + +**Windows (PowerShell):** +```powershell +$env:JAVA_HOME = "C:\Program Files\Amazon Corretto\jdk21.0.x_x" +``` + +**Windows (Command Prompt):** +```cmd +set JAVA_HOME=C:\Program Files\Amazon Corretto\jdk21.0.x_x +``` + +Verify it's correct: +```bash +echo $JAVA_HOME # Should NOT end with /bin +$JAVA_HOME/bin/java -version # Should print Java 21 +``` + +Add the export to your shell profile (`~/.zshrc`, `~/.bashrc`, or Windows System Environment Variables) to persist across sessions. + +**2. Configure your AWS credentials and region:** If you don't have an AWS CLI profile configured, create one pointing to the account where you want to deploy: @@ -81,17 +113,25 @@ aws configure If you have multiple profiles, set your desired profile as the default for this shell session: +**macOS/Linux:** ```bash export AWS_PROFILE=your-profile-name +export AWS_REGION=us-east-1 # Change to your preferred region ``` -Set the AWS region where you want to deploy the pattern: +**Windows (PowerShell):** +```powershell +$env:AWS_PROFILE = "your-profile-name" +$env:AWS_REGION = "us-east-1" # Change to your preferred region +``` -```bash -export AWS_REGION=us-east-1 # Change to your preferred region +**Windows (Command Prompt):** +```cmd +set AWS_PROFILE=your-profile-name +set AWS_REGION=us-east-1 ``` -**2. Clone the project:** +**3. Clone the project:** ```bash git clone https://github.com/aws-samples/serverless-patterns.git @@ -109,15 +149,37 @@ Then continue from [Build and Deploy](#build-and-deploy) below. ```bash cd durable-functions-sam/durable-functions mvn clean package -DskipTests +``` + +Build the Docker image. Use the command that matches your environment: + +**From EC2 instance (Amazon Linux x86_64):** +```bash docker build -t durable-functions-java-examples . ``` +**From local machine (macOS, Linux, or Windows with Docker Desktop):** +```bash +docker build --platform linux/amd64 --provenance=false -t durable-functions-java-examples . +``` + +> **Why these flags?** +> - `--platform linux/amd64` — Lambda runs on x86_64. Required on Apple Silicon Macs (M1/M2/M3/M4) to avoid building an ARM image. Harmless on x86_64 machines. +> - `--provenance=false` — Required on **all platforms** with Docker BuildKit (Docker 23+). Prevents Docker from producing OCI image indexes. Lambda only supports Docker V2 manifest format. Without this flag you'll see: *"The image manifest, config or layer media type... is not supported."* +> +> **Tip:** If you're unsure which platform you're on, always use the local machine command — it works everywhere. + ### 2. Push to ECR ```bash AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) AWS_REGION=${AWS_REGION:-$(aws configure get region)} +# Verify variables are set correctly before proceeding +echo "Account: $AWS_ACCOUNT_ID" +echo "Region: $AWS_REGION" + +# Login to ECR aws ecr get-login-password --region $AWS_REGION \ | docker login --username AWS --password-stdin \ $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com @@ -126,6 +188,7 @@ aws ecr get-login-password --region $AWS_REGION \ aws ecr delete-repository --repository-name durable-functions-java-examples --force 2>/dev/null aws ecr create-repository --repository-name durable-functions-java-examples +# Tag and push docker tag durable-functions-java-examples:latest \ $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/durable-functions-java-examples:latest @@ -133,20 +196,52 @@ docker push \ $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/durable-functions-java-examples:latest ``` +> **Checkpoint:** Before continuing, verify the push succeeded and the image has the correct manifest type: +> ```bash +> aws ecr describe-images --repository-name durable-functions-java-examples --region $AWS_REGION \ +> --query 'imageDetails[?imageTags[0]==`latest`].imageManifestMediaType' --output text +> ``` +> Expected output: `application/vnd.docker.distribution.manifest.v2+json` +> +> If you see `application/vnd.oci.image.index.v1+json` instead, rebuild the Docker image with `--provenance=false` and push again. + ### 3. Deploy with SAM -Delete any previously deployed stack first, then deploy: +Navigate to the SAM template directory: +**From EC2:** ```bash cd /home/ec2-user/serverless-patterns/lambda-durable-java-sam/durable-functions-sam -(adjust the folder path for local deployment) +``` + +**From local machine:** +```bash +cd ../.. +cd durable-functions-sam +``` -aws cloudformation delete-stack --stack-name lambda-durable-java-sam -aws cloudformation wait stack-delete-complete --stack-name lambda-durable-java-sam +If you have a previously deployed stack, delete it first (durable execution config cannot be added to existing functions): +```bash +aws cloudformation delete-stack --stack-name +aws cloudformation wait stack-delete-complete --stack-name +``` +Deploy: +```bash sam deploy --guided --capabilities CAPABILITY_NAMED_IAM ``` +When prompted: +- **Stack Name**: choose a name (e.g., `lambda-durable-java-sam`) +- **AWS Region**: enter your region (must match where you pushed the ECR image) +- **Parameter SNSTopicName**: press Enter to accept default +- **Confirm changes before deploy**: `N` +- **Allow SAM CLI IAM role creation**: `Y` +- **Disable rollback**: `N` +- **Save arguments to configuration file**: `Y` + +Wait for `CREATE_COMPLETE`. If it fails, check the [Troubleshooting](#troubleshooting) section below. + ### 4. Build the SNS Message Sender ```bash @@ -161,6 +256,55 @@ java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic chaining ``` +--- + +## Troubleshooting + +### "The image manifest, config or layer media type... is not supported" + +The Docker image was pushed in OCI format. Lambda requires Docker V2 format. Fix: +```bash +docker build --platform linux/amd64 --provenance=false -t durable-functions-java-examples . +aws ecr delete-repository --repository-name durable-functions-java-examples --force +aws ecr create-repository --repository-name durable-functions-java-examples +docker tag durable-functions-java-examples:latest \ + $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/durable-functions-java-examples:latest +docker push \ + $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/durable-functions-java-examples:latest +``` + +### "JAVA_HOME environment variable is not defined correctly" + +`JAVA_HOME` must point to the JDK root (e.g., `.../Contents/Home`), **not** the `bin` directory. Fix: +```bash +# Wrong: +export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-21.jdk/Contents/Home/bin + +# Correct: +export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-21.jdk/Contents/Home +``` + +### "Cannot connect to the Docker daemon" + +Docker is not running. Start your Docker runtime: +- **Docker Desktop**: Open Docker Desktop from Applications +- **Colima**: `colima start && docker context use colima` + +### AWS_REGION is empty / ECR endpoint errors + +Ensure `AWS_REGION` is set before running the commands: +```bash +export AWS_REGION=eu-west-2 # Your target region +``` + +### Stack stuck in ROLLBACK_COMPLETE + +Delete the failed stack before redeploying: +```bash +aws cloudformation delete-stack --stack-name +aws cloudformation wait stack-delete-complete --stack-name +``` + ## Triggering Each Pattern ```bash diff --git a/lambda-durable-java-sam/USER_GUIDE.md b/lambda-durable-java-sam/USER_GUIDE.md index 3acc2ad0a1..708f486d7d 100644 --- a/lambda-durable-java-sam/USER_GUIDE.md +++ b/lambda-durable-java-sam/USER_GUIDE.md @@ -99,9 +99,11 @@ You should see `BUILD SUCCESS`. ### Step 2: Build the Docker container image ```bash -docker build -t durable-functions-java-examples . +docker build --platform linux/amd64 --provenance=false -t durable-functions-java-examples . ``` +> **Note:** The `--platform linux/amd64` flag is required when building on Apple Silicon (M1/M2/M3) Macs. The `--provenance=false` flag ensures the image is pushed in Docker V2 manifest format rather than OCI format, which Lambda requires. + ### Step 3: Create ECR repository and push ```bash diff --git a/lambda-durable-java-sam/build-and-deploy.sh b/lambda-durable-java-sam/build-and-deploy.sh index 435d8067ae..c6b7f1e28e 100755 --- a/lambda-durable-java-sam/build-and-deploy.sh +++ b/lambda-durable-java-sam/build-and-deploy.sh @@ -25,7 +25,7 @@ echo " Build complete." # Step 2: Build Docker image echo "" echo ">>> Step 2: Building Docker image..." -docker build -t $ECR_REPO . +docker build --platform linux/amd64 --provenance=false -t $ECR_REPO . echo " Docker image built." # Step 3: Delete and recreate ECR repository From 9c4b036dcdf05458ed5419674704b703695a9edf Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Thu, 16 Jul 2026 12:34:38 -0700 Subject: [PATCH 16/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lambda-durable-java-sam/README.md b/lambda-durable-java-sam/README.md index 23162dc97c..5261400579 100644 --- a/lambda-durable-java-sam/README.md +++ b/lambda-durable-java-sam/README.md @@ -134,8 +134,11 @@ set AWS_REGION=us-east-1 **3. Clone the project:** ```bash -git clone https://github.com/aws-samples/serverless-patterns.git -cd serverless-patterns/lambda-durable-java-sam +git clone --depth 1 --filter=blob:none --sparse \ + https://github.com/aws-samples/serverless-patterns.git +cd serverless-patterns +git sparse-checkout set lambda-durable-java-sam +cd lambda-durable-java-sam ``` Then continue from [Build and Deploy](#build-and-deploy) below. From 87d5fb420a313eafc78be4e8cac39f4613383409 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Thu, 16 Jul 2026 13:01:55 -0700 Subject: [PATCH 17/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lambda-durable-java-sam/README.md b/lambda-durable-java-sam/README.md index 5261400579..ba03deebf2 100644 --- a/lambda-durable-java-sam/README.md +++ b/lambda-durable-java-sam/README.md @@ -254,11 +254,15 @@ mvn clean package ### 5. Trigger a Durable Function +Ensure `AWS_PROFILE` and `AWS_REGION` are set to the same profile/region you used for deployment (see Step 2 under Option B), then run: + ```bash java -cp target/sns-message-sender-1.0-SNAPSHOT.jar \ sns.producer.DurableFunctionsTrigger DurableFunctionsSNSTopic chaining ``` +> **Note:** On the EC2 instance (Option A), credentials are provided automatically via the instance role — no extra setup needed. If you get credential errors locally, see the [Troubleshooting](#troubleshooting) section. + --- ## Troubleshooting @@ -300,6 +304,26 @@ Ensure `AWS_REGION` is set before running the commands: export AWS_REGION=eu-west-2 # Your target region ``` +### "Unable to load credentials from any of the providers in the chain" when triggering patterns + +The Java AWS SDK cannot find valid credentials. Common causes and fixes: + +1. **`AWS_PROFILE` not set** — The Java SDK uses the `default` profile unless told otherwise: + ```bash + export AWS_PROFILE=your-profile-name + ``` + +2. **Profile uses `credential_process` or SSO** — Some credential sources (e.g., `credential_process`, `aws sso`) may not be compatible with all versions of the Java AWS SDK. Resolve by exporting credentials into the environment: + ```bash + eval $(aws configure export-credentials --profile your-profile --format env) + ``` + +3. **Verify credentials work** — Test that the Java SDK can reach AWS: + ```bash + aws sts get-caller-identity + ``` + If this works but the Java app doesn't, your profile likely uses a credential method the Java SDK can't invoke. Use the `eval` command above. + ### Stack stuck in ROLLBACK_COMPLETE Delete the failed stack before redeploying: From 097e7e42b7af16745099188c3f3b17f18e771f53 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Thu, 16 Jul 2026 19:39:39 -0700 Subject: [PATCH 18/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/README.md | 4 +- lambda-durable-java-sam/USER_GUIDE.md | 2 +- lambda-durable-java-sam/build-and-deploy.sh | 4 +- .../durable-functions/Dockerfile | 2 +- .../durable-functions/pom.xml | 6 ++ .../samples/durable/ChainingPatternTest.java | 85 +++++++++++++++ .../durable/ErrorHandlingPatternTest.java | 98 +++++++++++++++++ .../samples/durable/FanOutPatternTest.java | 56 ++++++++++ .../durable/HumanInteractionPatternTest.java | 94 ++++++++++++++++ .../durable/MapProcessingPatternTest.java | 99 +++++++++++++++++ .../durable/MonitoringPatternTest.java | 75 +++++++++++++ .../durable/SubOrchestrationPatternTest.java | 100 ++++++++++++++++++ .../samples/durable/TimerPatternTest.java | 84 +++++++++++++++ lambda-durable-java-sam/example-pattern.json | 86 +++++++++++++++ 14 files changed, 789 insertions(+), 6 deletions(-) create mode 100644 lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/ChainingPatternTest.java create mode 100644 lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/ErrorHandlingPatternTest.java create mode 100644 lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/FanOutPatternTest.java create mode 100644 lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/HumanInteractionPatternTest.java create mode 100644 lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/MapProcessingPatternTest.java create mode 100644 lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/MonitoringPatternTest.java create mode 100644 lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/SubOrchestrationPatternTest.java create mode 100644 lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/TimerPatternTest.java create mode 100644 lambda-durable-java-sam/example-pattern.json diff --git a/lambda-durable-java-sam/README.md b/lambda-durable-java-sam/README.md index ba03deebf2..507b6c5441 100644 --- a/lambda-durable-java-sam/README.md +++ b/lambda-durable-java-sam/README.md @@ -1,4 +1,4 @@ -# Java Lambda Durable Functions - Workshop Examples +# Java Lambda Durable Functions Examples This project demonstrates **AWS Lambda Durable Functions** patterns in Java. It provides working examples of all major durable execution patterns including chaining, fan-out/fan-in, human interaction, monitoring/polling, timers, error handling with saga compensation, map processing, and sub-orchestration. @@ -151,7 +151,7 @@ Then continue from [Build and Deploy](#build-and-deploy) below. ```bash cd durable-functions-sam/durable-functions -mvn clean package -DskipTests +mvn clean package ``` Build the Docker image. Use the command that matches your environment: diff --git a/lambda-durable-java-sam/USER_GUIDE.md b/lambda-durable-java-sam/USER_GUIDE.md index 708f486d7d..4131400056 100644 --- a/lambda-durable-java-sam/USER_GUIDE.md +++ b/lambda-durable-java-sam/USER_GUIDE.md @@ -91,7 +91,7 @@ cd serverless-patterns/lambda-durable-java-sam ```bash cd durable-functions-sam/durable-functions -mvn clean package -DskipTests +mvn clean package ``` You should see `BUILD SUCCESS`. diff --git a/lambda-durable-java-sam/build-and-deploy.sh b/lambda-durable-java-sam/build-and-deploy.sh index c6b7f1e28e..b78cf15945 100755 --- a/lambda-durable-java-sam/build-and-deploy.sh +++ b/lambda-durable-java-sam/build-and-deploy.sh @@ -19,7 +19,7 @@ echo "" # Step 1: Build the durable functions JAR echo ">>> Step 1: Building durable functions JAR..." cd durable-functions-sam/durable-functions -mvn clean package -DskipTests +mvn clean package echo " Build complete." # Step 2: Build Docker image @@ -61,7 +61,7 @@ sam deploy \ echo "" echo ">>> Step 6: Building SNS message sender..." cd ../sns-message-sender -mvn clean package -DskipTests +mvn clean package echo " SNS sender built." echo "" diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/Dockerfile b/lambda-durable-java-sam/durable-functions-sam/durable-functions/Dockerfile index b7ab0d71e9..115e6c8785 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/Dockerfile +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/Dockerfile @@ -2,7 +2,7 @@ FROM --platform=linux/amd64 amazoncorretto:21-alpine AS builder WORKDIR /build COPY pom.xml . COPY src ./src -RUN apk add --no-cache maven && mvn clean package -DskipTests +RUN apk add --no-cache maven && mvn clean package FROM public.ecr.aws/lambda/java:21 COPY --from=builder /build/target/*.jar ${LAMBDA_TASK_ROOT}/lib/ diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml b/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml index 9c104104d9..b64fdf5047 100644 --- a/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/pom.xml @@ -60,6 +60,12 @@ jackson-databind 2.17.0 + + software.amazon.lambda.durable + aws-durable-execution-sdk-java-testing + 1.0.0 + test + org.junit.jupiter junit-jupiter-api diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/ChainingPatternTest.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/ChainingPatternTest.java new file mode 100644 index 0000000000..533c6aa94f --- /dev/null +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/ChainingPatternTest.java @@ -0,0 +1,85 @@ +package com.amazonaws.samples.durable; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Map; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.lambda.model.OperationType; +import software.amazon.lambda.durable.TypeToken; +import software.amazon.lambda.durable.model.ExecutionStatus; +import software.amazon.lambda.durable.testing.LocalDurableTestRunner; + +import com.amazonaws.samples.durable.chaining.OrderProcessingHandler; + +class ChainingPatternTest { + + private static final TypeToken> MAP_TYPE = new TypeToken<>() {}; + + @Test + void executesAllStepsInSequence() { + var handler = new OrderProcessingHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "orderId", "ORD-TEST-001", + "totalAmount", 299.99, + "customerId", "CUST-001", + "shippingAddress", "123 Main St" + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + assertEquals("CHAINING", output.get("pattern")); + assertEquals("COMPLETED", output.get("finalStatus")); + assertEquals("ORD-TEST-001", output.get("orderId")); + assertNotNull(output.get("trackingNumber")); + assertNotNull(output.get("transactionId")); + } + + @Test + void executesAllFiveSteps() { + var handler = new OrderProcessingHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "orderId", "ORD-TEST-002", + "totalAmount", 100.00, + "customerId", "CUST-002" + ); + + var result = runner.runUntilComplete(input); + + var stepNames = result.getOperations().stream() + .filter(op -> op.getType() == OperationType.STEP) + .map(op -> op.getName()) + .toList(); + + assertTrue(stepNames.contains("validate-order")); + assertTrue(stepNames.contains("reserve-inventory")); + assertTrue(stepNames.contains("process-payment")); + assertTrue(stepNames.contains("ship-order")); + assertTrue(stepNames.contains("notify-customer")); + assertEquals(5, stepNames.size()); + } + + @Test + void failsOnInvalidAmount() { + var handler = new OrderProcessingHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "orderId", "ORD-TEST-003", + "totalAmount", -10.00, + "customerId", "CUST-003" + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.FAILED, result.getStatus()); + assertTrue(result.getError().isPresent()); + } +} diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/ErrorHandlingPatternTest.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/ErrorHandlingPatternTest.java new file mode 100644 index 0000000000..df0d43435c --- /dev/null +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/ErrorHandlingPatternTest.java @@ -0,0 +1,98 @@ +package com.amazonaws.samples.durable; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Map; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.lambda.model.OperationStatus; +import software.amazon.lambda.durable.TypeToken; +import software.amazon.lambda.durable.model.ExecutionStatus; +import software.amazon.lambda.durable.testing.LocalDurableTestRunner; + +import com.amazonaws.samples.durable.errorhandling.ResilientPaymentHandler; + +class ErrorHandlingPatternTest { + + private static final TypeToken> MAP_TYPE = new TypeToken<>() {}; + + @Test + void completesSuccessfullyOnHappyPath() { + var handler = new ResilientPaymentHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "orderId", "ORD-TEST-001", + "amount", 199.99, + "simulateInventoryFailure", false + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + assertEquals("ERROR_HANDLING", output.get("pattern")); + assertEquals("COMPLETED", output.get("status")); + assertNotNull(output.get("transactionId")); + assertNotNull(output.get("reservationId")); + } + + @Test + void inventoryFailureResultsInFailedExecution() { + var handler = new ResilientPaymentHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "orderId", "ORD-TEST-002", + "amount", 199.99, + "simulateInventoryFailure", true + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.FAILED, result.getStatus()); + + var inventoryOp = result.getOperation("reserve-inventory"); + assertNotNull(inventoryOp); + assertEquals(OperationStatus.FAILED, inventoryOp.getStatus()); + } + + @Test + void paymentSucceedsBeforeInventoryFails() { + var handler = new ResilientPaymentHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "orderId", "ORD-TEST-003", + "amount", 50.00, + "simulateInventoryFailure", true + ); + + var result = runner.runUntilComplete(input); + + var paymentOp = result.getOperation("charge-payment"); + assertNotNull(paymentOp); + assertEquals(OperationStatus.SUCCEEDED, paymentOp.getStatus()); + } + + @Test + void retriesPaymentOnTransientFailure() { + var handler = new ResilientPaymentHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "orderId", "ORD-TEST-004", + "amount", 75.00, + "simulateInventoryFailure", false + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + var paymentOp = result.getOperation("charge-payment"); + assertNotNull(paymentOp); + assertTrue(paymentOp.getAttempt() >= 1, "Payment should have retried at least once"); + } +} diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/FanOutPatternTest.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/FanOutPatternTest.java new file mode 100644 index 0000000000..13f7339bb9 --- /dev/null +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/FanOutPatternTest.java @@ -0,0 +1,56 @@ +package com.amazonaws.samples.durable; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Map; + +import org.junit.jupiter.api.Test; +import software.amazon.lambda.durable.TypeToken; +import software.amazon.lambda.durable.model.ExecutionStatus; +import software.amazon.lambda.durable.testing.LocalDurableTestRunner; + +import com.amazonaws.samples.durable.fanout.ParallelProcessingHandler; + +class FanOutPatternTest { + + private static final TypeToken> MAP_TYPE = new TypeToken<>() {}; + + @Test + void executesParallelBranchesAndMapConcurrently() { + var handler = new ParallelProcessingHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "dataId", "DATA-TEST-001", + "source", "s3://test-bucket/doc.pdf" + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + assertEquals("FAN_OUT_FAN_IN", output.get("pattern")); + assertEquals("COMPLETED", output.get("status")); + } + + @Test + void aggregatesResultsFromAllBranches() { + var handler = new ParallelProcessingHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of("dataId", "DATA-TEST-002"); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + @SuppressWarnings("unchecked") + Map aggregated = (Map) output.get("result"); + assertNotNull(aggregated.get("sentiment")); + assertNotNull(aggregated.get("entities")); + assertNotNull(aggregated.get("summary")); + assertNotNull(aggregated.get("documentsProcessed")); + } +} diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/HumanInteractionPatternTest.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/HumanInteractionPatternTest.java new file mode 100644 index 0000000000..7a4b47c65f --- /dev/null +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/HumanInteractionPatternTest.java @@ -0,0 +1,94 @@ +package com.amazonaws.samples.durable; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Map; + +import org.junit.jupiter.api.Test; +import software.amazon.lambda.durable.TypeToken; +import software.amazon.lambda.durable.model.ExecutionStatus; +import software.amazon.lambda.durable.testing.LocalDurableTestRunner; + +import com.amazonaws.samples.durable.humaninteraction.ApprovalWorkflowHandler; + +class HumanInteractionPatternTest { + + private static final TypeToken> MAP_TYPE = new TypeToken<>() {}; + + @Test + void completesWhenCallbackApproved() { + var handler = new ApprovalWorkflowHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "requestId", "REQ-TEST-001", + "amount", 5000.00, + "requestor", "employee@example.com" + ); + + var result = runner.run(input); + assertEquals(ExecutionStatus.PENDING, result.getStatus()); + + String callbackId = runner.getCallbackId("wait-for-approval"); + assertNotNull(callbackId); + + runner.completeCallback(callbackId, + "{\"decision\":\"APPROVED\",\"approver\":\"manager@example.com\"}"); + + result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + Map output = result.getResult(Map.class); + assertEquals("HUMAN_INTERACTION", output.get("pattern")); + assertEquals("COMPLETED", output.get("status")); + assertEquals("manager@example.com", output.get("approvedBy")); + } + + @Test + void handlesCallbackRejection() { + var handler = new ApprovalWorkflowHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "requestId", "REQ-TEST-002", + "amount", 15000.00, + "requestor", "employee@example.com" + ); + + var result = runner.run(input); + assertEquals(ExecutionStatus.PENDING, result.getStatus()); + + String callbackId = runner.getCallbackId("wait-for-approval"); + assertNotNull(callbackId); + + runner.failCallback(callbackId, software.amazon.awssdk.services.lambda.model.ErrorObject.builder() + .errorType("Rejected") + .errorMessage("Budget exceeded policy limit") + .build()); + + result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + Map output = result.getResult(Map.class); + assertEquals("HUMAN_INTERACTION", output.get("pattern")); + assertEquals("REJECTED", output.get("status")); + } + + @Test + void requiresVpApprovalForHighAmounts() { + var handler = new ApprovalWorkflowHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "requestId", "REQ-TEST-003", + "amount", 25000.00, + "requestor", "employee@example.com" + ); + + var result = runner.run(input); + assertEquals(ExecutionStatus.PENDING, result.getStatus()); + + var prepareOp = result.getOperation("prepare-approval"); + assertNotNull(prepareOp); + } +} diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/MapProcessingPatternTest.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/MapProcessingPatternTest.java new file mode 100644 index 0000000000..f44ccd2469 --- /dev/null +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/MapProcessingPatternTest.java @@ -0,0 +1,99 @@ +package com.amazonaws.samples.durable; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Map; + +import org.junit.jupiter.api.Test; +import software.amazon.lambda.durable.TypeToken; +import software.amazon.lambda.durable.model.ExecutionStatus; +import software.amazon.lambda.durable.testing.LocalDurableTestRunner; + +import com.amazonaws.samples.durable.mapprocessing.BatchDataProcessorHandler; + +class MapProcessingPatternTest { + + private static final TypeToken> MAP_TYPE = new TypeToken<>() {}; + + @Test + void processesAllItemsWithPartialFailureTolerance() { + var handler = new BatchDataProcessorHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "batchSize", 10, + "maxConcurrency", 3, + "toleratedFailures", 2 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + assertEquals("MAP_PROCESSING", output.get("pattern")); + } + + @Test + void reportsCorrectSuccessAndFailureCounts() { + var handler = new BatchDataProcessorHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "batchSize", 10, + "maxConcurrency", 3, + "toleratedFailures", 2 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + @SuppressWarnings("unchecked") + Map summary = (Map) output.get("summary"); + int succeeded = ((Number) summary.get("succeeded")).intValue(); + int failed = ((Number) summary.get("failed")).intValue(); + + assertEquals(8, succeeded); + assertEquals(2, failed); + assertEquals(10, ((Number) summary.get("totalItems")).intValue()); + } + + @Test + void respectsConcurrencyLimit() { + var handler = new BatchDataProcessorHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "batchSize", 5, + "maxConcurrency", 2, + "toleratedFailures", 1 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + } + + @Test + void handlesSmallBatch() { + var handler = new BatchDataProcessorHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "batchSize", 3, + "maxConcurrency", 3, + "toleratedFailures", 1 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + @SuppressWarnings("unchecked") + Map summary = (Map) output.get("summary"); + assertEquals(3, ((Number) summary.get("totalItems")).intValue()); + } +} diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/MonitoringPatternTest.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/MonitoringPatternTest.java new file mode 100644 index 0000000000..03aa64fda3 --- /dev/null +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/MonitoringPatternTest.java @@ -0,0 +1,75 @@ +package com.amazonaws.samples.durable; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Map; + +import org.junit.jupiter.api.Test; +import software.amazon.lambda.durable.TypeToken; +import software.amazon.lambda.durable.model.ExecutionStatus; +import software.amazon.lambda.durable.testing.LocalDurableTestRunner; + +import com.amazonaws.samples.durable.monitoring.JobMonitorHandler; + +class MonitoringPatternTest { + + private static final TypeToken> MAP_TYPE = new TypeToken<>() {}; + + @Test + void pollsUntilJobCompletes() { + var handler = new JobMonitorHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "jobId", "JOB-TEST-001", + "jobType", "DATA_EXPORT", + "maxPolls", 5 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + assertEquals("MONITORING", output.get("pattern")); + assertEquals("COMPLETED", output.get("status")); + assertEquals("JOB-TEST-001", output.get("jobId")); + } + + @Test + void completesWithinPollLimit() { + var handler = new JobMonitorHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "jobId", "JOB-TEST-002", + "maxPolls", 3 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + assertNotNull(output.get("pollAttempts")); + } + + @Test + void reportsCorrectPollAttemptCount() { + var handler = new JobMonitorHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "jobId", "JOB-TEST-003", + "maxPolls", 4 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + int pollAttempts = ((Number) output.get("pollAttempts")).intValue(); + assertTrue(pollAttempts >= 2, "Should have polled at least twice"); + } +} diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/SubOrchestrationPatternTest.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/SubOrchestrationPatternTest.java new file mode 100644 index 0000000000..51819fbc1d --- /dev/null +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/SubOrchestrationPatternTest.java @@ -0,0 +1,100 @@ +package com.amazonaws.samples.durable; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.lambda.model.OperationType; +import software.amazon.lambda.durable.TypeToken; +import software.amazon.lambda.durable.model.ExecutionStatus; +import software.amazon.lambda.durable.testing.LocalDurableTestRunner; + +import com.amazonaws.samples.durable.suborchestration.OrderFulfillmentHandler; + +class SubOrchestrationPatternTest { + + private static final TypeToken> MAP_TYPE = new TypeToken<>() {}; + + @Test + void completesFullOrderFulfillment() { + var handler = new OrderFulfillmentHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "orderId", "ORD-TEST-001", + "customerId", "CUST-TEST-001", + "amount", 499.99, + "items", List.of( + Map.of("productId", "PROD-001", "name", "Widget", "qty", 2) + ) + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + assertEquals("SUB_ORCHESTRATION", output.get("pattern")); + assertEquals("FULFILLED", output.get("status")); + assertEquals("ORD-TEST-001", output.get("orderId")); + } + + @Test + void executesPaymentAndInventorySubWorkflowsConcurrently() { + var handler = new OrderFulfillmentHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "orderId", "ORD-TEST-002", + "customerId", "CUST-TEST-002", + "amount", 150.00 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + var contextOps = result.getOperations().stream() + .filter(op -> op.getType() == OperationType.CONTEXT) + .toList(); + + var contextNames = contextOps.stream().map(op -> op.getName()).toList(); + assertTrue(contextNames.contains("payment-workflow")); + assertTrue(contextNames.contains("inventory-workflow")); + assertTrue(contextNames.contains("shipping-workflow")); + assertTrue(contextNames.contains("notification-workflow")); + } + + @Test + void producesPaymentAndShippingResults() { + var handler = new OrderFulfillmentHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "orderId", "ORD-TEST-003", + "customerId", "CUST-TEST-003", + "amount", 200.00 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + + @SuppressWarnings("unchecked") + Map payment = (Map) output.get("payment"); + assertEquals("CAPTURED", payment.get("status")); + assertNotNull(payment.get("transactionId")); + + @SuppressWarnings("unchecked") + Map shipping = (Map) output.get("shipping"); + assertNotNull(shipping.get("trackingNumber")); + + @SuppressWarnings("unchecked") + Map inventory = (Map) output.get("inventory"); + assertEquals("RESERVED", inventory.get("status")); + } +} diff --git a/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/TimerPatternTest.java b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/TimerPatternTest.java new file mode 100644 index 0000000000..178c3e0641 --- /dev/null +++ b/lambda-durable-java-sam/durable-functions-sam/durable-functions/src/test/java/com/amazonaws/samples/durable/TimerPatternTest.java @@ -0,0 +1,84 @@ +package com.amazonaws.samples.durable; + +import static org.junit.jupiter.api.Assertions.*; + +import java.util.Map; + +import org.junit.jupiter.api.Test; +import software.amazon.awssdk.services.lambda.model.OperationType; +import software.amazon.lambda.durable.TypeToken; +import software.amazon.lambda.durable.model.ExecutionStatus; +import software.amazon.lambda.durable.testing.LocalDurableTestRunner; + +import com.amazonaws.samples.durable.timer.ScheduledReminderHandler; + +class TimerPatternTest { + + private static final TypeToken> MAP_TYPE = new TypeToken<>() {}; + + @Test + void completesWithWaitsAdvancedAutomatically() { + var handler = new ScheduledReminderHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "taskId", "TASK-TEST-001", + "assignee", "dev@example.com", + "reminderIntervalSeconds", 30, + "escalationSeconds", 60 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + assertEquals("TIMER", output.get("pattern")); + assertEquals("ESCALATED", output.get("status")); + assertEquals("TASK-TEST-001", output.get("taskId")); + } + + @Test + void includesWaitOperationsInHistory() { + var handler = new ScheduledReminderHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "taskId", "TASK-TEST-002", + "assignee", "dev@example.com", + "reminderIntervalSeconds", 10, + "escalationSeconds", 20 + ); + + var result = runner.runUntilComplete(input); + + var waitNames = result.getOperations().stream() + .filter(op -> op.getType() == OperationType.WAIT) + .map(op -> op.getName()) + .toList(); + + assertTrue(waitNames.contains("first-reminder-delay"), "Should have first-reminder-delay wait"); + assertTrue(waitNames.contains("escalation-delay"), "Should have escalation-delay wait"); + assertTrue(waitNames.size() >= 2, "Should have at least 2 waits"); + } + + @Test + void escalatesToManager() { + var handler = new ScheduledReminderHandler(); + var runner = LocalDurableTestRunner.create(MAP_TYPE, handler); + + Map input = Map.of( + "taskId", "TASK-TEST-003", + "assignee", "dev@example.com", + "reminderIntervalSeconds", 5, + "escalationSeconds", 10 + ); + + var result = runner.runUntilComplete(input); + + assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus()); + + Map output = result.getResult(Map.class); + assertEquals("manager@example.com", output.get("escalatedTo")); + } +} diff --git a/lambda-durable-java-sam/example-pattern.json b/lambda-durable-java-sam/example-pattern.json new file mode 100644 index 0000000000..7bffe436c7 --- /dev/null +++ b/lambda-durable-java-sam/example-pattern.json @@ -0,0 +1,86 @@ +{ + "title": "AWS Lambda function subscribed to an Amazon MQ - Apache ActiveMQ in private subnets (Java)", + "description": "Creates a Lambda function that uses a private Amazon MQ (Apache ActiveMQ) as an event source.", + "language": "Java", + "level": "200", + "framework": "AWS SAM", + "introBox": { + "headline": "How it works", + "text": [ + "This pattern provides a Lambda function along with an Event Source Mapping to an Amazon MQ (Apache ActiveMQ) queue.", + "The CloudFormation template provided in this pattern installs an Amazon MQ (Apache ActiveMQ) Cluster in private subnets in a VPC.", + "For detailed deployment instructions instructions see the README.md" + ] + }, + "gitHub": { + "template": { + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/activemq-private-lambda-java-sam", + "templateURL": "serverless-patterns/activemq-private-lambda-java-sam", + "projectFolder": "activemq-private-lambda-java-sam", + "templateFile": "activemq_consumer_dynamo_sam/template_original.yaml" + } + }, + "resources": { + "bullets": [ + { + "text": "Configuring Amazon MQ event source for Lambda", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/process-mq-messages-with-lambda.html" + }, + { + "text": "Using Lambda with Amazon MQ", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html" + }, + { + "text": "Amazon MQ resource type reference", + "link": "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/AWS_AmazonMQ.html" + } + ] + }, + "deploy": { + "text": ["sam deploy --guided"] + }, + "testing": { + "text": ["See the GitHub repo for detailed testing instructions."] + }, + "cleanup": { + "text": ["Delete the template: sam delete."] + }, + "authors": [ + { + "name": "Indranil Banerjee", + "bio": "AWS - Senior Solutions Architect", + "image": "https://media.licdn.com/dms/image/v2/C5603AQEL3BG6JZca6A/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1653972622784?e=1762992000&v=beta&t=a9gnmtxyWBhfEfqDF3HiPHWDoc4KZjG2sdNsIakcJXw", + "linkedin": "https://www.linkedin.com/in/indranil-banerjee-b00a261/" + }, + { + "name": "Arghya Banerjee", + "bio": "AWS - Senior Solutions Architect", + "image": "https://media.licdn.com/dms/image/v2/C5603AQHFFKivT-1iKA/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1516305772138?e=1762992000&v=beta&t=dKgoxEfgZd3M5XW-GEJ9Ss4I5ka8-C7iEIy8Sb_PTOQ", + "linkedin": "https://www.linkedin.com/in/arghya-b-6130b57/" + }, + { + "name": "Kunal Ghosh", + "bio": "AWS - Sr SA, Strategic Accounts", + "image": "https://media.licdn.com/dms/image/v2/C5603AQHrj7mHd7Z1hg/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1516355158121?e=1762992000&v=beta&t=8h0cpHLR6v4-e3BJ7n9Wd_OHL2rRDa8F_74rTUnu8Js", + "linkedin": "https://www.linkedin.com/in/kunal-ghosh-6583058/" + }, + { + "name": "Angelo Spagnolo", + "bio": "AWS - Sr Technical Account Manager", + "image": "https://media.licdn.com/dms/image/v2/D5603AQFQj2a90KFFZQ/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1692659294509?e=1766620800&v=beta&t=wl2LxhFX4-KSVgnjn1gJtAMiDxsezjIsbgIDPAZTE1I", + "linkedin": "https://www.linkedin.com/in/aspagnolo/" + }, + { + "name": "Vinayak Datar", + "bio": "AWS - Sr. Customer Solutions Manager", + "image": "https://media.licdn.com/dms/image/v2/C5103AQFAa6JcLNknkA/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1548189034877?e=1762992000&v=beta&t=o2lDqU3V4ivFjt00rEDYd2yjGr55TszcG0J9hGuRM_w", + "linkedin": "https://www.linkedin.com/in/vinayakdatar/" + }, + { + "name": "Greg Medard", + "bio": "AWS - Solutions Architect", + "image": "https://media.licdn.com/dms/image/v2/C4E03AQGveSDnRH9aCg/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1565226836063?e=1762992000&v=beta&t=Jkir-cq-T1EU8MTqY7PPPxreVo2_zI4FXaXXrdTdpfQ", + "linkedin": "https://www.linkedin.com/in/gregorymedard/" + } + ] +} From 0c294732a710f84878d4467609b235a223b44cb5 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Mon, 20 Jul 2026 15:48:05 -0700 Subject: [PATCH 19/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/example-pattern.json | 62 +++++++------------- 1 file changed, 22 insertions(+), 40 deletions(-) diff --git a/lambda-durable-java-sam/example-pattern.json b/lambda-durable-java-sam/example-pattern.json index 7bffe436c7..8682442603 100644 --- a/lambda-durable-java-sam/example-pattern.json +++ b/lambda-durable-java-sam/example-pattern.json @@ -1,38 +1,38 @@ { - "title": "AWS Lambda function subscribed to an Amazon MQ - Apache ActiveMQ in private subnets (Java)", - "description": "Creates a Lambda function that uses a private Amazon MQ (Apache ActiveMQ) as an event source.", + "title": "AWS Lambda Durable Functions Examples Written in Java and deployed using AWS SAM", + "description": "Demonstrates multiple patterns of AWS Lambda Durable Functions written in Java and deployed using AWS SAM", "language": "Java", - "level": "200", + "level": "300", "framework": "AWS SAM", "introBox": { "headline": "How it works", "text": [ - "This pattern provides a Lambda function along with an Event Source Mapping to an Amazon MQ (Apache ActiveMQ) queue.", - "The CloudFormation template provided in this pattern installs an Amazon MQ (Apache ActiveMQ) Cluster in private subnets in a VPC.", + "This pattern provides example of AWS Lambda durable functions written in Java and deployed using AWS SAM", + "The different patterns demonstrated are chaining, fan-out/fan-in, human interaction, monitoring/polling, timers, error handling with saga compensation, map processing, and sub-orchestration", "For detailed deployment instructions instructions see the README.md" ] }, "gitHub": { "template": { - "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/activemq-private-lambda-java-sam", - "templateURL": "serverless-patterns/activemq-private-lambda-java-sam", - "projectFolder": "activemq-private-lambda-java-sam", - "templateFile": "activemq_consumer_dynamo_sam/template_original.yaml" + "repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/lambda-durable-java-sam", + "templateURL": "serverless-patterns/lambda-durable-java-sam", + "projectFolder": "durable-functions-sam", + "templateFile": "durable-functions-sam/template.yaml" } }, "resources": { "bullets": [ { - "text": "Configuring Amazon MQ event source for Lambda", - "link": "https://docs.aws.amazon.com/lambda/latest/dg/process-mq-messages-with-lambda.html" + "text": "Lambda Durable Functions", + "link": "https://docs.aws.amazon.com/lambda/latest/dg/durable-functions.html" }, { - "text": "Using Lambda with Amazon MQ", - "link": "https://docs.aws.amazon.com/lambda/latest/dg/with-mq.html" + "text": "AWS Lambda durable functions", + "link": "https://aws.amazon.com/lambda/lambda-durable-functions/" }, { - "text": "Amazon MQ resource type reference", - "link": "https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/AWS_AmazonMQ.html" + "text": "AWS Durable Execution SDK Java", + "link": "https://github.com/aws/aws-durable-execution-sdk-java/" } ] }, @@ -53,34 +53,16 @@ "linkedin": "https://www.linkedin.com/in/indranil-banerjee-b00a261/" }, { - "name": "Arghya Banerjee", + "name": "Christian Tomeldan", "bio": "AWS - Senior Solutions Architect", - "image": "https://media.licdn.com/dms/image/v2/C5603AQHFFKivT-1iKA/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1516305772138?e=1762992000&v=beta&t=dKgoxEfgZd3M5XW-GEJ9Ss4I5ka8-C7iEIy8Sb_PTOQ", - "linkedin": "https://www.linkedin.com/in/arghya-b-6130b57/" + "image": "https://media.licdn.com/dms/image/v2/C4E03AQFUq1LazkLjeg/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1516572681599?e=1785974400&v=beta&t=hQ4v986Zvjbw5su8_9Xuhj3QWOhmdv7NRh7kbFtOEBI", + "linkedin": "https://www.linkedin.com/in/christian-tomeldan/" }, { - "name": "Kunal Ghosh", - "bio": "AWS - Sr SA, Strategic Accounts", - "image": "https://media.licdn.com/dms/image/v2/C5603AQHrj7mHd7Z1hg/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1516355158121?e=1762992000&v=beta&t=8h0cpHLR6v4-e3BJ7n9Wd_OHL2rRDa8F_74rTUnu8Js", - "linkedin": "https://www.linkedin.com/in/kunal-ghosh-6583058/" - }, - { - "name": "Angelo Spagnolo", - "bio": "AWS - Sr Technical Account Manager", - "image": "https://media.licdn.com/dms/image/v2/D5603AQFQj2a90KFFZQ/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1692659294509?e=1766620800&v=beta&t=wl2LxhFX4-KSVgnjn1gJtAMiDxsezjIsbgIDPAZTE1I", - "linkedin": "https://www.linkedin.com/in/aspagnolo/" - }, - { - "name": "Vinayak Datar", - "bio": "AWS - Sr. Customer Solutions Manager", - "image": "https://media.licdn.com/dms/image/v2/C5103AQFAa6JcLNknkA/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1548189034877?e=1762992000&v=beta&t=o2lDqU3V4ivFjt00rEDYd2yjGr55TszcG0J9hGuRM_w", - "linkedin": "https://www.linkedin.com/in/vinayakdatar/" - }, - { - "name": "Greg Medard", - "bio": "AWS - Solutions Architect", - "image": "https://media.licdn.com/dms/image/v2/C4E03AQGveSDnRH9aCg/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1565226836063?e=1762992000&v=beta&t=Jkir-cq-T1EU8MTqY7PPPxreVo2_zI4FXaXXrdTdpfQ", - "linkedin": "https://www.linkedin.com/in/gregorymedard/" + "name": "Ajjay Govindaram", + "bio": "AWS - Senior Solutions Architect", + "image": "https://media.licdn.com/dms/image/v2/D5603AQETCOkwv00Lag/profile-displayphoto-crop_800_800/B56ZuQzht7GwAU-/0/1767660985531?e=1785974400&v=beta&t=HoKdUUL1BBmr0OpLFn9nnGwJclVB2UPh_4cxtP7XA_s", + "linkedin": "https://www.linkedin.com/in/ajjaykumar/" } ] } From 13c33ae07880208691e03a360435e96c3cd2f768 Mon Sep 17 00:00:00 2001 From: Indranil Banerjee Date: Thu, 30 Jul 2026 13:56:16 -0700 Subject: [PATCH 20/20] Added pattern lambda-durable-java-sam --- lambda-durable-java-sam/example-pattern.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lambda-durable-java-sam/example-pattern.json b/lambda-durable-java-sam/example-pattern.json index 8682442603..e3a5b64aa4 100644 --- a/lambda-durable-java-sam/example-pattern.json +++ b/lambda-durable-java-sam/example-pattern.json @@ -49,7 +49,7 @@ { "name": "Indranil Banerjee", "bio": "AWS - Senior Solutions Architect", - "image": "https://media.licdn.com/dms/image/v2/C5603AQEL3BG6JZca6A/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1653972622784?e=1762992000&v=beta&t=a9gnmtxyWBhfEfqDF3HiPHWDoc4KZjG2sdNsIakcJXw", + "image": "https://media.licdn.com/dms/image/v2/C5603AQEL3BG6JZca6A/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1653972622784?e=1787184000&v=beta&t=02c8Cs3dvk26XyKhsvieC9FcPEXa8toJnWlUk-rDsU0", "linkedin": "https://www.linkedin.com/in/indranil-banerjee-b00a261/" }, { @@ -63,6 +63,12 @@ "bio": "AWS - Senior Solutions Architect", "image": "https://media.licdn.com/dms/image/v2/D5603AQETCOkwv00Lag/profile-displayphoto-crop_800_800/B56ZuQzht7GwAU-/0/1767660985531?e=1785974400&v=beta&t=HoKdUUL1BBmr0OpLFn9nnGwJclVB2UPh_4cxtP7XA_s", "linkedin": "https://www.linkedin.com/in/ajjaykumar/" - } + }, + { + "name": "Greg Medard", + "bio": "AWS - Solutions Architect", + "image": "https://media.licdn.com/dms/image/v2/C4E03AQGveSDnRH9aCg/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1565226836110?e=1787184000&v=beta&t=XYi5wg0YCeRS5kigIA58hKRYrogUahMkzzLFtzowm5o", + "linkedin": "https://www.linkedin.com/in/gregorymedard/" + } ] }