Overview

Watch tutorial

Technologies Used

Eclipse Oxygen and Install Spring Tool Suite for Eclipse IDE

Spring Boot 2.1.0.BUILD-SNAPSHOT

spring-boot-starter-jdbc

spring-boot-starter-web

spring-boot-devtools

JSTL - JSP Standard Tag Library

tomcat-embed-jasper

mysql-connector-java

Bootstrap 4

Java 8

MySQL create database and tables

CREATE DATABASE `jackrutorial` /*!40100 DEFAULT CHARACTER SET utf8 */; DROP TABLE IF EXISTS `jackrutorial`.`employees`; CREATE TABLE `jackrutorial`.`employees` ( `employee_id` int(11) NOT NULL auto_increment, `first_name` varchar(45) NOT NULL default '', `last_name` varchar(45) NOT NULL default '', `email` varchar(45) NOT NULL default '', `phone` varchar(20) NOT NULL default '', `job_title` varchar(100) NOT NULL default '', PRIMARY KEY (`employee_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Project Directory

Creating a Spring Boot Project with Eclipse STS

Project Dependencies

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency>

<?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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jackrutorial</groupId> <artifactId>WebApplicationSpringBoot</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>WebApplicationSpringBoot</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.BUILD-SNAPSHOT</version> <relativePath /> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>4.0.0</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> </pluginRepositories> </project>

Model

package com.jackrutorial.model; public class Employee { private Integer employeeId; private String firstName; private String lastName; private String email; private String phone; private String jobTitle; public Integer getEmployeeId() { return employeeId; } public void setEmployeeId(Integer employeeId) { this.employeeId = employeeId; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getJobTitle() { return jobTitle; } public void setJobTitle(String jobTitle) { this.jobTitle = jobTitle; } }

package com.jackrutorial.model; import java.sql.ResultSet; import java.sql.SQLException; import org.springframework.jdbc.core.RowMapper; public class EmployeeRowMapper implements RowMapper<Employee> { @Override public Employee mapRow(ResultSet rs, int rowNum) throws SQLException { Employee employee = new Employee(); employee.setEmployeeId(rs.getInt("employee_id")); employee.setFirstName(rs.getString("first_name")); employee.setLastName(rs.getString("last_name")); employee.setEmail(rs.getString("email")); employee.setPhone(rs.getString("phone")); employee.setJobTitle(rs.getString("job_title")); return employee; } }

DAO Layer

package com.jackrutorial.dao; import java.util.List; import com.jackrutorial.model.*; public interface EmployeeDao { public List<Employee> getAllEmployees(); public Employee findeEmployeeById(int id); public void addEmployee(Employee employee); public void updateEmployee(Employee employee); public void deleteEmployee(int id); }

package com.jackrutorial.dao; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import com.jackrutorial.model.Employee; import com.jackrutorial.model.EmployeeRowMapper; @Transactional @Repository public class EmployeeDaoImpl implements EmployeeDao { @Autowired private JdbcTemplate jdbcTemplate; @Override public List<Employee> getAllEmployees() { String query = "SELECT * from employees"; RowMapper<Employee> rowMapper = new EmployeeRowMapper(); List<Employee> list = jdbcTemplate.query(query, rowMapper); return list; } @Override public Employee findeEmployeeById(int id) { String query = "SELECT * FROM employees WHERE employee_id = ?"; RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<Employee>(Employee.class); Employee employee = jdbcTemplate.queryForObject(query, rowMapper, id); return employee; } @Override public void addEmployee(Employee employee) { String query = "INSERT INTO employees(employee_id, first_name, last_name, email, phone, job_title) VALUES(?, ?, ?, ?, ?, ?)"; jdbcTemplate.update(query, employee.getEmployeeId(), employee.getFirstName(), employee.getLastName(), employee.getEmail(), employee.getPhone(), employee.getJobTitle()); } @Override public void updateEmployee(Employee employee) { String query = "UPDATE employees SET first_name=?, last_name=?, email=?, phone=?, job_title=? WHERE employee_id=?"; jdbcTemplate.update(query, employee.getFirstName(), employee.getLastName(), employee.getEmail(), employee.getPhone(), employee.getJobTitle(), employee.getEmployeeId()); } @Override public void deleteEmployee(int id) { String query = "DELETE FROM employees WHERE employee_id=?"; jdbcTemplate.update(query, id); } }

Service Layer

package com.jackrutorial.service; import java.util.List; import com.jackrutorial.model.Employee; public interface EmployeeService { public List<Employee> getAllEmployees(); public Employee findEmployeeById(int id); public void addEmployee(Employee employee); public void updateEmployee(Employee employee); public void deleteEmployee(int id); }

package com.jackrutorial.service; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.jackrutorial.dao.EmployeeDaoImpl; import com.jackrutorial.model.Employee; @Service public class EmployeeServiceImpl implements EmployeeService { @Autowired private EmployeeDaoImpl employeeDao; @Override public List<Employee> getAllEmployees() { return employeeDao.getAllEmployees(); } @Override public Employee findEmployeeById(int id) { return employeeDao.findeEmployeeById(id); } @Override public void addEmployee(Employee employee) { employeeDao.addEmployee(employee); } @Override public void updateEmployee(Employee employee) { employeeDao.updateEmployee(employee); } @Override public void deleteEmployee(int id) { employeeDao.deleteEmployee(id); } }

Employee Controller

package com.jackrutorial.controller; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import com.jackrutorial.model.Employee; import com.jackrutorial.service.EmployeeServiceImpl; @Controller @RequestMapping("/employee") public class EmployeeController { @Autowired private EmployeeServiceImpl employeeService; @RequestMapping(value= {"/", "/list"}, method=RequestMethod.GET) public ModelAndView getAllEmployees() { ModelAndView model = new ModelAndView(); List<Employee> list = employeeService.getAllEmployees(); model.addObject("employee_list", list); model.setViewName("employee_list"); return model; } @RequestMapping(value="/update/{id}", method=RequestMethod.GET) public ModelAndView editEmployee(@PathVariable int id) { ModelAndView model = new ModelAndView(); Employee employee = employeeService.findEmployeeById(id); model.addObject("employeeForm", employee); model.setViewName("employee_form"); return model; } @RequestMapping(value="/add", method=RequestMethod.GET) public ModelAndView addEmployee() { ModelAndView model = new ModelAndView(); Employee employee = new Employee(); model.addObject("employeeForm", employee); model.setViewName("employee_form"); return model; } @RequestMapping(value="/save", method=RequestMethod.POST) public ModelAndView saveOrUpdate(@ModelAttribute("employeeForm") Employee employee) { if(employee.getEmployeeId() != null) { employeeService.updateEmployee(employee); } else { employeeService.addEmployee(employee); } return new ModelAndView("redirect:/employee/list"); } @RequestMapping(value="/delete/{id}", method=RequestMethod.GET) public ModelAndView deleteEmployee(@PathVariable("id") int id) { employeeService.deleteEmployee(id); return new ModelAndView("redirect:/employee/list"); } }

Configuring Spring Boot for MySQL and view resolvers

spring.datasource.url=jdbc:mysql://localhost:3306/jackrutorial spring.datasource.username=root spring.datasource.password=root spring.mvc.view.prefix=/WEB-INF/jsp/ spring.mvc.view.suffix=.jsp

View Layer

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Employee List</title> <link href="../webjars/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" /> <script src="../webjars/bootstrap/4.0.0/js/bootstrap.min.js" ></script> <script src="../webjars/jquery/3.0.0/js/jquery.min.js" ></script> </head> <body> <div class="container"> <h2>Employee List</h2> <table class="table table-striped"> <thead> <tr> <th scope="row">Employee Id</th> <th scope="row">First Name</th> <th scope="row">Last Name</th> <th scope="row">Email</th> <th scope="row">Phone</th> <th scope="row">Job Title</th> <th scope="row">Edit</th> <th scope="row">Delete</th> </tr> </thead> <tbody> <c:forEach items="${employee_list }" var="employee" > <tr> <td>${employee.employeeId }</td> <td>${employee.firstName }</td> <td>${employee.lastName }</td> <td>${employee.email }</td> <td>${employee.phone }</td> <td>${employee.jobTitle }</td> <td> <spring:url value="/employee/update/${employee.employeeId }" var="updateURL" /> <a class="btn btn-primary" href="${updateURL }" role="button">Update</a> </td> <td> <spring:url value="/employee/delete/${employee.employeeId }" var="deleteURL" /> <a class="btn btn-primary" href="${deleteURL }" role="button">Delete</a> </td> </tr> </c:forEach> </tbody> </table> <spring:url value="/employee/add" var="addURL" /> <a class="btn btn-primary" href="${addURL }" role="button">Add New Employee</a> </div> </body> </html>

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %> <%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Employees</title> <link href="http://localhost:8080/webjars/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" /> <script src="http://localhost:8080/webjars/bootstrap/4.0.0/js/bootstrap.min.js" ></script> <script src="http://localhost:8080/webjars/jquery/3.0.0/js/jquery.min.js" ></script> </head> <body> <div class="container"> <spring:url value="/employee/save" var="saveURL" /> <h2>Employee</h2> <form:form modelAttribute="employeeForm" method="post" action="${saveURL }" cssClass="form"> <form:hidden path="employeeId"/> <div class="form-group"> <lable for="firstName">First Name</lable> <form:input path="firstName" cssClass="form-control" id="firstName" /> </div> <div class="form-group"> <lable for="lastName">Last Name</lable> <form:input path="lastName" cssClass="form-control" id="lastName" /> </div> <div class="form-group"> <lable for="email">Email</lable> <form:input path="email" cssClass="form-control" id="email" /> </div> <div class="form-group"> <lable for="phone">Phone</lable> <form:input path="phone" cssClass="form-control" id="phone" /> </div> <div class="form-group"> <lable for="jobTitle">Job Title</lable> <form:input path="jobTitle" cssClass="form-control" id="jobTitle" /> </div> <button type="submit" class="btn btn-primary">Save</button> </form:form> </div> </body> </html>

Run Spring Boot Application

Right click to the Project and follow the below steps:

select Run As -> Maven clean.

select Run As -> Maven install.

select Run As -> Spring Boot App.

INFO 15804 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/employee/add],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView com.jackrutorial.controller.EmployeeController.addEmployee() INFO 15804 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/employee/delete/{id}],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView com.jackrutorial.controller.EmployeeController.deleteEmployee(int) INFO 15804 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/employee/update/{id}],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView com.jackrutorial.controller.EmployeeController.editEmployee(int) INFO 15804 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/employee/save],methods=[POST]}" onto public org.springframework.web.servlet.ModelAndView com.jackrutorial.controller.EmployeeController.saveOrUpdate(com.jackrutorial.model.Employee) INFO 15804 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/employee/ || /employee/list],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView com.jackrutorial.controller.EmployeeController.getAllEmployees() INFO 15804 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest) INFO 15804 --- [ restartedMain] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse) INFO 15804 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] INFO 15804 --- [ restartedMain] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler] INFO 15804 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 INFO 15804 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup INFO 15804 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'dataSource' has been autodetected for JMX exposure INFO 15804 --- [ restartedMain] o.s.j.e.a.AnnotationMBeanExporter : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource] INFO 15804 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' INFO 15804 --- [ restartedMain] c.j.WebApplicationSpringBootApplication : Started WebApplicationSpringBootApplication in 3.427 seconds (JVM running for 4.655)

http://localhost:8080/employee/list

http://localhost:8080/employee/add

http://localhost:8080/employee/update/1

In this tutorial, we show you how to develop and Bootstrap a Spring Boot CRUD Web Application with Spring Boot JDBC, MySQL Database and Webjars Bootstrap 4. This Web Application can display the list of employee, create, edit, update and delete it.Find the MySQL database and table used in this tutorial.The following screenshot shows final structure of the project.Launch Eclipse IDE. Go to File -> New -> Other... Select Spring Starter Project under Spring Boot category then click Next as shown belowIn the next screen, you enter the content as shown below then click NextIn the next step, you choose Spring Boot Version is 2.1.0 (SNAPSHOT) and choose the Web + DevTools + JDBC + MySQL, then click Finish.We will add the required dependencies to Maven pom.xml FileThe updated pom.xml file will have the following codeCreate a Employee class under com.jackrutorial.model package with the following code.The RowMapper is used to map a single row to a single domain object. We will create a EmployeeRowMapper implementing RowMapper interface under com.jackrutorial.model package with the code.Create a EmployeeDao interface under com.jackrutorial.dao package and write the following code in it.Create a EmployeeDaoImpl class implements EmployeeDao interface under com.jackrutorial.dao package and write the following code in it.In code snippet above, we use JdbcTemplate query(), queryForObject() methods to query data from mysql database and use the JdbcTemplate update() method for updating records in database.Create a EmployeeService interface under com.jackrutorial.service package and write the following code in it.Create a EmployeeServiceImpl class implements EmployeeService interface under com.jackrutorial.service package and write the following code in it.We create a controller class named EmployeeController to integrate with the MySQL database using the EmployeeServiceImpl class. Create a EmployeeController class under com.jackrutorial.controller package and write the following code in it.In the sources folder, we will look for this project's a resource file under src/main/resources/application.properties. Open application.properties file and add the following properties.Create jsp folder under src\main\webapp\WEB-INF\ folder.Create employee_list.jsp and employee_form.jsp file under src\main\webapp\WEB-INF\jsp\ folder and write the following code in it.Type the following URLs in browser's address bar to open the Employee List page.Type the following URLs in browser's address bar to open the Add New Employee page.Type the following URLs in browser's address bar to open the Update Employee page.