From 864288661c02cf67fb87b7b427f64307e1663469 Mon Sep 17 00:00:00 2001 From: JohanHiths Date: Mon, 9 Mar 2026 19:03:44 +0100 Subject: [PATCH 1/3] Refactored templates, controllers, and styles for improved book management flow - Replaced JTE templates with Thymeleaf equivalents. - Updated `BookController` methods and added support for CRUD operations. - Introduced new Thymeleaf templates for creating and updating books. - Added global exception handling for runtime exceptions. - Enhanced styling with separate CSS files for forms and navigation. - Modified `application.properties` to enable hidden method filtering for DELETE/PUT requests. --- .../GlobalExceptionHandler.java | 26 ++++++++++ .../lab1springboot/book/BookService.java | 9 ++-- .../lab1springboot/book/CreateBookDTO.java | 7 +++ .../controller/BookController.java | 47 ++++++++++++++----- .../controller/HomeController.java | 7 +-- .../controller/UserController.java | 19 ++++++++ .../org/example/lab1springboot/user/User.java | 31 ++++++++++++ src/main/jte/books.jte | 22 --------- src/main/jte/home.jte | 14 ------ src/main/jte/updatebook.jte | 0 src/main/resources/application.properties | 2 +- src/main/resources/static/css/base.css | 3 ++ .../static/css/books.css} | 0 .../static/css/forms.css} | 0 src/main/resources/static/css/navbar.css | 4 ++ src/main/resources/static/style.css | 0 src/main/resources/templates/books.html | 45 ++++++++++++++---- src/main/resources/templates/create-book.html | 19 ++++++++ src/main/resources/templates/home.html | 27 +++-------- src/main/resources/templates/navbar.html | 27 +++++++++++ src/main/resources/templates/update-book.html | 23 +++++++++ 21 files changed, 245 insertions(+), 87 deletions(-) create mode 100644 src/main/java/org/example/lab1springboot/GlobalExceptionHandler.java create mode 100644 src/main/java/org/example/lab1springboot/controller/UserController.java create mode 100644 src/main/java/org/example/lab1springboot/user/User.java delete mode 100644 src/main/jte/books.jte delete mode 100644 src/main/jte/home.jte delete mode 100644 src/main/jte/updatebook.jte create mode 100644 src/main/resources/static/css/base.css rename src/main/{jte/createbook.jte => resources/static/css/books.css} (100%) rename src/main/{jte/deletebook.jte => resources/static/css/forms.css} (100%) create mode 100644 src/main/resources/static/css/navbar.css delete mode 100644 src/main/resources/static/style.css create mode 100644 src/main/resources/templates/create-book.html create mode 100644 src/main/resources/templates/navbar.html create mode 100644 src/main/resources/templates/update-book.html diff --git a/src/main/java/org/example/lab1springboot/GlobalExceptionHandler.java b/src/main/java/org/example/lab1springboot/GlobalExceptionHandler.java new file mode 100644 index 0000000..8af55d9 --- /dev/null +++ b/src/main/java/org/example/lab1springboot/GlobalExceptionHandler.java @@ -0,0 +1,26 @@ +package org.example.lab1springboot; + +import org.springframework.ui.Model; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +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.View; + +import java.util.HashMap; +import java.util.Map; + +import static org.springframework.util.ReflectionUtils.getField; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(RuntimeException.class) + public String handleRuntimeException(RuntimeException ex, Model model) { + + model.addAttribute("errorMessage", ex.getMessage()); + + return "error"; + } +} \ No newline at end of file diff --git a/src/main/java/org/example/lab1springboot/book/BookService.java b/src/main/java/org/example/lab1springboot/book/BookService.java index eea40b9..7da13a3 100644 --- a/src/main/java/org/example/lab1springboot/book/BookService.java +++ b/src/main/java/org/example/lab1springboot/book/BookService.java @@ -25,10 +25,11 @@ public List getAllBooks() { } public void deleteBook(Long id) { - if (!bookRepository.existsById(id)) { - throw new RuntimeException("Book not found with id: " + id); - } - bookRepository.deleteById(id); + + Book book = bookRepository.findById(id) + .orElseThrow(() -> new RuntimeException("Book not found")); + + bookRepository.delete(book); } public Book getBookById(Long id) { diff --git a/src/main/java/org/example/lab1springboot/book/CreateBookDTO.java b/src/main/java/org/example/lab1springboot/book/CreateBookDTO.java index ec3c824..1d4e0ce 100644 --- a/src/main/java/org/example/lab1springboot/book/CreateBookDTO.java +++ b/src/main/java/org/example/lab1springboot/book/CreateBookDTO.java @@ -5,17 +5,24 @@ import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.Data; import lombok.Getter; import lombok.Setter; @Getter @Setter +@Data public class CreateBookDTO { @NotBlank(message = "name cannot be empty") private String name; + @NotBlank(message = "title cannot be empty") + private String title; + @NotBlank(message = "author cannot be empty") + private String author; + @NotBlank(message = "Description cannot be empty") private String description; diff --git a/src/main/java/org/example/lab1springboot/controller/BookController.java b/src/main/java/org/example/lab1springboot/controller/BookController.java index c094005..df54c93 100644 --- a/src/main/java/org/example/lab1springboot/controller/BookController.java +++ b/src/main/java/org/example/lab1springboot/controller/BookController.java @@ -2,16 +2,20 @@ import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; import org.example.lab1springboot.book.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; + @Controller -@RequestMapping("/books") public class BookController { + Logger log = LoggerFactory.getLogger(BookController.class); BookService bookService; @@ -22,15 +26,18 @@ public class BookController { - @GetMapping("/{id}") - public String getBookById(@PathVariable Long id, Model model) { - Book book = bookService.getBookById(id); - model.addAttribute("book", book); - return "books"; - } +// @GetMapping("/{id}") +// public String getBookById(@PathVariable Long id, Model model) { +// Book book = bookService.getBookById(id); +// +// model.addAttribute("book", book); +// return "books"; +// } + + @GetMapping("/books") + public String getBooks(@RequestParam(required = false) String title,Model model) { - @GetMapping - public String getAllBooks(Model model) { + model.addAttribute("activePage", "viewBooks"); model.addAttribute("books", bookService.getAllBooks()); return "books"; } @@ -41,7 +48,7 @@ public String getAllBooks(Model model) { public String createBook(@Valid CreateBookDTO dto, BindingResult result) { if(result.hasErrors()){ - return "createbook"; + return "create-book"; } bookService.createBook(dto); return "redirect:/books"; @@ -50,8 +57,7 @@ public String createBook(@Valid CreateBookDTO dto, BindingResult result) { @PutMapping("/{id}") public String updateBook(@PathVariable Long id, @Valid UpdateBookDTO updateBookDTO, BindingResult bindingResult, Model model) { if (bindingResult.hasErrors()) { - model.addAttribute("updateBookDTO", updateBookDTO); - return "updatebook"; + return "update-book"; } bookService.updateBook(id, updateBookDTO); @@ -61,10 +67,27 @@ public String updateBook(@PathVariable Long id, @Valid UpdateBookDTO updateBookD @DeleteMapping("/{id}") public String deleteBook(@PathVariable Long id) { + bookService.deleteBook(id); return "redirect:/books"; } + @GetMapping("/update/{id}") + public String showUpdateForm(@PathVariable Long id, Model model) { + Book book = bookService.getBookById(id); + model.addAttribute("book", book); + return "update-book"; + } + + @GetMapping("books/create") + public String showCreateForm(Model model) { + + model.addAttribute("book", new CreateBookDTO()); + return "create-book"; + } + + + diff --git a/src/main/java/org/example/lab1springboot/controller/HomeController.java b/src/main/java/org/example/lab1springboot/controller/HomeController.java index 96e9eea..7d66534 100644 --- a/src/main/java/org/example/lab1springboot/controller/HomeController.java +++ b/src/main/java/org/example/lab1springboot/controller/HomeController.java @@ -11,11 +11,8 @@ public class HomeController { @GetMapping("/") public String home(Model model) { - System.out.println("DEBUG: Home controller triggered"); - - model.addAttribute("message", "Welcome to Thymeleaf!"); - model.addAttribute("currentDate", java.time.LocalDate.now()); - + model.addAttribute("activePage", "home"); return "home"; } + } diff --git a/src/main/java/org/example/lab1springboot/controller/UserController.java b/src/main/java/org/example/lab1springboot/controller/UserController.java new file mode 100644 index 0000000..817f0dc --- /dev/null +++ b/src/main/java/org/example/lab1springboot/controller/UserController.java @@ -0,0 +1,19 @@ +package org.example.lab1springboot.controller; + +import jakarta.validation.Valid; +import org.apache.catalina.User; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +@Controller +public class UserController { + + @PostMapping("/user") + public String CreateUser(@RequestBody @Valid User user) { + + return "user"; + + + } +} \ No newline at end of file diff --git a/src/main/java/org/example/lab1springboot/user/User.java b/src/main/java/org/example/lab1springboot/user/User.java new file mode 100644 index 0000000..e67ba7e --- /dev/null +++ b/src/main/java/org/example/lab1springboot/user/User.java @@ -0,0 +1,31 @@ +package org.example.lab1springboot.user; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class User { + + @NotNull(message = "Name cannot be empty") + private String name; + + @NotEmpty + @NotNull(message = "Username cannot be empty") + private String username; + + @NotNull(message = "Email cannot be empty") + private String email; + + @NotBlank(message = "Password cannot be blank") + private String password; + + @NotNull(message = "Id cannot be empty") + private String id; + + + +} diff --git a/src/main/jte/books.jte b/src/main/jte/books.jte deleted file mode 100644 index 68ef6be..0000000 --- a/src/main/jte/books.jte +++ /dev/null @@ -1,22 +0,0 @@ -@param String nameError - - - - - - Form demo - - -

Form demo

-
-
-
- @if(nameError != null) -
${nameError}

- @endif -
-

- -
- - diff --git a/src/main/jte/home.jte b/src/main/jte/home.jte deleted file mode 100644 index 5ca76dc..0000000 --- a/src/main/jte/home.jte +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - Title - - -
-

Hello Home

-
- - \ No newline at end of file diff --git a/src/main/jte/updatebook.jte b/src/main/jte/updatebook.jte deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6eed576..d87b370 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -6,4 +6,4 @@ spring.datasource.password=password spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.h2.console.enabled=true spring.jpa.hibernate.ddl-auto=update - +spring.mvc.hiddenmethod.filter.enabled=true diff --git a/src/main/resources/static/css/base.css b/src/main/resources/static/css/base.css new file mode 100644 index 0000000..dcb2aa2 --- /dev/null +++ b/src/main/resources/static/css/base.css @@ -0,0 +1,3 @@ +body { + font-family: Arial, sans-serif; +} diff --git a/src/main/jte/createbook.jte b/src/main/resources/static/css/books.css similarity index 100% rename from src/main/jte/createbook.jte rename to src/main/resources/static/css/books.css diff --git a/src/main/jte/deletebook.jte b/src/main/resources/static/css/forms.css similarity index 100% rename from src/main/jte/deletebook.jte rename to src/main/resources/static/css/forms.css diff --git a/src/main/resources/static/css/navbar.css b/src/main/resources/static/css/navbar.css new file mode 100644 index 0000000..33ad45f --- /dev/null +++ b/src/main/resources/static/css/navbar.css @@ -0,0 +1,4 @@ +.navbar { + display:flex; + justify-content:space-between; +} \ No newline at end of file diff --git a/src/main/resources/static/style.css b/src/main/resources/static/style.css deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/resources/templates/books.html b/src/main/resources/templates/books.html index da67182..31e70a8 100644 --- a/src/main/resources/templates/books.html +++ b/src/main/resources/templates/books.html @@ -2,15 +2,44 @@ - Bookstore + Book List + -

Bookstore

-
-

Book Name

-
- + + + +
+

All Books

+ + + + + + + + + + + + + + + + + + +
IDTitleAuthorActions
1TitelFörfattare + Edit + +
+ +
+
+ +
+ Add New Book +
+ \ No newline at end of file diff --git a/src/main/resources/templates/create-book.html b/src/main/resources/templates/create-book.html new file mode 100644 index 0000000..d96c968 --- /dev/null +++ b/src/main/resources/templates/create-book.html @@ -0,0 +1,19 @@ + + + + + Bookstore + + + + +
+ + +
+ + +
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html index 83ea100..7bb7e69 100644 --- a/src/main/resources/templates/home.html +++ b/src/main/resources/templates/home.html @@ -1,32 +1,17 @@ - - + - Home Page - - + Bookstore + -
-

Default Welcome Message

-
+
-

Today is: 2023-01-01

- -
-

Date is available!

-
- - - - +

Welcome Message

+

Today's date is: Date

- -
-

© 2026 My Application

-
\ No newline at end of file diff --git a/src/main/resources/templates/navbar.html b/src/main/resources/templates/navbar.html new file mode 100644 index 0000000..94016ca --- /dev/null +++ b/src/main/resources/templates/navbar.html @@ -0,0 +1,27 @@ + + + + + Bookstore + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/update-book.html b/src/main/resources/templates/update-book.html new file mode 100644 index 0000000..22f9820 --- /dev/null +++ b/src/main/resources/templates/update-book.html @@ -0,0 +1,23 @@ + + + + + Bookstore + + + + +
+ +
+ + + + + +
+ +
+ + + \ No newline at end of file From e49ad59f5b6f7e0836ab9f537080d78b76a3068c Mon Sep 17 00:00:00 2001 From: JohanHiths Date: Tue, 10 Mar 2026 17:55:55 +0100 Subject: [PATCH 2/3] Enhanced book management with pagination and global exception handling - Added pagination support to `BookController` and updated templates with pagination controls. - Introduced `BookNotFoundException` for improved error handling. - Enhanced `GlobalExceptionHandler` to handle various exceptions including validation and runtime errors. - Updated styles and templates to improve user experience for error and paging scenarios. - Refactored `BookService` for cleaner logic and added transactional annotations. --- pom.xml | 6 +-- .../lab1springboot/BookNotFoundException.java | 7 +++ .../GlobalExceptionHandler.java | 34 +++++++++++++- .../lab1springboot/book/BookService.java | 36 +++++++++++---- .../controller/BookController.java | 44 ++++++++++++++----- .../controller/UserController.java | 2 +- src/main/resources/application.properties | 1 + src/main/resources/static/css/books.css | 12 +++++ src/main/resources/templates/books.html | 14 ++++++ src/main/resources/templates/error.html | 19 ++++++++ 10 files changed, 148 insertions(+), 27 deletions(-) create mode 100644 src/main/java/org/example/lab1springboot/BookNotFoundException.java create mode 100644 src/main/resources/templates/error.html diff --git a/pom.xml b/pom.xml index c0c00fe..1c813cf 100644 --- a/pom.xml +++ b/pom.xml @@ -63,11 +63,7 @@ org.springframework.boot spring-boot-starter-thymeleaf - - - - - + diff --git a/src/main/java/org/example/lab1springboot/BookNotFoundException.java b/src/main/java/org/example/lab1springboot/BookNotFoundException.java new file mode 100644 index 0000000..cc86f84 --- /dev/null +++ b/src/main/java/org/example/lab1springboot/BookNotFoundException.java @@ -0,0 +1,7 @@ +package org.example.lab1springboot; + +public class BookNotFoundException extends RuntimeException { + public BookNotFoundException(String message) { + super(message); + } +} diff --git a/src/main/java/org/example/lab1springboot/GlobalExceptionHandler.java b/src/main/java/org/example/lab1springboot/GlobalExceptionHandler.java index 8af55d9..5487504 100644 --- a/src/main/java/org/example/lab1springboot/GlobalExceptionHandler.java +++ b/src/main/java/org/example/lab1springboot/GlobalExceptionHandler.java @@ -1,5 +1,6 @@ package org.example.lab1springboot; +import org.springframework.http.HttpStatus; import org.springframework.ui.Model; import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; @@ -13,14 +14,43 @@ import static org.springframework.util.ReflectionUtils.getField; +/* +Global exception handler to handle all exceptions more effectively + + */ @ControllerAdvice public class GlobalExceptionHandler { - @ExceptionHandler(RuntimeException.class) - public String handleRuntimeException(RuntimeException ex, Model model) { + + + @ExceptionHandler(BookNotFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) // 404 + public String notFoundException(BookNotFoundException ex, Model model) { model.addAttribute("errorMessage", ex.getMessage()); return "error"; } + + @ExceptionHandler(RuntimeException.class) + @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 500 + public String handleRuntimeException(Exception ex, Model model) { + + model.addAttribute("errorMessage", "Unexpected error"); + return "error"; + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + public String handleMethodArgumentNotValidException(MethodArgumentNotValidException ex, Model model) { + Map errors = new HashMap<>(); + + ex.getBindingResult().getFieldErrors().forEach(error -> + errors.put(error.getField(), error.getDefaultMessage()) + ); + + model.addAttribute("errors", errors); + return "error"; + } + } \ No newline at end of file diff --git a/src/main/java/org/example/lab1springboot/book/BookService.java b/src/main/java/org/example/lab1springboot/book/BookService.java index 7da13a3..a2c90f9 100644 --- a/src/main/java/org/example/lab1springboot/book/BookService.java +++ b/src/main/java/org/example/lab1springboot/book/BookService.java @@ -1,17 +1,24 @@ package org.example.lab1springboot.book; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.transaction.annotation.Transactional; + +import lombok.extern.slf4j.Slf4j; +import org.example.lab1springboot.BookNotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.util.List; - +@Slf4j @Service + public class BookService { - private static final Logger log = LoggerFactory.getLogger(BookService.class); private final BookRepository bookRepository; public BookService(BookRepository bookRepository) { @@ -19,33 +26,39 @@ public BookService(BookRepository bookRepository) { this.bookRepository = bookRepository; } + @Transactional(readOnly = true) public List getAllBooks() { return bookRepository.findAll(); } + @Transactional public void deleteBook(Long id) { + if(bookRepository.findById(id).isEmpty()) + throw new BookNotFoundException("Book not found with id: " + id); - Book book = bookRepository.findById(id) - .orElseThrow(() -> new RuntimeException("Book not found")); - - bookRepository.delete(book); + bookRepository.deleteById(id); } + @Transactional public Book getBookById(Long id) { return bookRepository.findById(id) - .orElseThrow(() -> new RuntimeException("Book not found with id: " + id)); + .orElseThrow(() -> new BookNotFoundException("Book not found with id: " + id)); } + + @Transactional public Book updateBook(Long id, UpdateBookDTO dto) { Book book = getBookById(id); book.setTitle(dto.getTitle()); book.setAuthor(dto.getName()); - bookRepository.save(book); + Book updatedBook = bookRepository.save(book); + log.info("Book updated successfully"); - return book; + return updatedBook; } + @Transactional public Book createBook(CreateBookDTO dto) { Book book = BookMapper.toEntity(dto); @@ -53,4 +66,9 @@ public Book createBook(CreateBookDTO dto) { return bookRepository.save(book); } + public Page getAllBooksPaginated(int page, int size){ + Pageable pageable = PageRequest.of(page, size); + return bookRepository.findAll(pageable); + } + } diff --git a/src/main/java/org/example/lab1springboot/controller/BookController.java b/src/main/java/org/example/lab1springboot/controller/BookController.java index df54c93..f662a83 100644 --- a/src/main/java/org/example/lab1springboot/controller/BookController.java +++ b/src/main/java/org/example/lab1springboot/controller/BookController.java @@ -3,20 +3,29 @@ import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; +import org.example.lab1springboot.BookNotFoundException; import org.example.lab1springboot.book.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + +import org.springframework.data.domain.Page; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; + + + @Controller + public class BookController { Logger log = LoggerFactory.getLogger(BookController.class); + BookService bookService; BookController(BookService bookService) { @@ -34,15 +43,6 @@ public class BookController { // return "books"; // } - @GetMapping("/books") - public String getBooks(@RequestParam(required = false) String title,Model model) { - - model.addAttribute("activePage", "viewBooks"); - model.addAttribute("books", bookService.getAllBooks()); - return "books"; - } - - @PostMapping("books/create") public String createBook(@Valid CreateBookDTO dto, BindingResult result) { @@ -75,7 +75,12 @@ public String deleteBook(@PathVariable Long id) { @GetMapping("/update/{id}") public String showUpdateForm(@PathVariable Long id, Model model) { Book book = bookService.getBookById(id); - model.addAttribute("book", book); + + UpdateBookDTO dto = new UpdateBookDTO(); + + + model.addAttribute("updateBookDTO", dto); + model.addAttribute("id", id); return "update-book"; } @@ -86,8 +91,27 @@ public String showCreateForm(Model model) { return "create-book"; } + @ExceptionHandler(BookNotFoundException.class) + @ResponseStatus(HttpStatus.NOT_FOUND) + public String handleBookNotFound(BookNotFoundException ex, Model model) { + model.addAttribute("errorMessage", ex.getMessage()); + return "error"; + } + + @GetMapping("/books") + public String getAllBooks( + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "5") int size, + Model model) { + + Page bookPage = bookService.getAllBooksPaginated(page, size); + model.addAttribute("books", bookPage.getContent()); + model.addAttribute("currentPage", page); + model.addAttribute("totalPages", bookPage.getTotalPages()); + return "books"; + } diff --git a/src/main/java/org/example/lab1springboot/controller/UserController.java b/src/main/java/org/example/lab1springboot/controller/UserController.java index 817f0dc..f2ae78e 100644 --- a/src/main/java/org/example/lab1springboot/controller/UserController.java +++ b/src/main/java/org/example/lab1springboot/controller/UserController.java @@ -1,7 +1,7 @@ package org.example.lab1springboot.controller; import jakarta.validation.Valid; -import org.apache.catalina.User; +import org.example.lab1springboot.user.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d87b370..ae767d3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -7,3 +7,4 @@ spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.h2.console.enabled=true spring.jpa.hibernate.ddl-auto=update spring.mvc.hiddenmethod.filter.enabled=true + diff --git a/src/main/resources/static/css/books.css b/src/main/resources/static/css/books.css index e69de29..26ac67a 100644 --- a/src/main/resources/static/css/books.css +++ b/src/main/resources/static/css/books.css @@ -0,0 +1,12 @@ +.pagination-container a { + padding: 8px 16px; + text-decoration: none; + border: 1px solid #ddd; + color: black; +} + +.pagination-container a.active { + background-color: #6d15b5; + color: white; + border: 1px solid #6d15b5; +} \ No newline at end of file diff --git a/src/main/resources/templates/books.html b/src/main/resources/templates/books.html index 31e70a8..9a80221 100644 --- a/src/main/resources/templates/books.html +++ b/src/main/resources/templates/books.html @@ -39,6 +39,20 @@

All Books


Add New Book + +
+ Previous + + + + + + Next +
diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html new file mode 100644 index 0000000..d2867f5 --- /dev/null +++ b/src/main/resources/templates/error.html @@ -0,0 +1,19 @@ + + + + + Title + +< +
+
🚀
+

404

+

Woopsie daisy! Page went to the moon.

+ + +

We cannot find the page you were looking for

+ + Back to Earth (Home) +
+ + \ No newline at end of file From 916e1ce50325c85579abea57f8af4182c9f8bb43 Mon Sep 17 00:00:00 2001 From: JohanHiths Date: Wed, 11 Mar 2026 07:10:51 +0100 Subject: [PATCH 3/3] Added `LoggingFilter` and `LoggingInterceptor` for request and response logging --- .../lab1springboot/filter/LoggingFilter.java | 37 +++++++++++++++++++ .../filter/LoggingInterceptor.java | 22 +++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/main/java/org/example/lab1springboot/filter/LoggingFilter.java create mode 100644 src/main/java/org/example/lab1springboot/filter/LoggingInterceptor.java diff --git a/src/main/java/org/example/lab1springboot/filter/LoggingFilter.java b/src/main/java/org/example/lab1springboot/filter/LoggingFilter.java new file mode 100644 index 0000000..b9aaf4c --- /dev/null +++ b/src/main/java/org/example/lab1springboot/filter/LoggingFilter.java @@ -0,0 +1,37 @@ +package org.example.lab1springboot.filter; + +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +@Order(1) +public class LoggingFilter implements Filter { + + + @Override + + public void doFilter( + + ServletRequest request, + ServletResponse response, + FilterChain chain + + ) throws IOException, ServletException { + + HttpServletRequest httpRequest = (HttpServletRequest) request; + System.out.println("Request received for: " + httpRequest.getRequestURI()); + + chain.doFilter(request, response); + HttpServletResponse httpResponse = (HttpServletResponse) response; + System.out.println("Response status: " + httpResponse.getStatus()); + + } + + + +} \ No newline at end of file diff --git a/src/main/java/org/example/lab1springboot/filter/LoggingInterceptor.java b/src/main/java/org/example/lab1springboot/filter/LoggingInterceptor.java new file mode 100644 index 0000000..18d9c82 --- /dev/null +++ b/src/main/java/org/example/lab1springboot/filter/LoggingInterceptor.java @@ -0,0 +1,22 @@ +package org.example.lab1springboot.filter; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +@Component +public class LoggingInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle( + HttpServletRequest request, + HttpServletResponse response, + Object handler) { + + System.out.println("Request: " + request.getRequestURI()); + + return true; + } + +} \ No newline at end of file