Welcome to Chapter 19 of our Java project series! Up until now, we’ve focused on building robust, production-ready applications locally. While running applications on your machine is great for development and testing, the real power of software comes when it’s accessible to users globally. This chapter marks a significant milestone: taking our “Basic To-Do List Application” (which we’ll assume has been developed as a Spring Boot REST API in previous chapters, allowing for a realistic cloud deployment scenario) and deploying it to a leading cloud platform.

The goal of this chapter is to guide you through the process of making your application publicly available, scalable, and resilient. We will focus on deploying to Amazon Web Services (AWS) using Elastic Beanstalk for our application and Amazon RDS for our database, providing a practical, step-by-step walkthrough. We’ll also briefly touch upon how a similar process would look in Microsoft Azure. By the end of this chapter, your To-Do List application will be running live in the cloud, accessible from anywhere with an internet connection.

Before we begin, ensure you have a fully functional Spring Boot To-Do List application from previous chapters, capable of running locally and interacting with a database (e.g., PostgreSQL). You will also need an active AWS account (with appropriate permissions) and optionally an Azure account if you wish to explore that path. The expected outcome is a publicly accessible To-Do List API, ready for consumption by front-end applications or other services.

Planning & Design

Deploying an application to the cloud involves more than just uploading a file; it requires careful planning to ensure scalability, security, and maintainability. For our To-Do List application, we’ll adopt a common architecture for Java web applications in the cloud:

  • Application Layer: We’ll use AWS Elastic Beanstalk. This Platform as a Service (PaaS) offering simplifies deployment by abstracting away the underlying infrastructure (EC2 instances, load balancers, auto-scaling groups). It’s an excellent choice for quickly deploying Spring Boot JARs.
  • Database Layer: For persistence, we’ll leverage AWS Relational Database Service (RDS) with PostgreSQL. RDS provides managed database instances, handling backups, patching, and scaling, so you don’t have to manage a database server directly.
  • Network Security: We’ll configure Virtual Private Clouds (VPCs) and Security Groups to control network traffic, ensuring only authorized access to our application and database.
  • Configuration Management: Database credentials and other sensitive information will be managed securely using environment variables within Elastic Beanstalk, adhering to best practices for secrets management.

The overall architecture will look something like this:

Client (Browser/Mobile) <--- Internet ---> AWS Load Balancer <--- AWS Elastic Beanstalk (EC2 instances running Spring Boot) <---> AWS RDS (PostgreSQL)

This setup provides a robust foundation, allowing for future scaling and integration with other AWS services.

Step-by-Step Implementation: Deploying to AWS

We’ll start by preparing our Spring Boot application for cloud deployment, then set up the necessary AWS infrastructure, and finally deploy our application.

1. Prepare the Application for Cloud Deployment

Before deploying, we need to ensure our Spring Boot application is ready for a cloud environment, particularly regarding externalized configuration and health checks.

a) Setup/Configuration: Externalize Database Configuration

In a production environment, database credentials should never be hardcoded or committed to version control. Instead, they should be injected as environment variables.

First, ensure your application.properties (or application.yml) is configured to read database properties from environment variables or provide sensible defaults for local development.

File: src/main/resources/application.properties

# Default local H2 database for development
spring.datasource.url=jdbc:h2:mem:todolistdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

# Override for PostgreSQL in production (using environment variables)
# These values will be picked up if set as environment variables in the cloud
spring.datasource.url=${JDBC_DATABASE_URL:jdbc:h2:mem:todolistdb}
spring.datasource.username=${JDBC_DATABASE_USERNAME:sa}
spring.datasource.password=${JDBC_DATABASE_PASSWORD:password}
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

# Spring Boot Actuator for health checks
management.endpoints.web.exposure.include=health,info
management.endpoint.health.show-details=always

Explanation:

  • We’ve kept the H2 in-memory database configuration as a default, which is great for local development and testing without needing a full database setup.
  • Crucially, we’ve added placeholders like ${JDBC_DATABASE_URL:jdbc:h2:mem:todolistdb}. This tells Spring Boot to look for an environment variable named JDBC_DATABASE_URL. If it’s not found (e.g., during local development), it falls back to the H2 URL.
  • We’ve also enabled Spring Boot Actuator’s health and info endpoints. The health endpoint is vital for cloud platforms to determine if our application is running correctly.
