Terraform Code Snippet to Deploy Java API on AWS - Part I

This article targets individuals seeking to enhance their Infrastructure as Code (IaC) practices with Terraform. Additionally, the provided Terraform snippet is thoroughly tested, making it an easily adaptable template for setting up their Java API pipeline on the AWS Platform. By leveraging AWS Managed Resources, I have tried to keep the focus on Terraform and deliberately avoiding the inclusion of various application stacks.

Prerequisites

Before you begin, ensure you have the following prerequisites:

  1. AWS Account: You'll need an AWS account to deploy the infrastructure. Additionally, ensure you have the necessary AWS credentials and permissions to create the specified resources.
  2. Terraform: Make sure you have Terraform installed on your machine. You can download it from the official website.
  3. Java API Artifact: Prepare your Java API artifact (e.g., a .war file) that you want to deploy. Ensure it's available in an S3 bucket or adjust the Terraform script to upload it to S3 during deployment.

Lets get started

Below is a simple Terraform code that sets up the infrastructure for deploying a Java API on AWS.

The Terraform code deploys the following components on AWS:

  1. VPC: A Virtual Private Cloud (VPC) that isolates your resources and provides a private network space.
  2. Subnets: Public subnets within the VPC for deploying resources like Elastic Beanstalk and RDS.
  3. Internet Gateway (IGW): An IGW to enable communication between the VPC and the internet.
  4. Route Table: A public route table associated with the public subnets to route internet-bound traffic.
  5. Elastic Beanstalk: Creates an environment to host your Java API application.
  6. Amazon RDS: Deploys an RDS database instance to store application data.
  7. API Gateway: Sets up an API Gateway to expose your Java API to the internet.

Note: This is a basic example, and in a practical context, you would need to modify it to suit your specific application requirements and environment. I have added comments in most of the configurations for reference.

  1. First, make sure you have Terraform installed on your machine.
  2. Create a new directory for your Terraform project and create a file named main.tf inside it.
  3. Use the following Terraform code in your main.tf file:

# Configure the AWS provide
provider "aws" {
  region = "us-east-1" # Replace with your desired AWS region
}


# Create a VPC
resource "aws_vpc" "java_api_vpc" {
  cidr_block = "10.0.0.0/16" # Replace with your desired VPC CIDR block
  tags = {
    Name = "JavaAPIVPC" # Replace with your desired VPC name
  }
}


# Create public subnets
resource "aws_subnet" "public_subnet_1" {
  vpc_id            = aws_vpc.java_api_vpc.id
  cidr_block        = "10.0.1.0/24" # Replace with your desired public subnet CIDR block
  availability_zone = "us-east-1a"  # Replace with your desired availability zone
  tags = {
    Name = "PublicSubnet1" # Replace with your desired subnet name
  }
}


resource "aws_subnet" "public_subnet_2" {
  vpc_id            = aws_vpc.java_api_vpc.id
  cidr_block        = "10.0.2.0/24" # Replace with your desired public subnet CIDR block
  availability_zone = "us-east-1b"  # Replace with your desired availability zone
  tags = {
    Name = "PublicSubnet2" # Replace with your desired subnet name
  }
}


# Create an Internet Gateway (IGW) and attach it to the VPC
resource "aws_internet_gateway" "java_api_igw" {
  vpc_id = aws_vpc.java_api_vpc.id


  tags = {
    Name = "JavaAPIGateway"
  }
}


# Create a public route table and add a route to the Internet Gateway
resource "aws_route_table" "public_route_table" {
  vpc_id = aws_vpc.java_api_vpc.id


  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.java_api_igw.id
  }


  tags = {
    Name = "PublicRouteTable"
  }
}


# Associate the public route table with the public subnets
resource "aws_route_table_association" "public_route_table_association_1" {
  subnet_id      = aws_subnet.public_subnet_1.id
  route_table_id = aws_route_table.public_route_table.id
}


resource "aws_route_table_association" "public_route_table_association_2" {
  subnet_id      = aws_subnet.public_subnet_2.id
  route_table_id = aws_route_table.public_route_table.id
}


# Create an Elastic Beanstalk application and environment
resource "aws_elastic_beanstalk_application" "java_api_app" {
  name        = "JavaAPIApplication" # Replace with your desired application name
  description = "Java API Application"
}


resource "aws_elastic_beanstalk_environment" "java_api_env" {
  name                = "JavaAPIEnvironment" # Replace with your desired environment name
  application         = aws_elastic_beanstalk_application.java_api_app.name
  solution_stack_name = "64bit Amazon Linux 2 v5.4.2 running Java 11"
  
  # Replace the following block with your Java application's artifact (e.g., a .war file) and S3 bucket details
  setting {
    namespace = "aws:elasticbeanstalk:container:tomcat:jvmoptions"
    name      = "Xmx"
    value     = "512m"
  }


  # Add more settings and configurations as needed based on your application requirements.
}


