diff --git a/enterprise-patterns/pom.xml b/enterprise-patterns/pom.xml new file mode 100644 index 0000000000..036a61c44a --- /dev/null +++ b/enterprise-patterns/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + com.baeldung.enterprise.patterns + enterprise-patterns-parent + pom + + spring-dispatcher-servlet + + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + + + diff --git a/enterprise-patterns/spring-dispatcher-servlet/pom.xml b/enterprise-patterns/spring-dispatcher-servlet/pom.xml new file mode 100644 index 0000000000..e7220eec59 --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + spring-dispatcher-servlet + 1.0.0-SNAPSHOT + war + + + com.baeldung.enterprise.patterns + enterprise-patterns-parent + 1.0.0-SNAPSHOT + .. + + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + org.springframework + spring-webmvc + 4.3.2.RELEASE + + + org.thymeleaf + thymeleaf-spring4 + 3.0.1.RELEASE + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.6.2 + + + org.apache.logging.log4j + log4j-core + 2.6.2 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + org.apache.maven.plugins + maven-war-plugin + 3.0.0 + + false + + + + org.eclipse.jetty + jetty-maven-plugin + 9.4.0.M1 + + + / + + + + + + diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/RootConfiguration.java b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/RootConfiguration.java new file mode 100644 index 0000000000..9b22e411c5 --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/RootConfiguration.java @@ -0,0 +1,19 @@ +package com.baeldung.enterprise.patterns.dispatcher.servlet; + +import com.baeldung.enterprise.patterns.dispatcher.servlet.models.Task; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.*; + +@Configuration +public class RootConfiguration { + @Bean + public Map> taskList() { + Map> taskMap = new HashMap<>(); + List taskList = new ArrayList<>(); + taskList.add(new Task("Clean the dishes!", new Date())); + taskMap.put("Cid", taskList); + return taskMap; + } +} diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/WebConfiguration.java b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/WebConfiguration.java new file mode 100644 index 0000000000..90f4f48f50 --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/WebConfiguration.java @@ -0,0 +1,41 @@ +package com.baeldung.enterprise.patterns.dispatcher.servlet; + +import org.springframework.context.annotation.Bean; +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; +import org.thymeleaf.spring4.SpringTemplateEngine; +import org.thymeleaf.spring4.view.ThymeleafViewResolver; +import org.thymeleaf.templatemode.TemplateMode; +import org.thymeleaf.templateresolver.ServletContextTemplateResolver; + +import javax.servlet.ServletContext; + +@Configuration +@ComponentScan("com.baeldung.enterprise.patterns.dispatcher.servlet.web") +@EnableWebMvc +public class WebConfiguration extends WebMvcConfigurerAdapter { + @Bean + public ServletContextTemplateResolver templateResolver(ServletContext servletContext) { + ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver(servletContext); + templateResolver.setPrefix("/WEB-INF/views/"); + templateResolver.setSuffix(".html"); + templateResolver.setTemplateMode(TemplateMode.HTML); + return templateResolver; + } + + @Bean + public SpringTemplateEngine templateEngine(ServletContextTemplateResolver templateResolver) { + SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.setTemplateResolver(templateResolver); + return templateEngine; + } + + @Bean + public ThymeleafViewResolver viewResolver(SpringTemplateEngine templateEngine) { + ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); + viewResolver.setTemplateEngine(templateEngine); + return viewResolver; + } +} diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/WebInitializer.java b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/WebInitializer.java new file mode 100644 index 0000000000..a544b2cbac --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/WebInitializer.java @@ -0,0 +1,20 @@ +package com.baeldung.enterprise.patterns.dispatcher.servlet; + +import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; + +public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { + @Override + protected Class[] getRootConfigClasses() { + return new Class[]{RootConfiguration.class}; + } + + @Override + protected Class[] getServletConfigClasses() { + return new Class[]{WebConfiguration.class}; + } + + @Override + protected String[] getServletMappings() { + return new String[]{"/example/*"}; + } +} diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/models/Task.java b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/models/Task.java new file mode 100644 index 0000000000..3a84f156a8 --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/models/Task.java @@ -0,0 +1,41 @@ +package com.baeldung.enterprise.patterns.dispatcher.servlet.models; + +import org.springframework.format.annotation.DateTimeFormat; + +import java.util.Date; + +public class Task { + + private String description; + + @DateTimeFormat(pattern = "yyyy-MM-dd'T'hh:mm") + private Date due; + + public Task() { + } + + public Task(Date due) { + this.due = due; + } + + public Task(String description, Date due) { + this.description = description; + this.due = due; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Date getDue() { + return due; + } + + public void setDue(Date due) { + this.due = due; + } +} diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/web/GlobalDefaultExceptionHandler.java b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/web/GlobalDefaultExceptionHandler.java new file mode 100644 index 0000000000..0c44d0a5e7 --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/web/GlobalDefaultExceptionHandler.java @@ -0,0 +1,24 @@ +package com.baeldung.enterprise.patterns.dispatcher.servlet.web; + +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; + +@ControllerAdvice +public class GlobalDefaultExceptionHandler { + @ExceptionHandler(Exception.class) + public ModelAndView defaultErrorHandler(HttpServletRequest request, Exception e) throws Exception { + if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) { + throw e; + } + ModelAndView modelAndView = new ModelAndView(); + modelAndView.addObject("exception", e); + modelAndView.addObject("url", request.getRequestURL()); + modelAndView.setViewName("error"); + return modelAndView; + } +} diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/web/HomeController.java b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/web/HomeController.java new file mode 100644 index 0000000000..6e4e437a44 --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/web/HomeController.java @@ -0,0 +1,26 @@ +package com.baeldung.enterprise.patterns.dispatcher.servlet.web; + +import com.baeldung.enterprise.patterns.dispatcher.servlet.models.Task; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Controller +public class HomeController { + @Autowired + private Map> taskMap; + + @GetMapping("/*") + public String home(Model model) { + List users = taskMap.keySet().stream() + .sorted() + .collect(Collectors.toList()); + model.addAttribute("users", users); + return "home"; + } +} diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/web/TaskController.java b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/web/TaskController.java new file mode 100644 index 0000000000..6930464f81 --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/java/com/baeldung/enterprise/patterns/dispatcher/servlet/web/TaskController.java @@ -0,0 +1,57 @@ +package com.baeldung.enterprise.patterns.dispatcher.servlet.web; + +import com.baeldung.enterprise.patterns.dispatcher.servlet.models.Task; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Controller +@RequestMapping("/tasks") +public class TaskController { + @Autowired + private Map> taskMap; + + @GetMapping("/{username}/list") + public String listForm( + Model model, + @PathVariable("username") String username + ) { + List tasks = taskMap.get(username).stream() + .sorted((t1, t2) -> t1.getDue().compareTo(t2.getDue())) + .collect(Collectors.toList()); + model.addAttribute("username", username); + model.addAttribute("tasks", tasks); + return "task-list"; + } + + @GetMapping("/{username}/add") + public String addForm( + Model model, + @PathVariable("username") String username + ) { + model.addAttribute("username", username); + model.addAttribute("task", new Task(new Date())); + return "task-add"; + } + + @PostMapping("/{username}/add") + public String addSubmit( + @PathVariable("username") String username, + @ModelAttribute Task task + ) { + List taskList = taskMap.get(username); + if (taskList == null) { + taskList = new ArrayList<>(); + } + taskList.add(task); + taskMap.put(username, taskList); + return "redirect:list"; + } +} diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/resources/log4j2.xml b/enterprise-patterns/spring-dispatcher-servlet/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..fb18e8279a --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/resources/log4j2.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/error.html b/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/error.html new file mode 100644 index 0000000000..c1b362e51a --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/error.html @@ -0,0 +1,11 @@ + + + + Error + + +

Error:

+

+

+ + diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/home.html b/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/home.html new file mode 100644 index 0000000000..1a333ed641 --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/home.html @@ -0,0 +1,14 @@ + + + + Welcome to TaskTools! + + +

TaskTools

+
    +
  • + +
  • +
+ + diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/task-add.html b/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/task-add.html new file mode 100644 index 0000000000..70f010e58d --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/task-add.html @@ -0,0 +1,14 @@ + + + + + + +

+
+ + + +
+ + diff --git a/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/task-list.html b/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/task-list.html new file mode 100644 index 0000000000..2fe628456f --- /dev/null +++ b/enterprise-patterns/spring-dispatcher-servlet/src/main/webapp/WEB-INF/views/task-list.html @@ -0,0 +1,19 @@ + + + + + + +

+
    +
  • +

    +

    +
  • +
+

+ Home + Add new +

+ +