b) Core Implementation: Add a Health Check

Spring Boot Actuator automatically provides a /actuator/health endpoint. We’ve enabled it in application.properties. This endpoint will be used by Elastic Beanstalk’s load balancer to check the application’s health.

Let’s ensure our pom.xml includes the Actuator dependency.

File: pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version> <!-- Use a recent stable Spring Boot version compatible with Java 25 -->
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>todo-list-app</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>todo-list-app</name>
    <description>Basic To-Do List Application</description>

    <properties>
        <java.version>25</java.version> <!-- Targeting Java 25 -->
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId> <!-- ADD THIS -->
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Explanation:

  • We’ve added spring-boot-starter-actuator to our dependencies. This pulls in all necessary Actuator components.
  • The java.version is set to 25. Assuming Spring Boot 3.3.0 (or newer) supports Java 25, this is the correct configuration. If not, you might need to use Java 21 LTS until Spring Boot officially supports 25. For this tutorial, we proceed with the assumption of Java 25 support.
c) Core Implementation: Build the Executable JAR

With our application configured, we can now build the executable JAR file. This JAR contains everything needed to run our application, including an embedded web server.

Open your terminal in the root directory of your project (where pom.xml is located) and run the Maven clean and package command:

mvn clean package

Expected Output (Snippet):

[INFO] --- spring-boot-maven-plugin:3.3.0:repackage (repackage) @ todo-list-app ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.452 s
[INFO] Finished at: 2025-12-04T10:30:00Z
[INFO] ------------------------------------------------------------------------

This command will compile your code, run tests, and create a todo-list-app-0.0.1-SNAPSHOT.jar (or similar, depending on your version) file in the target/ directory. This is the file we will deploy to AWS Elastic Beanstalk.

d) Testing This Component: Local Run with Environment Variables

To simulate the cloud environment, you can test your application locally by setting environment variables for the database:

First, ensure you have a local PostgreSQL instance running and create a database named todolistdb (or whatever you prefer) with a user and password.

Then, run your JAR with the environment variables:

JDBC_DATABASE_URL="jdbc:postgresql://localhost:5432/todolistdb" \
JDBC_DATABASE_USERNAME="your_pg_user" \
JDBC_DATABASE_PASSWORD="your_pg_password" \
java -jar target/todo-list-app-0.0.1-SNAPSHOT.jar

Expected Behavior: The application should start, connect to your local PostgreSQL database, and expose its REST API endpoints. You can verify this by accessing http://localhost:8080/actuator/health in your browser or using curl. You should see a JSON response indicating status: "UP".

{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "PostgreSQL",
        "validationQuery": "isValid()"
      }
    },
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 249704288256,
        "free": 218734008320,
        "threshold": 10485760,
        "exists": true
      }
    },
    "ping": {
      "status": "UP"
    }
  }
}

This confirms your application correctly reads environment variables and connects to the database.

2. AWS Setup - Database (RDS PostgreSQL)

Now, let’s set up our production-grade database in AWS RDS.

a) Setup/Configuration: Create an RDS PostgreSQL Instance
  1. Log in to AWS Management Console: Go to https://aws.amazon.com/console/.
  2. Navigate to RDS: Search for “RDS” and select it.
  3. Create Database: Click “Create database”.
    • Choose a database creation method: Select “Standard create”.
    • Engine options: Choose “PostgreSQL”.
    • Version: Select a recent stable version (e.g., PostgreSQL 16.x).
    • Templates: Select “Free tier” for this tutorial (or “Dev/Test” for more options). For production, consider “Production”.
    • DB instance identifier: todo-list-db (or a unique name).
    • Master username: admin (or a secure username).
    • Master password: Choose a strong, secure password. Remember this!
    • DB instance size: For Free Tier, t2.micro or t3.micro is usually selected. For production, choose an appropriate instance type.
    • Storage: Default settings are usually fine for a tutorial.
    • Connectivity:
      • VPC: Use the default VPC.
      • Subnet group: Choose “Create new DB Subnet group”.
      • Publicly accessible: Select “No” (this is a best practice; our application will connect internally).
      • VPC security group (firewall): Choose “Create new” and give it a name like todo-list-db-sg.
      • Database port: 5432 (default for PostgreSQL).
    • Additional configuration:
      • Initial database name: todolistdb (this matches our application.properties default).
    • Create database: Click the button.

