AWS Java SDK client for communicating with AWS Lambda Service for function management, invocation, and resource control
—
Type-safe, annotation-driven Lambda function invocation through proxy interfaces that eliminate boilerplate code and provide compile-time safety for remote function calls.
Central factory class for creating type-safe proxy interfaces that enable seamless Lambda function invocation with automatic serialization and error handling.
/**
* Factory for creating type-safe Lambda function invocation proxies
* Enables annotation-driven function calls with automatic serialization
* @see LambdaInvokerFactory.Builder for configuration options
*/
public class LambdaInvokerFactory {
/**
* Creates builder instance for configuring Lambda invoker factory
* @return LambdaInvokerFactoryConfig.Builder for fluent configuration
*/
public static LambdaInvokerFactoryConfig.Builder builder();
/**
* Creates type-safe proxy for Lambda function invocation interface
* @param interfaceClass Interface class annotated with @LambdaFunction methods
* @return Proxy implementation that handles Lambda invocation transparently
* @throws LambdaSerializationException if interface cannot be proxied
*/
public <T> T build(Class<T> interfaceClass);
}
/**
* Configuration builder for Lambda invoker factory
* Provides fluent API for setting up invocation behavior and serialization
*/
public static class LambdaInvokerFactoryConfig.Builder {
/**
* Sets Lambda client for function invocation
* @param lambdaClient AWSLambda client instance (required)
* @return Builder instance for method chaining
*/
public Builder lambdaClient(AWSLambda lambdaClient);
/**
* Sets function name resolver for dynamic function name resolution
* @param functionNameResolver Custom resolver implementation
* @return Builder instance for method chaining
*/
public Builder functionNameResolver(LambdaFunctionNameResolver functionNameResolver);
/**
* Sets object mapper for JSON serialization/deserialization
* @param objectMapper Jackson ObjectMapper instance
* @return Builder instance for method chaining
*/
public Builder objectMapper(ObjectMapper objectMapper);
/**
* Sets log type for function invocation
* @param logType LogType.None or LogType.Tail
* @return Builder instance for method chaining
*/
public Builder logType(LogType logType);
/**
* Builds configured Lambda invoker factory
* @return Configured LambdaInvokerFactory instance
* @throws IllegalArgumentException if required configuration is missing
*/
public LambdaInvokerFactory build();
}Interface and implementations for resolving Lambda function names from interface methods.
/**
* Interface for resolving Lambda function names from method metadata
* Enables custom function name resolution strategies beyond annotations
*/
public interface LambdaFunctionNameResolver {
/**
* Resolves Lambda function name for method invocation
* @param method Method being invoked with potential @LambdaFunction annotation
* @param lambdaFunction Annotation instance if present, null otherwise
* @return Function name to invoke (name, ARN, or partial ARN)
* @throws IllegalArgumentException if function name cannot be resolved
*/
String getFunctionName(Method method, LambdaFunction lambdaFunction);
}/**
* Default implementation of function name resolution
* Uses @LambdaFunction annotation value or method name as fallback
*/
public class DefaultLambdaFunctionNameResolver implements LambdaFunctionNameResolver {
/**
* Resolves function name using annotation value or method name
* @param method Method being invoked
* @param lambdaFunction Annotation instance if present
* @return Resolved function name
*/
@Override
public String getFunctionName(Method method, LambdaFunction lambdaFunction);
}Annotation-based configuration for mapping interface methods to Lambda functions.
/**
* Annotation for mapping interface methods to Lambda functions
* Provides metadata for function invocation and behavior customization
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LambdaFunction {
/**
* Lambda function name, ARN, or partial ARN
* If empty, uses method name or function name resolver
* @return Function identifier for invocation
*/
String functionName() default "";
/**
* Function invocation type
* @return InvocationType.RequestResponse (synchronous) or InvocationType.Event (asynchronous)
*/
InvocationType invocationType() default InvocationType.RequestResponse;
/**
* Log type for invocation response
* @return LogType.None or LogType.Tail to include logs
*/
LogType logType() default LogType.None;
/**
* Function version or alias qualifier
* @return Version number, alias name, or empty for $LATEST
*/
String qualifier() default "";
}Specialized exceptions for high-level invocation error scenarios.
/**
* Wrapper exception for Lambda function execution errors
* Provides access to function error details and metadata
*/
public class LambdaFunctionException extends Exception {
/**
* Creates exception with function error details
* @param message Error message from function execution
* @param handled Whether error was handled by function
* @param type Error type classification
*/
public LambdaFunctionException(String message, boolean handled, String type);
/**
* Creates exception with cause chain
* @param message Error message
* @param cause Underlying cause exception
*/
public LambdaFunctionException(String message, Throwable cause);
/**
* Indicates if error was handled by function code
* @return true if function caught and handled error, false for unhandled exceptions
*/
public boolean isHandled();
/**
* Gets error type classification
* @return Error type string (e.g., "User", "System")
*/
public String getType();
}/**
* Exception for JSON serialization/deserialization errors
* Thrown when request/response objects cannot be converted to/from JSON
*/
public class LambdaSerializationException extends RuntimeException {
/**
* Creates serialization exception with message and cause
* @param message Descriptive error message
* @param cause Underlying serialization error
*/
public LambdaSerializationException(String message, Throwable cause);
}// Define interface with Lambda function methods
public interface UserService {
@LambdaFunction(functionName = "user-authentication")
UserAuthResult authenticateUser(AuthRequest request) throws LambdaFunctionException;
@LambdaFunction(functionName = "user-profile-service")
UserProfile getUserProfile(String userId) throws LambdaFunctionException;
@LambdaFunction(functionName = "user-preferences",
invocationType = InvocationType.Event)
void updatePreferencesAsync(String userId, Map<String, Object> preferences);
}
// Request/Response classes
public class AuthRequest {
private String username;
private String password;
// getters and setters
}
public class UserAuthResult {
private boolean authenticated;
private String token;
private long expiresAt;
// getters and setters
}
public class UserProfile {
private String userId;
private String email;
private String displayName;
// getters and setters
}AWSLambda lambdaClient = AWSLambdaClientBuilder.defaultClient();
// Create factory with configuration
LambdaInvokerFactory invokerFactory = LambdaInvokerFactory.builder()
.lambdaClient(lambdaClient)
.logType(LogType.Tail)
.build();
// Create type-safe proxy
UserService userService = invokerFactory.build(UserService.class);
// Use proxy like local interface
try {
AuthRequest authRequest = new AuthRequest();
authRequest.setUsername("john.doe");
authRequest.setPassword("secret123");
UserAuthResult result = userService.authenticateUser(authRequest);
if (result.isAuthenticated()) {
System.out.println("Authentication successful. Token: " + result.getToken());
// Get user profile
UserProfile profile = userService.getUserProfile("john.doe");
System.out.println("Welcome, " + profile.getDisplayName());
// Update preferences asynchronously
Map<String, Object> preferences = new HashMap<>();
preferences.put("theme", "dark");
preferences.put("notifications", true);
userService.updatePreferencesAsync("john.doe", preferences);
} else {
System.out.println("Authentication failed");
}
} catch (LambdaFunctionException e) {
System.err.println("Function error: " + e.getMessage());
System.err.println("Error type: " + e.getType());
System.err.println("Handled: " + e.isHandled());
}// Custom function name resolver for environment-based routing
public class EnvironmentFunctionNameResolver implements LambdaFunctionNameResolver {
private final String environment;
public EnvironmentFunctionNameResolver(String environment) {
this.environment = environment;
}
@Override
public String getFunctionName(Method method, LambdaFunction lambdaFunction) {
String baseName = (lambdaFunction != null && !lambdaFunction.functionName().isEmpty())
? lambdaFunction.functionName()
: method.getName();
return baseName + "-" + environment;
}
}
// Configure factory with custom resolver
LambdaInvokerFactory factory = LambdaInvokerFactory.builder()
.lambdaClient(lambdaClient)
.functionNameResolver(new EnvironmentFunctionNameResolver("prod"))
.objectMapper(createCustomObjectMapper())
.logType(LogType.Tail)
.build();
private ObjectMapper createCustomObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
return mapper;
}public interface OrderProcessingService {
@LambdaFunction(functionName = "order-validation")
ValidationResult validateOrder(Order order) throws LambdaFunctionException;
@LambdaFunction(functionName = "payment-processing",
qualifier = "PROD")
PaymentResult processPayment(PaymentRequest payment) throws LambdaFunctionException;
@LambdaFunction(functionName = "inventory-check")
InventoryStatus checkInventory(List<String> productIds) throws LambdaFunctionException;
@LambdaFunction(functionName = "order-fulfillment",
invocationType = InvocationType.Event)
void initiateFullfillment(String orderId, Address shippingAddress);
@LambdaFunction(functionName = "notification-service",
invocationType = InvocationType.Event,
logType = LogType.Tail)
void sendOrderConfirmation(String orderId, String customerEmail);
}
// Usage in order processing workflow
public class OrderProcessor {
private final OrderProcessingService service;
public OrderProcessor(LambdaInvokerFactory factory) {
this.service = factory.build(OrderProcessingService.class);
}
public void processOrder(Order order) {
try {
// Validate order synchronously
ValidationResult validation = service.validateOrder(order);
if (!validation.isValid()) {
throw new OrderProcessingException("Order validation failed: " +
validation.getErrors());
}
// Check inventory synchronously
List<String> productIds = order.getItems().stream()
.map(OrderItem::getProductId)
.collect(Collectors.toList());
InventoryStatus inventory = service.checkInventory(productIds);
if (!inventory.isAvailable()) {
throw new OrderProcessingException("Insufficient inventory");
}
// Process payment synchronously
PaymentRequest paymentRequest = createPaymentRequest(order);
PaymentResult payment = service.processPayment(paymentRequest);
if (!payment.isSuccessful()) {
throw new OrderProcessingException("Payment failed: " +
payment.getErrorMessage());
}
// Initiate fulfillment asynchronously
service.initiateFullfillment(order.getId(), order.getShippingAddress());
// Send confirmation asynchronously
service.sendOrderConfirmation(order.getId(), order.getCustomerEmail());
} catch (LambdaFunctionException e) {
handleFunctionError(e);
throw new OrderProcessingException("Lambda function error", e);
}
}
private void handleFunctionError(LambdaFunctionException e) {
// Log error details
System.err.println("Lambda function error: " + e.getMessage());
System.err.println("Error type: " + e.getType());
System.err.println("Was handled: " + e.isHandled());
// Handle specific error types
if ("User".equals(e.getType()) && e.isHandled()) {
// Business logic error - safe to retry or handle gracefully
} else {
// System error - may need different handling
}
}
}public class ResilientLambdaService {
private final OrderProcessingService service;
private final int maxRetries = 3;
public ResilientLambdaService(LambdaInvokerFactory factory) {
this.service = factory.build(OrderProcessingService.class);
}
public ValidationResult validateOrderWithRetry(Order order) {
int attempt = 0;
while (attempt < maxRetries) {
try {
return service.validateOrder(order);
} catch (LambdaFunctionException e) {
attempt++;
if (shouldRetry(e) && attempt < maxRetries) {
System.out.println("Retrying validation, attempt " + (attempt + 1));
try {
Thread.sleep(1000 * attempt); // Exponential backoff
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted during retry", ie);
}
} else {
throw new RuntimeException("Validation failed after " + attempt + " attempts", e);
}
}
}
throw new RuntimeException("Max retries exceeded");
}
private boolean shouldRetry(LambdaFunctionException e) {
// Retry on system errors but not on business logic errors
return !e.isHandled() || !"User".equals(e.getType());
}
}// Mock implementation for testing
public class MockOrderProcessingService implements OrderProcessingService {
@Override
public ValidationResult validateOrder(Order order) {
// Mock validation logic
return new ValidationResult(true, Collections.emptyList());
}
@Override
public PaymentResult processPayment(PaymentRequest payment) {
// Mock payment processing
return new PaymentResult(true, "txn_12345", null);
}
@Override
public InventoryStatus checkInventory(List<String> productIds) {
// Mock inventory check
return new InventoryStatus(true, Collections.emptyMap());
}
@Override
public void initiateFullfillment(String orderId, Address shippingAddress) {
// Mock fulfillment - no-op for async methods
}
@Override
public void sendOrderConfirmation(String orderId, String customerEmail) {
// Mock notification - no-op for async methods
}
}
// Unit test
@Test
public void testOrderProcessing() {
OrderProcessor processor = new OrderProcessor(
// Use mock factory that returns mock implementation
createMockFactory()
);
Order testOrder = createTestOrder();
processor.processOrder(testOrder);
// Verify expected behavior
// ...
}Common exceptions when using high-level invocation:
Install with Tessl CLI
npx tessl i tessl/maven-com-amazonaws--aws-java-sdk-lambdadocs