CRUD operations with JAX-RS and JAXB
CRUD
stands for Create,Read,Update and Delete operation
These are the most common operations that we perform in any application.
Let’s do these operations using Rest service with Jersey.
Requirement :
Perform CRUD operations on USER object.
We have User Domain object, we can insert User data, read the inserted data,
Update some user information and finally delete the user data.
Create a new Maven Web project in eclipse (Refer Rest service Hello World project for the same)
Step 1
Update pom.xml with below dependencies
- <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>RestServiceWithJerseyAndJAXB</groupId>
- <artifactId>RestServiceWithJerseyAndJAXB</artifactId>
- <packaging>war</packaging>
- <version>0.0.1-SNAPSHOT</version>
- <name>RestServiceWithJerseyAndJAXB Maven Webapp</name>
- <url>http://maven.apache.org</url>
- <dependencies>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>3.8.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.glassfish.jersey.containers</groupId>
- <artifactId>jersey-container-servlet</artifactId>
- <version>2.24</version>
- </dependency>
- <dependency>
- <groupId>javax.xml</groupId>
- <artifactId>jaxb-api</artifactId>
- <version>2.1</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- <version>2.5</version>
- </dependency>
- </dependencies>
- <build>
- <finalName>RestServiceWithJerseyAndJAXB</finalName>
- </build>
- </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>RestServiceWithJerseyAndJAXB</groupId> <artifactId>RestServiceWithJerseyAndJAXB</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>RestServiceWithJerseyAndJAXB Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>2.24</version> </dependency> <dependency> <groupId>javax.xml</groupId> <artifactId>jaxb-api</artifactId> <version>2.1</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> </dependency> </dependencies> <build> <finalName>RestServiceWithJerseyAndJAXB</finalName> </build> </project>
We have added dependencies for Jersey servlet,Jaxb,servelt api and Junit in the above pom file.
Step 2
Update web.xml file with Jersey servlet container
we have defined a special servlet called “jersey-serlvet” in web.xml and mapped it by the URL pattern /rest/*
So just like any other servlet in web application,any request matching with the given pattern i.e /rest/* will be redirected to “Jersey servelt”.
- <!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
- <web-app>
- <display-name>Archetype Created Web Application</display-name>
- <servlet>
- <servlet-name>jersey-serlvet</servlet-name>
- <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
- <init-param>
- <param-name>jersey.config.server.provider.packages</param-name>
- <param-value>com.kb.rest.resource</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>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>jersey-serlvet</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>com.kb.rest.resource</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>
We have also provided the package of java classes(to be qualified as Rest services) under init-param tag.
This package will be considered by Jersey servlet container to identify the actual service when the request comes in.
Step 3
Create a domain class which represents the data with JAXB
We will perform CRUD operations on this object.
- package com.kb.model;
- import java.util.Date;
- import javax.xml.bind.annotation.XmlElement;
- import javax.xml.bind.annotation.XmlRootElement;
- @XmlRootElement(name="User")
- public class User {
- private String id;
- private String name;
- private int age;
- public String getId() {
- return id;
- }
- @XmlElement
- public void setId(String id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- @XmlElement
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- @XmlElement
- public void setAge(int age) {
- this.age = age;
- }
- }
package com.kb.model; import java.util.Date; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(name="User") public class User { private String id; private String name; private int age; public String getId() { return id; } @XmlElement public void setId(String id) { this.id = id; } public String getName() { return name; } @XmlElement public void setName(String name) { this.name = name; } public int getAge() { return age; } @XmlElement public void setAge(int age) { this.age = age; } }
We have created a User class with id,name and age to represent the data
@XmlRootElement – specifies the root tag of each user record in xml.
@XmlElement – specifies the child element for each attribute of User record.
Step 4
Create the resource mapping class which will have the URL mapping methods
- package com.kb.rest.resource;
- 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.MediaType;
- import com.kb.model.User;
- import com.kb.service.UserService;
- @Path("/userInfo")
- public class UserResource {
- UserService userService = new UserService();
- // CRUD -- CREATE operation
- @POST
- @Produces(MediaType.TEXT_XML)
- @Consumes(MediaType.APPLICATION_XML)
- public User createUser(User user) {
- User userResponse = userService.createUser(user);
- return userResponse;
- }
- // CRUD -- READ operation
- @GET
- @Produces(MediaType.APPLICATION_XML)
- public List<User> getAllUsers() {
- List<User> userList = userService.getAllUsers();
- return userList;
- }
- // CRUD -- READ operation based on id
- @GET
- @Path("/{id}")
- @Produces(MediaType.APPLICATION_XML)
- public User getUserForId(@PathParam("id") String id) {
- User user = userService.getUserForId(id);
- return user;
- }
- // CRUD -- UPDATE operation
- @PUT
- @Produces(MediaType.TEXT_XML)
- @Consumes(MediaType.APPLICATION_XML)
- public User updateUser(User user) {
- User userResponse = userService.updateUser(user);
- return userResponse;
- }
- // CRUD -- DELETE operation
- @DELETE
- @Path("/{id}")
- @Produces(MediaType.TEXT_XML)
- public User deleteeUser(@PathParam("id") String id) {
- User userResponse = userService.deleteUser(id);
- return userResponse;
- }
- }
package com.kb.rest.resource; 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.MediaType; import com.kb.model.User; import com.kb.service.UserService; @Path("/userInfo") public class UserResource { UserService userService = new UserService(); // CRUD -- CREATE operation @POST @Produces(MediaType.TEXT_XML) @Consumes(MediaType.APPLICATION_XML) public User createUser(User user) { User userResponse = userService.createUser(user); return userResponse; } // CRUD -- READ operation @GET @Produces(MediaType.APPLICATION_XML) public List<User> getAllUsers() { List<User> userList = userService.getAllUsers(); return userList; } // CRUD -- READ operation based on id @GET @Path("/{id}") @Produces(MediaType.APPLICATION_XML) public User getUserForId(@PathParam("id") String id) { User user = userService.getUserForId(id); return user; } // CRUD -- UPDATE operation @PUT @Produces(MediaType.TEXT_XML) @Consumes(MediaType.APPLICATION_XML) public User updateUser(User user) { User userResponse = userService.updateUser(user); return userResponse; } // CRUD -- DELETE operation @DELETE @Path("/{id}") @Produces(MediaType.TEXT_XML) public User deleteeUser(@PathParam("id") String id) { User userResponse = userService.deleteUser(id); return userResponse; } }
We have created the Rest service class above which will handle GET,POST,PUT and DELETE operations
@Path(“/userInfo”)
This annotation helps to map the request URL to the appropriate Rest service.
So any request with /userInfo (relative to the base URL) will be mapped to UserResource.
@POST
This annotation specifies that only POST requests will be accepted by this method.
@GET
This annotation specifies that only GET requests will be accepted by this method
@PUT
This annotation specifies that only PUT requests will be accepted by this method
@DELETE
This annotation specifies that only DELETE requests will be accepted by this method.
@Path(“/{id}”)
This annotation is used to specify that URL will contain input value to match exactly.
Example: /rest/userInfo/1
Above URL will be mapped to a particular method in UserResource class which is annotated with @Path(“/{id}”
Note:
If we use flower bracket {} with @Path, it is called Path variable which is also a part of URL but it can considered as a parameter along with the actual URL.
@Produces(MediaType.APPLICATION_XML)
This annotation is used to specify the representation of a data (MIME type) that the service can produce and send it to client.
This annotation can be used either at the class level or at the method level.
If this annotation is applied at the class level,all the methods in the class can produce the same MIME type data by default.
However we can override this at the method level with different MIME type.
We can also specify multiple MIME types as below@Produces({“application/xml”, “application/json”})
@Consumes(MediaType.APPLICATION_XML)
This annotation is used to specify the representation of a data (MIME type) that the service can accept from the client.
This annotation can be used either at the class level or at the method level.
If this annotation is applied at the class level,all the methods in the class will accept the same MIME type data from client by default.
However we can override this at the method level with different MIME type.
We can also specify multiple MIME types as below@Consumes({“application/xml”, “application/json”})
Note:
We should Use application/xml for the xml to be processed by programs and we should use text/xml if we are using xml for human reading purposes.
Step 5
Create the business service class
- package com.kb.service;
- import java.util.List;
- import com.kb.dao.UserDAO;
- import com.kb.model.User;
- public class UserService {
- UserDAO userDao = new UserDAO();
- public List<User> getAllUsers() {
- List<User> userList = userDao.getAllUsers();
- return userList;
- }
- public User getUserForId(String id) {
- User user = userDao.getUserForId(id);
- return user;
- }
- public User createUser(User user) {
- User userResponse = userDao.createUser(user);
- return userResponse;
- }
- public User updateUser(User user) {
- User userResponse = userDao.updateUser(user);
- return userResponse;
- }
- public User deleteUser(String id) {
- User userResponse = userDao.deleteUser(id);
- return userResponse;
- }
- }
package com.kb.service; import java.util.List; import com.kb.dao.UserDAO; import com.kb.model.User; public class UserService { UserDAO userDao = new UserDAO(); public List<User> getAllUsers() { List<User> userList = userDao.getAllUsers(); return userList; } public User getUserForId(String id) { User user = userDao.getUserForId(id); return user; } public User createUser(User user) { User userResponse = userDao.createUser(user); return userResponse; } public User updateUser(User user) { User userResponse = userDao.updateUser(user); return userResponse; } public User deleteUser(String id) { User userResponse = userDao.deleteUser(id); return userResponse; } }
We have defined 5 methods in the above class
getAllUsers() – This method is used to get all the users, helps to serve GET request
getUserForId(String id) – This method is used to get the user details for a specific user,helps to serve the GET request for a specific user
createUser(User user) – This method is used to insert the new user details,helps to serve the POST request
updateUser(User user) – This method is used to update the user details,helps to serve the PUT request
deleteUser(String id) – This method is used to delete the user details,helps to serve the DELETE request
Step 6
Create the DAO class
- package com.kb.dao;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import com.kb.model.User;
- //Just to avoid DB calls in this example, Assume below data is interacting with DB
- public class UserDAO {
- static HashMap<String, User> usersMap = new HashMap<String, User>();
- public UserDAO() {
- User user1 = new User();
- user1.setId("1");
- user1.setAge(20);
- user1.setName("raj");
- User user2 = new User();
- user2.setId("2");
- user2.setAge(21);
- user2.setName("ram");
- usersMap.put("1", user1);
- usersMap.put("2", user2);
- }
- public List<User> getAllUsers() {
- List<User> userList = new ArrayList<User>(usersMap.values());
- return userList;
- }
- public User getUserForId(String id) {
- User user = usersMap.get(id);
- return user;
- }
- public User createUser(User user) {
- usersMap.put(user.getId(), user);
- return usersMap.get(user.getId());
- }
- public User updateUser(User user) {
- if (usersMap.get(user.getId()) != null) {
- usersMap.get(user.getId()).setName(user.getName());
- } else {
- usersMap.put(user.getId(), user);
- }
- return usersMap.get(user.getId());
- }
- public User deleteUser(String id) {
- User userResponse = usersMap.remove(id);
- return userResponse;
- }
- }
package com.kb.dao; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import com.kb.model.User; //Just to avoid DB calls in this example, Assume below data is interacting with DB public class UserDAO { static HashMap<String, User> usersMap = new HashMap<String, User>(); public UserDAO() { User user1 = new User(); user1.setId("1"); user1.setAge(20); user1.setName("raj"); User user2 = new User(); user2.setId("2"); user2.setAge(21); user2.setName("ram"); usersMap.put("1", user1); usersMap.put("2", user2); } public List<User> getAllUsers() { List<User> userList = new ArrayList<User>(usersMap.values()); return userList; } public User getUserForId(String id) { User user = usersMap.get(id); return user; } public User createUser(User user) { usersMap.put(user.getId(), user); return usersMap.get(user.getId()); } public User updateUser(User user) { if (usersMap.get(user.getId()) != null) { usersMap.get(user.getId()).setName(user.getName()); } else { usersMap.put(user.getId(), user); } return usersMap.get(user.getId()); } public User deleteUser(String id) { User userResponse = usersMap.remove(id); return userResponse; } }
We have created DAO class to support all the CRUD operations
We have used a usersMap to store user details(just to avoid DB interaction)
In the constructor , we have added 2 user details in the userMap.
and all the other methods will use this userMap to read,insert,update and delete the user details.
Step 7
Build and deploy the project
Step 8
Let’s see the output of all CRUD operations by using Advanced Rest client
POST
url:
http://localhost:8080 /CRUDWithRest/rest/userInfo
Select content type “application/xml”
Request body
- <User>
- <age>30</age>
- <id>3</id>
- <name>John</name>
- </User>
<User> <age>30</age> <id>3</id> <name>John</name> </User>
Select POST method
We can see 200 status in the response.
GET
url:
http://localhost:8080 /CRUDWithRest/rest/userInfo
Select GET method
GET with specific user ID
url:
http://localhost:8080 /CRUDWithRest/rest/userInfo/1
Select GET method
PUT
url:
http://localhost:8080 /CRUDWithRest/rest/userInfo
Select content type “application/xml”
Request body
- <User>
- <age>40</age>
- <id>3</id>
- <name>John</name>
- </User>
<User> <age>40</age> <id>3</id> <name>John</name> </User>
Select PUT method
We can see 200 status in the response.
DELETE
url:
http://localhost:8080 /CRUDWithRest/rest/userInfo/3
Select DELETE method
Now try to fetch this record using GET to verify whether it’s deleted or not
We can see the record got deleted.
nice
I am not able to access http://localhost:8080/CRUDWithRest/rest/userInfo. The error displayed “The requested resource is not available.” Please help to resolve the issue