The database creation will take a few minutes.

b) Core Implementation: Configure RDS Security Group

Once the RDS instance is created, we need to allow our Elastic Beanstalk application to connect to it.

  1. Navigate to RDS: Go back to the RDS dashboard.
  2. Select your database: Click on todo-list-db.
  3. Connectivity & security tab: Scroll down to the “Security” section.
  4. Click on the VPC security group: This will take you to the EC2 Security Groups page.
  5. Edit Inbound Rules:
    • Select the security group (e.g., todo-list-db-sg).
    • Click “Actions” -> “Edit inbound rules”.
    • Add rule:
      • Type: PostgreSQL (port 5432).
      • Source: This is crucial. Instead of allowing Anywhere (which is insecure), we will allow traffic from the security group of our Elastic Beanstalk application. We don’t have this yet, so for now, you can temporarily set it to “My IP” or “Custom” to test connectivity from your machine, but remember to update this later.
      • (Self-correction: We will create the Elastic Beanstalk environment first, then update this rule with the Beanstalk’s security group. This is the more secure and practical approach.)

For now, leave the RDS security group as is (likely only allowing your IP if you configured it that way, or no inbound rules if you didn’t touch it). We will update it once the Elastic Beanstalk environment is up and running.

c) Core Implementation: Get RDS Connection Details

Once your RDS instance status is “Available”, get its endpoint.

  1. Navigate to RDS: Go back to the RDS dashboard.
  2. Select your database: Click on todo-list-db.
  3. Connectivity & security tab: Copy the Endpoint (e.g., todo-list-db.xxxxxxxx.us-east-1.rds.amazonaws.com).
    • Port: 5432
    • Database Name: todolistdb
    • Username: admin (or your chosen master username)
    • Password: (Your chosen master password)

These details will be used as environment variables in Elastic Beanstalk.

3. AWS Setup - Elastic Beanstalk Environment

Now we’ll create the environment where our Spring Boot application will run.

a) Setup/Configuration: Create Elastic Beanstalk Application
  1. Log in to AWS Management Console: Go to https://aws.amazon.com/console/.
  2. Navigate to Elastic Beanstalk: Search for “Elastic Beanstalk” and select it.
  3. Create a new application: Click “Create application”.
    • Application name: todo-list-app
    • Tags: (Optional)
    • Platform:
      • Managed platform: Select “Managed platform”.
      • Platform: “Java”
      • Platform branch: “Corretto with Tomcat” (This is a common choice for Spring Boot JARs; it runs the JAR as a standalone process).
      • Platform version: Choose the latest stable Java version available (e.g., Corretto 21 running on 64bit Amazon Linux 2). While Java 25 is our target, AWS might not have Corretto 25 available yet in Elastic Beanstalk. We will proceed with the latest available Corretto LTS (e.g., 21) as it’s a production-ready choice.
    • Application code:
      • Sample application: Select “Upload your code”.
      • Source code origin: “Local file”.
      • Choose file: Upload the todo-list-app-0.0.1-SNAPSHOT.jar you built earlier from your target/ directory.
      • Version label: v1.0.0 (or similar).
    • Presets: “Single instance” for development/testing, or “High availability” for production. Let’s start with “Single instance” to minimize costs.
    • Click “Create application”.

Elastic Beanstalk will now provision the necessary resources (EC2 instance, security groups, etc.). This process can take 5-10 minutes.

b) Core Implementation: Configure Environment Variables

