Skip to content

Java Spring Boot REST API, JPA, Native SQL Queries, MySQL, Apache Tomcat, AWS EC2, AWS Beanstalk, JWT, STS

Notifications You must be signed in to change notification settings

seanmayer/java-restful-refresher

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Java Spring Framework Refresher

Quick refresher on Java Spring Framework with REST Webservices.

Spring Framework

Spring Framework is a Java platform that provides comprehensive infrastructure support for developing Java applications. Spring handles the infrastructure so you can focus on your application.

Start up

  1. Prefered IDE: VSCode
  2. VSCode extensions:
  • Spring Boot Dashboard
  • Spring Boot Extension Pack
  • Spring Boot Tools
  • Spring Initializer Java Support
  • Test Runner for Java
  • Maven for Java -> if Mac -> xcode-select --install -> brew install maven
  • Debugger for Java
  • Extension Pack for Java
  • Java prettier formatter
  • XML
  1. Start webservices: ./mvnw spring-boot:run or VSCode UI

Running Web Services App

  1. Build your project with mvn install command
  2. Upload the deployable .jar file to a production server
  3. Run application with java -jar command

Running Webservices without Security Token Service (STS)

  1. Navigate to /mobile-app-ws directroy folder
  2. Run ./mvnw install this will compile, build the project and unit tests
  3. Run ./mvnw spring-boot:run this will run the RESTful webservices application in a apache tomcat server container

