By Aditya, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud's incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.
With the increased adoption of digital technology, we see that same applications are typically available across different devices, notably on laptops, mobile phones, and TV. Most of the applications built or being built today are multi-tier. In a multi-tier application, you have clear distinctions of what each type can achieve. This makes sense from a business prospective as it significantly reduces costs. However, to cater to the different needs of the same data being available across different applications, we need to have a common place where we can access data with proper security rules.
From a developer's perspective, the increase need of data being replicated across different devices and the technology shift is happening very rapidly. We can't afford to take down the entire system just for a simple upgrade for a backend change. We should also be able to adapt to the newer technologies without much development effort. Taking all these conditions into account, we see that the REST framework gives us a clear abstraction between the other layers of how the data can be accessed across a different technology, such as mobile (Android and IOS) and web JavaScript Technologies.
Deploying a REST API onto an on-premises server is inefficient and time-consuming. Instead, we'll see how we can leverage Alibaba Cloud Elastic Compute Service to deploy our Java REST API and expose the service to internet. But before we even talk about deploying our API on to the cloud, we need to create one first. We will see how to create a Simple Jersey based Java REST API and test the API with selected tools.
Creating JAVA REST API
REST means "Representational State Transfer". REST was intended to create a decoupling between the server and the client, maintain reusable components, and can be replaced at any time. REST is stateless and you can implement cache on the server to improve performance and efficiency.
Now we will create a simple API which fetches the Employee Details & records the employee details.
Below are the complete tools I use for development.
- Eclipse IDE for JAVA EE Developers
- Latest Maven
- Apache Tomcat web server 7
- Insomnia REST Client
Setting Up the ECS Instance
Select Elastic Compute Instance from Products after logging into the Alibaba Cloud Console.
Create an Instance, preferably at the region closest to you. The following are the steps. For my server, I have selected the "Pay-as-you-go" model with the below configuration.
I will be using the Windows 2016 Data Center Image for my ECS instance. I have set the Networking, System Configurations, and other values to default. Click on Create Instance to continue.
Once the instance is created you will see something like this in your console.
Click on the ECS instance name and select security groups > configure rules > Add security group rules. Fill in the following information
Please note here that the 8080 is where my tomcat is deployed. You should change it to where your Apache Tomcat is actually deployed.
Connect the ECS Instance via RDP Protocol & we will do the further development using the windows VM Created.
Creating the API:
Download the latest "Eclipse IDE for JAVA EE Developers" and install.
- You need to install the latest version of JDK & set the installation path to "JAVA_HOME" & also to the "Path" environment variables
- You also need to install maven. It is so simple you need to download the latest binary distribution .zip and extract it & set the installation path to the "M2_HOME" & "Path" environment variables.
For the purpose of this article the code is provided as a zip file. Please download and import the project onto your eclipse workspace.
Download the Code Repository here: https://alicloud-common.oss-ap-southeast-1.aliyuncs.com/RESTCodeRepo.
You can import the code via "File > Import" and select "General" in the Dialog box.
Let’s see the imported code. You will see the below project structure in Eclipse.
We see the what included in the "pom.xml" the deployment descriptor for our complete project, holds the dependencies for our project.
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.aditya.restapi</groupId>
<artifactId>RESTfulExample</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>RESTfulExample Maven WebApplication</name>
<url>http://maven.apache.org</url>
<repositories>
<repository>
<id>maven2-repository.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
<layout>default</layout>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.8</version>
</dependency>
</dependencies>
<build>
<finalName>RESTfulExample</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Model-version : This is the version which the current pom complies to, to support maven 3 we make the version to 4.0.0
Artifact Id, packaging, groupID, version, name : These are used while packaging and to describe the project while deployment.
Repositories : This tag consists of all the repositories the dependencies to pull from. You can specify multiple repositories under this. Here we specified the central public repository for java
Dependencies : This tag consists of all the dependencies which are needed for the project. We used jersey related jars for our API and a JUNIT jar
Build: the build tag contains the complete information of how the application will be packaged into the WAR format, naming & which version of maven assembly plugin will be used for packaging
We need a model to hold the data we receive and send, we have created a Employee.java model which holds the name, age, salary, company.
package com.aditya.model;
public class Employee {
private String name;
private String age;
private int salary;
private String company;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
@Override
public String toString() {
return "Employee [name=" + name + ", age=" + age + ", salary=" + salary + ", company=" + company + "]";
}
}
This model consists of the getters, setters & toString() method for the getting, storing & display the information.
In the package "com.aditya.rest" for "JSONService.java" which has the complete code for REST API.
package com.aditya.rest;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.aditya.model.Employee;
@Path("/json/empservice")
public class JSONService {
@GET
@Path("/get")
@Produces(MediaType.APPLICATION_JSON)
public Employee getEmpDetails() {
Employee emp = new Employee();
emp.setName("Aditya");
emp.setCompany("ABC Corporation");
emp.setAge("31");
emp.setSalary(1000);
return emp;
}
@POST
@Path("/post")
@Consumes(MediaType.APPLICATION_JSON)
public Response createEmpInJSON(Employee emp) {
String result = "Employee saved : " + emp.toString();
return Response.status(201).entity(result).build();
}
}
We initially has the package declaration & we also notice that all the imports & annotations are imported from the Jersey jars.
The initial path maps the class with the map & methods are identified by @GET / @POST
@GET:
If we see the @GET is mapped to getEmpDetails() which returns an information of hardcoded data. The unmarshalling (JAVA Object to JSON) will happen automatically . This is one of the advantage of Jersey Servlet. We will see how.
@POST:
The @POST is mapped createEMPInJSON() which receives the marshalled Object from the request to Jersey Servlet to the emp object. The response is created with status 201 (Created) along with the result.
Web.xml
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Restful Web Application</display-name>
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.aditya.rest</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
This is the deployment descriptor of the API. The display-name is obvious as it consists of the name of the application. This consists of the servlet-name we use, servlet-class consists of the fully qualified name of the servlet.
We also created the param-name & param-value gives the features we needed for the web application.
com.sun.jersey.api.json.POJOMappingFeature gives the capability of mapping the JSON to the java object.
The servlet-mapping maps the servlet feature with a specific URL Pattern.
Apache Tomcat 7:
Download the Windows installer at the official link
http://www-us.apache.org/dist/tomcat/tomcat-7/v7.0.85/bin/apache-tomcat-7.0.85.exe
execute the Tomcat7.exe and point the folder where you want the tomcat 7 to be installed.
Deploying and Testing the API:
Right Click on the servers section, select "New > Server"
Select "Tomcat 7 Server" select "Next"
You select "Browse" and point to the tomcat installation folder & the server will be created.
Right click on the project select "Run as " > "Run on server". Once your API is deployed, you will see the following status
Install the Insomnia Client, and create a new request and use the following URI:
GET : http://localhost:8080/RESTfulExample/rest/json/empservice/get
POST : http://localhost:8080/RESTfulExample/rest/json/empservice/post
You will see the following response
You can also access the same API using the public IP of the ECS Instance, There will no change with the API URL if we change that, The resultant URL will be
GET – http://:8080/RESTfulExample/rest/json/empservice/get
POST – http://:8080/RESTfulExample/rest/json/empservice/post
Additional Steps:
1.In Production, you can reduce the cost by using the Version 1709 Windows server Image which only gives the console based access, But it cuts a lot of software on your ECS Instance increasing the performance.
2.You should also use server load balancer for the API of we are planning to scale it up using multiple ECS images.
3.You can better have authentication in place like OAuth for the API to prevent abuse and better security.
4.You can also consider using Alibaba Cloud DNS and Anti-DDOS Pro for better security features for your API.