Once the Elastic Beanstalk environment is created (or while it’s being created), we need to set the database connection environment variables.

  1. Navigate to Elastic Beanstalk: Go to your todo-list-app application.

  2. Select the environment: Click on the environment name (e.g., todo-list-app-env).

  3. Configuration: In the left-hand menu, select “Configuration”.

  4. Software section: Click “Edit” for the “Software” category.

  5. Environment properties: Add the following environment variables, replacing the placeholders with your RDS instance’s details:

    • JDBC_DATABASE_URL: jdbc:postgresql://<YOUR_RDS_ENDPOINT>:5432/todolistdb (e.g., jdbc:postgresql://todo-list-db.xxxxxxxx.us-east-1.rds.amazonaws.com:5432/todolistdb)
    • JDBC_DATABASE_USERNAME: admin (your RDS master username)
    • JDBC_DATABASE_PASSWORD: YOUR_RDS_MASTER_PASSWORD (your RDS master password)
    • SERVER_PORT: 5000 (Elastic Beanstalk’s default proxy expects the application to listen on port 5000 for Java SE environments)

    Important Note on SERVER_PORT: For Spring Boot applications deployed as JARs on Elastic Beanstalk, the application typically needs to listen on port 5000, as the Nginx proxy is configured to forward requests to this port. If you don’t set this, Spring Boot will default to 8080, and the proxy won’t find your application.

  6. Apply: Click “Apply” at the bottom. This will update your environment, causing a brief redeployment.

c) Core Implementation: Update Security Groups for Connectivity

Now that Elastic Beanstalk has created its EC2 instances and associated security groups, we can update the RDS security group to allow inbound traffic from our application.

  1. Find Elastic Beanstalk’s Security Group:
    • Go to your Elastic Beanstalk environment dashboard (todo-list-app-env).
    • In the “Configuration” section, find the “Security” category and click “Edit”.
    • Under “EC2 security groups”, you’ll see a security group created by Elastic Beanstalk (e.g., awseb-e-xxxxxxxx-stack-AWSEBSecurityGroup-YYYYYYYY). Copy this security group ID.
  2. Update RDS Security Group:
    • Go to the RDS dashboard, select your todo-list-db instance.
    • Go to “Connectivity & security” and click on the associated VPC security group (e.g., todo-list-db-sg). This takes you to the EC2 Security Groups page.
    • Select todo-list-db-sg and click “Actions” -> “Edit inbound rules”.
    • Add rule:
      • Type: PostgreSQL (port 5432).
      • Source: Select “Custom” and paste the Elastic Beanstalk security group ID you copied. This ensures only your application can connect to the database.
      • Description: Allow inbound from todo-list-app-env
    • Click “Save rules”.

This establishes a secure, internal connection between your application and database.

d) Deploy and Verify

