Spring 4 MVC Hibernate JPA Java Config Tutorial

Spring 4 MVC Hibernate JPA Java Config Tutorial helps developers who are looking for spring java based configuration to initiate MVC and database  application context.  In this spring mvc jpa example, we will see customer CRUD operations, where it displays list of customers, add and edit customer.

If you are looking for XML bases example for this same, please visit below tutorial:

Spring 4 MVC Hibernate JPA XML Config Example

Spring 4 MVC Hibernate JPA XML Config Example helps developers who are looking for spring XML based configuration to initiate MVC and root application context. READ MORE

Installations:

  • Eclipse
  • Tomcat 8
  • Spring 4
  • Spring ORM and Transaction Management
  • Hibernate 5
  • Bootstrap
  • MVC
  • Maven

As shown in the below, This tutorial is more like Spring MVC CRUD with transactions with below functionalities:

  • Displaying Customer List
  • Adding new customer
  • Editing customer
  • Deleting customer.

Spring 4 MVC CRUD Tutorial

Spring 4 MVC Hibernate CRUD Example:

  • Lets create a maven project with below details: In Eclipse, click File -> New  -> Project -> Maven -> Maven Project
  • Select simple maven project and click on Next
  • Give below details and click on FinishMaven New Project
  • Lets create the below project structure and we will follow recommended standards in  creating layers:
    • org.javasavvy.demo.app.config:  This package contains root application context such as database config, services etc
    • org.javasavvy.demo.web.config :  It contans web mvc dispatcher servlet config and web application intializer as we are not using web.xml file
    • org.javasavvy.demo.ui.controller : It contains controllers
    • org.javasavvy.demo.dao   :    Data access layer that inject EntityManager
    • org.javasavvy.demo.services : Service Layer classes
    • org.javasavvy.demo.entity:  Contains JPA EntitiesProject Strucure
  • As this is maven project, you need to update pom.xml file with dependencies.Please click here to download pom.xml

Application Java Configuration Initialization:

  • In this tutorial, We will not use web.xml. Spring provides WebApplicationInitializer interface, detects the class automatically and intializes Dispatcher Servlet.
  • AbstractDispatcherServletInitializer class is abstract class and implementation of WebApplicationInitializer makes easy to register the DispatcherServlet by simply overriding methods to specify the servlet mapping and the location of the DispatcherServlet
  • Create  WebAppinitializer  class which is replacement of web.xml like shown below:
  • In this, register DatabaseConfig and WebMVCConfig to AnnotationConfigWebApplicationContext class.
    1.  public class CustomerWebAppIntializer implements WebApplicationInitializer {
        public void onStartup(ServletContext container) throws ServletException {
            AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
             webContext.register(DatabaseConfig.class);
             webContext.register(CustomerWebMVCConfig.class);
             webContext.setServletContext(container);
             ServletRegistration.Dynamic reg=container.addServlet("dispatcherServlet", new DispatcherServlet(webContext));
             reg.setLoadOnStartup(1);
             reg.addMapping("*.action");
        }
      }

Spring MVC Java Config Class:

  • Spring MVC Configuration required for distacher servlet to create handlers, controllers and view resolvers.
  • . Lets create CustomerWebMVCConfig class to configures that need to annotate with @Configuration,@EnableMVC :
    • View Resolver : Create ViewResolver bean
    • Static View Paths via ViewControllerRegistry:  This is equivalant to <mvc:view-controller  /> annotations to register view with controllers directly
    • Cotroller Component Scan :  In this set basePackages to MVC Controller packages and it will scan the packages and create controller bean automatically
    • @Configuration
      @EnableWebMvc
      @ComponentScan(basePackages={"org.javasavvy.demo.ui.controller"})
      public class CustomerWebMVCConfig extends WebMvcConfigurerAdapter {
       @Override
       public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/").setViewName("home");
            registry.addViewController("/home.action").setViewName("home");
            registry.addViewController("/customer/customerForm.action").setViewName("addCustomer");
       }
        @Bean
       public ViewResolver viewResolver() {
            InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
            viewResolver.setViewClass(JstlView.class);
            viewResolver.setPrefix("/WEB-INF/views/");
            viewResolver.setSuffix(".jsp");
            return viewResolver;
       } 
       }

