Last Updated May 8, 202511 min read

Automate deployment of Java Spring Boot apps to AWS Elastic Beanstalk

Olususi Oluyemi

Fullstack Developer and Tech Author

Developer A sits at a desk working on an intermediate-level project.

The benefits of automating deployments for your Java Spring Boot application are undeniable. Automation makes it possible to set up images and run tests or compatibility checks before updating the production environment. CI/CD providers like CircleCI take things a step further by streamlining the entire delivery process from code changes to deployment.

Your team may assume that the specifics of their development stack or deployment process will make automation difficult to achieve. In this article, I will show you how to easily implement a CI/CD pipeline for a Spring Boot application running on AWS Elastic Beanstalk. You’ll make use of the Elastic Beanstalk orb to simplify and accelerate project setup so you can start shipping new features right away.

Prerequisites

In addition to a basic understanding of Java and Spring Boot, you will need the following to get the most from this tutorial:

Cloning the demo project

To demonstrate how to automate deployments for your Spring Boot applications with CI/CD, you’ll be using a basic sample project, an exchange rate API with three endpoints:

S/N Endpoint Method Function
1. /currency GET Get all currencies supported by the API
2. /rates GET Get all the exchange rates for all the supported currencies
3. /rates/{currency} GET Get the exchange rates for a single currency

You can clone the sample project by running the following command.

git clone https://github.com/CIRCLECI-GWP/spring-exchange-api-eb.git

Next, go to the root of the new folder created by the previous command (spring-exchange-api-eb)

cd spring-exchange-api-eb

Now, issue the following command to build and run the project:

mvn -B -DskipTests clean package

mvn spring-boot:run

The mvn -B -DskipTests clean package command will clear the target directory if existed, builds the project and skip test during the build. Finally, the mvn spring-boot:run command will run the project on the default port.

By default, your application will be served to port 8080. Navigate to http://127.0.0.1:8080/rates in order to view the JSON response.

2022-12-03-running-app-locally

Add user with programmatic access

To successfully deploy your application to AWS, you need to create a user with the appropriate credentials and required permissions for deployment. Head to the AWS Add User page. Select a username and AWS access type as shown in the screenshot below.

025-04-08-specify-IAM-user.png{: .zoomable }

Select Provide user access to the AWS management console option. This will give you access to your Beanstalk environment via the CLI. Then select the option to create an IAM user and either generate or create a new password for them.

On the next page, select permissions for the user. Click Next > Attach existing policies directly. Search and select these policies:

  • AdministratorAccess-AWSElasticBeanstalk: This grants the user an administrative permissions and allows them to gain direct access to resources they need to manage AWS Elastic Beanstalk applications.
  • AmazonS3FullAccess: This provides full access to all buckets via the AWS Management Console. It is important to include this policy because Elastic Beanstalk CLI will need to upload your source code file to Amazon S3 using multipart upload, especially if the size is greater than 7mb.
  • AmazonEC2FullAccess: This provides access to the AWS Elastic Beanstalk to spin up EC2 instances for the required computing needs
  • ElasticLoadBalancingFullAccess: This provides access to the Amazon Elastic Beanstalk to scale the environment based on user traffic to your application

Click Next to create the new user after a reeview.

You will be greeted with a success message along with your user credentials. This page is only displayed once, so make a note of the Access Key ID and the Secret access key, which you will need later on. Alternatively, you can download the provided .csv file, which contains the same credentials. The folowing are the user details that the user should have and also their permissions.

AWS credentials

After the user has been created you will need to navigate to IAM in aws console, select user and generate both their access key and secret access key. Copy and store these values as you will need them.

Next, you need to configure the AWS CLI credentials to use the details of the newly created user. Run this command:

aws configure

Note: You can simply run this command or a new terminal tab or from the root directory of your project. It doesn’t really matter where.

You will be prompted to enter the AWS Access Key ID and AWS Secret Access Key, that you generated for your java-user. Press Enter when you are done. You can use these credentials to authenticate awsebcli and continue with the deployment process.

Initializing the Elastic Beanstalk environment

Initialize your Elastic Beanstalk CLI repository by issuing the following command from the root of your project.

eb init -p corretto-17 exchangeRatesApi

The p tag specifies the platform you want your Beanstalk to run on. In our case, we will use Amazon Corretto 17, a no-cost, multiplatform, production-ready distribution of the Open Java Development Kit (OpenJDK).

A successful execution results in this output.

Application exchangeRatesApi has been created.

If you are yet to provide an access-id and secret-key for awsebcli, you may get this error message:

ERROR: The current user does not have the correct permissions. Reason: Operation Denied. The security token included in the request is invalid.
ERROR: The current user does not have the correct permissions. Reason: Operation Denied. The security token included in the request is invalid.
You have not yet set up your credentials or your credentials are incorrect
• You must provide your credentials.

