☕ ⚡ Serverless Development with TuskLang Java

Java Documentation

⚡ Serverless Development with TuskLang Java

"We don't bow to any king" - Serverless Java Edition

TuskLang Java enables building serverless applications with AWS Lambda, Azure Functions, and cloud-native serverless patterns that scale automatically and pay only for what you use.

🎯 Serverless Architecture Overview

Serverless Configuration

// serverless-app.tsk
[serverless]
platform: "aws"
runtime: "java17"
memory_size: 512
timeout: 30
environment: "production"

[functions] user_management: { name: "user-management-function" handler: "com.tusklang.serverless.UserManagementHandler::handleRequest" memory_size: 1024 timeout: 60 environment: { DB_HOST: @env("DB_HOST", "localhost") DB_PORT: @env("DB_PORT", "5432") DB_NAME: @env("DB_NAME", "serverless_app") DB_USER: @env("DB_USER", "lambda_user") DB_PASSWORD: @env.secure("DB_PASSWORD") JWT_SECRET: @env.secure("JWT_SECRET") } events: [ { type: "http" path: "/users" method: "GET" cors: true authorizer: "jwt_authorizer" }, { type: "http" path: "/users" method: "POST" cors: true authorizer: "jwt_authorizer" }, { type: "http" path: "/users/{id}" method: "PUT" cors: true authorizer: "jwt_authorizer" }, { type: "http" path: "/users/{id}" method: "DELETE" cors: true authorizer: "jwt_authorizer" } ] vpc: { security_groups: ["sg-12345678"] subnet_ids: ["subnet-12345678", "subnet-87654321"] } layers: ["arn:aws:lambda:us-east-1:123456789012:layer:tusklang-java:1"] }

order_processing: { name: "order-processing-function" handler: "com.tusklang.serverless.OrderProcessingHandler::handleRequest" memory_size: 2048 timeout: 120 environment: { DB_HOST: @env("DB_HOST", "localhost") DB_PORT: @env("DB_PORT", "5432") DB_NAME: @env("DB_NAME", "serverless_app") DB_USER: @env("DB_USER", "lambda_user") DB_PASSWORD: @env.secure("DB_PASSWORD") PAYMENT_API_KEY: @env.secure("PAYMENT_API_KEY") INVENTORY_API_URL: @env("INVENTORY_API_URL") } events: [ { type: "http" path: "/orders" method: "POST" cors: true authorizer: "jwt_authorizer" }, { type: "http" path: "/orders/{id}" method: "GET" cors: true authorizer: "jwt_authorizer" }, { type: "s3" bucket: "order-uploads" events: ["s3:ObjectCreated:*"] filter: { suffix: ".json" } }, { type: "sqs" arn: "arn:aws:sqs:us-east-1:123456789012:order-queue" batch_size: 10 maximum_batching_window: 5 } ] vpc: { security_groups: ["sg-12345678"] subnet_ids: ["subnet-12345678", "subnet-87654321"] } layers: ["arn:aws:lambda:us-east-1:123456789012:layer:tusklang-java:1"] }

notification_service: { name: "notification-service-function" handler: "com.tusklang.serverless.NotificationHandler::handleRequest" memory_size: 512 timeout: 30 environment: { SES_REGION: @env("SES_REGION", "us-east-1") SES_FROM_EMAIL: @env("SES_FROM_EMAIL", "noreply@example.com") SNS_TOPIC_ARN: @env("SNS_TOPIC_ARN") } events: [ { type: "sns" arn: "arn:aws:sns:us-east-1:123456789012:notification-topic" }, { type: "eventbridge" schedule: "rate(5 minutes)" } ] layers: ["arn:aws:lambda:us-east-1:123456789012:layer:tusklang-java:1"] }

