Dogukan Sonmez

Currently in Munich, Germany

Java Groovy Python

No-Sql TDD Scrum

Django Shell Cloud

May 09 2012

All in One - Spring Maven MySQL Hibernate JPA REST

With this from scratch series I build an application with spring 3, maven 3, MySQL, Hibernate , JPA, REST
I used new features of these technologies to give an idea for your personel project needs. I'll try to explain building a web application from scratch and give brief information about each step. This is sort of a template not a complete full project, you can change use case of this project based on your project requirments.

Create folder structure

Before start coding we need to create folder hiararchy of our web application project. Right now this is basic folder structure of my applicaiton I'll add new folders and classes by next steps.


            +-- spring-example
            |   +-- src
            |       +-- main
            |       |   +-- java
            |       |   +-- resources
            |       |   +-- webapp
            |       |       +-- META-INF
            |       |       +-- WEB-INF
            |       +-- test

        

Create web.xml file

The web.xml file provides configuration and deployment information for the Web components that comprise a Web application.

            <?xml version="1.0" encoding="UTF-8"?>
            <!-- Use this definition if using a Java EE 6 container This also stops Eclipse
            from complaining that 3.0 is not a valid version <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
            http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> -->
            <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
            version="2.5">

            <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            </welcome-file-list>
            </web-app>
        

Create Pom.xml file under the spring-example

POM stands for "Project Object Model". It is an XML representation of a Maven project held in a file named pom.xml. I added all required libs in pom xml. For more information visit the Maven POM

I just added a code snipped of pom file you can find full pom.xml

            <?xml version="1.0" encoding="UTF-8"?>
            <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>com.ds.springexample</groupId>
            <artifactId>spring-example</artifactId>
            <packaging>war</packaging>
            <version>1.0-SNAPSHOT</version>
            <name>spring-example</name>
            <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <spring.version>3.0.5.RELEASE</spring.version>
            <slf4j.version>1.5.10</slf4j.version>
            <java.version>1.5</java.version>
            <junit.version>4.8.2</junit.version>
            <org.aspectj-version>1.6.9</org.aspectj-version>
            <force.sdk.version>22.0.3-BETA</force.sdk.version>
            </properties>
            <dependencies>
            <!-- Bean Validation Dependencies -->
            <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.0.0.GA</version>
            <scope>compile</scope>
            </dependency>
            <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>4.0.0.GA</version>
            <scope>compile</scope>
            </dependency>
            <!-- JPA Persistence Dependencies -->
            
        

Run Maven !

Even though we don't have any piece of java code let's try if we build right project structure. After running below command if you see BUILD SUCCESS than let's move on next step.

            mvn clean install

            [INFO] BUILD SUCCESS
            [INFO] ------------------------------------------------------------------------
            [INFO] Total time: 5.641s
            [INFO] Finished at: Sun Oct 09 20:06:46 EEST 2011
            [INFO] Final Memory: 5M/15M
            [INFO] ------------------------------------------------------------------------

       

Add spring framework to web xml file

New web.xml with spring configuration. For more information about web.xml file please visit the web site web.xml

            <?xml version="1.0" encoding="UTF-8"?>
            <!-- Use this definition if using a Java EE 6 container This also stops Eclipse
            from complaining that 3.0 is not a valid version <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
            http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> -->
            <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
            version="2.5">

            <!-- The definition of the Root Spring Container shared by all Servlets  and Filters -->
            <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/root-context.xml</param-value>
            </context-param>

            <!-- Creates the Spring Container shared by all Servlets and Filters -->
            <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
            </listener>

            <!-- Processes application requests -->
            <servlet>
            <servlet-name>appServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/servlet-context.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
            </servlet>

            <servlet-mapping>
            <servlet-name>appServlet</servlet-name>
            <url-pattern>/</url-pattern>
            </servlet-mapping>


            <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            </welcome-file-list>
            </web-app>

        

Dispatcher Servlet