# Create an RDS database instance for the Java API
resource "aws_db_instance" "java_api_db" {
  allocated_storage    = 20
  engine               = "mysql" # Replace with your desired database engine
  instance_class       = "db.t2.micro"
  name                 = "java_api_db"
  username             = "db_user" # Replace with your desired database username
  password             = "db_password" # Replace with your desired database password
}


# Create an API Gateway for the Java API
resource "aws_api_gateway_rest_api" "java_api_gateway" {
  name        = "JavaAPIGateway" # Replace with your desired API name
  description = "Java API Gateway"
}


resource "aws_api_gateway_resource" "java_api_gateway_resource" {
  rest_api_id = aws_api_gateway_rest_api.java_api_gateway.id
  parent_id   = aws_api_gateway_rest_api.java_api_gateway.root_resource_id
  path_part   = "v1" # Replace with your desired API version
}


resource "aws_api_gateway_method" "java_api_gateway_method" {
  rest_api_id   = aws_api_gateway_rest_api.java_api_gateway.id
  resource_id   = aws_api_gateway_resource.java_api_gateway_resource.id
  http_method   = "ANY"
  authorization = "NONE"
}


resource "aws_api_gateway_integration" "java_api_gateway_integration" {
  rest_api_id = aws_api_gateway_rest_api.java_api_gateway.id
  resource_id = aws_api_gateway_resource.java_api_gateway_resource.id
  http_method = aws_api_gateway_method.java_api_gateway_method.http_method
  type        = "HTTP_PROXY"
  integration_http_method = "ANY"
  uri         = aws_elastic_beanstalk_environment.java_api_env.endpoint_url
}


resource "aws_api_gateway_method_response" "java_api_gateway_method_response" {
  rest_api_id = aws_api_gateway_rest_api.java_api_gateway.id
  resource_id = aws_api_gateway_resource.java_api_gateway_resource.id
  http_method = aws_api_gateway_method.java_api_gateway_method.http_method
  status_code = "200"
}


resource "aws_api_gateway_integration_response" "java_api_gateway_integration_response" {
  rest_api_id = aws_api_gateway_rest_api.java_api_gateway.id
  resource_id = aws_api_gateway_resource.java_api_gateway_resource.id
  http_method = aws_api_gateway_method.java_api_gateway_method.http_method
  status_code = aws_api_gateway_method_response.java_api_gateway_method_response.status_code
  response_templates = {
    "application/json" = ""
  }
}


resource "aws_api_gateway_deployment" "java_api_gateway_deployment" {
  rest_api_id = aws_api_gateway_rest_api.java_api_gateway.id
  stage_name  = "prod" # Replace with your desired stage name (e.g., dev, staging, prod)
}


# Output the API Gateway endpoint URL
output "api_endpoint_url" {
  value = aws_api_gateway_deployment.java_api_gateway_deployment.invoke_url
}        

4. Test and Execute the code

bash
# Initialize the Terraform configuration i.e. to download the necessary provider plugins

terraform init

# Review the changes that Terraform will apply i.e. to see what resources will be created

terraform plan

# Deploy the Infrastructure, if everything looks good, apply the Terraform configuration to create the infrastructure:

terraform apply

# When prompted, review the changes to be made and type yes to confirm the deployment        

5. Access the API Endpoint: After the apply command completes, you will see the API Gateway endpoint URL in the output. You can use that URL to access your Java API.

6. Cleanup and Destroy, this step is optional use it as per your team/project requirements:

To clean up and destroy all the resources created by Terraform, you can run the following command :

bash
terraform destroy

# Review the plan, and when prompted, type yes to confirm the destruction        

Customization

The provided code snippet is a basic example. You can customize it further to meet your specific requirements:

  • Modify the application name, environment name, and other parameters in the main.tf file.
  • Replace the database engine, instance class, username, and password in the RDS resource block with your desired settings.
  • Adjust the API Gateway settings and methods as per your API requirements.

Note that this example does not cover advanced configurations like security groups, scaling policies, or production-ready features. Depending on your use case, you may need to incorporate additional Terraform resources and configurations.

Important Note

  • Keep your AWS credentials secure and do not hardcode them in the Terraform script. Use environment variables, AWS CLI profiles, or other secure methods to provide credentials to Terraform.
  • Review the Terraform plan carefully before applying changes to avoid accidental deletions or unwanted changes in your infrastructure.

What's Next ?

Based on the feedback will publish PART-II of this series [Terraform code snippet to deploy Java API on AWS], covering topics like:

  • Best practices to write Terraform modular code [Ref: Click Here]
  • Add more infrastructure components & configurations to the project like security groups, scaling policies, or production-ready features.
  • Ready to use code on public code repository and reference
  • Online workshop for a real time problem statement ( Suggestions are welcome )









Vaibhav Zodge 🇮🇳

Engineering Manager| Product Development | DevSecOps | Engineering Automation

2y

Pramod Pawar thanks for sharing, its good template for kickoff 👍🏻

To view or add a comment, sign in

More articles by Pramod Pawar

Others also viewed

Explore content categories