App and Database Java config : 

  • This is root application context which need to register with AnnotationConfigWebApplicationContext class to load beans
  • @ComponentScan  :  Set services and dao layer packages path to basePackages attribute. It scans these folder and creates bean which are annotated with @Component,@Service,@Repository

Spring JPA and Transaction Configuration:

  • spring JPA configuration is available in org.springframework.orm.jpa library which you need to add dependency
  • JPA requires EntityManager to perform data base operations. In Spring, you can get the EntityManager below ways:
    • LocalEntityManagerFactoryBean: This is suitable for simple applications that uses JPA for Data access only. It requires persistence unit name only. you can not use the existing data source and  no support for global transactions
    • LocalContainerEntityManagerFactoryBean : It gives full control and most powerful JPA setup option, allows for flexible local configuration within the application.  This allows you to customize below :
      • persistance unit name
      • entity packages path to scan
      • existing Data Source
      • JPA properties
      • you can set local and global transaction

Spring Transaction Managers:

  • @EnableTransactionManagement is equivalent to <tx:annotation-driven/> and looks for @Transaction classes and enables declarative transaction.
  • JtaTransactionManager:  is appropriate for handling distributed transactions, where  transactions that spans multiple resources, and for controlling transactions on application server resources. Mostly you will use this for JNDI data source
  • DataSourceTransactionManager is appropriate for a single JDBCDataSource or Spring JDBC
  • HibernateTransactionManager is appropriate for accessing a single resource with Hibernate SessionFactory
  • JpaTransactionManager is appropriate for applications that uses EntityManagerFactory and provides belowcapabilities
    • local JDBC transactions such as transaction-specific isolation levels
    • resource-level read-only optimizations against  regular JDBC connection pool
    • It also supports direct DataSource access within  transaction
    • JpaTransctionManager need to configure with JPA Provider to make transactions. In this example, we set JPA Provider which HibernateJPAProvider to EnityManagerFactoryBean. Spring supports out of the box dialects for the EclipseLink, Hibernate and OpenJPA JPA implementations
  • @Configuration
    @ComponentScan(basePackages={"org.javasavvy.demo.services","org.javasavvy.demo.dao"})
    @EnableTransactionManagement
    public class DatabaseConfig {
     
     @Bean
     public DriverManagerDataSource getDataSource() {
           DriverManagerDataSource dataSource = new DriverManagerDataSource();
              dataSource.setDriverClassName("com.mysql.jdbc.Driver");
              dataSource.setUrl("jdbc:mysql://localhost:3306/javasavvy");
              dataSource.setUsername("root");
              dataSource.setPassword("root");
          return dataSource;
     }
     @Bean
     @Autowired
     public PlatformTransactionManager getTransactionManager(EntityManagerFactory emf) throws NamingException{
          JpaTransactionManager jpaTransaction = new JpaTransactionManager();
          jpaTransaction.setEntityManagerFactory(emf);
          return jpaTransaction;
     }
    @Bean
     public LocalContainerEntityManagerFactoryBean getEMF() {
     
         LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
         emf.setDataSource(getDataSource());
         emf.setPersistenceUnitName("spring-jpa-unit");
         emf.setJpaVendorAdapter(getHibernateAdapter());
             Properties jpaProperties = new Properties();
            jpaProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
            jpaProperties.put("hibernate.hbm2ddl.auto", "update");
            jpaProperties.put("hibernate.show_sql", "true");
            jpaProperties.put("hibernate.format_sql","false");
          emf.setJpaProperties(jpaProperties);
       return emf;
     }
      @Bean
      public JpaVendorAdapter getHibernateAdapter() {
          return new HibernateJpaVendorAdapter();
      }
     
    }