Running Application as a Java App (with an Apache tomcat container)

  1. Run ./mvnw install` this will compile, build the project and unit tests (create jar in target)
  2. cd /mobile-app-ws/target
  3. cp mobile-app-ws-0.0.1-SNAPSHOT.jar /Users/{user-name}/Desktop
  4. Navigate to desktop where the jar has been copied
  5. java -jar mobile-app-ws-0.0.1-SNAPSHOT.jar

Running Application as a War file (on an existing Apache tomcat container [Mac])

  1. Update pom.xml ->
<packaging>war</packaging>
  1. ./mvnw clean clears out target folder
  2. ./mvnw install creates the war package in /target
  3. Install tomcat zip from http://tomcat.apache.org (with the appropriate corrosponding java version)
  4. Unzip on to desktop
  5. Switch directories to cd /Desktop/apache-tomcat-9.0.65/bin/
  6. Elevate permissions to make script files executable chmod a+x *.sh
  7. Run ./startup.sh
  8. Navigate to http://localhost:8080 (tomat is running!)
  9. Run ./shutdown.sh
  10. Create Tomcat user for deployments
  11. Switch directoires to cd /Desktop/apach-tomcat-9.0.65/conf
  12. Open tomcat-users.xml
  13. Add
<role rolename="manager-gui"/>
<user username="admin" password="admin" roles="manager-gui"/>
  1. Go to maven project directory where the war package has been created /mobile-app-ws/target/
  2. Rename mobile-app-ws-0.0.1-SNAPSHOT.war -> mobile-app-ws.war
  3. Deploy war on tomcat 'WAR file to deploy': Screenshot
  4. Webservices are deployed :)

Deploying to Amazon Cloud EC2

Create EC2 Linux Instance

  1. Login to https://aws.amazon.com/
  2. Navigate to EC2 Dashboard
  3. Select availability zone Screenshot
  4. Select 'Launch instance'
  5. Configuration settings:
  • Name and tags: 'DemoAPIServer'
  • App and OS Images: Amazon Linux (Free tier)
  • Instance type: t2.micro (Free tier)
  • Key pair (login): Create private key for login
  • Storage (volumes): 8GB (Free tier)
  • Network settings: SSH, HTTP, HTTPS, Custom TCP port 8080
  • Advanced settings: Shutdown behaviour: Stop
  1. Launch the instance

Connect to EC2 via SSH

  1. Navigate to EC2 Running containers
  2. Get Public IPv4 DNS name to start SSH the connection
  3. SSH into AWS instance:
  • sudo su (if required)
  • chmod 400 myprivatekey.cer (if required)
  • ssh -i myprivatekey.cer ec2-user@{DNS-name}

Update EC2 and install Java

  1. Install updates: sudo yum update
  2. Check Java version: sudo java -version
  3. Check all Java packages available: sudo yum list java
  4. Install Java: sudo yum install java-1.8.0
  5. Switch Java version:
  • sudo /usr/sbin/alternatives --config java
  • sudo /usr/sbin/alternatives --config javac

Download and install Tomcat

  1. Go to https://tomcat.apache.org/ select the version and get the url link for the tar.gz file type
  2. Download tomcat with the link extracted (example):sudo wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.65/bin/apache-tomcat-9.0.65.tar.gz
  3. Check file is there: ls
  4. Extract files: sudo tar xvf apache-tomcat-9.0.65.tar.gz -C /usr/share
  5. Check its extracted: ls -lrt /usr/share
  6. Rename tomact directory: sudo ln -s /usr/share/apache-tomcat-9.0.65 /usr/share/tomcat9
  7. ls -lrt /usr/share is now: tomcat9 -> /usr/share/apache-tomcat-9.0.65 :)

Configure remote access to Manager app

  1. Create a new tomcat group:
  • sudo groupadd --system tomcat
  • sudo useradd -d /usr/share/tomcat9 -r -s /bin/false -g tomcat tomcat
  • sudo chown -R tomcat:tomcat /usr/share/apache-tomcat-9.0.65 (set tomcat folder permissions for this new user)
  1. Make tomcat start on reboot (will need to create a service file)
  • sudo vi /etc/systemd/system/tomcat9.service
  • Copy and paste these setting into this file:
[Unit]
Description=Tomcat Server
After=syslog.target network.target

[Service]
Type=forking
User=tomcat
Group=tomcat

Environment=JAVA_HOME=/usr/lib/jvm/jre
Environment='JAVA_OPTS=-Djava.awt.headless=true'
Environment=CATALINA_HOME=/usr/share/tomcat9
Environment=CATALINA_BASE=/usr/share/tomcat9
Environment=CATALINA_PID=/usr/share/tomcat9/temp/tomcat.pid
Environment='CATALINA_OPTS=-Xms512M -Xmx1024M'
ExecStart=/usr/share/tomcat9/bin/catalina.sh start
ExecStop=/usr/share/tomcat9/bin/catalina.sh stop

[Install]
WantedBy=multi-user.target

  • sudo systemctl daemon-reload
  1. Start tomcat
  • sudo systemctl enable tomcat9
  • sudo systemctl start tomcat9 (to stop sudo systemctl stop tomcat9)
  1. Navigate to tomcat URL
  • {AWS Public IPv4 DNS}.com:8080
  1. sudo vi /usr/share/tomcat9/webapps/manager/META-INF/context.xml
  • Comment out line (key i -> INSERT to edit):
  <!--  <Valve className="org.apache.catalina.valves.RemoteAddrValve"
  allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /> -->
  • esc + :wq to save changes
  • sudo systemctl restart tomcat9

Configure Tomcat users

  1. sudo vi /usr/share/tomcat9/conf/tomcat-users.xml
  • (Copy and paste from the tomcat 401 page) (key i -> INSERT to edit):
<role rolename="manager-gui"/>
<user username="tomcat" password="s3cret" roles="manager-gui"/>
  • esc + :wq to save changes
  1. sudo systemctl restart tomcat9

Install MySQL

  1. sudo yum install https://dev.mysql.com/get/mysql80-community-release-el7-6.noarch.rpm
  2. sudo amazon-linux-extras install epel -y
  3. sudo yum install mysql-community-server
  • Optional: Navigate to /etc/yum.repos.d/mysql-community.repo and disable gpg if you trust repos
gpgcheck=0
  1. sudo systemctl enable --now mysqld
  2. systemctl status mysqld
  3. sudo grep 'temporary password' /var/log/mysqld.log
  4. sudo mysql_secure_installation
  • Set new password
  • Remove anonymous users? - Yes
  • Disallow root login remotely? - Yes
  • Remove test Database? - Yes
  • Reload privilege tables now? - Yes
  1. mysql -u root -p
  • Login

Create database and add user

  1. Sign into user root: mysql -u root -p
  2. create database photo_app;
  3. show databases;
  4. create user '{my username here}'@'localhost' identified by '{my password here}';
  5. grant all privileges on photo_app.* to '{my username here}'@'localhost';
  6. Make changes to take affect: flush privileges;
  7. exit
  8. mysql -u {my username here} -p;
  9. show databases;

Deploy webservices on tomcat

  1. Navigate to maven webservices project: e.g.cd mobile-app-ws
  2. ./mvnw install
  3. Go to cd mobile-app-ws/target/mobile-app-ws-0.0.1-SNAPSHOT.war
  • Rename it if needed
  1. Navigate to tomcat URL
  • {AWS Public IPv4 DNS}.com:8080
  • Login if needed
  • Navigate to tomcat web application manager
  1. Deploy .war file to "War file to deploy

Deploy with AWS Elastic Beanstalk

Introduction

One of the fastest and simplest ways of deploying spring boot applications. You simply upload your application and your application will automatically handle your capacity provisioning, load balancing, auto-scaling and application health monitoring.

So you could use your application in a production environment within just a few minutes, without any infrastrucutre or resource configuration work yourself.

Elastic beanstalk is:

  • Easy to use service
  • Deploying applications
  • Scaling applications

As depicted below, you will get an EC2 instance started and configured auotmatically, additionally to that you wll get an autoscaling, so if need your EC2 instance, this can scale up and handle more traffic.

draw.io

To load balance the incoming traffic, Elastic Load Balancer is created and configured for you automatically, the incoming HTTP traffic will be equally balanced between the running EC2 instances.

Amazon RDS can be used here to, Amazon RDS is a relational database and this supports many different types of relational databases, for this demo I will be using MySQL again. Also by using Amazon RDS, you will also get autoscaling included here too, you do not need to aquire specialist or develop additional skills here, Amazon RDS will do it for you! :)

So as our spring boot application scales up and down it will work with MySQL server that will use Amazon RDS service. By deploying your application with Beanstalk and running your database in Amazon RDS, you access capabilities of production ready environment in just a few minutes! No need to manually configure infrastructure, and no need for installing and maintaining database software, you get this all provided by Amazon.

Amazon RDS - Creating MySQL Database

  1. Login to AWS and search for RDS
  2. Select databases -> create database
  3. Database configuration: (Free tier configuration/none production)
  • Engine type: MySQL
  • Edition: MySQL Community
  • Templates: Free Tier! :)
  • DB instance identifier: photoappuserapi
  • Credentials Settings: set username and password
  • Instance configuration: Burstable classes (includes t classes) (db.t3.micro)
  • Storage settings: (keep as they are)
  • Connectivity:
    • Public Access: true
    • VPC: Default
    • DB Subnet Group: Default
    • Database port: 3306
  1. Database Authentication: Password authentication
  2. Initial Databse name: photoappusers_db
  3. Backups: disable
  4. Encryption: disable

Security Group Configuration

  1. Select database instance in AWS and select inbound rules
  2. Select AWS/Aurora TCP - default at port 3306 draw.io

Configure App to use MySQL RDS

  1. In the applicaiton.properties in the main maven project - update appropriately:
server.error.whitelabel.enabled=false
spring.datasource.username={username}
spring.datasource.password={password}
spring.datasource.url=jdbc:mysql://{rds-endpoint-address.amazonaws.com}:3306/{database name configuration}
spring.jpa.hibernate.ddl-auto=update
tokenSecret=tokenSecret
server.error.include-stacktrace=never
server.servlet.context-path=/mobile-app-ws
  1. Run ./mvnw package (Take the compiled code and package it in its distributable format, such as a JAR or WAR)

Deploying WAR to AWS Elastic Beanstalk

  1. In AWS search for Elastic Beanstalk, once navigates select:
  • Create Application
  1. Then configure/create web app
  • Application name: PhotoAppUsersApi
  • Platform: Tomcat
  • Application code: "Upload your code"
  • Source code origin: "local file" -> upload file -> mobile-app-ws-0.0.1-SNAPSHOT.war
  • Stat application (The rest of the configuration can be skipped for this)
  1. Elastic Beanstalk App has been deployed :)

Testing AWS Elastic Beanstalk Webservice App

  1. Open Postman
  2. Test the sign up http://{{aws-beanstalk-instance-name}}/users
  • Headers:

    • Content-Type: application/json
    • Accept: application/json
  • Body:

{
				"firstName":"Joe",
				"lastName":"Bloggs",
				"email":"[email protected]",
				"password":"AmazingPassword"
}

Spring Security

Adding Spring Security to a project

  1. Update Pom.xml
  •    <dependency>
      	<groupId>org.springframework.boot</groupId>
      	<artifactId>spring-boot-starter-security</artifactId>
      </dependency> 
    
  1. Run Project and use generate security password
  2. Navigate to localhost:8080/login Screenshot

Adding Expression-Based Access Control to endpoints with Roles and Authorities

https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

When to enable CORS?

Cross Origin Resource Scripting - is only required when we need to allow different domain names or other origins (this include port numbers, comm protocols) to access our API, this is disabed by default in Springboot.

Example below of the cross origin annoation, this can be applied on the controller request methods or the entire class itself:

@CrossOrigin(origins = "*") @CrossOrigin(origins = "http://localhost:8080","http://localhost:8081")

Verification Service Process

Sequence Diagram

Setting up Amazon Simple Email Service (SES)

  1. Navigate to Amazon Simple Email Service:

Amazon Simple Email Service

  1. Ensure that you have selected the region you want to target these emails (please note that the sender/source domain will need to be verified with AWS)

  2. Select Create Identity:

Create Identity

  1. From here you will then be able to add your email address you want to use for sending emails out, this will then need to be verified in your inbox.

Create Identity

Setting up Amazon Notification Email Service (SNS)

  1. Navigate to Amazon Notification Service:

Amazon Notification Email Service

  1. Create topic, with name "bounces":

Create Topic

  1. Set topic to default configurations:

Topic Config

  1. Topic has now been created, and now is viewable on the dashboard:

Topic Created

  1. Repeat this process again but this time make a topic for "complain":

Complain Created

  1. Navigate to Subscriptions:

Navigate to Subscriptions

  1. Configure subscription for "bounces" to the email address you want:

Configure subscriptions

  1. Confirm subscription via the email you set, received in the inbox

Configure subscriptions

  1. Repeat this process again for complain

  2. Navigate back to SNS and select configurations for the email address you set on feedback notifications:

SNS configuration

  1. Configure SNS configuration on feedback notifications to the email that has been set both for bounces and complain:

SNS configuration

  1. After setting this, you should get confirmation in your inbox that this it is set.

Raising a support ticket for SES limit increase

  1. Navigate to support center to create a ticket

Support Center

  1. Raise a support ticket with a service limit increase
  • Limit Type: SES Sending Limits
  • New limit value: 100
  • Region: {region you are using}

Create AWS IAM Access Credentials

  1. Naviate to security credentials by select username top right corner:

Navigate Security Credentials

  1. Once in the console select users and create new user

Add IAM User

  1. User configuration
  • user name: {username}
  • access type: programmatic access
  • set permission group: {create permission group -> name it: SES-SERVICE-USERS select AmazonSESFullAccess -> create group}
  • Once completed make note of "Access key ID" and "Secret access key" (only available once!)

Create a shared credentials file

Used for access details and authenticate with AWS.

  1. Create a new file containing this, and paste the following lines you have just create in prior steps:
[default]
aws_access_key_id = YOUR_AWS_ACCESS_KEY_ID
aws_secret_access_key = YOUR_AWS_SECRET_ACCESS_KEY
  1. Save the file (do not use a file extension when saving the file):

If Linux/Mac OS: ~/.aws/credentials

If Windows: C:\Users\USERNAME\.aws\credentials

Run Tomcat and add Spring Security Token Service (STS)

  1. Create war package from https://github.com/seanmayer/verification-service -> mvn clean -> mvn install

  2. Deploy the .war to your local tomcat server

  3. Open brower and check: http://localhost:8080/verification-service/email-verification.html

  4. Create war package from https://github.com/seanmayer/java-restful-refresher -> mvn clean -> mvn install

  • Please note if you get an error on deployment that is: Deploy Upload Failed, Exception: [org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException please got to web.xml of the manager application (for instance it could be under /tomcat9/webapps/manager/WEB-INF/web.xml. Increase the max-file-size and max-request-size
  1. Run Sign up in the local postman collection /postman/REST Refresher.postman_collection.json

  2. Open MySQL workbench and preview the users table, find the new user you have created and copy the email-verification_token field.

  3. With the token apply this to the token param in Sign up verification in the local postman collection /postman/REST Refresher.postman_collection.json and then run it

  4. Repeat step 5 and 6. But this time go to your browser to verify this token with verfication webpage instead:http://localhost:8080/verification-service/email-verification.html?token={you-copied-token}

Run Tomcat and add Spring Security Token Service (STS) on AWS

  1. Removed dependency dotenv package was breaking the .war file:
<dependency>
	<groupId>io.github.cdimascio</groupId>
	<artifactId>dotenv-java</artifactId>
	<version>2.2.4</version>
</dependency>
  1. Add aws variables to AmazonSES.java in this repo, and email-verification.html in https://github.com/seanmayer/verification-service

  2. Maven clean and install both repos and deploy the .war(s) to your AWS/tomcat instance

  3. Now you should be able to run the signup in postman with the SES email address, this will then sign up the user in the RDS database and send a verification link, once the link is navigated it will verify the email address and update the database entry that the email is verified :)

Reset Password Service

Screenshot

H2 In-Memory Database Set up

  1. For setup, please reference commit id: https://github.com/seanmayer/java-restful-refresher/commit/5de8ce0ad5bb5f77638e8740cacc4f780a4a628c (and post commits after)

  2. Run project

  3. Navigate to http://localhost:8888/mobile-app-ws/h2-console/ a) you can change h2 path in application.properties file spring.h2.console.path=/h2-console\

  4. H2 console supports a number of relational databases that you can connect to besides H2

  5. Using the application.properties file configuration you should be able to use the connection details defined in there to connect to H2 database: Screenshot

REST Assured Integration Tests

Run JUnit tests here: https://github.com/seanmayer/mobile-app-ws-rest-assured-test

Further Integration tests using native queries and JPQL queries in /src/test/java/com/appsdeveloperblog/app/ws/io/repositories

Swagger

API Documentation.

References:

JSON: http://localhost:8080/mobile-app-ws/v2/api-docs

Browser docs: http://localhost:8080/mobile-app-ws/swagger-ui.html

You can also share your API/docs to: https://swagger.io/tools/swaggerhub/

That is all, I hope you found this guide helpful :)