Provide a valid aws-access-id and aws-secret-key to complete the set-up process. If you don’t have one already, you can follow these steps:

Create a new environment by running:

eb create spring-env

You output will be similar to this:

Creating application version archive "app-4517-221213_155152698834".
Uploading exchangeRatesApi/app-4517-221213_155152698834.zip to S3. This may take a while.
Upload Complete.
Environment details for: spring-env
  Application name: exchangeRatesApi
  Region: us-west-2
  Deployed Version: app-4517-221213_155152698834
  Environment ID: e-jzwrpunr2n
  Platform: arn:aws:elasticbeanstalk:us-west-2::platform/Corretto 17 running on 64bit Amazon Linux 2/3.4.1
  Tier: WebServer-Standard-1.0
  CNAME: UNKNOWN
  Updated: 2022-12-13 15:51:58.735000+00:00

This creates an Elastic Beanstalk environment named spring-env, which takes about 5 minutes. Once the process is completed, you can find the domain for the new environment by running:

eb status

The output:

Environment details for: spring-env
  Application name: exchangeRatesApi
  Region: us-west-2
  Deployed Version: app-4517-221213_155152698834
  Environment ID: e-jzwrpunr2n
  Platform: arn:aws:elasticbeanstalk:us-west-2::platform/Corretto 17 running on 64bit Amazon Linux 2/3.4.1
  Tier: WebServer-Standard-1.0
  CNAME: spring-env.eba-28m5wkuj.us-west-2.elasticbeanstalk.com
  Updated: 2022-12-13 15:55:04.289000+00:00
  Status: Ready
  Health: Red

At this point, the health status of the spring-env environment will be RED.

Deploying the application to Elastic Beanstalk

Next, you need to specify an artifact in your Beanstalk configuration. This will be the JAR file that is generated when the project is built. Open the .elasticbeanstalk/config.yml file, and add this:

deploy:
  artifact: target/exchangeRates-0.0.1-SNAPSHOT.jar

After you append the previous snippet, your .elasticbeanstalk/config.yml file should contain:

branch-defaults:
  main:
    environment: spring-env
    group_suffix: null
global:
  application_name: exchangeRatesApi
  branch: null
  default_ec2_keyname: null
  default_platform: Corretto 17
  default_region: us-west-2
  include_git_submodules: true
  instance_profile: null
  platform_name: null
  platform_version: null
  profile: null
  repository: null
  sc: git
  workspace_type: Application
deploy:
  artifact: target/exchangeRates-0.0.1-SNAPSHOT.jar

Next, deploy the changes. Because you are using Git for version control, commit your changes first before running eb deploy.

git add .
git commit -m "Add EBS config"
eb deploy

Once this process is completed, run the eb status command again. This time, the health status should be GREEN. Paste the CNAME property into your browser to review your API.

Although the health status turns GREEN, if you run the eb status command after a minute, you will notice the status has turned YELLOW. Also, if you visit the CNAME on your browser, you will get a 502 error. This does not mean that there is a problem with the deployment or the application. Instead, the port configured in the application is not the default port assigned by Elastic Beanstalk. You will need to configure the port manually, as described in the next section.

Setting the port configuration

By default, Spring Boot applications run on port 8080. However, Elastic Beanstalk applications listen on port 5000. As a result, opening the application in your browser will display a 502 error. To fix this, you can add a SERVER_PORT environment variable to your beanstalk.

Go to the Configuration section of your environment and edit the Software options.

2022-12-03-setting-aws-configuration-on-aws

Next, go to Environment properties and add a new one named SERVER_PORT. Set the value to 5000.

Add environment properties

Click Apply to persist the changes and trigger an update process for your environment. You will be able to review the rates for your application by visiting the CNAME/rates.

Application updates

Set up a CI/CD pipeline on CircleCI

With CircleCI, you can automate all the processes required to build and deploy your Spring Boot application to Elastic Beanstalk. The pipeline would initially build the Maven application and then deploy it on Elastic Beanstalk, whenever a new commit is made to the repository.

At the root of the project, locate the folder named .circleci. In this folder, modify the content of the config.yml file as shown here:

version: 2.1

orbs:
  eb: circleci/aws-elastic-beanstalk@2.0.1

jobs:
  build-and-test:
    description: "Setup Spring boot application and run tests"
    docker:
      - image: cimg/openjdk:19.0.1
    steps:
      - checkout
      - run:
          name: Build
          command: mvn -B -DskipTests clean package
      - persist_to_workspace:
          root: .
          paths:
            - .

      - run:
          name: Test
          command: mvn test

  deploy:
    docker:
      - image: "cimg/base:stable"
    description: "Deploying updates to Elastic Beanstalk"
    steps:
      - attach_workspace:
          at: .
      - eb/setup
      - run:
          command: |
            eb init exchangeRatesApi -r $AWS_DEFAULT_REGION -p corretto-17
            echo "deploy:
                    artifact: target/exchangeRates-0.0.1-SNAPSHOT.jar" >> .elasticbeanstalk/config.yml
            eb deploy spring-env

