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:
- Eclipse IDE. Click here to download
- Restlet jar file Click here to download
- MySQL database
- MySQL ODBC driver jar file. Click here to download
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 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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
Step 5.2: Second package com.myapp.server and create class EmployeeApplication.java within as shown below:
com/myapp/server/EmployeeApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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).
Good Article. Can you please share the code that will be helpful.
ReplyDelete