The Dispatcher Servlet as represented by org.springframework.web.servlet.DispatcherServlet, follows the Front Controller Design Pattern for handling Client Requests. It means that whatever Url comes from the Client, this Servlet will intercept the Client Request before passing the Request Object to the Controller. The Web Configuration file should be given definition in such a way that this Dispatcher Servlet should be invoked for Client Requests.

It is wise sometimes to split all the Configuration information across multiple Configuration Files. In such a case we have to depend on a Listener Servlet called Context Loader represented by org.springframework.web.context.ContextLoaderListener. By default, this Context Listener will try to look for the Configuration File by name 'applicationContext.xml' in the '/WEB-INF' directory. But with the help of the parameter 'contextConfigLocation' the default location can be overridden. Even multiple Configuration Files each containing separate piece of Information is also possible.

As you can see from new Web xml file, please create folder and files which is under the WEB-INF directory. These files are root-context.xml and servlet-context.xml

Right now just add following xml definition inside of root-context.xml file. We will fill this xml file letter on

Content of root-context.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:tx="http://www.springframework.org/schema/tx"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

             </beans>

        

Content of servlet-context.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:mvc="http://www.springframework.org/schema/mvc"
                    xmlns:tx="http://www.springframework.org/schema/tx"
                    xmlns:context="http://www.springframework.org/schema/context"
                    xsi:schemaLocation="http://www.springframework.org/schema/mvc
                    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
                    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

                    <!-- Dispatcher`Servlet Context: defines this servlet's request-processing infrastructure -->

                    <!-- Enables the Spring MVC @Controller programming model -->
                    <mvc:annotation-driven/>


                    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
                    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                    <property name="prefix" value="/WEB-INF/views/"/>
                    <property name="suffix" value=".jsp"/>
                    </bean>

                    <context:component-scan base-package="com.ds.springexample"/>

                    </beans>

                

Create package structure and views folder

After creating all necessary folders your project should looks like as below


        ── src
        ├── main
        │   ├── java
        │   │   └── com
        │   │       └── ds
        │   │           └── springexample
        │   ├── resources
        │   └── webapp
        │       ├── META-INF
        │       └── WEB-INF
        │           ├── spring
        │           │   ├── root-context.xml
        │           │   └── servlet-context.xml
        │           ├── views
        │           └── web.xml
        └── test

                

Content of home.jsp file

Under the views folder create first view with name home.jsp. This is a simple jsp file for welcome page.


        <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
        <%@ page session="false" %>
        <html>
        <head>
        <title>Home</title>
        </head>
        <body>
        <h1>
        Hello world!
        </h1>
        ${controllerMessage}<br/>
        </body>
        </html>
                

Main Page Controller

This spring controller handle main page request and response with simple welcome message. Create a package under the com.ds.springexample package with name controller and create following controller class.


package com.ds.springexample.controller;

/**
 * @author Dogukan Sonmez
 */

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class MainPageController {

    private static final Logger logger = LoggerFactory.getLogger(MainPageController.class);


    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Model model) {
        model.addAttribute("controllerMessage", "Welcome to Home page of Spring example application");
        logger.info("requesting home");
        return "home";
    }

}
                

Adding Log4J logging

Adding log4j logging to your project is quite simple. just create log4j.xml file under the resource folder. You can find content of log4j.xml below. Do not forget to update this xml when you add new packages to your project.

        <?xml version="1.0" encoding="UTF-8"?>
        <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd" >
        <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

        <!-- Appenders -->
        <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out"/>
        <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%-5p: %c - %m%n"/>
        </layout>
        </appender>

        <!-- Application Loggers -->
        <logger name="com.ds.springexample.controller">
        <level value="info"/>
        </logger>


        <!-- 3rdparty Loggers -->
        <logger name="org.springframework.core">
        <level value="info"/>
        </logger>

        <logger name="org.springframework.beans">
        <level value="info"/>
        </logger>

        <logger name="org.springframework.context">
        <level value="info"/>
        </logger>

        <logger name="org.springframework.web">
        <level value="info"/>
        </logger>

        <logger name="org.hibernate">
        <level value="warn"/>
        </logger>


        <!-- Root Logger -->
        <root>
        <priority value="warn"/>
        <appender-ref ref="console"/>
        </root>

        </log4j:configuration>

Run Jetty run

We've created our first view and controller so it's time to see our application on the fly. run mvn clean install and then run mvn jetty:run command. After that type http://localhost:8080/spring-example/ url to your browser. If everything goes well you should see welcome page.

        mvn clean install
        mvn jetty:run
    

Create model object

Based on our business logic and use case let's start business part of our project. Spring example project aim to display products and apply basic CRUD operations on it. So far We've created our main page and main controller now it's time to create domain object which is Product.java. Create a new package with name model and create a Product.java class in this folder.

package com.ds.springexample.model;

import javax.persistence.*;
import java.io.Serializable;

/**
 * @author Dogukan Sonmez
 */

@Entity
public class Product implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String description;

    @Column
    private Double price;

    public Product(){

    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append(id)
                .append(description)
                .append(price);
        return sb.toString();
    }

}
    

As you can see there are many annotations on this class. These are jpa annotations which is specify class is entity and properties of its fields.
@Entity : This annotation is used when you want to mark a class as persistent
@Id :This annotation is used to define a field to use for the identity of the class
@Column: This annotation is used to define the column where a field is stored
@GeneratedValue: This annotation is used to define the generation of a value for a (PK) field.
For more information about JPA annotations please visit the JPA annotations

Develop Service Layer

First we create our model object and now we need to a service class to manage our domain. Create a new package with name service and create service class in this folder.

package com.ds.springexample.service;

import com.ds.springexample.model.Product;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import java.util.List;

/**
 * @author Dogukan Sonmez
 */

@Service
public class ProductManagerService {

    private static final Logger logger = LoggerFactory.getLogger(ProductManagerService.class);


    public Product getProductById(Long id) {
        return null;
    }

    public List getAllProducts() {
        return null;
    }

    public void saveProduct(Product product) {

    }

    public void updateProduct(Product product) {
    }

    public void deleteProduct(Long id) {

    }


}
    

Basically the main difference between component and service annotation is: When annotating your class with @Component you mark it as a regular java component class When annotating with @Service you mark it as a “special” type of component for special purpose like transaction or associating with aspects. Right now there is no logic in this class. We will write logic after creating our repository class

Develop Dao Layer

Let's move on, we have model object, we have service layer now we'll create dao layer. Create repository package with dao name and create ProductRepository.java with following content

package com.ds.springexample.dao;

import com.ds.springexample.model.Product;
import org.hibernate.annotations.Entity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;

/**
 * @author Dogukan Sonmez
 */

@Repository
public class ProductRepository {

    private static final Logger logger = LoggerFactory.getLogger(ProductRepository.class);

    @PersistenceContext
    private EntityManager entityManager;


    public void save(Product product) {

    }

    public void update(Product product) {

    }

    @Transactional(readOnly = true)
    public Product get(Long id) {
        return null;
    }

    @Transactional(readOnly = true)
    public List getAll() {
        return null;
    }

}
   

Spring provides the capability of automatically detecting 'stereotyped' classes and registering corresponding BeanDefinitions with the ApplicationContext.In this class
@Repository: Indicates that an annotated class is a "Repository". Annotations is very useful when it comes to see the whole picture. Regarding other spring stereotyped annotations:
@Component: Generic stereotype annotation for any Spring-managed component.
@Service:Stereotypes a component as a service.
@Repository: Stereotypes a component as a repository. Also indicates that SQLExceptions thrown from the component’s methods should be translated into Spring DataAccessExceptions.
@Controller:Stereotypes a component as a Spring MVC controller.

Configure Database Connection

To store our products I've used MySQL db. For database connection configuration create new application context under the WEB-INF/spring folder with name applicationContext-dao.xml. Content of this XML is below.

        <?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:context="http://www.springframework.org/schema/context"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
        default-autowire="byName">

        <!-- Scans within the base package of the application for @Components to configure as beans -->
        <bean id="placeholderConfig"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:/environment/db.properties" />
        </bean>


        <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="showSql" value="true" />
        <property name="generateDdl" value="true" />
        <property name="databasePlatform" value="${db.dialect}" />
        </bean>
        </property>
        <property name="persistenceUnitName" value="forceDatabase"/>
        </bean>

        <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${db.driver}" />
        <property name="url" value="${db.url}" />
        <property name="username" value="${db.username}" />
        <property name="password" value="${db.password}" />
        </bean>

        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"/>

        <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />


        </beans>
    

In addition to this configuration class we need persistence.xml under the resource META-INF folder. PropertyPlaceholderConfigurerer helps to read configuration from properties file. Create db.properties file under the environment package.Do not for get to import this new application context from root-context xml. Add following line into root-context.xml file

        <import resource="applicationContext-dao.xml"/>
    

Currently our projects structure should be like below.

        └── src
        ├── main
        │   ├── java
        │   │   └── com
        │   │       └── ds
        │   │           └── springexample
        │   │               ├── controller
        │   │               │   └── MainPageController.java
        │   │               ├── dao
        │   │               │   └── ProductRepository.java
        │   │               ├── model
        │   │               │   └── Product.java
        │   │               └── service
        │   │                   └── ProductManagerService.java
        │   ├── resources
        │   │   ├── environment
        │   │   │   └── db.properties
        │   │   ├── log4j.xml
        │   │   └── META-INF
        │   │       └── persistence.xml
        │   └── webapp
        │       ├── META-INF
        │       └── WEB-INF
        │           ├── spring
        │           │   ├── applicationContext-dao.xml
        │           │   ├── root-context.xml
        │           │   └── servlet-context.xml
        │           ├── views
        │           │   └── home.jsp
        │           └── web.xml
        └── test

    

Content of persistence.xml

        <persistence xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
        version="1.0">

        <persistence-unit name="forceDatabase" transaction-type="RESOURCE_LOCAL">
        <properties>
        <property name="datanucleus.storeManagerType" value="force"/>
        <property name="datanucleus.autoCreateSchema" value="true"/>
        <property name="datanucleus.validateTables" value="false"/>
        <property name="datanucleus.validateConstraints" value="false"/>
        <property name="datanucleus.Optimistic" value="false"/>
        <property name="datanucleus.datastoreTransactionDelayOperations" value="true"/>
        <property name="datanucleus.jpa.addClassTransformer" value="false"/>
        <property name="datanucleus.cache.level2.type" value="none"/>
        <property name="datanucleus.detachAllOnCommit" value="true"/>
        <property name="datanucleus.copyOnAttach" value="false"/>

        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.transaction.flush_before_completion" value="true"/>
        <property name="hibernate.cache.provider_class" value="org.hibernate.cache.HashtableCacheProvider"/>
        </properties>
        </persistence-unit>
        </persistence>
    

Content of db properties

        db.password=6512896
        db.username=root
        db.url=jdbc:mysql://localhost:3306/Inventory
        db.dialect=org.hibernate.dialect.MySQL5Dialect
        db.driver=com.mysql.jdbc.Driver
    

I've created database with name Inventory. When application initialize hibernate automatically create Product table inside of Inventory database.

Create Product Controller

package com.ds.springexample.controller;

import com.ds.springexample.model.Product;
import com.ds.springexample.service.ProductManagerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.inject.Inject;
import java.util.List;

/**
 * @author Dogukan Sonmez
 */

@Controller
@RequestMapping("/product/")
public class ProductController {

    private static final Logger logger = LoggerFactory.getLogger(ProductController.class);

    @Inject
    public ProductManagerService managerService;

    @RequestMapping(method = RequestMethod.GET, value = "edit")
    public ModelAndView editPerson(@RequestParam(value = "product", required = false) Product product) {
        logger.debug("Received request to edit person id : ");
        ModelAndView mav = new ModelAndView();
        mav.setViewName("edit");
        if (product == null) {
            product = new Product();
        }
        mav.addObject("product", product);
        return mav;
    }


    @RequestMapping(value = "{id}", method = RequestMethod.GET)
    public ModelAndView getProductById(@PathVariable Long id) {
        logger.info("Get product by id : " + id);
        ModelAndView mav = new ModelAndView();
        mav.setViewName("edit");
        Product product = null;
        if (id == null) {
            product = new Product();
        } else {
            product = managerService.getProductById(id);
        }
        mav.addObject("product", product);
        return mav;
    }


    @RequestMapping(value = "list", method = RequestMethod.GET)
    public ModelAndView getProducts() {
        List productList = managerService.getAllProducts();
        ModelAndView mv = new ModelAndView();
        mv.addObject("products", productList);
        mv.setViewName("list");
        logger.info("requesting /product");
        return mv;
    }


    @RequestMapping(method = RequestMethod.POST)
    public String addProduct(@ModelAttribute("product") Product product) {
        logger.info("Received post back on product " + product);
        managerService.saveProduct(product);
        logger.info("POST");
        return "redirect:list";

    }

    @RequestMapping(method = RequestMethod.DELETE)
    public String deleteProduct(@PathVariable Long id) {
        logger.info("DELETE ");
        return "redirect:list";
    }

    @RequestMapping(method = RequestMethod.PUT)
    public String updateProduct() {
        logger.info("PUT ");
        return "redirect:list";
    }

}
    

I injected productmanagerservice to manage our product object.
@RequestMapping:Maps a URL pattern and/or HTTP method to a method or controller type.

RESTful Web services

As we can see from product controller class with spring it is very easy to develop RESTful web services. Spring added support for building RESTful web services in Release 3. Although the REST support is not an implementation of JAX-RS, it has more features than the specification defines. The REST support is integrated seamlessly into Spring's MVC layer and can be easily adopted by applications that build with Spring.

The major features of Spring REST support include:
Annotations, such as @RequestMapping and @PathVariable, to support resource identification and URI mappings
ContentNegotiatingViewResolver to support different representations with different MIME/content types Seamless integration into the original MVC layer with a similar programming model

REST asks developers to use HTTP methods explicitly and in a way that's consistent with the protocol definition. This basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods. According to this mapping:
To create a resource on the server, use POST.
To retrieve a resource, use GET.
To change the state of a resource or to update it, use PUT.
To remove or delete a resource, use DELETE.

Create new views

To list products or edit and save products we need following jsp files. Create list.jsp and edit.jsp under the views folder And we need to modify home.jsp file add following line to point products list. Content of home.jsp file.


        <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
        <%@ page session="false" %>
        <html>
        <head>
        <title>Home</title>
        </head>
        <body>
        <h1>
        Hello world!
        </h1>
        ${controllerMessage}<br/>
        <br/>
        <br/>
        <a href="product/list">Go to the Product list</a>
        </body>
        </html>
    

Content of edit.jsp file

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <%@ page session="false" %>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <html>
    <head>
    <title>Home</title>
    </head>
    <body>
    <form:form method="POST" commandName="product" style="padding:8px">
    <p>
    Description<br/>
    <form:input path="description"/>
    </p>
    <p>
    Price<br/>
    <form:input path="price"/>
    </p>
    <input type="submit" value="Save"/>
    </form:form>
    </body>
    </html>

Content of list.jsp file

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ page session="false"%>
    <html>
    <head>
    <title>Home</title>
    </head>
    <body>
    <h1>Listing Products</h1>
    <c:forEach items="${products}" var="prd">
    <a href="edit?id=${prd.id}">${prd.id} -
    ${prd.description} ${prd.price}</a>
    <br />
    </c:forEach>
    <a href="edit"> Add Product</a>
    </body>
    </html>

Write logic for service layer and dao layer

Up to now we've created our project folder structure,model object,service object,repository object and required configurations. We are one step behind to finish the project.
Fill methods of productManagerService object with following code.

package com.ds.springexample.service;

import com.ds.springexample.dao.ProductRepository;
import com.ds.springexample.model.Product;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Dogukan Sonmez
 */

@Service
public class ProductManagerService {

    private static final Logger logger = LoggerFactory.getLogger(ProductManagerService.class);

    @Autowired
    private ProductRepository repository;

    public Product getProductById(Long id) {
        if (id != null) {
            return repository.get(id);

        } else {
            return new Product();
        }
    }

    public List getAllProducts() {
        return repository.getAll();
    }


    public void saveProduct(Product product) {
        logger.info("Saing product: " + product);
        repository.save(product);

    }

    public void updateProduct(Product product) {
        repository.update(product);
    }

    public void deleteProduct(Long id) {

    }

}
   

According to me we don't need service object at this project. we can directly use repository class. But to see the many technology in one project I added service layer.
@Autowired:Declares a constructor, field, setter method, or configuration method to be autowired by type. Items annotated with @Autowired do not have to be public.

Content of repository object:

package com.ds.springexample.dao;

import com.ds.springexample.model.Product;
import org.hibernate.annotations.Entity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;

/**
 * @author Dogukan Sonmez
 */

@Repository
public class ProductRepository {

    private static final Logger logger = LoggerFactory.getLogger(ProductRepository.class);

    @PersistenceContext
    private EntityManager entityManager;


    public void save(Product product) {
        logger.info("Product repository save product:" + product);
        EntityManager em = entityManager.getEntityManagerFactory().createEntityManager();
        em.getTransaction().begin();
        em.persist(product);
        em.getTransaction().commit();
        logger.info("entity manager" + entityManager);
    }

    public void update(Product product) {
        entityManager.merge(product);
        entityManager.getTransaction().commit();
    }

    @Transactional(readOnly = true)
    public Product get(Long id) {
        logger.info("get product by id:" + id);
        return entityManager.find(Product.class, id);
    }

    @Transactional(readOnly = true)
    public List getAll() {
        return entityManager.createQuery("select p from Product p").getResultList();
    }

}

The @Transactional annotation is used along with the <tx:annotation-driven> element to declare transactional boundaries and rules as class and method metadata in Java.
@Transactional: Declares transactional boundaries and rules on a bean and/or its methods.

Project directory structure

    └── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── ds
    │   │           └── springexample
    │   │               ├── controller
    │   │               │   ├── MainPageController.java
    │   │               │   └── ProductController.java
    │   │               ├── dao
    │   │               │   └── ProductRepository.java
    │   │               ├── model
    │   │               │   └── Product.java
    │   │               └── service
    │   │                   └── ProductManagerService.java
    │   ├── resources
    │   │   ├── environment
    │   │   │   └── db.properties
    │   │   ├── log4j.xml
    │   │   └── META-INF
    │   │       └── persistence.xml
    │   └── webapp
    │       └── WEB-INF
    │           ├── spring
    │           │   ├── applicationContext-dao.xml
    │           │   ├── root-context.xml
    │           │   └── servlet-context.xml
    │           ├── views
    │           │   ├── edit.jsp
    │           │   ├── home.jsp
    │           │   └── list.jsp
    │           └── web.xml
    └── test

We done!

To sum up all our work. By using spring 3 we've created a web application based on RESTful concept(as much as possible) We've used hibernate and JPA for object relational mapping. We've used maven for building project and jetty plugin quickly see our work. So run following command and see what have you done! For those who want to download all code you can find in https://github.com/dogukansonmez/spring-example

        mvn clean install
        mvn jetty:run