├── README.md ├── pom.xml └── src ├── main ├── java │ └── net │ │ └── guides │ │ └── springboot │ │ └── todomanagement │ │ ├── TodoManagementSpringBoot2Application.java │ │ ├── controller │ │ ├── ErrorController.java │ │ ├── LogoutController.java │ │ ├── TodoController.java │ │ └── WelcomeController.java │ │ ├── model │ │ └── Todo.java │ │ ├── repository │ │ └── TodoRepository.java │ │ ├── security │ │ └── SecurityConfiguration.java │ │ └── service │ │ ├── ITodoService.java │ │ └── TodoService.java ├── resources │ └── application.properties └── webapp │ └── WEB-INF │ └── jsp │ ├── common │ ├── footer.jspf │ ├── header.jspf │ └── navigation.jspf │ ├── error.jsp │ ├── list-todos.jsp │ ├── todo.jsp │ └── welcome.jsp └── test └── java └── net └── guides └── springboot └── todomanagementspringboot └── TodoManagementSpringBoot2ApplicationTests.java /README.md: -------------------------------------------------------------------------------- 1 | # todo-management-spring-boot 2 | 3 | 4 | # Mini Todo Management Project using Spring Boot + Spring MVC + Spring Security + JSP + Hibernate + MySQL 5 | 6 | - http://www.javaguides.net/2018/09/mini-todo-management-project-using-spring-boot-springmvc-springsecurity-jsp-hibernate-mysql.html 7 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | net.guides.springboot 8 | todo-management-spring-boot 9 | 0.0.1-SNAPSHOT 10 | jar 11 | 12 | todo-management-spring-boot 13 | Demo project for Spring Boot 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-parent 18 | 2.0.4.RELEASE 19 | 20 | 21 | 22 | 23 | UTF-8 24 | UTF-8 25 | 1.8 26 | 27 | 28 | 29 | 30 | javax.servlet 31 | jstl 32 | 33 | 34 | 35 | org.webjars 36 | bootstrap 37 | 3.3.6 38 | 39 | 40 | 41 | org.webjars 42 | bootstrap-datepicker 43 | 1.0.1 44 | 45 | 46 | 47 | org.webjars 48 | jquery 49 | 1.9.1 50 | 51 | 52 | 53 | org.apache.tomcat.embed 54 | tomcat-embed-jasper 55 | provided 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-data-jpa 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-security 65 | 66 | 67 | org.springframework.boot 68 | spring-boot-starter-web 69 | 70 | 71 | 72 | org.springframework.boot 73 | spring-boot-devtools 74 | runtime 75 | 76 | 77 | mysql 78 | mysql-connector-java 79 | runtime 80 | 81 | 82 | org.springframework.boot 83 | spring-boot-starter-test 84 | test 85 | 86 | 87 | org.springframework.security 88 | spring-security-test 89 | test 90 | 91 | 92 | 93 | 94 | 95 | 96 | org.springframework.boot 97 | spring-boot-maven-plugin 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/main/java/net/guides/springboot/todomanagement/TodoManagementSpringBoot2Application.java: -------------------------------------------------------------------------------- 1 | package net.guides.springboot.todomanagement; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class TodoManagementSpringBoot2Application { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(TodoManagementSpringBoot2Application.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/net/guides/springboot/todomanagement/controller/ErrorController.java: -------------------------------------------------------------------------------- 1 | package net.guides.springboot.todomanagement.controller; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.web.bind.annotation.ExceptionHandler; 7 | import org.springframework.web.servlet.ModelAndView; 8 | 9 | @Controller("error") 10 | public class ErrorController { 11 | 12 | @ExceptionHandler(Exception.class) 13 | public ModelAndView handleException 14 | (HttpServletRequest request, Exception ex){ 15 | ModelAndView mv = new ModelAndView(); 16 | 17 | mv.addObject("exception", ex.getLocalizedMessage()); 18 | mv.addObject("url", request.getRequestURL()); 19 | 20 | mv.setViewName("error"); 21 | return mv; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/net/guides/springboot/todomanagement/controller/LogoutController.java: -------------------------------------------------------------------------------- 1 | package net.guides.springboot.todomanagement.controller; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.servlet.http.HttpServletResponse; 5 | 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RequestMethod; 12 | 13 | @Controller 14 | public class LogoutController { 15 | 16 | @RequestMapping(value = "/logout", method = RequestMethod.GET) 17 | public String logout(HttpServletRequest request, 18 | HttpServletResponse response) { 19 | 20 | Authentication authentication = SecurityContextHolder.getContext() 21 | .getAuthentication(); 22 | 23 | if (authentication != null) { 24 | new SecurityContextLogoutHandler().logout(request, response, 25 | authentication); 26 | } 27 | 28 | return "redirect:/"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/net/guides/springboot/todomanagement/controller/TodoController.java: -------------------------------------------------------------------------------- 1 | package net.guides.springboot.todomanagement.controller; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | 6 | import javax.validation.Valid; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.beans.propertyeditors.CustomDateEditor; 10 | import org.springframework.security.core.context.SecurityContextHolder; 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | import org.springframework.stereotype.Controller; 13 | import org.springframework.ui.ModelMap; 14 | import org.springframework.validation.BindingResult; 15 | import org.springframework.web.bind.WebDataBinder; 16 | import org.springframework.web.bind.annotation.InitBinder; 17 | import org.springframework.web.bind.annotation.RequestMapping; 18 | import org.springframework.web.bind.annotation.RequestMethod; 19 | import org.springframework.web.bind.annotation.RequestParam; 20 | 21 | import net.guides.springboot.todomanagement.model.Todo; 22 | import net.guides.springboot.todomanagement.service.ITodoService; 23 | 24 | @Controller 25 | public class TodoController { 26 | 27 | @Autowired 28 | private ITodoService todoService; 29 | 30 | @InitBinder 31 | public void initBinder(WebDataBinder binder) { 32 | // Date - dd/MM/yyyy 33 | SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); 34 | binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false)); 35 | } 36 | 37 | @RequestMapping(value = "/list-todos", method = RequestMethod.GET) 38 | public String showTodos(ModelMap model) { 39 | String name = getLoggedInUserName(model); 40 | model.put("todos", todoService.getTodosByUser(name)); 41 | // model.put("todos", service.retrieveTodos(name)); 42 | return "list-todos"; 43 | } 44 | 45 | private String getLoggedInUserName(ModelMap model) { 46 | Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 47 | 48 | if (principal instanceof UserDetails) { 49 | return ((UserDetails) principal).getUsername(); 50 | } 51 | 52 | return principal.toString(); 53 | } 54 | 55 | @RequestMapping(value = "/add-todo", method = RequestMethod.GET) 56 | public String showAddTodoPage(ModelMap model) { 57 | model.addAttribute("todo", new Todo()); 58 | return "todo"; 59 | } 60 | 61 | @RequestMapping(value = "/delete-todo", method = RequestMethod.GET) 62 | public String deleteTodo(@RequestParam long id) { 63 | todoService.deleteTodo(id); 64 | // service.deleteTodo(id); 65 | return "redirect:/list-todos"; 66 | } 67 | 68 | @RequestMapping(value = "/update-todo", method = RequestMethod.GET) 69 | public String showUpdateTodoPage(@RequestParam long id, ModelMap model) { 70 | Todo todo = todoService.getTodoById(id).get(); 71 | model.put("todo", todo); 72 | return "todo"; 73 | } 74 | 75 | @RequestMapping(value = "/update-todo", method = RequestMethod.POST) 76 | public String updateTodo(ModelMap model, @Valid Todo todo, BindingResult result) { 77 | 78 | if (result.hasErrors()) { 79 | return "todo"; 80 | } 81 | 82 | todo.setUserName(getLoggedInUserName(model)); 83 | todoService.updateTodo(todo); 84 | return "redirect:/list-todos"; 85 | } 86 | 87 | @RequestMapping(value = "/add-todo", method = RequestMethod.POST) 88 | public String addTodo(ModelMap model, @Valid Todo todo, BindingResult result) { 89 | 90 | if (result.hasErrors()) { 91 | return "todo"; 92 | } 93 | 94 | todo.setUserName(getLoggedInUserName(model)); 95 | todoService.saveTodo(todo); 96 | return "redirect:/list-todos"; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/net/guides/springboot/todomanagement/controller/WelcomeController.java: -------------------------------------------------------------------------------- 1 | package net.guides.springboot.todomanagement.controller; 2 | 3 | import org.springframework.security.core.context.SecurityContextHolder; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | import org.springframework.stereotype.Controller; 6 | import org.springframework.ui.ModelMap; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestMethod; 9 | 10 | @Controller 11 | public class WelcomeController { 12 | 13 | @RequestMapping(value = "/", method = RequestMethod.GET) 14 | public String showWelcomePage(ModelMap model) { 15 | model.put("name", getLoggedinUserName()); 16 | return "welcome"; 17 | } 18 | 19 | private String getLoggedinUserName() { 20 | Object principal = SecurityContextHolder.getContext() 21 | .getAuthentication().getPrincipal(); 22 | 23 | if (principal instanceof UserDetails) { 24 | return ((UserDetails) principal).getUsername(); 25 | } 26 | 27 | return principal.toString(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/net/guides/springboot/todomanagement/model/Todo.java: -------------------------------------------------------------------------------- 1 | package net.guides.springboot.todomanagement.model; 2 | 3 | import java.util.Date; 4 | 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | import javax.persistence.Table; 10 | import javax.validation.constraints.Size; 11 | 12 | @Entity 13 | @Table(name = "todos") 14 | public class Todo { 15 | 16 | @Id 17 | @GeneratedValue(strategy = GenerationType.AUTO) 18 | private long id; 19 | 20 | private String userName; 21 | 22 | @Size(min = 10, message = "Enter at least 10 Characters...") 23 | private String description; 24 | 25 | private Date targetDate; 26 | 27 | public Todo() { 28 | super(); 29 | } 30 | 31 | public Todo(String user, String desc, Date targetDate, boolean isDone) { 32 | super(); 33 | this.userName = user; 34 | this.description = desc; 35 | this.targetDate = targetDate; 36 | } 37 | 38 | public long getId() { 39 | return id; 40 | } 41 | 42 | public void setId(long id) { 43 | this.id = id; 44 | } 45 | 46 | public String getUserName() { 47 | return userName; 48 | } 49 | 50 | public void setUserName(String userName) { 51 | this.userName = userName; 52 | } 53 | 54 | public String getDescription() { 55 | return description; 56 | } 57 | 58 | public void setDescription(String description) { 59 | this.description = description; 60 | } 61 | 62 | public Date getTargetDate() { 63 | return targetDate; 64 | } 65 | 66 | public void setTargetDate(Date targetDate) { 67 | this.targetDate = targetDate; 68 | } 69 | } -------------------------------------------------------------------------------- /src/main/java/net/guides/springboot/todomanagement/repository/TodoRepository.java: -------------------------------------------------------------------------------- 1 | package net.guides.springboot.todomanagement.repository; 2 | 3 | import java.util.List; 4 | 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | 7 | import net.guides.springboot.todomanagement.model.Todo; 8 | 9 | public interface TodoRepository extends JpaRepository{ 10 | List findByUserName(String user); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/net/guides/springboot/todomanagement/security/SecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | package net.guides.springboot.todomanagement.security; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 6 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 7 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 8 | import org.springframework.security.crypto.password.NoOpPasswordEncoder; 9 | 10 | @Configuration 11 | public class SecurityConfiguration extends WebSecurityConfigurerAdapter{ 12 | @Autowired 13 | public void configureGlobalSecurity(AuthenticationManagerBuilder auth) 14 | throws Exception { 15 | auth.inMemoryAuthentication() 16 | .passwordEncoder(NoOpPasswordEncoder.getInstance()) 17 | .withUser("admin").password("admin") 18 | .roles("USER", "ADMIN"); 19 | } 20 | 21 | @Override 22 | protected void configure(HttpSecurity http) throws Exception { 23 | http.authorizeRequests().antMatchers("/login", "/h2-console/**").permitAll() 24 | .antMatchers("/", "/*todo*/**").access("hasRole('USER')").and() 25 | .formLogin(); 26 | 27 | http.csrf().disable(); 28 | http.headers().frameOptions().disable(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/net/guides/springboot/todomanagement/service/ITodoService.java: -------------------------------------------------------------------------------- 1 | package net.guides.springboot.todomanagement.service; 2 | 3 | import java.util.Date; 4 | 5 | import java.util.List; 6 | import java.util.Optional; 7 | 8 | import net.guides.springboot.todomanagement.model.Todo; 9 | 10 | public interface ITodoService { 11 | 12 | List getTodosByUser(String user); 13 | 14 | Optional getTodoById(long id); 15 | 16 | void updateTodo(Todo todo); 17 | 18 | void addTodo(String name, String desc, Date targetDate, boolean isDone); 19 | 20 | void deleteTodo(long id); 21 | 22 | void saveTodo(Todo todo); 23 | 24 | } -------------------------------------------------------------------------------- /src/main/java/net/guides/springboot/todomanagement/service/TodoService.java: -------------------------------------------------------------------------------- 1 | package net.guides.springboot.todomanagement.service; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | import java.util.Optional; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import net.guides.springboot.todomanagement.model.Todo; 11 | import net.guides.springboot.todomanagement.repository.TodoRepository; 12 | 13 | @Service 14 | public class TodoService implements ITodoService { 15 | 16 | @Autowired 17 | private TodoRepository todoRepository; 18 | 19 | @Override 20 | public List getTodosByUser(String user) { 21 | return todoRepository.findByUserName(user); 22 | } 23 | 24 | @Override 25 | public Optional getTodoById(long id) { 26 | return todoRepository.findById(id); 27 | } 28 | 29 | @Override 30 | public void updateTodo(Todo todo) { 31 | todoRepository.save(todo); 32 | } 33 | 34 | @Override 35 | public void addTodo(String name, String desc, Date targetDate, boolean isDone) { 36 | todoRepository.save(new Todo(name, desc, targetDate, isDone)); 37 | } 38 | 39 | @Override 40 | public void deleteTodo(long id) { 41 | Optional todo = todoRepository.findById(id); 42 | if (todo.isPresent()) { 43 | todoRepository.delete(todo.get()); 44 | } 45 | } 46 | 47 | @Override 48 | public void saveTodo(Todo todo) { 49 | todoRepository.save(todo); 50 | } 51 | } -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | ## Spring view resolver set up 2 | spring.mvc.view.prefix=/WEB-INF/jsp/ 3 | spring.mvc.view.suffix=.jsp 4 | 5 | ## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties) 6 | spring.datasource.url = jdbc:mysql://localhost:3306/users_database?useSSL=false 7 | spring.datasource.username = root 8 | spring.datasource.password = root 9 | 10 | 11 | ## Hibernate Properties 12 | # The SQL dialect makes Hibernate generate better SQL for the chosen database 13 | spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect 14 | 15 | # Hibernate ddl auto (create, create-drop, validate, update) 16 | spring.jpa.hibernate.ddl-auto = update 17 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/common/footer.jspf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 10 | 11 | 12 | 19 | 20 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/common/header.jspf: -------------------------------------------------------------------------------- 1 | <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 2 | <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> 3 | <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> 4 | 5 | 6 | 7 | 8 | Todo Management 9 | 11 | 12 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/common/navigation.jspf: -------------------------------------------------------------------------------- 1 | 2 | 16 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/error.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf"%> 2 | <%@ include file="common/navigation.jspf"%> 3 |
4 | An exception occurred! Please contact Support! 5 |
6 | <%@ include file="common/footer.jspf"%> -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/list-todos.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf"%> 2 | <%@ include file="common/navigation.jspf"%> 3 | 4 |
5 |
6 | Add Todo 7 |
8 |
9 |
10 |
11 |

