## What we will do: - One More Spring Rest Services. - @PathVariable("id") int id ## Useful Snippets ``` produces = MediaType.APPLICATION_JSON_VALUE ``` ## Files List ### /pom.xml ``` 4.0.0 com.in28minutes in28Minutes-springmvc 0.0.1-SNAPSHOT war javax javaee-web-api 6.0 provided org.springframework spring-webmvc 4.2.2.RELEASE org.springframework.security spring-security-web 4.0.1.RELEASE org.springframework.security spring-security-config 4.0.1.RELEASE com.fasterxml.jackson.core jackson-databind 2.5.3 javax.servlet jstl 1.2 org.webjars bootstrap 3.3.6 org.webjars jquery 1.9.1 org.webjars bootstrap-datepicker 1.0.1 org.hibernate hibernate-validator 5.0.2.Final log4j log4j 1.2.17 org.apache.maven.plugins maven-compiler-plugin 3.2 true 1.8 1.8 true org.apache.tomcat.maven tomcat7-maven-plugin 2.2 / true ``` ### /src/main/java/com/in28minutes/common/ExceptionController.java ``` package com.in28minutes.common; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @ControllerAdvice @EnableWebMvc public class ExceptionController { private Log logger = LogFactory.getLog(ExceptionController.class); @ExceptionHandler(value = Exception.class) public String handleError(HttpServletRequest req, Exception exception) { logger.error("Request: " + req.getRequestURL() + " raised " + exception); return "error"; } } ``` ### /src/main/java/com/in28minutes/common/LogoutController.java ``` package com.in28minutes.common; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class LogoutController { @RequestMapping(value = "/logout", method = RequestMethod.GET) public String logout(HttpServletRequest request, HttpServletResponse response) { Authentication auth = SecurityContextHolder.getContext() .getAuthentication(); if (auth != null) { new SecurityContextLogoutHandler().logout(request, response, auth); } return "redirect:/"; } } ``` ### /src/main/java/com/in28minutes/model/Todo.java ``` package com.in28minutes.model; import java.util.Date; import javax.validation.constraints.Size; public class Todo { private int id; private String user; @Size(min = 10, message = "Enter atleast 10 Characters.") private String desc; private Date targetDate; private boolean isDone; public Todo() { super(); } public Todo(int id, String user, String desc, Date targetDate, boolean isDone) { super(); this.id = id; this.user = user; this.desc = desc; this.targetDate = targetDate; this.isDone = isDone; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUser() { return user; } public void setUser(String user) { this.user = user; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } public Date getTargetDate() { return targetDate; } public void setTargetDate(Date targetDate) { this.targetDate = targetDate; } public boolean isDone() { return isDone; } public void setDone(boolean isDone) { this.isDone = isDone; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + id; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Todo other = (Todo) obj; if (id != other.id) return false; return true; } @Override public String toString() { return String.format( "Todo [id=%s, user=%s, desc=%s, targetDate=%s, isDone=%s]", id, user, desc, targetDate, isDone); } } ``` ### /src/main/java/com/in28minutes/security/SecurityConfiguration.java ``` package com.in28minutes.security; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; @Configuration @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication().withUser("in28Minutes").password("dummy") .roles("USER", "ADMIN"); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/login").permitAll() .antMatchers("/", "/*todo*/**").access("hasRole('USER')").and() .formLogin(); } } ``` ### /src/main/java/com/in28minutes/todo/rest/TodoRestController.java ``` package com.in28minutes.todo.rest; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; 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.bind.annotation.RestController; import com.in28minutes.model.Todo; import com.in28minutes.todo.service.TodoService; @RestController public class TodoRestController { @Autowired private TodoService service; @RequestMapping(value = "/todo/", method = RequestMethod.GET) public List listAllTodos() { List users = service.retrieveTodos("in28Minutes"); return users; } @RequestMapping(value = "/todo/{id}", method = RequestMethod.GET) public Todo retrieveTodo(@PathVariable("id") int id) { return service.retrieveTodo(id); } } ``` ### /src/main/java/com/in28minutes/todo/service/TodoService.java ``` package com.in28minutes.todo.service; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import org.springframework.stereotype.Service; import com.in28minutes.model.Todo; @Service public class TodoService { private static List todos = new ArrayList(); private static int todoCount = 3; static { todos.add(new Todo(1, "in28Minutes", "Learn Spring MVC", new Date(), false)); todos.add(new Todo(2, "in28Minutes", "Learn Struts", new Date(), false)); todos.add(new Todo(3, "in28Minutes", "Learn Hibernate", new Date(), false)); } public List retrieveTodos(String user) { List filteredTodos = new ArrayList(); for (Todo todo : todos) { if (todo.getUser().equals(user)) filteredTodos.add(todo); } return filteredTodos; } public Todo retrieveTodo(int id) { for (Todo todo : todos) { if (todo.getId() == id) return todo; } return null; } public void updateTodo(Todo todo) { todos.remove(todo); todos.add(todo); } public void addTodo(String name, String desc, Date targetDate, boolean isDone) { todos.add(new Todo(++todoCount, name, desc, targetDate, isDone)); } public void deleteTodo(int id) { Iterator iterator = todos.iterator(); while (iterator.hasNext()) { Todo todo = iterator.next(); if (todo.getId() == id) { iterator.remove(); } } } } ``` ### /src/main/java/com/in28minutes/todo/TodoController.java ``` package com.in28minutes.todo; import java.text.SimpleDateFormat; import java.util.Date; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import com.in28minutes.model.Todo; import com.in28minutes.todo.service.TodoService; @Controller public class TodoController { @Autowired private TodoService service; @InitBinder protected void initBinder(WebDataBinder binder) { SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); binder.registerCustomEditor(Date.class, new CustomDateEditor( dateFormat, false)); } @RequestMapping(value = "/list-todos", method = RequestMethod.GET) public String showTodosList(ModelMap model) { String user = getLoggedInUserName(); model.addAttribute("todos", service.retrieveTodos(user)); return "list-todos"; } @RequestMapping(value = "/add-todo", method = RequestMethod.GET) public String showAddTodoPage(ModelMap model) { model.addAttribute("todo", new Todo()); return "todo"; } @RequestMapping(value = "/add-todo", method = RequestMethod.POST) public String addTodo(ModelMap model, @Valid Todo todo, BindingResult result) { if (result.hasErrors()) return "todo"; service.addTodo(getLoggedInUserName(), todo.getDesc(), todo.getTargetDate(), false); model.clear();// to prevent request parameter "name" to be passed return "redirect:/list-todos"; } private String getLoggedInUserName() { Object principal = SecurityContextHolder.getContext() .getAuthentication().getPrincipal(); if (principal instanceof UserDetails) return ((UserDetails) principal).getUsername(); return principal.toString(); } @RequestMapping(value = "/update-todo", method = RequestMethod.GET) public String showUpdateTodoPage(ModelMap model, @RequestParam int id) { model.addAttribute("todo", service.retrieveTodo(id)); return "todo"; } @RequestMapping(value = "/update-todo", method = RequestMethod.POST) public String updateTodo(ModelMap model, @Valid Todo todo, BindingResult result) { if (result.hasErrors()) return "todo"; todo.setUser(getLoggedInUserName()); service.updateTodo(todo); model.clear();// to prevent request parameter "name" to be passed return "redirect:/list-todos"; } @RequestMapping(value = "/delete-todo", method = RequestMethod.GET) public String deleteTodo(@RequestParam int id) { service.deleteTodo(id); return "redirect:/list-todos"; } } ``` ### /src/main/java/com/in28minutes/welcome/WelcomeController.java ``` package com.in28minutes.welcome; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class WelcomeController { @RequestMapping(value = "/", method = RequestMethod.GET) public String showWelcomePage(ModelMap model) { model.put("name", getLoggedInUserName()); return "welcome"; } private String getLoggedInUserName() { Object principal = SecurityContextHolder.getContext() .getAuthentication().getPrincipal(); if (principal instanceof UserDetails) return ((UserDetails) principal).getUsername(); return principal.toString(); } } ``` ### /src/main/resources/log4j.properties ``` log4j.rootLogger=DEBUG, Appender1 log4j.appender.Appender1=org.apache.log4j.ConsoleAppender log4j.appender.Appender1.layout=org.apache.log4j.PatternLayout log4j.appender.Appender1.layout.ConversionPattern=%-7p %d [%t] %c %x - %m%n ``` ### /src/main/resources/messages_en.properties ``` welcome.message=Welcome in English todo.caption= Todo Caption in English ``` ### /src/main/resources/messages_fr.properties ``` welcome.message=Welcome in French todo.caption= Todo Caption in French ``` ### /src/main/webapp/WEB-INF/todo-servlet.xml ``` /WEB-INF/views/ .jsp ``` ### /src/main/webapp/WEB-INF/views/common/footer.jspf ``` ``` ### /src/main/webapp/WEB-INF/views/common/header.jspf ``` <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> Todos Application ``` ### /src/main/webapp/WEB-INF/views/common/navigation.jspf ``` ``` ### /src/main/webapp/WEB-INF/views/error.jsp ``` <%@ include file="common/header.jspf"%> <%@ include file="common/navigation.jspf"%>
Application has encountered an error. Please contact support on ...
<%@ include file="common/footer.jspf"%> ``` ### /src/main/webapp/WEB-INF/views/list-todos.jsp ``` <%@ include file="common/header.jspf"%> <%@ include file="common/navigation.jspf"%>
Description Date Completed
${todo.desc} ${todo.done} Edit Delete
Add
<%@ include file="common/footer.jspf"%> ``` ### /src/main/webapp/WEB-INF/views/todo.jsp ``` <%@ include file="common/header.jspf"%> <%@ include file="common/navigation.jspf"%>
Description
Target Date
<%@ include file="common/footer.jspf"%> ``` ### /src/main/webapp/WEB-INF/views/welcome.jsp ``` <%@ include file="common/header.jspf"%> <%@ include file="common/navigation.jspf"%>
${name}.
<%@ include file="common/footer.jspf"%> ``` ### /src/main/webapp/WEB-INF/web.xml ``` To do List dispatcher org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/todo-servlet.xml 1 dispatcher / springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy springSecurityFilterChain /* /WEB-INF/views/error.jsp ```