workflows:
  build-and-deploy:
    jobs:
      - build-and-test
      - deploy:
          requires:
            - build-and-test
          context: aws-credentials

This configuration makes use of the eb orb to set up the application environment during the build and deploy the changes to the environment you created earlier.

In addition to the orbs declaration, two jobs are declared:

  • The build-and-test job checks out the latest code from the repository, builds the project, and runs the tests. Because the package and JAR file generated during the build process is required in the deployment phase, the files are persisted to the workspace, making them available for the subsequent jobs.

  • The deploy job attaches the persisted workspace to the build before setting up the Elastic Beanstalk CLI. Next, you will add a set of commands. The first instantiates your environment in the CLI. The second updates the Beanstalk config to match your use case - one which requires a deploy key to be present and pointing to the JAR file generated during the build process. Finally, the changes are deployed to the spring-env environment.

In the workflow, after running the build-and-test job, the deploy job deploys the changes. In addition to the requires key, which ensures that the build-and-test job runs first, the application name, environment name, and platform version are specified for the job. A context named aws-credentials is passed to the job. You will populate this context with the necessary credentials in a moment.

To test your changes, add a new rate to the application. Update the expectedCurrencies array in src/test/java/com/example/exchangeRates/ExchangeRatesApplicationTests.java to match this:

final String[] expectedCurrencies = {"EUR", "GBP", "NGN", "USD", "YEN", "CFA"};

In the same way, update the supportedCurrencies array in src/main/java/com/example/exchangeRates/service/ExchangeRatesService.java:

final String[] supportedCurrencies = {"EUR", "GBP", "NGN", "USD", "YEN", "CFA"};

Next, commit and push the changes to your GitHub repository. Review Pushing a project to GitHubfor instructions.

Add AWS credentials to your pipeline

In your CircleCI dashboard, click the link in the sidebar to go to the Organization Settings page. Select Contexts and click the Create Context button. Add a unique name for your Context. The Context appears in a list with security set to All members. This indicates that anyone in your organization can access the Context at runtime. As specified in the .circleci/config.yml configuration for this tutorial, the Context name should be aws-credentials.

2022-12-03-adding-aws-context

Next, select the aws-credentials context.

2022-12-03-adding-aws-credentials

Click the Add Environment Variable button and enter the variable name and value you want. Click the Add Variable button to save it. The aws-credentials context requires these three environment variables:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • The AWS_DEFAULT_REGION variable. The value of this is specified in the .elasticbeanstalk/config.yml file in the project, under the global section.

Deploy your Spring Boot app to AWS with CircleCI

In this section, you will link the project to CircleCI and trigger your first automated deployment. Log into your CircleCI account. If you signed up with your GitHub account, all your repositories will be available on your project’s dashboard.

2022-12-03-connecting-application-to-circleci

Click Set Up Project next to your spring-exchange-api-eb project.

You will be prompted to either write a new configuration file or use the one in your project. Select the existing one and enter the name of the branch where your code is. Click Set Up Project.

2022-12-03-project-setup-to-circleci

Your first workflow will start running and complete successfully.

2022-12-03-pipeline-ran-successfully

To confirm that your workflow was successful, you can open your newly deployed app in your browser using the CNAME property with a /rates URL suffix.

2022-12-03-project-deployed-successfully

Now, on every change to your project repository, CircleCI will automatically run your workflow and deploy a new version of your application to Elastic Beanstalk. For a more robust CI/CD pipeline, consider adding tests to your Spring Boot app to validate your changes before deploying.

Conclusion

In this tutorial, you learned how to set up a CI/CD pipeline for a Spring Boot API using GitHub, CircleCI, and AWS Elastic Beanstalk. You have also learned that it is possible to implement best practices for automated deployments of software updates for Spring Boot projects. You can add custom commands in your pipeline configuration to cater to peculiarities in your deployment process while taking advantage of the preset builds made available by your CI/CD provider.

With this knowledge, you can confidently automate the deployment of your Spring Boot applications, ensuring a streamlined and efficient software development and release process. If you haven’t already, sign up for your free CircleCI account and get 6,000 monthly build minutes to try it yourself.


Oluyemi is a tech enthusiast with a background in Telecommunication Engineering. With a keen interest in solving day-to-day problems encountered by users, he ventured into programming and has since directed his problem solving skills at building software for both web and mobile. A full stack software engineer with a passion for sharing knowledge, Oluyemi has published a good number of technical articles and blog posts on several blogs around the world. Being tech savvy, his hobbies include trying out new programming languages and frameworks.

Copy to clipboard