🧩 Perfect Clean Architecture + Hexagonal + AWS Lambda

This folder structure is a fully aligned Clean Architecture (a.k.a. Hexagonal Architecture) that supports DDD, Layered, Event-Driven principles and integrates seamlessly with Spring Boot and AWS Lambda.

✅ Clean Architecture Alignment

Layer Folder Description Example Classes
Entities (Domain Layer) domain/ Pure business logic, no frameworks. Independent of Spring, AWS, or databases. User.java, BusinessRules.java, DomainEvent.java, UserCreatedEvent.java
Use Cases (Application Layer) application/ Core use cases and business rules orchestration. Contains interfaces (ports) and use case implementations. CreateUserUseCase.java, GetUserService.java
Interface Adapters (Adapters Layer) adapter/ Converts data between external systems (REST, Lambda, Database, Kafka) and the core domain. UserController.java, JpaUserRepositoryAdapter.java, LambdaHandler.java, KafkaEventPublisherAdapter.java
Frameworks & Drivers (Infrastructure Layer) adapter/config/ + main class Entry points, Spring configuration, and infrastructure setup (Spring, AWS SDK, Kafka, etc.). BeanConfig.java, KafkaConfig.java, SpringbootLambdaApplication.java

🧱 How Each Pattern Fits

Layered (n-tier)
REST controllers → application services → persistence adapters
DDD / Modular Monolith
Domain separated into model, service, and event packages with clear aggregates and bounded contexts
Event-Driven / Reactive
domain/event + adapter/events enable Kafka/SNS/SQS integration for asynchronous communication
Hexagonal / Clean Architecture
Ports (application/port) and Adapters (adapter/*) perfectly isolate the domain logic from frameworks
Microservices-ready
Each bounded context under domain/ and application/ can evolve into its own independent microservice

⚙️ How It Plays with AWS Lambda

package org.ldschurch.rest_api.adapter.lambda;

import org.springframework.cloud.function.adapter.aws.SpringBootRequestHandler;
import org.ldschurch.rest_api.application.service.CreateUserService;
import org.ldschurch.rest_api.adapter.rest.dto.UserRequest;

public class LambdaHandler extends SpringBootRequestHandler<UserRequest, String> {
    // Handles AWS Lambda request and delegates to Spring Boot bean
}
  

In AWS SAM (template.yaml), the function points to this Lambda handler:

Resources:
  SpringbootLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: org.ldschurch.rest_api.adapter.lambda.LambdaHandler
      Runtime: java17
      CodeUri: build/distributions/springboot-lambda-0.0.1-SNAPSHOT.zip
      MemorySize: 1024
      Timeout: 30
      Events:
        Api:
          Type: Api
          Properties:
            Path: /users
            Method: post
  

🧩 Clean Architecture Dependencies Rule

✅ Inner layers must not depend on outer layers.
Dependencies flow inward only:

adapter --> application --> domain
    

🧠 Folder Layout Summary

springboot-lambda/
├── build.gradle
├── template.yaml
├── src/
│   └── main/
│       ├── java/org/ldschurch/rest_api/
│       │   ├── domain/                # Core business entities & events
│       │   ├── application/           # Ports and Use Cases
│       │   ├── adapter/               # Adapters (REST, Persistence, Lambda, Kafka)
│       │   └── SpringbootLambdaApplication.java
│       └── resources/
│           ├── application.yml
│           └── logback-spring.xml
└── build/distributions/