Automate deployment of Java Spring Boot apps to AWS Elastic Beanstalk

Fullstack Developer and Tech Author

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:
- A GitHub account
- A CircleCI account
- An AWS account
- AWS Elastic Beanstalk CLI installed on your computer
- Apache Maven installed on your system.
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.
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 needsElasticLoadBalancingFullAccess
: 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.
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.
Next, go to Environment properties and add a new one named SERVER_PORT
. Set the value to 5000.
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
.
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 adeploy
key to be present and pointing to the JAR file generated during the build process. Finally, the changes are deployed to thespring-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
.
Next, select the aws-credentials
context.
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 theglobal
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.
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.
Your first workflow will start running and complete 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.
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.