← Back to Home

Module 4: AWS Lambda

Module Overview

Master working with AWS Lambda functions, cloud logging, and how to effectively test serverless applications.

Introduction to AWS Lambda

AWS Lambda is a serverless computing service that lets you run code without provisioning or managing servers. You pay only for the compute time you consume, with no charge when your code is not running.

Lambda functions are event-driven, executing your code in response to triggers like HTTP requests, file uploads, database changes, or scheduled events.

// Basic AWS Lambda function in Java
public class MyLambdaHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
    @Override
    public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
        // Get the logger from the context
        LambdaLogger logger = context.getLogger();
        
        // Log information about the request
        logger.log("Received request: " + input.getBody());
        
        // Process the request
        String result = processRequest(input.getBody());
        
        // Create and return the response
        APIGatewayProxyResponseEvent response = new APIGatewayProxyResponseEvent();
        response.setStatusCode(200);
        response.setBody(result);
        return response;
    }
    
    private String processRequest(String requestBody) {
        // Business logic here
        return "Request processed successfully";
    }
}

Learning Objectives

CloudWatch Logging

Effective logging is critical for monitoring and debugging serverless applications, especially since you don't have direct access to the server environment.

AWS Lambda automatically integrates with CloudWatch Logs, storing all output from your Lambda function's console (stdout/stderr).

// Effective logging in Lambda functions
public class LoggingExample implements RequestHandler<Map<String, Object>, String> {
    // Create a logger instance
    private static final Logger logger = LogManager.getLogger(LoggingExample.class);
    
    @Override
    public String handleRequest(Map<String, Object> input, Context context) {
        // Different log levels for different purposes
        logger.trace("TRACE: Detailed information for debugging");
        logger.debug("DEBUG: Information useful for debugging");
        logger.info("INFO: Highlights progress of the application");
        logger.warn("WARN: Potentially harmful situations that should be addressed");
        logger.error("ERROR: Error events that might still allow the application to continue");
        
        try {
            // Business logic that might throw an exception
            Object result = processSomething(input);
            return result.toString();
        } catch (Exception e) {
            // Log the full exception with stack trace
            logger.error("Failed to process input", e);
            return "Error processing request";
        }
    }
}

Testing Lambda Functions

Testing Lambda functions requires different approaches compared to traditional applications:

  1. Local testing: Test the handler logic without deploying to AWS
  2. Integration testing: Test the deployed function with real AWS services
  3. Mocking AWS services: Use libraries like localstack or AWS SDK mocking
// Example of unit testing a Lambda function
@Test
public void testHandleRequest() {
    // Create test input
    APIGatewayProxyRequestEvent input = new APIGatewayProxyRequestEvent();
    input.setBody("{\"name\":\"John\"}");
    
    // Mock the AWS Lambda context
    Context context = createMockContext();
    
    // Create the handler
    MyLambdaHandler handler = new MyLambdaHandler();
    
    // Execute the function
    APIGatewayProxyResponseEvent response = handler.handleRequest(input, context);
    
    // Verify the response
    assertEquals(200, response.getStatusCode().intValue());
    assertTrue(response.getBody().contains("Successfully processed John"));
}

private Context createMockContext() {
    // Create a mock implementation of Context
    Context context = mock(Context.class);
    LambdaLogger logger = mock(LambdaLogger.class);
    
    // Setup the mock behavior
    when(context.getLogger()).thenReturn(logger);
    when(context.getRemainingTimeInMillis()).thenReturn(10000);
    
    return context;
}

Resources