GenericTypesExample.java
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package software.amazon.lambda.durable.examples.general;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;
import software.amazon.lambda.durable.TypeToken;
import software.amazon.lambda.durable.config.StepConfig;
import software.amazon.lambda.durable.retry.RetryStrategies;
/**
* Example demonstrating TypeToken support for complex generic types.
*
* <p>This example shows how to use TypeToken to work with generic types like {@code List<String>}, {@code Map<String,
* Object>}, and nested generics that cannot be represented by simple Class objects.
*/
public class GenericTypesExample extends DurableHandler<GenericTypesExample.Input, GenericTypesExample.Output> {
private static final Logger logger = LoggerFactory.getLogger(GenericTypesExample.class);
public static class Input {
public String userId;
public Input() {}
public Input(String userId) {
this.userId = userId;
}
}
public static class Output {
public List<String> items;
public Map<String, Integer> counts;
public Map<String, List<String>> categories;
public Output() {}
public Output(List<String> items, Map<String, Integer> counts, Map<String, List<String>> categories) {
this.items = items;
this.counts = counts;
this.categories = categories;
}
}
@Override
public Output handleRequest(Input input, DurableContext context) {
logger.info("Starting generic types example for user: {}", input.userId);
// Step 1: Fetch a list of items (List<String>)
List<String> items = context.step("fetch-items", new TypeToken<List<String>>() {}, stepCtx -> {
logger.info("Fetching items for user: {}", input.userId);
return List.of("item1", "item2", "item3", "item4");
});
logger.info("Fetched {} items", items.size());
// Step 2: Count items by category (Map<String, Integer>)
Map<String, Integer> counts =
context.step("count-by-category", new TypeToken<Map<String, Integer>>() {}, stepCtx -> {
logger.info("Counting items by category");
var result = new HashMap<String, Integer>();
result.put("electronics", 2);
result.put("books", 1);
result.put("clothing", 1);
return result;
});
logger.info("Counted {} categories", counts.size());
// Step 3: Fetch nested generic type with retry (Map<String, List<String>>)
Map<String, List<String>> categories = context.step(
"fetch-categories",
new TypeToken<Map<String, List<String>>>() {},
stepCtx -> {
logger.info("Fetching category details");
var result = new HashMap<String, List<String>>();
result.put("electronics", List.of("laptop", "phone"));
result.put("books", List.of("fiction"));
result.put("clothing", List.of("shirt"));
return result;
},
StepConfig.builder()
.retryStrategy(RetryStrategies.Presets.DEFAULT)
.build());
logger.info("Fetched {} category details", categories.size());
logger.info("Generic types example completed successfully");
return new Output(items, counts, categories);
}
}