Your Elastic Beanstalk environment should now be updating with the new configuration. Monitor the events in the Elastic Beanstalk console.

  1. Monitor Events: On your environment’s dashboard, check the “Events” tab. Look for messages indicating the environment update is complete and healthy.

  2. Access Application URL: Once the environment health is “OK”, click the environment URL at the top of the dashboard (e.g., http://todo-list-app-env.us-east-1.elasticbeanstalk.com).

  3. Test Health Endpoint: Append /actuator/health to the URL (e.g., http://todo-list-app-env.us-east-1.elasticbeanstalk.com/actuator/health). You should see the status: "UP" response, including database connectivity details.

  4. Test API Endpoints: Use a tool like Postman or curl to test your To-Do List API endpoints (e.g., POST /api/todos, GET /api/todos).

    Example curl command to add a todo:

    curl -X POST -H "Content-Type: application/json" \
         -d '{"title": "Deploy Java app", "description": "Successfully deploy our Spring Boot app to AWS Elastic Beanstalk", "completed": false}' \
         http://todo-list-app-env.us-east-1.elasticbeanstalk.com/api/todos
    

    Example curl command to get all todos:

    curl http://todo-list-app-env.us-east-1.elasticbeanstalk.com/api/todos
    

Expected Behavior: You should be able to create, retrieve, update, and delete to-do items, with the data being persistently stored in your AWS RDS PostgreSQL database.

Production Considerations

Deploying to the cloud is just the first step. Ensuring your application runs reliably, securely, and efficiently in production requires additional considerations.

  • Error Handling and Logging:

    • Structured Logging: Configure your application to output logs in a structured format (e.g., JSON) to AWS CloudWatch. This makes logs easier to parse, search, and analyze. Spring Boot’s default logging integrates well with CloudWatch Logs.
    • Exception Tracking: Integrate a service like Sentry or AWS X-Ray for centralized error tracking and performance monitoring.
    • Alerting: Set up CloudWatch Alarms to notify you via email or SMS if application errors exceed a threshold, CPU utilization is too high, or the application becomes unhealthy.
  • Performance Optimization:

    • Instance Sizing: Monitor your application’s resource usage (CPU, memory) in CloudWatch and adjust the EC2 instance type in Elastic Beanstalk accordingly. Start small and scale up as needed.
    • Auto-scaling: For high availability and to handle varying load, configure auto-scaling within Elastic Beanstalk. This automatically adds or removes EC2 instances based on predefined metrics (e.g., CPU utilization).
    • Caching: For frequently accessed data, consider adding a caching layer (e.g., AWS ElastiCache for Redis or Memcached) to reduce database load and improve response times.
    • Database Optimization: Regularly review database query performance, add appropriate indexes, and consider read replicas for read-heavy applications.
  • Security Considerations:

    • HTTPS/SSL: Always enable HTTPS for your application. Elastic Beanstalk allows easy integration with AWS Certificate Manager (ACM) and configures the load balancer to handle SSL termination. This encrypts all traffic between users and your application.
    • Secrets Management: While environment variables are better than hardcoding, for highly sensitive secrets, consider AWS Secrets Manager or AWS Parameter Store. These services provide more robust secret rotation, auditing, and access control.
    • IAM Roles: Use granular IAM roles for your EC2 instances (via Elastic Beanstalk) to ensure they only have the minimum necessary permissions to interact with other AWS services (e.g., RDS, S3, CloudWatch).
    • VPC and Security Groups: Continue to refine your VPC and security group rules, applying the principle of least privilege. Only open ports and allow traffic from known sources.
    • Regular Updates: Keep your Java runtime, Spring Boot version, and all dependencies updated to patch known vulnerabilities.
  • Monitoring:

    • CloudWatch Dashboards: Create custom dashboards in CloudWatch to visualize key metrics like request latency, error rates, CPU/memory usage, and database connections.
    • Health Checks: Leverage Elastic Beanstalk’s enhanced health reporting to get detailed insights into your application’s health.

Code Review Checkpoint

At this point, you’ve successfully:

  • Configured your Spring Boot application to externalize database credentials using environment variables.
  • Included Spring Boot Actuator for health checks.
  • Built an executable JAR file.
  • Provisioned a managed PostgreSQL database instance on AWS RDS.
  • Deployed your Spring Boot application to AWS Elastic Beanstalk.
  • Configured environment variables in Elastic Beanstalk to connect to RDS.
  • Secured network access between your application and database using AWS Security Groups.

The main files modified were src/main/resources/application.properties and pom.xml. The core logic of the To-Do List application itself remained unchanged, demonstrating how cloud deployment focuses on infrastructure and configuration rather than application code.

Common Issues & Solutions

  1. Application Failing to Start (Health Check Red/Degraded):

    • Symptom: Elastic Beanstalk health status is “Red” or “Degraded,” logs show “Application failed to start” or “Port 5000 not listening.”
    • Cause:
      • Incorrect SERVER_PORT: Spring Boot defaults to 8080, but Elastic Beanstalk’s Nginx proxy for Java SE environments expects the application to listen on port 5000.
      • Missing Dependencies: A required dependency (e.g., postgresql driver) is not included or available at runtime.
      • Configuration Errors: Issues in application.properties or environment variables.
    • Solution:
      • Ensure SERVER_PORT: 5000 is set in Elastic Beanstalk environment variables.
      • Check pom.xml for all necessary dependencies.
      • Review /var/log/web.stdout.log and /var/log/eb-activity.log on the EC2 instance (via SSH or Elastic Beanstalk’s “Logs” section) for detailed Java application logs.
    • Prevention: Always test environment variable configuration locally before deploying.
  2. Database Connection Issues (Caused by: org.postgresql.util.PSQLException: Connection refused):

    • Symptom: Application starts, but fails when trying to connect to the database. Logs show connection refused errors.
    • Cause:
      • Incorrect RDS Endpoint/Credentials: Typo in JDBC_DATABASE_URL, JDBC_DATABASE_USERNAME, or JDBC_DATABASE_PASSWORD.
      • RDS Security Group: The RDS security group does not allow inbound traffic from the Elastic Beanstalk application’s security group.
      • VPC Mismatch: RDS and Elastic Beanstalk are in different VPCs or subnets that cannot communicate.
    • Solution:
      • Double-check all RDS connection details in Elastic Beanstalk environment variables.
      • Verify the RDS security group inbound rules explicitly allow traffic from your Elastic Beanstalk EC2 security group (not “Anywhere”).
      • Ensure both RDS and Elastic Beanstalk are within the same VPC.
    • Prevention: Always verify network connectivity and security group rules thoroughly. Use a database client (like DBeaver or psql) from your local machine (with your IP temporarily whitelisted in RDS SG) to ensure RDS is accessible with the provided credentials.
  3. Deployment Timeouts:

    • Symptom: Elastic Beanstalk deployment takes longer than expected and eventually fails with a timeout error.
    • Cause:
      • Large Application Size: The JAR file is excessively large, taking a long time to upload and unpack.
      • Application Startup Time: The Spring Boot application takes too long to start up within the configured timeout period.
      • Resource Constraints: The EC2 instance type chosen is too small, leading to slow startup or insufficient memory.
    • Solution:
      • Optimize your JAR size by removing unnecessary dependencies or resources.
      • Review application startup logs to identify bottlenecks. Optimize @PostConstruct methods or initial data loading.
      • Increase the EC2 instance size in Elastic Beanstalk configuration (e.g., from t2.micro to t2.medium).
      • Increase the deployment timeout in Elastic Beanstalk configuration (though this often masks underlying issues).
    • Prevention: Profile application startup time locally. Use appropriate instance sizes for deployment environments.

Testing & Verification

To ensure your cloud deployment is fully functional and robust:

  1. Access the Public URL: Open your browser and navigate to the Elastic Beanstalk environment URL (e.g., http://todo-list-app-env.us-east-1.elasticbeanstalk.com). While this might show a 404 for a REST API, you should verify it’s reachable.
  2. Test Health Endpoint: Access http://todo-list-app-env.us-east-1.elasticbeanstalk.com/actuator/health. Confirm the status is UP and db component also shows UP.
  3. Perform CRUD Operations:
    • Use Postman, Insomnia, or curl to send POST, GET, PUT, and DELETE requests to your To-Do List API endpoints.
    • Verify that new to-do items can be created, existing ones retrieved, updated, and deleted.
    • After creating items, restart the application (or even terminate and recreate the EC2 instance via Elastic Beanstalk) and verify that the data persists, confirming database connectivity.
  4. Check CloudWatch Logs: Navigate to AWS CloudWatch, then “Log groups”. Find the log group associated with your Elastic Beanstalk environment (e.g., /aws/elasticbeanstalk/todo-list-app-env/var/log/web.stdout.log). Review the application logs for any errors or warnings.
  5. Monitor Metrics: In the Elastic Beanstalk console, check the “Monitoring” tab for CPU utilization, network I/O, and other metrics to ensure the application is running smoothly.

Summary & Next Steps

Congratulations! You have successfully deployed your Java Spring Boot To-Do List application to AWS Elastic Beanstalk, backed by an AWS RDS PostgreSQL database. This is a monumental step, transitioning your local development project into a globally accessible, production-ready service. You’ve learned how to prepare your application for cloud environments, provision cloud resources, secure inter-service communication, and verify deployment.

While we focused on AWS Elastic Beanstalk, the core principles apply to other cloud providers like Azure. For instance, on Azure, you would typically use Azure App Service for deploying your Spring Boot JAR, and Azure Database for PostgreSQL as your managed database. The steps would involve creating an App Service instance, configuring environment variables for database connection strings, and setting up network security rules (e.g., VNet integration and network security groups) similar to AWS.

In the next chapter, we will delve deeper into enhancing our deployed application’s robustness and maintainability. We will explore advanced topics such as setting up a Continuous Integration/Continuous Deployment (CI/CD) pipeline to automate deployments, implementing more sophisticated monitoring and alerting, and potentially integrating a front-end application to consume our cloud-hosted API.