.code { background:#f5f8fa; background-repeat:no-repeat; border: solid #5C7B90; border-width: 1px 1px 1px 20px; color: #000000; font: 13px 'Courier New', Courier, monospace; line-height: 16px; margin: 10px 0 10px 10px; max-height: 200px; min-height: 16px; overflow: auto; padding: 28px 10px 10px; width: 90%; } .code:hover { background-repeat:no-repeat; } .code { background:#f5f8fa; background-repeat:no-repeat; border: solid #5C7B90; border-width: 1px 1px 1px 20px; color: #000000; font: 13px 'Courier New', Courier, monospace; line-height: 16px; margin: 10px 0 10px 10px; min-height: 16px; overflow: auto; padding: 28px 10px 10px; width: 90%; } .code:hover { background-repeat:no-repeat; }

Friday, April 3, 2020

SPRING MVC SIMPLE CRUD APPLICATION




Spring MVC is one of the Most Popular Application Framework on the internet, So today in this article, let’s build a simple CRUD application.

The goal of the application is to display the list of books, adding a new book, updating the existing book and deleting a book.

TOOLS AND TECHNOLOGIES USED
  • Spring 4
  • Hibernate 5
  • MYSQL
  • Maven 3.3.9
  • eclips Oxygen
  • Apache Tomcat 8

step 1

First let’s create a DB for our application, open your MySQL Workbench and add execute the following command,





Let’s start with the backend, Here is the project structure of Spring REST application



      I don’t go over in detail about the REST API’s, I believe you all know that the concept of API. Long story short, API’s are nothing but URL’s when we hit those URL’s/Consume those URL’s we will get JSON data that’s it. 
So let’s look at how to build such API’s using Spring REST

step 2


Create Maven project using Eclips IDE.

step 3

Since we are using a maven, first let’s add all the dependencies that are required for our application.

pom.xml

 <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 https://maven.apache.org/xsd/maven-4.0.0.xsd">  
  <modelVersion>4.0.0</modelVersion>  
  <groupId>com.madhusanka</groupId>  
  <artifactId>BookAPI</artifactId>  
  <version>0.0.1-SNAPSHOT</version>  
  <packaging>war</packaging>  
  <properties>  
   <failOnMissingWebXml>false</failOnMissingWebXml>  
  </properties>  
   <dependencies>  

   <!-- Spring MVC Dependency -->  
   <dependency>  
    <groupId>org.springframework</groupId>  
    <artifactId>spring-webmvc</artifactId>  
    <version>4.3.10.RELEASE</version>  
   </dependency>  

   <!-- Spring ORM -->  
   <dependency>  
    <groupId>org.springframework</groupId>  
    <artifactId>spring-orm</artifactId>  
    <version>4.3.10.RELEASE</version>  
   </dependency>  

   <!-- Hibernate ORM -->  
   <dependency>  
    <groupId>org.hibernate</groupId>  
    <artifactId>hibernate-core</artifactId>  
    <version>5.2.11.Final</version>  
   </dependency>  

   <!-- Hibernate-C3P0 Integration -->  
   <dependency>  
    <groupId>org.hibernate</groupId>  
    <artifactId>hibernate-c3p0</artifactId>  
    <version>5.2.11.Final</version>  
   </dependency>  

   <!-- c3p0 -->  
   <dependency>  
    <groupId>com.mchange</groupId>  
    <artifactId>c3p0</artifactId>  
    <version>0.9.5.2</version>  
   </dependency>  

   <!-- Mysql Connector -->  
   <dependency>  
    <groupId>mysql</groupId>  
    <artifactId>mysql-connector-java</artifactId>  
    <version>6.0.5</version>  
   </dependency>  

   <!-- Jackson API for JSON -->  
   <dependency>  
    <groupId>com.fasterxml.jackson.core</groupId>  
    <artifactId>jackson-databind</artifactId>  
    <version>2.8.7</version>  
   </dependency>  

   <!-- Servlet Dependency -->  
   <dependency>  
    <groupId>javax.servlet</groupId>  
    <artifactId>javax.servlet-api</artifactId>  
    <version>3.1.0</version>  
    <scope>provided</scope>  
   </dependency>  

  </dependencies>  
  <build>  
   <plugins>  
    <plugin>  
     <artifactId>maven-compiler-plugin</artifactId>  
     <version>3.5.1</version>  
     <configuration>  
      <source>1.8</source>  
      <target>1.8</target>  
     </configuration>  
    </plugin>  
    <!-- Embedded Apache Tomcat required for testing web application -->  
    <plugin>  
     <groupId>org.apache.tomcat.maven</groupId>  
     <artifactId>tomcat7-maven-plugin</artifactId>  
     <version>2.2</version>  
     <configuration>  
      <path>/</path>  
     </configuration>  
    </plugin>  
   </plugins>  
  </build>  
 </project>  

Step 4

Next step is to create a Property file inside the resources folder and specify the database properties

db.properties

 # MySQL properties  
 mysql.driver=com.mysql.cj.jdbc.Driver  
 mysql.url=jdbc:mysql://localhost:3306/bookapi  
 mysql.user=root  
 mysql.password=sajith  

 # Hibernate properties  
 hibernate.show_sql=true  
 hibernate.hbm2ddl.auto=update  

 #C3P0 properties  
 hibernate.c3p0.min_size=5  
 hibernate.c3p0.max_size=20  
 hibernate.c3p0.acquire_increment=1  
 hibernate.c3p0.timeout=1800  
 hibernate.c3p0.max_statements=150  

Step 5


Once it’s done, let’s configure the spring and hibernate. Inside the config, package create a class called AppConfig and write the following code.

We will annotate this class with @Configuration, @PropertySource, @EnableTransactionManagement and @ComponentScan

@Configuration: It is a replacement to the XML based configuration for configuring spring beans. So instead of an XML file, we write a class and annotate that with @Configuration and define the beans in it using @Bean annotation on the methods.

@PropertySource: Specify the classpath of the property file. Reading values from a property file are far superior to hard coding them in our class files. If we hard code then we need to recompile if we want to change any of them.

@EnableTransactionManagement: It enables the transaction management. @ComponentScans: To scan the multiple packages.

Appconfig.java

 package com.madhusanka.spring.config;  
 import java.util.Properties;  
 import org.springframework.beans.factory.annotation.Autowired;  
 import org.springframework.context.annotation.Bean;  
 import org.springframework.context.annotation.ComponentScan;  
 import org.springframework.context.annotation.ComponentScans;  
 import org.springframework.context.annotation.Configuration;  
 import org.springframework.context.annotation.PropertySource;  
 import org.springframework.core.env.Environment;  
 import org.springframework.orm.hibernate5.HibernateTransactionManager;  
 import org.springframework.orm.hibernate5.LocalSessionFactoryBean;  
 import org.springframework.transaction.annotation.EnableTransactionManagement;  
 import static org.hibernate.cfg.Environment.*;  
 @Configuration  
 @PropertySource("classpath:db.properties")  
 @EnableTransactionManagement  
 @ComponentScans(value = {  
           @ComponentScan("com.madhusanka.spring.dao"),  
           @ComponentScan("com.madhusanka.spring.service")  
 })  
 public class Appconfig {  
      @Autowired  
        private Environment env;  
        @Bean  
        public LocalSessionFactoryBean getSessionFactory() {  
         LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();  
         Properties props = new Properties();  
         // Setting JDBC properties  
         props.put(DRIVER, env.getProperty("mysql.driver"));  
         props.put(URL, env.getProperty("mysql.url"));  
         props.put(USER, env.getProperty("mysql.user"));  
         props.put(PASS, env.getProperty("mysql.password"));  
         // Setting Hibernate properties  
         props.put(SHOW_SQL, env.getProperty("hibernate.show_sql"));  
         props.put(HBM2DDL_AUTO, env.getProperty("hibernate.hbm2ddl.auto"));  
         // Setting C3P0 properties  
         props.put(C3P0_MIN_SIZE, env.getProperty("hibernate.c3p0.min_size"));  
         props.put(C3P0_MAX_SIZE, env.getProperty("hibernate.c3p0.max_size"));  
         props.put(C3P0_ACQUIRE_INCREMENT,   
            env.getProperty("hibernate.c3p0.acquire_increment"));  
         props.put(C3P0_TIMEOUT, env.getProperty("hibernate.c3p0.timeout"));  
         props.put(C3P0_MAX_STATEMENTS, env.getProperty("hibernate.c3p0.max_statements"));  
         factoryBean.setHibernateProperties(props);  
         factoryBean.setPackagesToScan("com.madhusanka.spring.model");  
         return factoryBean;  
        }  
        @Bean  
        public HibernateTransactionManager getTransactionManager() {  
              HibernateTransactionManager transactionManager = new HibernateTransactionManager();  
              transactionManager.setSessionFactory(getSessionFactory().getObject());  
              return transactionManager;  
             }  
 }  

Step 6


Next step is to create MyWebAppInitializer class to initialize the servlet container, instead of using traditional web.xml, we will use java class that will extends AbstractAnnotationConfigDispatcherServletInitializer.

MyWebAppInitializer.java

 package com.madhusanka.spring.config;  
 import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;  
 public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{  
      @Override  
      protected Class<?>[] getRootConfigClasses() {  
           return new Class[] { Appconfig.class };  
      }  
      @Override  
      protected Class<?>[] getServletConfigClasses() {  
           return new Class[] { Webconfig.class };  
      }  
      @Override  
      protected String[] getServletMappings() {  
           return new String[] { "/" };  
      }  
 }  


Step 7


Next step is to create WebConfig class inside the config package, we will annotate this class with @Configuration, @EnableWebMvc, and @ComponentScan

@EnableWebMvc: @EnableWebMvc is used to enable Spring MVC. @EnableWebMvc is equivalent to <mvc:annotation-driven /> in XML.

Webconfig.java

 package com.madhusanka.spring.config;  
 import org.springframework.context.annotation.ComponentScan;  
 import org.springframework.context.annotation.Configuration;  
 import org.springframework.web.servlet.config.annotation.EnableWebMvc;  
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;  
 @Configuration  
 @EnableWebMvc  
 @ComponentScan(basePackages = {"com.madhusanka.spring.controller"})   
 public class Webconfig extends WebMvcConfigurerAdapter {  
 }  

Above three files are required for the spring and hibernate configuration.

Step 8


Now, let’s write the model class, create a Book class inside the model package.
Step 8

Above three files are required for the spring and hibernate configuration.

Now, let’s write the model class, create a Book class inside the model package.

Book.java

 package com.madhusanka.spring.model;  
 import javax.persistence.Entity;  
 import javax.persistence.GeneratedValue;  
 import javax.persistence.GenerationType;  
 import javax.persistence.Id;  
 @Entity(name = "Book")  
 public class Book {  
      @Id  
      @GeneratedValue(strategy = GenerationType.IDENTITY)  
      private Long id;  
      private String title;  
      private String auther;  
      public Long getId() {  
           return id;  
      }  
      public void setId(Long id) {  
           this.id = id;  
      }  
      public String getTitle() {  
           return title;  
      }  
      public void setTitle(String title) {  
           this.title = title;  
      }  
      public String getAuther() {  
           return auther;  
      }  
      public void setAuther(String auther) {  
           this.auther = auther;  
      }  
      @Override  
      public String toString() {  
           return "Book [id=" + id + ", title=" + title + ", auther=" + auther + "]";  
      }  
 }  

Step 9

Now, let’s create an Interface for DAO, we will create BookDAO interface inside the dao package

BookDao.java

 package com.madhusanka.spring.dao;  
 import java.util.List;  
 import com.madhusanka.spring.model.Book;  
 public interface BookDAO { 
 
      //save the record  
      long save(Book book);  

      //get the single record  
      Book get(long id);  

      //get the all the record  
      List<Book> list();  

      //update the record  
      void update(long id,Book book);  

      //delete record  
      void delete(long id);  
 }  

Step 10


Now, let’s implement those methods in the BookDaoImp class and annotate this class with @Repository
@Repository: It is an annotation that marks the specific class as a Data Access Object, thus clarifying its role.

BookDaoImp.java


 package com.madhusanka.spring.dao;  
 import java.nio.channels.SeekableByteChannel;  
 import java.util.List;  
 import javax.websocket.Session;  
 import org.hibernate.SessionFactory;  
 import org.springframework.beans.factory.annotation.Autowired;  
 import org.springframework.stereotype.Repository;  
 import com.madhusanka.spring.model.Book;  
 @Repository  
 public class BookDAOImp implements BookDAO {  
      @Autowired  
      private SessionFactory SessionFactory;  
      @Override  
      public long save(Book book) {  
           SessionFactory.getCurrentSession().save(book);  
           return book.getId();  
      }  
      @Override  
      public Book get(long id) {  
           return SessionFactory.getCurrentSession().get(Book.class, id);  
      }  
      @Override  
      public List<Book> list() {  
           List<Book> list=SessionFactory.getCurrentSession().createQuery("from Book").list();  
           return list;  
      }  
      @Override  
      public void update(long id, Book book) {  
           Book oldBook= SessionFactory.getCurrentSession().byId(Book.class).load(id);  
           oldBook.setAuther(book.getAuther());  
           oldBook.setTitle(book.getTitle());  
      }  
      @Override  
      public void delete(long id) {  
      Book book = SessionFactory.getCurrentSession().byId(Book.class).load(id);  
      SessionFactory.getCurrentSession().delete(book);  
      }  
 }  



Step 11


Now, let’s create another Interface for service, we will be creating this service inside the service package

BookService.java

 package com.madhusanka.spring.service;  
 import java.util.List;  
 import com.madhusanka.spring.model.Book;  
 public interface BookService {  

      //save the record  
      long save(Book book);  

      //get the single record  
      Book get(long id);  

      //get the all the record  
      List<Book> list();  

      //update the record  
      void update(long id,Book book);  

      //delete record  
      void delete(long id);  
 }  

Step 12


Now, let’s implement those methods in the BookServiceImp class and annotate this with @Service
@Service: This tells hibernate it is a Service class where you will have @Transactional etc Service layer related annotations so hibernate treats it as a Service component.

BookServiceImp.java

 package com.madhusanka.spring.service;  
 import java.util.List;  
 import com.madhusanka.spring.model.Book;  
 public interface BookService {  

      //save the record  
      long save(Book book);  

      //get the single record  
      Book get(long id);  

      //get the all the record  
      List<Book> list();  

      //update the record  
      void update(long id,Book book);  

      //delete record  
      void delete(long id);  
 }  

Step 13


Finally, we will create a controller BookController inside the controller package and annotate with @RestController, which specifies that this is a REST controller

BookController.java

 package com.madhusanka.spring.controller;  
 import java.util.List;  
 import org.springframework.beans.factory.annotation.Autowired;  
 import org.springframework.http.ResponseEntity;  
 import org.springframework.web.bind.annotation.DeleteMapping;  
 import org.springframework.web.bind.annotation.GetMapping;  
 import org.springframework.web.bind.annotation.PathVariable;  
 import org.springframework.web.bind.annotation.PostMapping;  
 import org.springframework.web.bind.annotation.PutMapping;  
 import org.springframework.web.bind.annotation.RequestBody;  
 import org.springframework.web.bind.annotation.RestController;  
 import com.madhusanka.spring.model.Book;  
 import com.madhusanka.spring.service.BookService;  
 @RestController  
 public class BookController {  

      //get all the book  
      @Autowired  
      private BookService bookService;  
      @GetMapping("/api/book")  
      public ResponseEntity<List<Book>> list(){  
           List<Book> list= bookService.list();  
           return ResponseEntity.ok().body(list);  
      }  

      //save the book  
      @PostMapping("/api/book")  
      public ResponseEntity<?> save(@RequestBody Book book){  
           long id = bookService.save(book);  
           return ResponseEntity.ok().body("Book created ID: " +id);  
      }  

      //get single record  
      @GetMapping("/api/book/{id}")  
      public ResponseEntity<Book> get(@PathVariable("id") long id){  
           Book book = bookService.get(id);  
           return ResponseEntity.ok().body(book);  
      }  

      //update book record  
      @PutMapping("/api/book/{id}")  
      public ResponseEntity<?> update(@PathVariable long id,@RequestBody Book book){  
           bookService.update(id, book);  
           return ResponseEntity.ok().body("Record are updated:");  
      }  

      //delete book record  
      @DeleteMapping("/api/book/{id}")  
      public ResponseEntity<?> delete(@PathVariable("id") long id){  
           bookService.delete(id);  
           return ResponseEntity.ok().body("Book record deteted");  
      }  
 }  

That’s it for the backend, now we have 5 REST API’s

OUTPUT

  1. Create a new resource ( equivalent to SQL INSERT statement)       http://localhost:8081/bookapi/api/book
  2. Retrieve a resource ( equivalent to SQL SELECT statement)    http://localhost:8081/bookapi/api/book
  3. Update or modify a resource ( equivalent to SQL UPDATE statement)   http://localhost:8081/bookapi/api/book/2
  4. Delete a resource ( equivalent to SQL DELETE statement)     http://localhost:8081/bookapi/api/book/3



By : Madhusanka Edirimanna
        Pramodi Samaratunga
        Undergraduates- University of Moratuwa

No comments:

Post a Comment

SPRING MVC SIMPLE CRUD APPLICATION