Monday, January 26, 2015
Java/J2EE Blog: Little Bit of REST
Java/J2EE Blog: Little Bit of REST: Before we write our first RESTful web service lets have a brief introduction of web service and how they are different from web applicati...
Little Bit of REST
Before we write our first RESTful web service lets have a brief introduction of web service and how they are different from web application. Both web application and web services are accessed over the web or the internet. So, what is the basic difference. Well a web application is supposed to be consumed by human over the web whereas a web service is supposed to be consumed by another application or software component over the web. So a web service is a piece of code exposed over the web to be consumed by another piece of software code over the web or the internet. This piece of code that is exposed over the web is called service which is consumed by the consumer or the client which again is an another software component.
When a web service client makes a request to a web service endpoint, they are usually messages transmitted from one machine to another. These messages need to be in a format, a language, that both the client and the server can understand. This language, or protocol, is standardized in some web service types. For example, SOAP web services is a type of web services, where the protocol always has to follow the standard called SOAP. All SOAP web services uses this protocol to communicate with clients. It used to stand for Simple Object Access Protocol. But that name is now discontinued and we are stuck with just the acronym. There is a specific format, which is XML, and there are specific rules which detail how that XML should be. The client and the server needs to talk to each other using this SOAP protocol only!
So, what is the protocol used by REST. Well the answer is none. A REST client can send and receive messages in any format like XML,JSON, HTML, Text etc. There are no rules as long as the client and server understand each other. REST or Representational state transfer is actually an architecture style. The term REST was coined by Roy Fielding who is one of the principal authors of HTTP specification. That is the reason the ideas behind REST makes good use of HTTP specification. REST web services exposes data using the HTTP methods like GET(to read the data),POST(to create the data),PUT(to update the data),DELETE(to delete the data) and any restful resource is exposed to the outside world via a URI on the web.
JAX-RS or Java API for Restful Web Services is a new API that aims to make development of RESTful web services in Java simple and intuitive. Ok, so enough of the background about web services. In this blog i will be using Jackson which is the implementation of JAX-RS API to write RESTful web services. I will also use Gson which is a google API to convert JSON to Java objects and vice versa. My sample appolication will use Hibernate as the ORM tool and Spring core just for dependency injection. This sample application will read/write data from the users table and expose methods perfrom CRUD operation on this table.
This is how my folder structure looks like:-
And below are the JARs that will be required:-
Inside the model package i have the User class, its a simple pojo with gettters/setters. Below is the code:-
package com.sanjiv.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.hibernate.annotations.FetchProfile;
@Entity
@Table(name="USERS")
//@JsonAutoDetect
//@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Users {
@Id
@Column(name="USER_ID")
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="userid_seq")
@SequenceGenerator(name="userid_seq",sequenceName="userid_sequence",allocationSize=1)
private int userID;
@Column(name="USER_NAME")
private String userName;
@Column(name="EMAIL_ID")
private String emailID;
public Users(){}
public Users(String userName, String emailID, int userID) {
this.userName = userName;
this.userID = userID;
this.emailID = emailID;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getUserID() {
return userID;
}
public void setUserID(int userID) {
this.userID = userID;
}
public String getEmailID() {
return emailID;
}
public void setEmailID(String emailID) {
this.emailID = emailID;
}
@Override
public String toString() {
return new StringBuffer(" User Name : ").append(this.userName)
.append(" Email Id : ").append(this.emailID)
.append(" User ID : ")
.append(this.userID).toString();
}
}
Inside the dao package i have a UserDaoInterface and UserDao implementation class which is responsible for database related stuff using Hibernate as ORM. Below is the code for interface
package com.sanjiv.dao;
import java.util.List;
import com.sanjiv.model.Users;
public interface UserDaoInterface {
public List<Users> getUsers();
public Users getUserById(int userid);
public void deleteUsers();
public void deleteUserById(int userid);
public void addUser(Users user);
void updateUser(Users user);
}
Implementation class:-
package com.sanjiv.dao;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.sanjiv.model.Users;
public class UserDao implements UserDaoInterface {
SessionFactory sessionFactory;
public UserDao(){
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public UserDao(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
public List<Users> getUsers() {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
List<Users> usersList = session.createQuery("from Users").list();
tx.commit();
return usersList;
}
public Users getUserById(int userid) {
Users user = null;
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
user = (Users) session.get(Users.class, userid);
tx.commit();
return user;
}
public void addUser(Users user) {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
}
@Override
public void deleteUsers() {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("Delete from Users");
int result = query.executeUpdate();
tx.commit();
}
@Override
public void deleteUserById(int userid) {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("Delete from Users where userID= :ID");
query.setParameter("ID", userid);
int result = query.executeUpdate();
tx.commit();
}
@Override
public void updateUser(Users user) {
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
session.saveOrUpdate(user);
tx.commit();
}
}
Our REST resource does not call the methods directly on the dao, instead its users service class UserService which is inside the service package. Below is the complete code:-
package com.sanjiv.service;
import java.util.ArrayList;
import java.util.List;
import com.sanjiv.dao.UserDao;
import com.sanjiv.model.Users;
public class UserService {
UserDao userDao;
public UserService(){
}
public UserDao getUserDao() {
return userDao;
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public UserService(UserDao userDao){
this.userDao = userDao;
}
public void addUser(Users user){
userDao.addUser(user);
}
public Users getUserById(int userid){
Users user = userDao.getUserById(userid);
return user;
}
public List<Users> getUsers(){
List<Users> userList = new ArrayList<Users>();
userList = userDao.getUsers();
return userList;
}
public void deleteUser(int userid){
userDao.deleteUserById(userid);
}
public void deleteUsers(){
userDao.deleteUsers();
}
public void updateUser(Users user){
userDao.updateUser(user);
}
}
Next is Hibernate.cfg.xml :-
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<!-- session-factory name=""> -->
<session-factory>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:devDB</property>
<property name="hibernate.connection.username">system</property>
<property name="hibernate.connection.password">admin123</property>
<property name="hibernate.connection.pool_size">1</property>
<property name="show_sql">true</property>
<property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
<property name="hibernate.current_session_context_class">thread</property>
<!-- property name="mappingDirectoryLocations">classpath:WEB-INF/classes/hibernate</property-->
<!-- Mapping classes -->
<mapping class="com.sanjiv.model.Users"/>
</session-factory>
</hibernate-configuration>
And spring.xml-
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<bean id="userDao" class="com.sanjiv.dao.UserDao">
<property name="sessionFactory" ref="hibernate3SessionFactory" />
</bean>
<bean id="userService" class="com.sanjiv.service.UserService">
<property name="userDao" ref="userDao" />
</bean>
<!-- Hibernate3 XML SessionFactory Bean definition-->
<bean id="hibernate3SessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation">
<value>hibernate.cfg.xml</value>
</property>
</bean>
</beans>
Now its to write our first REST web service which in my case is a UserResource class:-
package com.sanjiv.restws;
import java.util.ArrayList;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import weblogic.application.ApplicationContext;
import com.sanjiv.dao.UserDao;
import com.sanjiv.model.Users;
import com.sanjiv.service.UserService;
import com.sanjiv.utility.ConnectionHelper;
import com.sanjiv.utility.HibernateUtility;
import com.sun.jersey.json.impl.provider.entity.JSONArrayProvider;
@Path("/v1")
public class UserResource implements UserResourceInterface{
/* UsersService userService = new UsersService(new UsersDao
(HibernateUtility.buildSessionFactory()));*/
@Context
private UriInfo uriInfo;
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userService = (UserService) context.getBean("userService");
@GET
@Path("/users")
@Produces(MediaType.APPLICATION_JSON)
public List<Users> getUsers() {
List<Users> usersList = new ArrayList<Users>();
usersList = userService.getUsers();
return usersList;
}
@GET
@Path("/users/{userid}")
@Produces(MediaType.APPLICATION_JSON)
public Users getUser(@PathParam("userid") int userid) {
Users user = userService.getUserById(userid);
return user;
}
@DELETE
@Path("/users/delete/{userid}")
public Response deleteUser(@PathParam("userid")int userid){
userService.deleteUser(userid);
return Response.ok().build();
}
@DELETE
@Path("/users/delete")
public Response deleteUsers(){
userService.deleteUsers();
return Response.ok().build();
}
/*@POST
@Consumes("application/json")
@Path("/users/{username}-{emailid}")
public Response saveUser(@PathParam("username") String userName,@PathParam("emailid") String emailID){
Users user = new Users();
user.setEmailID(emailID);
user.setUserName(userName);
userService.addUser(user);
return Response.ok().build();
}*/
@POST
@Path("/users")
@Consumes(MediaType.APPLICATION_JSON)
public String saveUser(Users user){
userService.addUser(user);
return Response.ok().build().toString();
}
@PUT
public Response updateUser(Users user){
userService.updateUser(user);
return Response.ok().build();
}
}
Now we will write our client which will call the methods on if the weservice. The code for client is inside client package. Below is the complete code:-
package com.sanjiv.restclient;
import javax.ws.rs.core.MediaType;
import com.google.gson.Gson;
import com.sanjiv.model.Users;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.api.json.JSONConfiguration;
public class RestJersyClient {
/**
* @param args
*/
public static void main(String[] args) {
final String ENDPOINT_URL = "http://localhost:7001/UsersRestWS/rest/v1/users/";
httpPost(ENDPOINT_URL);
//httpGet(ENDPOINT_URL,5);
//httpGet(ENDPOINT_URL,);
//httpDelete(ENDPOINT_URL);
}
private static void httpDelete(String endpointURL, int userid) {
endpointURL = endpointURL + "delete/" +userid;
System.out.println(endpointURL);
httpDelete(endpointURL);
}
private static void httpGet(String endpointURL, int userid) {
endpointURL = endpointURL +userid;
System.out.println(endpointURL);
httpGet(endpointURL);
}
private static void httpGet(String endpointURL){
try {
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(
JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
WebResource webResource = client
.resource(endpointURL);
ClientResponse response = webResource.type(MediaType.APPLICATION_JSON).get(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
String output = response.getEntity(String.class);
System.out.println("Server response .... \n");
System.out.println(output);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void httpPost(String endpointURL){
try {
Users user = new Users();
user.setUserName("Sanjiv Dutta");
user.setEmailID("duttamca@gmail.com");
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(
JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
WebResource webResource = client
.resource(endpointURL);
String request = new Gson().toJson(user);
System.out.println(request);
ClientResponse response = webResource.type(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, request);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
String output = response.getEntity(String.class);
System.out.println("Server response .... \n");
System.out.println(output);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void httpDelete(String endpointURL){
endpointURL = endpointURL + "delete/";
System.out.println(endpointURL);
try {
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(
JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
WebResource webResource = client
.resource(endpointURL);
ClientResponse response = webResource.type(MediaType.APPLICATION_JSON).delete(ClientResponse.class);
if (response.getStatus() != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
String output = response.getEntity(String.class);
System.out.println("Server response .... \n");
System.out.println(output);
} catch (Exception e) {
e.printStackTrace();
}
}
}
This was just the very basic of REST web service. Thank for reading.
Subscribe to:
Posts (Atom)