Data Access Layer Configuration:

  • Lets create a entity customer and map the customer entry persistence.xml file in src/main/resource/META-INF folder.
  • @Entity
    @Table(name="customer")
    public class Customer {
     
     @Id
     @GeneratedValue(strategy=GenerationType.AUTO)
     private long customerId;
     private String customerName;
     private String country;
     
     @Temporal(TemporalType.TIMESTAMP)
     private Date createdDate;
     
     @Temporal(TemporalType.TIMESTAMP)
     private Date updateDate;
  • Create persistence.xml in src/main/resource/META-INF folder and create persitence unit name “spring-jpa-unit” which need to map to EntityManagerFactory bean
    1. <?xml version="1.0" encoding="UTF-8"?>
      <persistence version="2.0" 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_2_0.xsd">
       <persistence-unit name="spring-jpa-unit">
       <class>org.javasavvy.demo.entity.Customer</class>
       </persistence-unit>
      </persistence>
  • Create CustomerDAO Interface that exposes below methods
    1. public interface CustomerDAO {
       
       public Customer addCustomer(Customer customer);
       public Customer updateCustomer(Customer customer);
       public void deleteCustomer(long customerId);
       public Customer getCustomer(long customerId);
       public List<Customer> getCustomers();
      
      }
  • Create CustomerDAOImpl class for CRUD operations on customer entity. This class uses entityManager via @PersistenceContext annotation
    1. @Repository("customerDAO")
      @Transactional
      public class CustomerDAOImpl implements CustomerDAO{
       
        @PersistenceContext
       public EntityManager entityManager;
      
       @Transactional(readOnly=false)
       public Customer addCustomer(Customer customer) {
           entityManager.persist(customer);
           return customer;
       }
       @Transactional(readOnly=false)
       public Customer updateCustomer(Customer customer) {
             entityManager.merge(customer);
             return customer;
       }
       @Transactional(readOnly=false)
       public void deleteCustomer(long customerId) {
       // delete code goes here
       }
      
       @Transactional(readOnly=true)
       public Customer getCustomer(long customerId) {
            String sql = "select customer from Customer customer where customer.customerId="+customerId;
            try{
                return (Customer) entityManager.createQuery(sql).getSingleResult();
            }catch(Exception e){
           }
            return null;
       }
       @Transactional(readOnly=true)
       public List<Customer> getCustomers() {
           return entityManager.createQuery("select customer from Customer customer").getResultList();
       }
      }

Service Layer:

Lets create Service Layer that uses CustomerDAO  classes

  • Customer Service Interface:
    1. public interface CustomerService {
       
       public Customer addCustomer(String customerName, String country);
       public Customer updateCustomer(long customerId,String customerName, String country);
       public Customer getCustomer(long customerId);
       public List<Customer> getAllCustomers();
      }
  • CustomerServiceImpl:  annotate CustomerServiceImpl class wtih @Service(“customerService”), provide the bean name also here to avoid autowire dependency issues.
  • @Transactional annotatation will creates new transction if not exists
    1. @Service("customerService")
      @Transactional
      public class CustomerServiceImpl implements CustomerService {
      
       @Autowired(required=true)
       @Qualifier("customerDAO")
       private CustomerDAO customerDAO;
       
       @Transactional
       public Customer addCustomer(String customerName, String country) {
              System.out.println("Cusomer Service create invoked:"+customerName);
              Customer customer = new Customer();
              customer.setCountry(country);
              customer.setCustomerName(customerName);
              customer.setCreatedDate(new Date());
              customer.setUpdateDate(new Date());
             customer = customerDAO.addCustomer(customer);
             return customer;
       }
       @Transactional
       public Customer updateCustomer(long customerId,String customerName, String country) {
       
            System.out.println("Cusomer Service Update invoked:"+customerName);
            Customer customer = new Customer();
            customer.setCustomerId(customerId);
            customer.setCountry(country);
            customer.setCustomerName(customerName);
           customer.setUpdateDate(new Date());
            customer = customerDAO.updateCustomer(customer);
            return customer;
       }
       public Customer getCustomer(long customerId) {
             return customerDAO.getCustomer(customerId);
       }
       public List<Customer> getAllCustomers() {
           return customerDAO.getCustomers();
       }
      }

MVC Layer:

  • Create Controller class that uses CustomerService to access CRUD operations.
    Spring MVC 4 CRUD Exampleheader.jsp
  • <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <c:set var="appPath" value="${pageContext.request.contextPath}"/>
    <%
     String contextPath = request.getContextPath();
    %>
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href='<%=contextPath+"/css/bootstrap.min.css" %>' rel="stylesheet">
    <link href='<%=contextPath+"/css/font-awesome.min.css" %>' rel="stylesheet">
    <link href='<%=contextPath+"/css/customer.css" %>' rel="stylesheet">
    </head>
    <body>
     <div class="navbar navbar-inverse navbar-fixed-left">
     <div class="container-fluid">
     <div class="navbar-header">
     <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
     <span class="icon-bar"></span>
     <span class="icon-bar"></span>
     <span class="icon-bar"></span> 
     </button>
     <a class="navbar-brand" href="#">JavaSavvy</a>
     </div>
     <div class="collapse navbar-collapse" id="myNavbar">
     <ul class="nav navbar-nav">
     
     <li ><a href="<%=contextPath%>/home.action">Home</a></li>
     <li><a href="<%=contextPath%>/customer/customers.action">Customers</a></li>
     <li><a href="#">Page 2</a></li> 
     <li><a href="#">Page 3</a></li> 
     </ul>
     <ul class="nav navbar-nav navbar-right">
     <li><a href="#"><span class="glyphicon glyphicon-user"></span> Sign Up</a></li>
     <li><a href="#"><span class="glyphicon glyphicon-log-in"></span> Login</a></li>
     </ul>
     </div>
     </div>
     </div>
  • footer.jsp
    • <script src="<%=request.getContextPath() + "/js/jquery-1.11.1.min.js"%>"></script>
      <script src="<%=request.getContextPath() + "/js/bootstrap.min.js"%>"></script>
      </body>
      </html>
  • customers.jsp
    • <%@ include file="header.jsp" %>
      
      <div class="container-fluid">
       <div class="row">
       
       <div class="col-md-12">
       <div class="">
       <a class="btn btn-primary" href="<%=contextPath%>/customer/customerForm.action" style="margin-left:50%;">Add Customer</a>
       </div>
       <div class="table-responsive">
      
       <table id="mytable" class="table table-bordered" style="margin:10px;width:60%;">
       <thead>
       <th>Customer Id</th>
       <th>Customer Name</th>
       <th>Country</th>
       <th>Created Date</th>
       <th>Edit</th>
       </thead>
       <tbody>
       <c:forEach var="customer" items="${customers}">
       <tr>
       <td>${customer.customerId }</td>
       <td>${customer.customerName }</td>
       <td>${customer.country }</td>
       <td>${customer.createdDate }</td>
       <td>
       <a class="btn btn-primary" href="<%=contextPath%>/customer/editCustomerView/${customer.customerId}.action">Edit</a>
       <a class="btn btn-warning" href="<%=contextPath%>/customer/deleteCustomer/customerId=${customer.customerId}.action">Delete</a>
       </td>
       </tr>
       </c:forEach>
       </tbody>
       </table>
       <div class="clearfix"></div>
       </div>
       </div>
       </div>
      </div>
      
      <%@ include file="footer.jsp" %>
  • add Customer.jsp
    • <%@ include file="header.jsp" %>
      <div class="container-fluid">
      
       <div class="row">
       <div class="col-md-6">
       </div>
       <div class="col-md-6">
       <h2>Add Customer</h2>
       <form class="form-horizontal" action="<%=request.getContextPath()%>/customer/addCustomer.action" method="post" role="form">
       <div class="form-group">
       <label for="title">Customer Name</label>
       <div class="input-group">
       <span class="input-group-addon"> <span class="glyphicon glyphicon-cog"></span></span>
       <input type="text" class="form-control" name="name" id="name"
       placeholder="Enter Name" required>
       </div>
       </div>
       <div class="form-group">
       <label for="desc">Country</label>
       <div class="input-group">
       <span class="input-group-addon"> <span
       class="glyphicon glyphicon-pencil"></span></span> <input type="text"
       class="form-control" name="country" id="desc"
       placeholder="Enter Country" required>
       </div>
       </div>
       <button type="submit" class="btn btn-primary">Submit</button>
       </form>
       
       </div>
       </div>
      </div>
  • edit customer.jsp
    • <%@ include file="header.jsp" %>
      <div class="container-fluid">
      
       <div class="row">
       <div class="col-md-6">
       </div>
       <div class="col-md-6">
       <h2>Edit Customer: ${customer.customerName }</h2>
       <form class="form-horizontal" action="<%=request.getContextPath()%>/customer/editCustomer.action" method="post" role="form">
       <input type="hidden" value="${customer.customerId }" name="customerId" id="customerId">
       <div class="form-group">
       <label for="title">Customer Name</label>
       <div class="input-group">
       <span class="input-group-addon"> <span class="glyphicon glyphicon-cog"></span></span>
       <input type="text" value="${customer.customerName }" class="form-control" name="name" id="name"
       placeholder="Enter Name" required>
       </div>
       </div>
       <div class="form-group">
       <label for="desc">Country</label>
       <div class="input-group">
       <span class="input-group-addon"> <span
       class="glyphicon glyphicon-pencil"></span></span> <input type="text"
       class="form-control" name="country" value="${customer.country }"
       placeholder="Enter Country" required>
       </div>
       </div>
       <button type="submit" class="btn btn-primary">Update</button>
       </form>
       
       </div>
       </div>
      </div>
  • home.jsp
    • <%@ include file="header.jsp" %>
       <div class="row">
       
       <div class="col-md-12">
       
       This is Home page
       </div>
       </div>
      
      <%@ include file="footer.jsp" %>
  • customer.css
    • .navbar-inverse .navbar-nav>li>a {
       color: white;
      }
      .navbar-inverse {
       background-color: #428bca;
       border-color: none;
      }
  • Please add Jquery and bootstrap files as per below folder structure in webapp directory
  • view

Hope this helps.

10 Comments

  1. Krunal Patel

    Nice article and very helpful.

    Can we create spring mvc porlet in liferay using java config which you mention above?

    Thanks,
    Krunal

    Reply
    1. Jayaram Pokuri (Post author)

      Yes. We can create Spring MVC Portlet as it follows JSR 286 Portlet Specifications.

      Reply
  2. CAIO DE ALMEIDA SANTORO SANTORO

    didn’t work. i’m getting 404

    Reply
  3. DevRock

    Cannot find link to download source code

    Reply
    1. Jayaram Pokuri (Post author)
  4. Alex

    Hi guys! I’m newbie in Spring and I need your help. I receive 404 error when try to run the example under my GF server. May be I missed any config files?

    Reply
  5. Jayaram Pokuri (Post author)
  6. kumar

    Hi Jayaram,

    While running this example, getting this error. Can you please help me in this.

    The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application

    Reply
    1. saravanan

      how to resolve ?

      The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application

      Reply
      1. Emma Keyes

        I solved the same problem. I’ve just added JSTL-1.2.jar to /apache-tomcat-x.x.x/lib and set scope to provided in maven pom.xml:

        jstl
        jstl
        1.2
        provided

        Reply

Leave a Comment

Your email address will not be published. Required fields are marked *