Sunday, 25 October 2015

Simple REST service that provides CRUD operations to clients using java Restlet API



This tutorial demonstrates how to create a REST service application in Eclipse IDE using the java Restlet API and the database as MYSQL.
This is an example that includes creating a RESTful service which allows clients to use any REST client and CRUD (create, retirieve, update or delete) employee details stored in a MYSQL database. The HTTP methods GET (retrieve), PUT(create), DELETE(delete),POST(update) are supported for this service. The response for all methods would be XML (DOMRepresentation).

Before we start with the application we need the following:

Step 1: Create a database called 'employeedb' using the MySQL workbench and create a table called 'employeeDetails' (which will store the employee ID, first and last names, telephone numbers of employees) and insert some data into the tables.

EmployeeDetails table





Step 2: Create a Java project in Eclipse.


Step 3: Provide a name for your project and click on ‘Finish’


Step 4: Add the following jars (which are present in the downloaded restlet-x.x -> lib -> required folder)  and also the downloaded mysql odbc jar file to the project by right clicking on the project name followed by Properties ->Java Build Path -> Libraries -> Add External jars


  • org.restlet.jar
  • org.restlet.ext.xml.jar
  • mysql-connector-java.xxxx.jar


Step 5: Create 4 packages as follows:


Step 5.1: First package com.myapp.object and create class Employee.java within as shown below:

com/myapp/object/Employee.java
package com.myapp.object;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class Employee {
int empID;
String firstName;
String lastName;
String telNo;
public Employee() {
}
public Employee(int empID, String firstName, String lastName, String telNo) {
super();
this.empID = empID;
this.firstName = firstName;
this.lastName = lastName;
this.telNo = telNo;
}
/**
* @return the empID
*/
public int getEmpID() {
return empID;
}
/**
* @param empID the empID to set
*/
public void setEmpID(int empID) {
this.empID = empID;
}
/**
* @return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* @param firstName the firstName to set
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
/**
* @return the lastName
*/
public String getLastName() {
return lastName;
}
/**
* @param lastName the lastName to set
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}
/**
* @return the telNo
*/
public String getTelNo() {
return telNo;
}
/**
* @param telNo the telNo to set
*/
public void setTelNo(String telNo) {
this.telNo = telNo;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Employee [empID=" + empID + ", firstName=" + firstName
+ ", lastName=" + lastName + ", telNo=" + telNo + "]";
}
public Document toXML() throws ParserConfigurationException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document doc = docBuilder.newDocument();
Element empElement = doc.createElement("employee");
Element empIDElement = doc.createElement("EmployeeID");
empIDElement.setTextContent(String.valueOf(empID));
empElement.appendChild(empIDElement);
Element empFirstNameElement = doc.createElement("FirstName");
empFirstNameElement.setTextContent(firstName);
empElement.appendChild(empFirstNameElement);
Element empLastNameElement = doc.createElement("LastName");
empLastNameElement.setTextContent(lastName);
empElement.appendChild(empLastNameElement);
Element empTelNoElement = doc.createElement("TelNo");
empTelNoElement.setTextContent(telNo);
empElement.appendChild(empTelNoElement);
doc.appendChild(empElement);
return doc;
}
}
view raw Employee.java hosted with ❤ by GitHub



Step 5.2: Second package com.myapp.server and create class EmployeeApplication.java within as shown below:

com/myapp/server/EmployeeApplication.java
package com.myapp.server;
import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Restlet;
import org.restlet.data.Protocol;
import org.restlet.routing.Router;
import com.myapp.server.resource.EmployeeResource;
public class EmployeeApplication extends Application {
public static void runServer(int port) throws Exception {
Component component = new Component();
component.getServers().add(Protocol.HTTP, port);
component.getClients().add(Protocol.FILE);
Application application = new EmployeeApplication();
String contextRoot = "/employeeResource";
component.getDefaultHost().attach(contextRoot, application);
component.start();
}
public Restlet createInboundRoot() {
Router router = new Router(getContext());
router.attach("/getEmployee/{empID}", EmployeeResource.class);
router.attach("/deleteEmployee/{empID}", EmployeeResource.class);
router.attach("/putEmployee/{empID},{firstName},{lastName},{telNo}", EmployeeResource.class);
router.attach("/updateEmployee/{empID},{firstName},{lastName},{telNo}", EmployeeResource.class);
return router;
}
public static void main(String args[]) throws Exception {
runServer(8112);
}
}



Step 5.3: Third package com.myapp.server.dao and create class EmployeeDAO.java within as shown below:

com/myapp/server/dao/EmployeeDAO.java
package com.myapp.server.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import com.myapp.object.Employee;
public class EmployeeDAO {
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost/employeedb";
// Database credentials
static final String USER = "root";
static final String PASS = "";
public int addEmployee(Employee emp) {
Connection conn = null;
Statement stmt = null;
int result =0;
try{
//STEP 2: Register JDBC driver
Class.forName("com.mysql.jdbc.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
//STEP 4: Execute a query
System.out.println("Creating statement...");
stmt = conn.createStatement();
String sql = "INSERT INTO employeeDetails (empID,firstName,lastName,telNo) VALUES ("+emp.getEmpID()+",'"+emp.getFirstName()+"','"+emp.getLastName()+"','"+emp.getTelNo()+"')";
System.out.println("Executing insert statement "+sql);
result = stmt.executeUpdate(sql);
stmt.close();
conn.close();
}catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
}catch(Exception e){
//Handle errors for Class.forName
e.printStackTrace();
}finally{
//finally block used to close resources
try{
if(stmt!=null)
stmt.close();
}catch(SQLException se2){
}// nothing we can do
try{
if(conn!=null)
conn.close();
}catch(SQLException se){
se.printStackTrace();
}//end finally try
}//end try
return result;
}
public Employee getEmployee(int empID) {
Connection conn = null;
Statement stmt = null;
Employee e = null;
try{
//STEP 2: Register JDBC driver
Class.forName("com.mysql.jdbc.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
//STEP 4: Execute a query
System.out.println("Creating statement...");
stmt = conn.createStatement();
String sql = "SELECT * FROM employeeDetails where empID = "+empID;
ResultSet rs = stmt.executeQuery(sql);
//STEP 5: Extract data from result set
while(rs.next()){
//Retrieve by column name
e = new Employee();
e.setEmpID(rs.getInt("empID"));
e.setFirstName(rs.getString("firstName"));
e.setLastName(rs.getString("lastName"));
e.setTelNo(rs.getString("telNo"));
System.out.println("The return employee "+e);
}
rs.close();
stmt.close();
conn.close();
}catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
}catch(Exception ex){
//Handle errors for Class.forName
ex.printStackTrace();
}finally{
//finally block used to close resources
try{
if(stmt!=null)
stmt.close();
}catch(SQLException se2){
}// nothing we can do
try{
if(conn!=null)
conn.close();
}catch(SQLException se){
se.printStackTrace();
}//end finally try
}//end try
return e;
}
public int deleteEmployee(int empId) {
Connection conn = null;
Statement stmt = null;
int result =0;
try{
//STEP 2: Register JDBC driver
Class.forName("com.mysql.jdbc.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
//STEP 4: Execute a query
System.out.println("Creating statement...");
stmt = conn.createStatement();
String sql = "DELETE FROM employeeDetails where empID = "+empId;
System.out.println("Executing delete statement "+sql);
result = stmt.executeUpdate(sql);
stmt.close();
conn.close();
}catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
}catch(Exception e){
//Handle errors for Class.forName
e.printStackTrace();
}finally{
//finally block used to close resources
try{
if(stmt!=null)
stmt.close();
}catch(SQLException se2){
}// nothing we can do
try{
if(conn!=null)
conn.close();
}catch(SQLException se){
se.printStackTrace();
}//end finally try
}//end try
return result;
}
public int updateEmployee(Employee emp) {
Connection conn = null;
Statement stmt = null;
int result =0;
try{
//STEP 2: Register JDBC driver
Class.forName("com.mysql.jdbc.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
//STEP 4: Execute a query
System.out.println("Creating statement...");
stmt = conn.createStatement();
String sql = "Update employeeDetails set firstName = '"+emp.getFirstName()+"', lastName = '"+emp.getLastName()+"'"
+ ", telNo='"+emp.getTelNo()+"' where empID = "+emp.getEmpID();
System.out.println("Executing update statement "+sql);
result = stmt.executeUpdate(sql);
stmt.close();
conn.close();
}catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
}catch(Exception e){
//Handle errors for Class.forName
e.printStackTrace();
}finally{
//finally block used to close resources
try{
if(stmt!=null)
stmt.close();
}catch(SQLException se2){
}// nothing we can do
try{
if(conn!=null)
conn.close();
}catch(SQLException se){
se.printStackTrace();
}//end finally try
}//end try
return result;
}
}



Step 5.4: Fourth package com.myapp.server.resource and create class EmployeeResource.java within as shown below:

com/myapp/server/resource/EmployeeResource.java
package com.myapp.server.resource;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.restlet.ext.xml.DomRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.Delete;
import org.restlet.resource.Get;
import org.restlet.resource.Post;
import org.restlet.resource.Put;
import org.restlet.resource.ServerResource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.myapp.object.Employee;
import com.myapp.server.dao.EmployeeDAO;
public class EmployeeResource extends ServerResource {
EmployeeDAO empDAO = new EmployeeDAO();
@Get
public Representation getEmployeeDetails() throws IOException,
ParserConfigurationException {
DomRepresentation result = new DomRepresentation();
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document resultDoc = docBuilder.newDocument();
String empID = (String) getRequestAttributes().get("empID");
Employee emp = empDAO.getEmployee(Integer.parseInt(empID));
if (emp == null)
result.setDocument(resultDoc);
else
result.setDocument(emp.toXML());
return result;
}
@Put
public Representation addEmployee() throws IOException, ParserConfigurationException {
String empID = (String) getRequestAttributes().get("empID");
String firstName = (String) getRequestAttributes().get("firstName");
String lastName = (String) getRequestAttributes().get("lastName");
String telNo = (String) getRequestAttributes().get("telNo");
Employee e = new Employee(Integer.parseInt(empID), firstName, lastName, telNo);
DomRepresentation result = new DomRepresentation();
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document resultDoc = docBuilder.newDocument();
Element resultDocElement = resultDoc.createElement("result");
int res = empDAO.addEmployee(e);
if(res==1)
resultDocElement.setTextContent("Successfully added");
else
resultDocElement.setTextContent("Failed");
resultDoc.appendChild(resultDocElement);
result.setDocument(resultDoc);
return result;
}
@Delete
public Representation deleteEmployee() throws IOException, ParserConfigurationException {
String empID = (String) getRequestAttributes().get("empID");
DomRepresentation result = new DomRepresentation();
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document resultDoc = docBuilder.newDocument();
Element resultDocElement = resultDoc.createElement("result");
int res = empDAO.deleteEmployee(Integer.parseInt(empID));
if(res==1)
resultDocElement.setTextContent("Successfully deleted");
else
resultDocElement.setTextContent("Failed");
resultDoc.appendChild(resultDocElement);
result.setDocument(resultDoc);
return result;
}
@Post
public Representation updateEmployee() throws IOException, ParserConfigurationException {
String empID = (String) getRequestAttributes().get("empID");
String firstName = (String) getRequestAttributes().get("firstName");
String lastName = (String) getRequestAttributes().get("lastName");
String telNo = (String) getRequestAttributes().get("telNo");
Employee e = new Employee(Integer.parseInt(empID), firstName, lastName, telNo);
DomRepresentation result = new DomRepresentation();
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
// root elements
Document resultDoc = docBuilder.newDocument();
Element resultDocElement = resultDoc.createElement("result");
int res = empDAO.updateEmployee(e);
if(res==1)
resultDocElement.setTextContent("Successfully updated");
else
resultDocElement.setTextContent("Failed");
resultDoc.appendChild(resultDocElement);
result.setDocument(resultDoc);
return result;
}
}


Step 6: The final directory structure would look as follows:



Step 7: Start the REST service.

Run the EmployeeApplication.java (it contains the main method)

Step 8: Using the REST service. 
Any REST client can be used (Firefox REST Client has been used in this example)

Step 8.1: GET Resource

Method:GET, URI:http://localhost:8112/employeeResource/getEmployee/1



Step 8.2: PUT (create/add)Resource

Method:PUT, URI:http://localhost:8112/employeeResource/putEmployee/4,scooby,doo,324234




Step 8.3: POST (update)Resource

Method:POST, URI:http://localhost:8112/employeeResource/updateEmployee/3,fred,flintstone,33234



Step 8.4: DELETE (delete)Resource

Method:DELETE, URI:http://localhost:8112/employeeResource/deleteEmployee/3





Notes:
  • The EmployeeDAO would vary depending on the database or the way server accesses the data and must be updated with the appropriate login credentials.
  • The REST service (step 4 completion) can be started on any port. In this example port 8112 has been used. The details of the port or the URL's to be allowed for various resources are given in com/myapp/server/EmployeeApplication.java.
  • The Restlet version used in this sample is 2.3.5
  • The response for all methods in com/myapp/server/resource/EmployeeResource.java is a Representation. DomRepresentation is being used in this example as XML is usually the standard response and is easy to parse. However, any subclass of  org.restlet.representation.Representation can be used(http://restlet.com/technical-resources/restlet-framework/javadocs/2.1/jse/api/org/restlet/representation/Representation.html).





    1 comment:

    1. Good Article. Can you please share the code that will be helpful.

      ReplyDelete