List of TODO's

12 |
13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 32 | 33 | 34 | 35 |
DescriptionTarget Date
${todo.description}Update 30 | Delete
36 |
37 |
38 | 39 |
40 | <%@ include file="common/footer.jspf"%> -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/todo.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf"%> 2 | <%@ include file="common/navigation.jspf"%> 3 |
4 |
5 |
6 |
7 |
Add TODO
8 |
9 | 10 | 11 |
12 | Description 13 | 15 | 16 |
17 | 18 |
19 | Target Date 20 | 22 | 23 |
24 | 25 | 26 |
27 |
28 |
29 |
30 |
31 |
32 | <%@ include file="common/footer.jspf"%> -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/jsp/welcome.jsp: -------------------------------------------------------------------------------- 1 | <%@ include file="common/header.jspf"%> 2 | <%@ include file="common/navigation.jspf"%> 3 |
4 | 5 |
6 |
Home Page
7 |
8 | Welcome ${name}!! Click here to manage your 9 | todo's. 10 |
11 |
12 |
13 | <%@ include file="common/footer.jspf"%> -------------------------------------------------------------------------------- /src/test/java/net/guides/springboot/todomanagementspringboot/TodoManagementSpringBoot2ApplicationTests.java: -------------------------------------------------------------------------------- 1 | package net.guides.todo.todomanagementspringboot2; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class TodoManagementSpringBoot2ApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------