diff --git a/spring-web-modules/pom.xml b/spring-web-modules/pom.xml index 37ee84da25..ca96dcff35 100644 --- a/spring-web-modules/pom.xml +++ b/spring-web-modules/pom.xml @@ -41,6 +41,7 @@ spring-thymeleaf spring-thymeleaf-2 spring-thymeleaf-3 + spring-boot-jsp diff --git a/spring-web-modules/spring-boot-jsp/README.md b/spring-web-modules/spring-boot-jsp/README.md new file mode 100644 index 0000000000..8242461917 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/README.md @@ -0,0 +1,6 @@ +## Spring MVC Forms JSP + +This module contains articles about Spring Boot used with JSP + +### Relevant Articles +- [Spring Boot with JSP](https://www.baeldung.com/?) diff --git a/spring-web-modules/spring-boot-jsp/pom.xml b/spring-web-modules/spring-boot-jsp/pom.xml new file mode 100644 index 0000000000..1599f4aa34 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + + com.baeldung + spring-boot-jsp + 0.0.1-SNAPSHOT + spring-boot-jsp + war + + + com.baeldung + spring-web-modules + 0.0.1-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + javax.servlet + jstl + ${jstl.version} + + + org.apache.tomcat.embed + tomcat-embed-jasper + + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + org.springframework.boot + spring-boot-starter-web + + + + + + + + + + + spring-boot-jsp + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.boot.jsp.SpringBootJspApplication + + + + + repackage + + + + + + + + + 1.2 + 2.4.0 + + + \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/SpringBootJspApplication.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/SpringBootJspApplication.java new file mode 100644 index 0000000000..c77554f9f6 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/SpringBootJspApplication.java @@ -0,0 +1,19 @@ +package com.baeldung.boot.jsp; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication(scanBasePackages = "com.baeldung.boot.jsp") +public class SpringBootJspApplication extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { + return builder.sources(SpringBootJspApplication.class); + } + + public static void main(String[] args) { + SpringApplication.run(SpringBootJspApplication.class); + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/SpringBootJspConfiguration.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/SpringBootJspConfiguration.java new file mode 100644 index 0000000000..83847a40a3 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/SpringBootJspConfiguration.java @@ -0,0 +1,30 @@ +package com.baeldung.boot.jsp; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import com.baeldung.boot.jsp.repository.BookRepository; +import com.baeldung.boot.jsp.repository.impl.InMemoryBookRepository; +import com.baeldung.boot.jsp.repository.model.BookData; + +@Configuration +@ComponentScan(basePackages = "com.baeldung.boot.jsp") +public class SpringBootJspConfiguration { + + @Bean + public BookRepository provideBookRepository() { + return new InMemoryBookRepository(initialBookData()); + } + + private static Map initialBookData() { + Map initData = new HashMap<>(); + initData.put("ISBN-TEST-1", new BookData("ISBN-TEST-1", "Book 1", "Book 1 Author")); + initData.put("ISBN-TEST-2", new BookData("ISBN-TEST-2", "Book 2", "Book 2 Author")); + initData.put("ISBN-TEST-3", new BookData("ISBN-TEST-3", "Book 3", "Book 3 Author")); + return initData; + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/controller/BookController.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/controller/BookController.java new file mode 100644 index 0000000000..c104a9cad3 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/controller/BookController.java @@ -0,0 +1,45 @@ +package com.baeldung.boot.jsp.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import org.springframework.web.servlet.view.RedirectView; + +import com.baeldung.boot.jsp.dto.Book; +import com.baeldung.boot.jsp.service.BookService; + +@Controller +@RequestMapping("/book") +public class BookController { + + private final BookService bookService; + + public BookController(BookService bookService) { + this.bookService = bookService; + } + + @GetMapping("/viewBooks") + public String viewBooks(Model model) { + model.addAttribute("books", bookService.getBooks()); + return "view-books"; + } + + @GetMapping("/addBook") + public String addBookView(Model model) { + model.addAttribute("book", new Book()); + return "add-book"; + } + + @PostMapping("/addBook") + public RedirectView addBook(@ModelAttribute("book") Book book, RedirectAttributes redirectAttributes) { + final RedirectView redirectView = new RedirectView("/book/addBook", true); + Book savedBook = bookService.addBook(book); + redirectAttributes.addFlashAttribute("savedBook", savedBook); + redirectAttributes.addFlashAttribute("addBookSuccess", true); + return redirectView; + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/dto/Book.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/dto/Book.java new file mode 100644 index 0000000000..f4cd6b0b3b --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/dto/Book.java @@ -0,0 +1,14 @@ +package com.baeldung.boot.jsp.dto; + +import lombok.*; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +@ToString +public class Book { + private String isbn; + private String name; + private String author; +} \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/exception/DuplicateBookException.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/exception/DuplicateBookException.java new file mode 100644 index 0000000000..bd52a591e3 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/exception/DuplicateBookException.java @@ -0,0 +1,13 @@ +package com.baeldung.boot.jsp.exception; + +import com.baeldung.boot.jsp.dto.Book; +import lombok.Getter; + +@Getter +public class DuplicateBookException extends RuntimeException { + private final Book book; + + public DuplicateBookException(Book book) { + this.book = book; + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/exception/LibraryControllerAdvice.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/exception/LibraryControllerAdvice.java new file mode 100644 index 0000000000..8217fea2e3 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/exception/LibraryControllerAdvice.java @@ -0,0 +1,19 @@ +package com.baeldung.boot.jsp.exception; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.servlet.ModelAndView; + +@ControllerAdvice +public class LibraryControllerAdvice { + + @ExceptionHandler(value = DuplicateBookException.class) + public ModelAndView duplicateBookException(DuplicateBookException e) { + final ModelAndView modelAndView = new ModelAndView(); + modelAndView.addObject("ref", e.getBook().getIsbn()); + modelAndView.addObject("object", e.getBook()); + modelAndView.addObject("message", "Cannot add an already existing book"); + modelAndView.setViewName("error-book"); + return modelAndView; + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/repository/BookRepository.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/repository/BookRepository.java new file mode 100644 index 0000000000..f10cecfa81 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/repository/BookRepository.java @@ -0,0 +1,14 @@ +package com.baeldung.boot.jsp.repository; + +import java.util.Collection; +import java.util.Optional; + +import com.baeldung.boot.jsp.repository.model.BookData; + +public interface BookRepository { + Collection findAll(); + + Optional findById(String isbn); + + BookData add(BookData book); +} diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/repository/impl/InMemoryBookRepository.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/repository/impl/InMemoryBookRepository.java new file mode 100644 index 0000000000..8fae303158 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/repository/impl/InMemoryBookRepository.java @@ -0,0 +1,36 @@ +package com.baeldung.boot.jsp.repository.impl; + +import java.util.*; + +import com.baeldung.boot.jsp.repository.BookRepository; +import com.baeldung.boot.jsp.repository.model.BookData; + +public class InMemoryBookRepository implements BookRepository { + + private final Map storedBooks; + + public InMemoryBookRepository(Map storedBooks) { + this.storedBooks = new HashMap<>(); + this.storedBooks.putAll(storedBooks); + } + + @Override + public Collection findAll() { + if (storedBooks.isEmpty()) { + return Collections.emptyList(); + } + + return storedBooks.values(); + } + + @Override + public Optional findById(String isbn) { + return Optional.ofNullable(storedBooks.get(isbn)); + } + + @Override + public BookData add(BookData book) { + storedBooks.put(book.getIsbn(), book); + return book; + } +} diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/repository/model/BookData.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/repository/model/BookData.java new file mode 100644 index 0000000000..7c722a92e5 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/repository/model/BookData.java @@ -0,0 +1,16 @@ +package com.baeldung.boot.jsp.repository.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class BookData { + private String isbn; + private String name; + private String author; +} \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/service/BookService.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/service/BookService.java new file mode 100644 index 0000000000..7c2c401ef2 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/service/BookService.java @@ -0,0 +1,11 @@ +package com.baeldung.boot.jsp.service; + +import java.util.Collection; + +import com.baeldung.boot.jsp.dto.Book; + +public interface BookService { + Collection getBooks(); + + Book addBook(Book book); +} \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/service/impl/BookServiceImpl.java b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/service/impl/BookServiceImpl.java new file mode 100644 index 0000000000..519ee19205 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/java/com/baeldung/boot/jsp/service/impl/BookServiceImpl.java @@ -0,0 +1,50 @@ +package com.baeldung.boot.jsp.service.impl; + +import java.util.Collection; +import java.util.Optional; +import java.util.stream.Collectors; + +import com.baeldung.boot.jsp.exception.DuplicateBookException; +import org.springframework.stereotype.Service; + +import com.baeldung.boot.jsp.dto.Book; +import com.baeldung.boot.jsp.repository.BookRepository; +import com.baeldung.boot.jsp.repository.model.BookData; +import com.baeldung.boot.jsp.service.BookService; + +@Service +public class BookServiceImpl implements BookService { + + private final BookRepository bookRepository; + + public BookServiceImpl(BookRepository bookRepository) { + this.bookRepository = bookRepository; + } + + @Override + public Collection getBooks() { + return bookRepository.findAll() + .stream() + .map(BookServiceImpl::convertBookData) + .collect(Collectors.toList()); + } + + @Override + public Book addBook(Book book) { + final Optional existingBook = bookRepository.findById(book.getIsbn()); + if (existingBook.isPresent()) { + throw new DuplicateBookException(book); + } + + final BookData savedBook = bookRepository.add(convertBook(book)); + return convertBookData(savedBook); + } + + private static Book convertBookData(BookData bookData) { + return new Book(bookData.getIsbn(), bookData.getName(), bookData.getAuthor()); + } + + private static BookData convertBook(Book book) { + return new BookData(book.getIsbn(), book.getName(), book.getAuthor()); + } +} diff --git a/spring-web-modules/spring-boot-jsp/src/main/resources/application.properties b/spring-web-modules/spring-boot-jsp/src/main/resources/application.properties new file mode 100644 index 0000000000..56638f8c1a --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/resources/application.properties @@ -0,0 +1,4 @@ +server.servlet.context-path=/spring-boot-jsp + +spring.mvc.view.prefix: /WEB-INF/jsp/ +spring.mvc.view.suffix: .jsp \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/resources/static/css/common.css b/spring-web-modules/spring-boot-jsp/src/main/resources/static/css/common.css new file mode 100644 index 0000000000..a32d81c6a2 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/resources/static/css/common.css @@ -0,0 +1,10 @@ +table { + font-family: arial, sans-serif; + border-collapse: collapse; +} + +td, th { + border: 1px solid #dddddd; + text-align: left; + padding: 8px; +} \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/resources/static/error/4xx.html b/spring-web-modules/spring-boot-jsp/src/main/resources/static/error/4xx.html new file mode 100644 index 0000000000..c27bd8bb7a --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/resources/static/error/4xx.html @@ -0,0 +1,10 @@ + + + + + Error + + +Opps! 4xx Error Occurred. + + \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/add-book.jsp b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/add-book.jsp new file mode 100644 index 0000000000..3b815dfafb --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/add-book.jsp @@ -0,0 +1,23 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Add Book + + + + +
Successfully added Book with ISBN: ${savedBook.isbn}
+
+ + + + ISBN: + Book Name: + Author Name: + + + + + \ No newline at end of file diff --git a/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/error-book.jsp b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/error-book.jsp new file mode 100644 index 0000000000..c04756462d --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/error-book.jsp @@ -0,0 +1,18 @@ +<%-- + Created by IntelliJ IDEA. + User: jason + Date: 3/13/21 + Time: 10:39 PM + To change this template use File | Settings | File Templates. +--%> +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + Error + + +

Reference: ${ref}

+

Error Message: ${message}

+

Object: ${object}

+ + diff --git a/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/view-books.jsp b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/view-books.jsp new file mode 100644 index 0000000000..46bfbbac99 --- /dev/null +++ b/spring-web-modules/spring-boot-jsp/src/main/webapp/WEB-INF/jsp/view-books.jsp @@ -0,0 +1,30 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> + + + View Books + + " rel="stylesheet" type="text/css"> + + + + + + + + + + + + + + + + + + + + +
ISBNNameAuthor
${book.isbn}${book.name}${book.author}
+ + \ No newline at end of file