[api_gateway] name: "serverless-api" stage: @env("API_STAGE", "prod") cors: { allowed_origins: ["https://app.example.com", "https://admin.example.com"] allowed_methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"] allowed_headers: ["Content-Type", "Authorization", "X-Requested-With"] allow_credentials: true max_age: 3600 }

authorizers: { jwt_authorizer: { type: "jwt" issuer: @env("JWT_ISSUER", "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_123456789") audience: @env("JWT_AUDIENCE", "serverless-app") } }

[databases] primary: { type: "aurora_serverless" cluster_identifier: "serverless-cluster" engine: "aurora-postgresql" engine_version: "13.7" database_name: @env("DB_NAME", "serverless_app") master_username: @env("DB_USER", "lambda_user") master_password: @env.secure("DB_PASSWORD") vpc_security_group_ids: ["sg-12345678"] db_subnet_group_name: "serverless-subnet-group" scaling_configuration: { min_capacity: 1 max_capacity: 16 auto_pause: true seconds_until_auto_pause: 300 } }

cache: { type: "elasticache" engine: "redis" node_type: "cache.t3.micro" num_cache_nodes: 1 vpc_security_group_ids: ["sg-12345678"] subnet_group_name: "serverless-subnet-group" }

[storage] s3: { buckets: [ { name: "user-uploads" versioning: true encryption: "AES256" lifecycle: { transition_days: 30 expiration_days: 365 } }, { name: "order-uploads" versioning: true encryption: "AES256" lifecycle: { transition_days: 7 expiration_days: 90 } } ] }

[monitoring] cloudwatch: { enabled: true log_retention: 30 metrics: [ "duration", "errors", "throttles", "invocations" ] }

xray: { enabled: true sampling_rate: 0.1 }

[alerts] error_rate: { enabled: true threshold: 0.05 period: 300 evaluation_periods: 2 actions: [ { type: "sns" arn: "arn:aws:sns:us-east-1:123456789012:alerts-topic" } ] }

duration: { enabled: true threshold: 5000 period: 300 evaluation_periods: 2 actions: [ { type: "sns" arn: "arn:aws:sns:us-east-1:123456789012:alerts-topic" } ] }

🚀 AWS Lambda Implementation

Lambda Handler Base Class

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.tusklang.java.TuskLang;
import org.tusklang.java.annotations.TuskConfig;
import java.util.Map;

public abstract class BaseLambdaHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { protected final TuskLang tuskLang; protected final ObjectMapper objectMapper; protected final Map<String, Object> config; public BaseLambdaHandler() { this.tuskLang = new TuskLang(); this.objectMapper = new ObjectMapper(); this.config = loadConfiguration(); } protected Map<String, Object> loadConfiguration() { try { return tuskLang.parseFile("config/serverless.tsk"); } catch (Exception e) { log.error("Failed to load configuration", e); return Map.of(); } } @Override public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { try { // Add correlation ID for tracing String correlationId = input.getHeaders().get("X-Correlation-ID"); if (correlationId == null) { correlationId = java.util.UUID.randomUUID().toString(); } // Log request log.info("Processing request: {} {} with correlation ID: {}", input.getHttpMethod(), input.getPath(), correlationId); // Process request APIGatewayProxyResponseEvent response = processRequest(input, context); // Add correlation ID to response response.getHeaders().put("X-Correlation-ID", correlationId); // Log response log.info("Request completed with status: {} and correlation ID: {}", response.getStatusCode(), correlationId); return response; } catch (Exception e) { log.error("Error processing request", e); return createErrorResponse(500, "Internal Server Error", e.getMessage()); } } protected abstract APIGatewayProxyResponseEvent processRequest( APIGatewayProxyRequestEvent input, Context context); protected APIGatewayProxyResponseEvent createSuccessResponse(Object body) { try { String jsonBody = objectMapper.writeValueAsString(body); return new APIGatewayProxyResponseEvent() .withStatusCode(200) .withHeaders(Map.of( "Content-Type", "application/json", "Access-Control-Allow-Origin", "*", "Access-Control-Allow-Headers", "Content-Type,Authorization,X-Requested-With", "Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS" )) .withBody(jsonBody); } catch (Exception e) { log.error("Error serializing response", e); return createErrorResponse(500, "Internal Server Error", "Failed to serialize response"); } } protected APIGatewayProxyResponseEvent createErrorResponse(int statusCode, String error, String message) { Map<String, String> errorBody = Map.of( "error", error, "message", message, "timestamp", java.time.Instant.now().toString() ); try { String jsonBody = objectMapper.writeValueAsString(errorBody); return new APIGatewayProxyResponseEvent() .withStatusCode(statusCode) .withHeaders(Map.of( "Content-Type", "application/json", "Access-Control-Allow-Origin", "*", "Access-Control-Allow-Headers", "Content-Type,Authorization,X-Requested-With", "Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS" )) .withBody(jsonBody); } catch (Exception e) { log.error("Error serializing error response", e); return new APIGatewayProxyResponseEvent() .withStatusCode(statusCode) .withBody("{\"error\":\"Internal Server Error\"}"); } } protected <T> T parseRequestBody(APIGatewayProxyRequestEvent input, Class<T> clazz) { try { if (input.getBody() == null) { throw new IllegalArgumentException("Request body is required"); } return objectMapper.readValue(input.getBody(), clazz); } catch (Exception e) { log.error("Error parsing request body", e); throw new IllegalArgumentException("Invalid request body format"); } } protected String getPathParameter(APIGatewayProxyRequestEvent input, String name) { Map<String, String> pathParameters = input.getPathParameters(); if (pathParameters == null) { throw new IllegalArgumentException("Path parameter '" + name + "' is required"); } String value = pathParameters.get(name); if (value == null) { throw new IllegalArgumentException("Path parameter '" + name + "' is required"); } return value; } protected String getQueryParameter(APIGatewayProxyRequestEvent input, String name) { Map<String, String> queryStringParameters = input.getQueryStringParameters(); if (queryStringParameters == null) { return null; } return queryStringParameters.get(name); } }

User Management Lambda Handler

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;

@Component public class UserManagementHandler extends BaseLambdaHandler { private final UserService userService; private final JwtAuthorizer jwtAuthorizer; public UserManagementHandler(UserService userService, JwtAuthorizer jwtAuthorizer) { this.userService = userService; this.jwtAuthorizer = jwtAuthorizer; } @Override protected APIGatewayProxyResponseEvent processRequest( APIGatewayProxyRequestEvent input, Context context) { // Authorize request String token = extractToken(input); if (token == null) { return createErrorResponse(401, "Unauthorized", "Missing or invalid authorization token"); } try { UserPrincipal user = jwtAuthorizer.authorize(token); if (user == null) { return createErrorResponse(401, "Unauthorized", "Invalid token"); } } catch (Exception e) { log.error("Authorization failed", e); return createErrorResponse(401, "Unauthorized", "Invalid token"); } // Route request based on HTTP method switch (input.getHttpMethod()) { case "GET": return handleGetUsers(input, context); case "POST": return handleCreateUser(input, context); case "PUT": return handleUpdateUser(input, context); case "DELETE": return handleDeleteUser(input, context); default: return createErrorResponse(405, "Method Not Allowed", "HTTP method " + input.getHttpMethod() + " is not supported"); } } private APIGatewayProxyResponseEvent handleGetUsers( APIGatewayProxyRequestEvent input, Context context) { try { // Get query parameters String page = getQueryParameter(input, "page"); String size = getQueryParameter(input, "size"); String search = getQueryParameter(input, "search"); int pageNum = page != null ? Integer.parseInt(page) : 0; int pageSize = size != null ? Integer.parseInt(size) : 20; // Get users from service Page<User> users = userService.getUsers(pageNum, pageSize, search); // Create response Map<String, Object> response = Map.of( "users", users.getContent(), "page", users.getNumber(), "size", users.getSize(), "totalElements", users.getTotalElements(), "totalPages", users.getTotalPages() ); return createSuccessResponse(response); } catch (Exception e) { log.error("Error getting users", e); return createErrorResponse(500, "Internal Server Error", "Failed to retrieve users"); } } private APIGatewayProxyResponseEvent handleCreateUser( APIGatewayProxyRequestEvent input, Context context) { try { // Parse request body CreateUserRequest request = parseRequestBody(input, CreateUserRequest.class); // Validate request if (request.getEmail() == null || request.getEmail().trim().isEmpty()) { return createErrorResponse(400, "Bad Request", "Email is required"); } if (request.getFirstName() == null || request.getFirstName().trim().isEmpty()) { return createErrorResponse(400, "Bad Request", "First name is required"); } if (request.getLastName() == null || request.getLastName().trim().isEmpty()) { return createErrorResponse(400, "Bad Request", "Last name is required"); } // Create user User user = userService.createUser(request); return createSuccessResponse(user); } catch (IllegalArgumentException e) { return createErrorResponse(400, "Bad Request", e.getMessage()); } catch (Exception e) { log.error("Error creating user", e); return createErrorResponse(500, "Internal Server Error", "Failed to create user"); } } private APIGatewayProxyResponseEvent handleUpdateUser( APIGatewayProxyRequestEvent input, Context context) { try { // Get user ID from path String userId = getPathParameter(input, "id"); // Parse request body UpdateUserRequest request = parseRequestBody(input, UpdateUserRequest.class); // Update user User user = userService.updateUser(userId, request); if (user == null) { return createErrorResponse(404, "Not Found", "User not found"); } return createSuccessResponse(user); } catch (IllegalArgumentException e) { return createErrorResponse(400, "Bad Request", e.getMessage()); } catch (Exception e) { log.error("Error updating user", e); return createErrorResponse(500, "Internal Server Error", "Failed to update user"); } } private APIGatewayProxyResponseEvent handleDeleteUser( APIGatewayProxyRequestEvent input, Context context) { try { // Get user ID from path String userId = getPathParameter(input, "id"); // Delete user boolean deleted = userService.deleteUser(userId); if (!deleted) { return createErrorResponse(404, "Not Found", "User not found"); } return createSuccessResponse(Map.of("message", "User deleted successfully")); } catch (Exception e) { log.error("Error deleting user", e); return createErrorResponse(500, "Internal Server Error", "Failed to delete user"); } } private String extractToken(APIGatewayProxyRequestEvent input) { String authorization = input.getHeaders().get("Authorization"); if (authorization == null || !authorization.startsWith("Bearer ")) { return null; } return authorization.substring(7); } }

Order Processing Lambda Handler

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent;
import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent;
import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import com.amazonaws.services.lambda.runtime.events.S3Event;
import org.springframework.stereotype.Component;
import java.util.List;

@Component public class OrderProcessingHandler extends BaseLambdaHandler { private final OrderService orderService; private final PaymentService paymentService; private final InventoryService inventoryService; private final NotificationService notificationService; public OrderProcessingHandler(OrderService orderService, PaymentService paymentService, InventoryService inventoryService, NotificationService notificationService) { this.orderService = orderService; this.paymentService = paymentService; this.inventoryService = inventoryService; this.notificationService = notificationService; } // HTTP API Gateway handler public APIGatewayProxyResponseEvent handleHttpRequest( APIGatewayProxyRequestEvent input, Context context) { return processRequest(input, context); } // SQS handler public void handleSqsEvent(SQSEvent event, Context context) { for (SQSEvent.SQSMessage message : event.getRecords()) { try { log.info("Processing SQS message: {}", message.getMessageId()); // Parse order from SQS message OrderRequest orderRequest = objectMapper.readValue( message.getBody(), OrderRequest.class); // Process order Order order = orderService.processOrder(orderRequest); // Send notification notificationService.sendOrderConfirmation(order); log.info("Successfully processed SQS message: {}", message.getMessageId()); } catch (Exception e) { log.error("Error processing SQS message: {}", message.getMessageId(), e); // Message will be retried by SQS throw e; } } } // S3 handler public void handleS3Event(S3Event event, Context context) { for (S3Event.S3EventNotificationRecord record : event.getRecords()) { try { String bucketName = record.getS3().getBucket().getName(); String key = record.getS3().getObject().getKey(); log.info("Processing S3 event for bucket: {} key: {}", bucketName, key); // Download and parse order file String orderJson = downloadS3Object(bucketName, key); OrderRequest orderRequest = objectMapper.readValue(orderJson, OrderRequest.class); // Process order Order order = orderService.processOrder(orderRequest); // Send notification notificationService.sendOrderConfirmation(order); log.info("Successfully processed S3 event for key: {}", key); } catch (Exception e) { log.error("Error processing S3 event", e); throw e; } } } @Override protected APIGatewayProxyResponseEvent processRequest( APIGatewayProxyRequestEvent input, Context context) { // Authorize request String token = extractToken(input); if (token == null) { return createErrorResponse(401, "Unauthorized", "Missing or invalid authorization token"); } try { UserPrincipal user = jwtAuthorizer.authorize(token); if (user == null) { return createErrorResponse(401, "Unauthorized", "Invalid token"); } } catch (Exception e) { log.error("Authorization failed", e); return createErrorResponse(401, "Unauthorized", "Invalid token"); } // Route request based on HTTP method switch (input.getHttpMethod()) { case "POST": return handleCreateOrder(input, context); case "GET": return handleGetOrder(input, context); default: return createErrorResponse(405, "Method Not Allowed", "HTTP method " + input.getHttpMethod() + " is not supported"); } } private APIGatewayProxyResponseEvent handleCreateOrder( APIGatewayProxyRequestEvent input, Context context) { try { // Parse request body CreateOrderRequest request = parseRequestBody(input, CreateOrderRequest.class); // Validate request if (request.getItems() == null || request.getItems().isEmpty()) { return createErrorResponse(400, "Bad Request", "Order items are required"); } // Check inventory for (OrderItem item : request.getItems()) { boolean available = inventoryService.checkAvailability( item.getProductId(), item.getQuantity()); if (!available) { return createErrorResponse(400, "Bad Request", "Product " + item.getProductId() + " is not available in requested quantity"); } } // Process payment PaymentResult paymentResult = paymentService.processPayment(request.getPayment()); if (!paymentResult.isSuccess()) { return createErrorResponse(400, "Payment Failed", paymentResult.getErrorMessage()); } // Create order Order order = orderService.createOrder(request, paymentResult.getTransactionId()); // Update inventory for (OrderItem item : order.getItems()) { inventoryService.updateStock(item.getProductId(), item.getQuantity()); } // Send notification notificationService.sendOrderConfirmation(order); return createSuccessResponse(order); } catch (IllegalArgumentException e) { return createErrorResponse(400, "Bad Request", e.getMessage()); } catch (Exception e) { log.error("Error creating order", e); return createErrorResponse(500, "Internal Server Error", "Failed to create order"); } } private APIGatewayProxyResponseEvent handleGetOrder( APIGatewayProxyRequestEvent input, Context context) { try { // Get order ID from path String orderId = getPathParameter(input, "id"); // Get order Order order = orderService.getOrder(orderId); if (order == null) { return createErrorResponse(404, "Not Found", "Order not found"); } return createSuccessResponse(order); } catch (Exception e) { log.error("Error getting order", e); return createErrorResponse(500, "Internal Server Error", "Failed to retrieve order"); } } private String downloadS3Object(String bucketName, String key) { // Implementation for downloading S3 object // This would use AWS SDK for S3 return ""; // Placeholder } private String extractToken(APIGatewayProxyRequestEvent input) { String authorization = input.getHeaders().get("Authorization"); if (authorization == null || !authorization.startsWith("Bearer ")) { return null; } return authorization.substring(7); } }

🔧 Best Practices

1. Lambda Function Design

- Keep functions small and focused - Use environment variables for configuration - Implement proper error handling - Use connection pooling for databases

2. Performance Optimization

- Use Lambda layers for shared dependencies - Implement cold start optimization - Use async processing for long-running tasks - Optimize memory allocation

3. Security

- Use IAM roles with least privilege - Implement proper input validation - Use VPC for database access - Encrypt sensitive data

4. Monitoring and Observability

- Use CloudWatch for logging and metrics - Implement distributed tracing with X-Ray - Set up proper alarms and alerts - Monitor cold start times

5. Cost Optimization

- Use provisioned concurrency for critical functions - Implement proper timeout handling - Use SQS for async processing - Monitor and optimize memory usage

🎯 Summary

TuskLang Java serverless development provides:

- AWS Lambda Integration: Complete serverless function support - Event-Driven Architecture: SQS, S3, and API Gateway integration - Serverless Patterns: Cold start optimization and cost management - Security: IAM roles, VPC, and encryption - Monitoring: CloudWatch, X-Ray, and comprehensive observability

The combination of TuskLang's executable configuration with Java's serverless capabilities creates a powerful platform for building scalable, cost-effective, and maintainable serverless applications.

"We don't bow to any king" - Build serverless applications that scale automatically!