{"id":9,"date":"2015-07-11T16:28:17","date_gmt":"2015-07-11T16:28:17","guid":{"rendered":"http:\/\/localhost\/tfcom_wp\/2015\/07\/11\/rest-service-spring-hibernate\/"},"modified":"2025-06-30T02:25:52","modified_gmt":"2025-06-30T02:25:52","slug":"rest-service-spring-hibernate","status":"publish","type":"post","link":"https:\/\/www.tech-freaks.com\/java\/jsp-servlets\/rest-service-spring-hibernate.html","title":{"rendered":"RESTful service using Spring MVC and Hibernate"},"content":{"rendered":"<p style=\"text-align: left;\"><strong>Requirement<\/strong><\/p>\n<p style=\"text-align: left;\">Create a RESTful service using Spring MVC and Hibernate for fetching, adding, updating and deleting product information.\u00a0 The product information will be persisted in a database table. The service should be available to be consumed by any client like mobile, html, java application etc. using the REST url created.<\/p>\n<p style=\"text-align: left;\"><strong>GitHub Project URL<\/strong><\/p>\n<p style=\"color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;\"><strong><span style=\"font-size: 10pt;\"><a style=\"color: #1b57b1; text-decoration: none; font-weight: normal;\" href=\"https:\/\/github.com\/tech-freaks\/catalog-service\" target=\"_blank\" rel=\"alternate noopener noreferrer\">https:\/\/github.com\/tech-freaks\/catalog-service<\/a><\/span><\/strong><\/p>\n<p style=\"text-align: left;\"><strong>Pre-requisites<\/strong><\/p>\n<ul style=\"text-align: left;\">\n<li>MySQL and Tomcat is already installed<\/li>\n<li>Eclipse with JEE support is already installed<\/li>\n<li>Basics about Spring and Hibernate framework<\/li>\n<li>Basics about RESTful service<\/li>\n<\/ul>\n<p><!--more--><\/p>\n<p style=\"text-align: left;\"><strong>Analysis and Design<\/strong><\/p>\n<p style=\"text-align: left;\">We will use a bottom-up approach to design our application. We start from the database layer, then hibernate layer and finally the Spring layer.<\/p>\n<p style=\"text-align: left;\">Database<\/p>\n<p>For implementing this requirement, we create a table\u00a0PRODUCT. It has basic information about a product like name, description, partnumber, unit price etc. We do not have any more table for fulfilling this requirement. However, if you create a complex application, your product information might be normalized into multiple related tables.<\/p>\n<p style=\"text-align: left;\">Below is the CREATE table statement for creating the PRODUCT table.<\/p>\n<pre class=\"brush:sql\" style=\"color: #333333; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;\"> CREATE TABLE IF NOT EXISTS `product` (\n  `product_id` int(11) NOT NULL AUTO_INCREMENT,\n  `name` varchar(50) NOT NULL,\n  `partnumber` varchar(50) NOT NULL,\n  `description` varchar(1024) NOT NULL,\n  `thumbnail_url` varchar(240) DEFAULT NULL,\n  `buyable` char(1) NOT NULL DEFAULT 'Y',\n  `unitprice` decimal(8,2) NOT NULL,\n  PRIMARY KEY (`product_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=latin1;<\/pre>\n<p style=\"text-align: left;\">There is two sql script in the github repository root folder create_tables.sql and product_load.sql. As the name suggests, the first sql can be used to create a database and PRODUCT table. The second sql can be run to insert some starter products.<\/p>\n<p style=\"text-align: left;\"><span style=\"text-decoration: underline;\">Hibernate<\/span><\/p>\n<p style=\"text-align: left;\">Nothing to think about here! We will have a hibernate class Product.java which will be mapped to PRODUCT table. If you would want to reverse engineer the Product.java from the database table, review the steps in the article\u00a0<a title=\"Reverse Engineering Hibernate objects using JBoss eclipse plugin\" href=\"jsp-servlets\/jboss-reverse-engineer-hibernate.html\" target=\"_blank\" rel=\"alternate noopener noreferrer\">Reverse Engineering Hibernate objects using JBoss eclipse plugin<\/a><\/p>\n<p style=\"text-align: left;\"><span style=\"text-decoration: underline;\">Spring<\/span><\/p>\n<p style=\"text-align: left;\">We will have a single Controller, which will have different methods for each verb like GET, PUT, POST and DELETE and will act upon Product table data. Following the Spring convention, we will interact with\u00a0the database using the following layered approach<\/p>\n<p style=\"text-align: left;\">Spring Controller -&gt; Service -&gt; DAO -&gt; Hibernate -&gt; Database<\/p>\n<p style=\"text-align: left;\"><em>Spring Controller:<\/em><br \/>\nCatalogRestController<\/p>\n<p style=\"text-align: left;\"><em>Service<\/em>:<br \/>\nProductService<br \/>\nProductServiceImpl<\/p>\n<p style=\"text-align: left;\"><em>DAO<\/em>:<br \/>\nProductDAO<br \/>\nProductDAOImpl<\/p>\n<p style=\"text-align: left;\">Furthermore, the Rest controller will have the following methods<\/p>\n<pre class=\"language-java\"><code>@RequestMapping(method = RequestMethod.GET)\npublic List&lt;Product&gt; getProducts(); - Get all products\n\n@RequestMapping(value = \"\/{productId}\", method = RequestMethod.GET)\npublic ResponseEntity&lt;?&gt; getProduct(@PathVariable Integer productId) &lt;- Get Products with ProductId\n\n@RequestMapping(method = RequestMethod.POST)\npublic ResponseEntity&lt;?&gt; add(@RequestBody Product input) &lt;- Insert a product for input received\n\n@RequestMapping(value = \"\/{productId}\", method = RequestMethod.PUT)\npublic ResponseEntity&lt;?&gt; update(@PathVariable Integer productId,\n@RequestBody Product input) &lt;- Update product information for productId\n\n@RequestMapping(value = \"\/{productId}\", method = RequestMethod.DELETE)\npublic ResponseEntity&lt;?&gt; remove(@PathVariable Integer productId) &lt;- Delete product for the provided productId<\/code><\/pre>\n<p style=\"text-align: left;\">The above also shows at a high level usage\u00a0of Spring annotations for specifying\u00a0different verbs.<\/p>\n<blockquote><p><span style=\"text-decoration: underline;\">Word of caution<\/span>:\u00a0This design allows a REST client to insert, delete or update records in database, without any authentication and authorization. For a production application, generally, the only verb which might allow access without authorization is the GET. All the other verbs which modify the database might be authenticated and authorized. Oauth is a commonly used open standard of authorization used to authorize client before they can make changes to the underlying data source.<\/p><\/blockquote>\n<p style=\"text-align: left;\">We will need to further create XML configuration file for web application, Spring framework and add libraries. We will cover this in environment setup and development sections.<\/p>\n<hr class=\"system-pagebreak\" title=\"Environment Setup\" \/>\n<p style=\"text-align: left;\"><strong>Environment Setup<\/strong><\/p>\n<ul style=\"text-align: left;\">\n<li>Open eclipse and create a &#8220;Dynamic Web Project&#8221; in eclipse with the name &#8220;catalog-service&#8221;.<\/li>\n<li>Click next, then next and finish.<\/li>\n<li>If you are using Maven or Gradle, setup to download libraries for Hibernate 4 or above, Spring 4.1 or above and MySQL drivers. If you are using Spring 4.1, make sure to also include the latest libraries for Jackson FastXML. The conversion of Object to JSON and vice versa is handle by Jackson library and it does not work without the latest libraries.<\/li>\n<li>If you are not using maven or gradle, make sure the following jars are in your WEB-INF\/lib folder as provided in the below screenshot<\/li>\n<\/ul>\n<p style=\"color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;\"><img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/www.tech-freaks.com\/wp-content\/uploads\/2015\/07\/dependent_libraries.png\" alt=\"Library Jars\" width=\"404\" height=\"710\" \/><\/p>\n<p style=\"color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;\">The source code in the GitHub contains all required libraries.<\/p>\n<p style=\"text-align: left;\"><span style=\"text-decoration: underline;\">Web.xml configuration<\/span><\/p>\n<p style=\"text-align: left;\">We configure Spring DispatcherServlet, specify the patch to Spring configuration file (if not using default path and file name) and map the request to a URL pattern. For this project, we use *.json mapping. Hence, all the request URL should have .json at the end. Note that, if you perform a partial URL mapping like \/product\/*, you will have to configuring the ViewResolver, so that it could use the appropriate resolvers for JSON. However, when an extension mapping like .json, no ViewResolver configuration is required.<\/p>\n<pre class=\"language-markup\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;web-app xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" \nxmlns=\"http:\/\/java.sun.com\/xml\/ns\/javaee\" xsi:schemaLocation=\"http:\/\/java.sun.com\/xml\/ns\/javaee http:\/\/java.sun.com\/xml\/ns\/javaee\/web-app_3_0.xsd\" id=\"WebApp_ID\" version=\"3.0\"&gt;\n  &lt;display-name&gt;Catalog REST Services&lt;\/display-name&gt;\n  &lt;welcome-file-list&gt;\n    &lt;welcome-file&gt;Login.jsp&lt;\/welcome-file&gt;\n  &lt;\/welcome-file-list&gt;\n  &lt;servlet&gt;\n    &lt;servlet-name&gt;CatalogServlet&lt;\/servlet-name&gt;\n    &lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;\/servlet-class&gt;\n    &lt;init-param&gt;\n      &lt;param-name&gt;contextConfigLocation&lt;\/param-name&gt;\n      &lt;param-value&gt;\/WEB-INF\/Catalog-Servlet.xml&lt;\/param-value&gt;\n    &lt;\/init-param&gt;\n    &lt;load-on-startup&gt;1&lt;\/load-on-startup&gt;\n  &lt;\/servlet&gt;\n  &lt;servlet-mapping&gt;\n    &lt;servlet-name&gt;CatalogServlet&lt;\/servlet-name&gt;\n    &lt;url-pattern&gt;*.json&lt;\/url-pattern&gt;\n  &lt;\/servlet-mapping&gt;\n&lt;\/web-app&gt;<\/code><\/pre>\n<p style=\"text-align: left;\"><span style=\"text-decoration: underline;\">WEB-INF\/Catalog-Servlet.xml<\/span><\/p>\n<p style=\"text-align: left;\">Most of the tags are self-explanatory. Although this is a Spring configuration, it references Hibernate related files and hibernate.cfg.xml. The &#8220;datasource&#8221;\u00a0needs to be updated with your username, password and dbname. Also, note the configuration for transactionManager. Once this is configured, Spring handles the hibernate transactions and you do not have to manually manage the transaction in your code. Just mark the service method with @Transactional annotation.<\/p>\n<p style=\"text-align: left;\">The ProductDao and ProductService is also declared. We have marked them as @Autowired and hence we do not have to pass the reference for productDao into productService in the XML.<\/p>\n<pre class=\"language-markup\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\n\txmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n\txmlns:context=\"http:\/\/www.springframework.org\/schema\/context\"\n\txmlns:mvc=\"http:\/\/www.springframework.org\/schema\/mvc\"\n\txmlns:tx=\"http:\/\/www.springframework.org\/schema\/tx\"\n\txsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/beans http:\/\/www.springframework.org\/schema\/beans\/spring-beans-4.1.xsd\n\t\thttp:\/\/www.springframework.org\/schema\/context http:\/\/www.springframework.org\/schema\/context\/spring-context-4.1.xsd\n\t\thttp:\/\/www.springframework.org\/schema\/mvc http:\/\/www.springframework.org\/schema\/mvc\/spring-mvc-4.1.xsd\n\t\thttp:\/\/www.springframework.org\/schema\/tx http:\/\/www.springframework.org\/schema\/tx\/spring-tx-4.1.xsd\"&gt;\n\n\t&lt;mvc:annotation-driven \/&gt;\n&lt;!-- Configure JDBC Connection - @TODO update url, username and password per your database configuration --&gt;\n      &lt;bean id=\"dataSource\"\n            class=\"org.springframework.jdbc.datasource.DriverManagerDataSource\"&gt;\n            &lt;property name=\"driverClassName\" value=\"com.mysql.jdbc.Driver\" \/&gt;\n            &lt;property name=\"url\" value=\"jdbc:mysql:\/\/localhost:3306\/tfcom_articles\" \/&gt;\n            &lt;property name=\"username\" value=\"admin\" \/&gt;\n            &lt;property name=\"password\" value=\"admin*\" \/&gt;\n      &lt;\/bean&gt;\n      \n    &lt;tx:annotation-driven transaction-manager=\"transactionManager\" \/&gt;\n    \n     &lt;bean id=\"transactionManager\"\n            class=\"org.springframework.orm.hibernate4.HibernateTransactionManager\"&gt;\n        &lt;property name=\"sessionFactory\" ref=\"sessionFactory\"\/&gt;\n    &lt;\/bean&gt;\n    \n      \n    &lt;bean id=\"sessionFactory\" class=\"org.springframework.orm.hibernate4.LocalSessionFactoryBean\"&gt;\n    &lt;property name=\"dataSource\"&gt;\n                  &lt;ref bean=\"dataSource\" \/&gt;\n            &lt;\/property&gt;\n    &lt;property name=\"configLocation\" value=\"classpath:hibernate.cfg.xml\" \/&gt;\n\t&lt;\/bean&gt;\n\t\n\t&lt;context:component-scan base-package=\"com.tech_freaks.catalog\"\/&gt;\n\t\n\t&lt;bean id=\"productDao\"\n   \tclass=\"com.tech_freaks.catalog.dao.ProductDAOImpl\"\/&gt;\n   \t\n   \t&lt;bean id=\"productService\"\n   \tclass=\"com.tech_freaks.catalog.service.ProductServiceImpl\"\/&gt;\n&lt;\/beans&gt;<\/code><\/pre>\n<pre class=\"brush:xml\" style=\"color: #333333; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;\"><\/pre>\n<p style=\"text-align: left;\"><span style=\"text-decoration: underline;\">src\/hibernate.cfg.xml<\/span><\/p>\n<p style=\"text-align: left;\">We have used the XML configuration for hibernate and\u00a0not\u00a0annotations. This mainly declares\u00a0the Product hibernate class and its mapping file Product.hbm.xml.<\/p>\n<p style=\"text-align: left;\">The commented fields in this file will need to be un-commented, if you are reverse engineering the hibernate object as explained in the article\u00a0<a title=\"Reverse Engineering Hibernate objects using JBoss eclipse plugin\" href=\"jsp-servlets\/jboss-reverse-engineer-hibernate.html\" target=\"_blank\" rel=\"alternate noopener noreferrer\">Reverse Engineering Hibernate objects using JBoss eclipse plugin<\/a><\/p>\n<hr class=\"system-pagebreak\" title=\"Development\" \/>\n<p style=\"text-align: left;\"><strong>Development<\/strong><\/p>\n<p style=\"text-align: left;\"><span style=\"text-decoration: underline;\">Hibernate Object<\/span><br \/>\nProduct.java &#8211; We reverse engineer this class from the database. It is the model for the application, which is mapped to the database table. It is self-explanatory.<\/p>\n<p style=\"text-align: left;\"><span style=\"text-decoration: underline;\">DAO layer<\/span><\/p>\n<p style=\"text-align: left;\"><em>AbstractDAO&lt;T&gt;<\/em>\u00a0&#8211; This is a generic class which contains common calls to hibernate API. All DAO can extend this class to reuse these pre-implemented class. Note, how the sessionFactory is injected by Spring framework into the DAO layer using @Autowired annotation. The sessionFactory is declared\u00a0in the Catalog-Servlet.xml file which we defined earlier.<\/p>\n<p style=\"color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;\">The JavaDoc comments on each of the method, explain the use of the function.<\/p>\n<pre class=\"language-java\"><code>package com.tech_freaks.catalog.dao;\n\nimport org.hibernate.Session;\nimport org.hibernate.SessionFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n\/**\n * Generic Base class which encapsulates hibernate specific calls which will be available from the \n * extending DAO which is mapped to the database table.\n * @author Tech Freaks\n *\n * @param &lt;T&gt; - The Hibernate object which it works on\n *\/\npublic class AbstractDAO &lt;T&gt; {\n\t\n\t@Autowired\n    private SessionFactory sessionFactory;\n \n\t\/**\n\t * Gets a current session from the hibernate factory\n\t * @return\n\t *\/\n    protected Session getSession(){\n        return sessionFactory.getCurrentSession();\n    }\n    \n    \/**\n     * Generic method for finding by primary key. \n     * @param id  - Primary key value in integer\n     * @param myClass - Type of Class which will be loaded\n     * @return T representing instance of the loaded hibernate class instance\n     *\/\n    public &lt;T&gt;  T findById(Integer id, Class myClass) {\n    \treturn (T) getSession().load(myClass, id);\n    }\n \n    \/**\n     * Inserts record into database\n     * @param t - Instance of the Hibernate object which needs to be persisted in the db\n     * @return - Key value of the newly inserted record\n     *\/\n    public Integer persist(T t) {\n       return (Integer) getSession().save(t);\n    }\n    \n    \/**\n     * Updates the database for provided generic type\n     * @param t Generic type for the hibernate object\n     *\/\n    public void update(T t) {\n    \tgetSession().update(t);\n    \tgetSession().flush();\n    }\n     \n    \/**\n     * Deletes the entity from the database for the provided generic type\n     * @param t  Generic type for the hibernate object\n     *\/\n    public void delete(T t) {\n        getSession().delete(t);\n        getSession().flush();\n    }\n}<\/code><\/pre>\n<p style=\"text-align: left;\"><em>ProductDAOImpl &amp; ProductDAO<\/em><br \/>\nThis is the actual DAO interface and its implementation. It extends the AbstractDAO&lt;Product&gt; and utilizes the methods defined there.<\/p>\n<pre class=\"language-java\"><code>package com.tech_freaks.catalog.dao;\n\nimport java.util.List;\n\nimport org.hibernate.Session;\nimport org.hibernate.SessionFactory;\n\nimport com.tech_freaks.catalog.model.Product;\n\npublic class ProductDAOImpl extends AbstractDAO&lt;Product&gt; implements ProductDAO {\n\t\n\t\n\t\/**\n\t * Fetches all the product from the PRODUCT table\n\t *\/\n\t@Override\n\tpublic List&lt;Product&gt; getAllProducts() {\n\t\tSession session = getSession();\n        List&lt;Product&gt; productList = session.createQuery(\"from Product\").list();\n        return productList;\n\t}\n\t\n\t\/**\n\t * Fetches product based on the primary key productId\n\t *\/\n\t@Override\n\tpublic Product findById(Integer id) {\n\t\treturn (Product) getSession().get(Product.class, id);\n\t}\n\t\n\t\/**\n\t * Inserts a new record in the product table.\n\t *\/\n\t@Override\n\tpublic Integer insert(Product product) {\n\t\treturn persist(product);\n\t}\n\t\n\t\/**\n\t * Loads the product using the primary key and then removes it from the database.\n\t *\/\n\t@Override\n\tpublic boolean remove(Integer id)  {\n\t\tboolean deleted = false;\n\t\tProduct delProduct = findById(id);\n\t\tif(delProduct!=null) {\n\t\t\tdelete(delProduct);\n\t\t\tdeleted = true;\n\t\t} \n\t\treturn deleted;\n\t}\n}<\/code><\/pre>\n<p style=\"text-align: left;\"><em>ProductServiceImpl &amp; ProductService<\/em><\/p>\n<p style=\"text-align: left;\">The is the Service layer interface and its implementation for the Product manipulation. It internally calls the DAO layer. The Service layer is called from the Controller class. The methods are self-explanatory.<\/p>\n<p style=\"text-align: left;\">The below excerpt from ProductServiceImpl shows\u00a0@Autowiring\u00a0annotation on productDAO, which is injected in by the Spring framework. Also, each method is marked with annotation\u00a0@Transactional. This is the reason, you do not see any code related to transaction management in the DAO layer. Spring manages the transaction code for you.<\/p>\n<pre class=\"language-java\"><code>...\n@Autowired\n\tprivate ProductDAO productDAO;\n\t\n\t@Override\n\t@Transactional\n\tpublic List&lt;Product&gt; listProducts() {\n\t\t\n\t\treturn productDAO.getAllProducts();\n\t}\n...<\/code><\/pre>\n<p style=\"text-align: left;\"><em>CatalogRestController\u00a0<\/em>is the entry point into the code for all REST service verbs. The\u00a0@RestController\u00a0annotation eliminates the need to mark each method with\u00a0@ResponseBody\u00a0when it returns an Object or a Collection of objects. Now even without\u00a0@ResponseBody, when an object or collection of object is returned, it is automatically converted into JSON.\u00a0The class is also marked with\u00a0@RequestMapping(&#8220;\/products&#8221;). This means the REST URL for every verb call will have &#8216;\/products&#8217; in it, after the application context name. Now, each method is marked with\u00a0@RequestMethod.\u00a0We follow the REST specification by mapping GET to retrieve data, POST for insert data, PUT for update data and DELETE for deleting data.<\/p>\n<p style=\"text-align: left;\">If we look at the method &#8220;add&#8221;, there are certain points worth noticing.<\/p>\n<p style=\"text-align: left;\">First, after every REST call, we return a HttpStatusCode. If the insert is successful, we return CREATED status or 201. If it fails, because the Product object was not populated, it means, the JSON was not well formed. In this case, we return BAD_REQUEST or 400. This helps the client to read the HttpHeader in the response and take appropriate action.<\/p>\n<p style=\"text-align: left;\">Second, after insert, the method create a REST URL to fetching the newly inserted record. This is set in the Location HttpHeader.<\/p>\n<p style=\"text-align: left;\">The private method isValid() is called internally to perform some basic validation before the service layer is invoked.<\/p>\n<p style=\"text-align: left;\">Similarly, all the other method are developed. The complete CatalogRestController code is below.<\/p>\n<pre class=\"language-java\"><code>package com.tech_freaks.catalog.controller;\n\nimport java.net.URI;\nimport java.util.List;\n\nimport org.apache.commons.logging.Log;\nimport org.apache.commons.logging.LogFactory;\nimport org.hibernate.HibernateException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.servlet.support.ServletUriComponentsBuilder;\n\nimport com.tech_freaks.catalog.model.Product;\nimport com.tech_freaks.catalog.service.ProductService;\n\n@RestController\n@RequestMapping(\"\/products\")\n\/**\n * Entry point for REST service calls. Different method for handling insert, update, delete and get\n *\/\npublic class CatalogRestController {\n\n\tprotected final Log logger = LogFactory.getLog(getClass());\n\n\t@Autowired\n\tprivate ProductService productService;\n\n\t@RequestMapping(method = RequestMethod.GET)\n\tpublic List&lt;Product&gt; getProducts() {\n\t\treturn productService.listProducts();\n\n\t}\n\n\t@RequestMapping(value = \"\/{productId}\", method = RequestMethod.DELETE)\n\tpublic ResponseEntity&lt;?&gt; remove(@PathVariable Integer productId) {\n\t\tboolean deleted = false;\n\t\tResponseEntity&lt;?&gt; response = null;\n\t\ttry {\n\t\t\tdeleted = productService.removeProduct(productId);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"Error deleting product from database: \"\n\t\t\t\t\t+ e.getMessage());\n\t\t}\n\t\tif (deleted)\n\t\t\tresponse = new ResponseEntity&lt;&gt;(HttpStatus.OK);\n\t\telse\n\t\t\tresponse = new ResponseEntity&lt;&gt;(HttpStatus.NO_CONTENT);\n\t\treturn response;\n\t}\n\n\t@RequestMapping(value = \"\/{productId}\", method = RequestMethod.GET)\n\tpublic ResponseEntity&lt;?&gt; getProduct(@PathVariable Integer productId) {\n\t\tResponseEntity&lt;Product&gt; response = null;\n\t\tProduct product = productService.getProduct(productId);\n\t\tif (product != null) {\n\t\t\tresponse = new ResponseEntity&lt;&gt;(product, HttpStatus.OK);\n\t\t} else {\n\t\t\tresponse = new ResponseEntity&lt;&gt;(HttpStatus.NO_CONTENT);\n\t\t}\n\t\treturn response;\n\t}\n\n\t@RequestMapping(value = \"\/{productId}\", method = RequestMethod.PUT)\n\tpublic ResponseEntity&lt;?&gt; update(@PathVariable Integer productId,\n\t\t\t@RequestBody Product input) {\n\t\tResponseEntity&lt;?&gt; response = new ResponseEntity&lt;&gt;(HttpStatus.OK);\n\t\tlogger.info(\"Product Id to be updated is \" + productId);\n\t\tlogger.info(\"New Product Name will be \" + input.getName());\n\t\ttry {\n\t\t\tif (productId &gt; 0 &amp;&amp; isValid(input)) {\n\t\t\t\tinput.setProductId(productId);\n\t\t\t\tproductService.updateProduct(input);\n\t\t\t\tresponse = new ResponseEntity&lt;&gt;(HttpStatus.OK);\n\t\t\t\t\n\t\t\t} else {\n\t\t\t\tresponse = new ResponseEntity&lt;&gt;(HttpStatus.BAD_REQUEST);\n\t\t\t}\n\t\t} catch (HibernateException he) {\n\t\t\tlogger.error(\"Unable to update product in database: \"+ he.getMessage());\n\t\t\tresponse = new ResponseEntity&lt;&gt;(HttpStatus.NO_CONTENT);\n\t\t} catch (Exception e) {\n\t\t\tlogger.error(\"Unable to update product in database: \"+ e.getMessage());\n\t\t\tresponse = new ResponseEntity&lt;&gt;(HttpStatus.BAD_REQUEST);\n\t\t}\n\t\treturn response;\n\t}\n\n\t@RequestMapping(method = RequestMethod.POST)\n\tpublic ResponseEntity&lt;?&gt; add(@RequestBody Product input) {\n\t\tHttpHeaders httpHeaders = new HttpHeaders();\n\t\tResponseEntity&lt;?&gt; response = null;\n\t\tif (isValid(input)) {\n\t\t\tlogger.info(\"Product description is \" + input.getDescription());\n\t\t\ttry {\n\t\t\t\tInteger productId = productService.createProduct(input);\n\t\t\t\tURI location = ServletUriComponentsBuilder\n\t\t\t\t\t\t.fromCurrentServletMapping()\n\t\t\t\t\t\t.path(\"\/products\/{productId}.json\").build()\n\t\t\t\t\t\t.expand(productId).toUri();\n\t\t\t\tlogger.info(\"Location uri is \" + location.toString());\n\t\t\t\thttpHeaders.setLocation(location);\n\t\t\t\tresponse = new ResponseEntity&lt;&gt;(null, httpHeaders,\n\t\t\t\t\t\tHttpStatus.CREATED);\n\t\t\t} catch (Exception e) {\n\t\t\t\tlogger.error(\"Unable to insert new product in database: \"\n\t\t\t\t\t\t+ e.getMessage());\n\n\t\t\t\tresponse = new ResponseEntity&lt;&gt;(null, httpHeaders,\n\t\t\t\t\t\tHttpStatus.UNPROCESSABLE_ENTITY);\n\t\t\t}\n\t\t} else {\n\t\t\tresponse = new ResponseEntity&lt;&gt;(null, httpHeaders,\n\t\t\t\t\tHttpStatus.BAD_REQUEST);\n\t\t}\n\t\treturn response;\n\t}\n\n\t\/*\n\t * Internally used to validate the fields to make sure, all required fields\n\t * are present before calling the service layer for insert\n\t *\/\n\tprivate boolean isValid(Product product) {\n\t\tboolean valid = false;\n\t\tif (product != null) {\n\t\t\tif (!StringUtils.isEmpty(product.getName())\n\t\t\t\t\t&amp;&amp; !StringUtils.isEmpty(product.getDescription())\n\t\t\t\t\t&amp;&amp; !StringUtils.isEmpty(product.getPartnumber())\n\t\t\t\t\t&amp;&amp; !StringUtils.isEmpty(product.getName()))\n\t\t\t\tvalid = true;\n\t\t}\n\t\treturn valid;\n\t}\n}<\/code><\/pre>\n<p style=\"text-align: left;\">At this point, you can download the complete project from GitHub at\u00a0<a href=\"https:\/\/github.com\/tech-freaks\/catalog-service\" target=\"_blank\" rel=\"alternate noopener noreferrer\">https:\/\/github.com\/tech-freaks\/catalog-service<\/a><\/p>\n<hr class=\"system-pagebreak\" title=\"Unit Testing\" \/>\n<p style=\"text-align: left;\"><strong>Unit Testing<\/strong><\/p>\n<p style=\"text-align: left;\">The first part of the unit test, is to figure out the REST URL to invoke. We can figure this out, if we look at the CatalogRestController and web.xml. Remember, web.xml maps *.json to the controller. Hence, for all verbs our URL will end with .json.<\/p>\n<p style=\"text-align: left;\">We used the following information:<\/p>\n<p style=\"text-align: left;\">Tomcat host: http:\/\/localhost:8080<br \/>\nApplication Context: \/catalog-service<br \/>\nCatalogRestController mapping: \/products<\/p>\n<p style=\"text-align: left;\">Now, the method\u00a0getProducts()\u00a0do not have any value mapping. But, it needs to be a GET call. Hence, for accessing this method, you will use the URL http:\/\/localhost:8080\/catalog-service\/products.json and it needs to be a GET call. You can therefore, just paste the URL in a browser and it will show the JSON with all products.<\/p>\n<p style=\"text-align: left;\">Similarly, if you look at\u00a0getProduct(), the request mapping has \/{productId}. This is equivalent to the primary key, product_id value in the database. Hence, the URL will be http:\/\/localhost:8080\/catalog-service\/products\/1.json , where product_id=1. This will be again a GET verb again, as we are fetching information.<\/p>\n<p style=\"text-align: left;\">Now, similarly, we can figure out the remaining URL for calling remove(), update() and add(). The below table provide the remaining URL and verbs.<\/p>\n<table style=\"margin-left: 0px; margin-right: auto;\">\n<tbody>\n<tr>\n<td width=\"120\">Method<\/td>\n<td width=\"540\">URL<\/td>\n<td width=\"120\">Verb<\/td>\n<\/tr>\n<tr>\n<td width=\"120\">remove()<\/td>\n<td width=\"540\">http:\/\/localhost:8080\/catalog-service\/products\/{productId}.json<\/td>\n<td width=\"120\">DELETE<\/td>\n<\/tr>\n<tr>\n<td width=\"120\">update()<\/td>\n<td width=\"540\">http:\/\/localhost:8080\/catalog-service\/products\/{productId}.json<\/td>\n<td width=\"120\">PUT<\/td>\n<\/tr>\n<tr>\n<td width=\"120\">add()<\/td>\n<td width=\"540\">http:\/\/localhost:8080\/catalog-service\/products.json<\/td>\n<td width=\"120\">POST<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p style=\"text-align: left;\">Where\u00a0{productId}\u00a0will be replaced by product_id value in the database.<\/p>\n<p style=\"text-align: left;\">Now, there will be two question:<br \/>\n1. How to invoke DELETE, PUT and POST verb? When we paste the URL in the browser, they all are by default GET requests.<br \/>\n2. How to pass the product information for add() and update()?<\/p>\n<p style=\"text-align: left;\">For # 1, we can download a browser plugin called as Poster (Just search Poster plugin), which is available for Chrome and Firefox. The below screenshot shows, Poster in action for Firefox.<\/p>\n<p style=\"color: #333333; font-family: Tahoma, Helvetica, Arial, sans-serif; font-size: 12.16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 15.808px; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px;\"><img decoding=\"async\" data-src=\"https:\/\/www.tech-freaks.com\/wp-content\/uploads\/2015\/07\/poster_request_response.png\" alt=\"Poster plugin for Firefox in Action\" width=\"870\" height=\"867\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" class=\"lazyload\" style=\"--smush-placeholder-width: 870px; --smush-placeholder-aspect-ratio: 870\/867;\" \/><\/p>\n<p style=\"text-align: left;\">For # 2, we need to send an input json containing the product information to be insert or updated in the product table. The POST performs and insert, while PUT updates. The json format is exactly as the response received from http:\/\/localhost:8080\/catalog-service\/products\/{productId}.json GET verb. However, we have provided an input file by the name POST_PUT_Input.json, which is in the root folder of the project.<\/p>\n<p style=\"text-align: left;\">In Poster plugin, you need to make sure, that to add a Header by the name\u00a0&#8220;Content-Type&#8221;\u00a0with value\u00a0&#8220;application\/json&#8221;.<\/p>\n<p style=\"text-align: left;\">For integration testing, we generally run the client code like the mobile application in same network and point to the URLs provided above. However, integration testing is beyond the scope of this article.<\/p>\n<p style=\"text-align: left;\">This completes the workshop for creating a simple product REST service using Spring MVC 4.<\/p>\n<p style=\"text-align: left;\">Happy RESTing!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Requirement Create a RESTful service using Spring MVC and Hibernate for fetching, adding, updating and deleting product information.\u00a0 The product [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":7,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[10],"tags":[],"class_list":["post-9","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-jsp-servlets"],"_links":{"self":[{"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/posts\/9","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/comments?post=9"}],"version-history":[{"count":1,"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/posts\/9\/revisions"}],"predecessor-version":[{"id":133,"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/posts\/9\/revisions\/133"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/media\/7"}],"wp:attachment":[{"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/media?parent=9"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/categories?post=9"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tech-freaks.com\/wp-json\/wp\/v2\/tags?post=9"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}