Browse Source

Common clean-up; update string formats & Book class annotations

Signed-off-by: Pekka Helenius <fincer89@hotmail.com>
v0.0.1-alpha
Pekka Helenius 4 years ago
parent
commit
64b26e407f
8 changed files with 341 additions and 325 deletions
  1. +6
    -6
      bookstore/src/main/java/com/fjordtek/bookstore/BookstoreApplication.java
  2. +11
    -2
      bookstore/src/main/java/com/fjordtek/bookstore/annotation/CurrentYear.java
  3. +5
    -5
      bookstore/src/main/java/com/fjordtek/bookstore/annotation/CurrentYearValidator.java
  4. +61
    -50
      bookstore/src/main/java/com/fjordtek/bookstore/model/Book.java
  5. +1
    -2
      bookstore/src/main/java/com/fjordtek/bookstore/model/BookRepository.java
  6. +186
    -189
      bookstore/src/main/java/com/fjordtek/bookstore/web/BookController.java
  7. +20
    -20
      bookstore/src/main/java/com/fjordtek/bookstore/web/HttpExceptionHandler.java
  8. +51
    -51
      bookstore/src/main/java/com/fjordtek/bookstore/web/HttpServerLogger.java

+ 6
- 6
bookstore/src/main/java/com/fjordtek/bookstore/BookstoreApplication.java View File

@ -1,18 +1,18 @@
// Pekka Helenius <fincer89@hotmail.com>, Fjordtek 2020
package com.fjordtek.bookstore; package com.fjordtek.bookstore;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner; import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import com.fjordtek.bookstore.model.Book;
import com.fjordtek.bookstore.model.BookRepository; import com.fjordtek.bookstore.model.BookRepository;
import com.fjordtek.bookstore.model.*;
@SpringBootApplication @SpringBootApplication
public class BookstoreApplication extends SpringBootServletInitializer { public class BookstoreApplication extends SpringBootServletInitializer {
private static final Logger commonLogger = LoggerFactory.getLogger(BookstoreApplication.class); private static final Logger commonLogger = LoggerFactory.getLogger(BookstoreApplication.class);
@ -23,10 +23,10 @@ public class BookstoreApplication extends SpringBootServletInitializer {
@Bean @Bean
public CommandLineRunner bookDatabaseRunner(BookRepository repository) { public CommandLineRunner bookDatabaseRunner(BookRepository repository) {
return (args) -> { return (args) -> {
commonLogger.info("Add new sample books to database"); commonLogger.info("Add new sample books to database");
repository.save(new Book("Book 1 title", "Book 1 author", 2020, "1231231-12", 40.00)); repository.save(new Book("Book 1 title", "Book 1 author", 2020, "1231231-12", 40.00));
repository.save(new Book("Book 2 title", "Book 2 author", 2005, "3213221-3", 20.17)); repository.save(new Book("Book 2 title", "Book 2 author", 2005, "3213221-3", 20.17));
@ -38,5 +38,5 @@ public class BookstoreApplication extends SpringBootServletInitializer {
}; };
} }
} }

+ 11
- 2
bookstore/src/main/java/com/fjordtek/bookstore/annotation/CurrentYear.java View File

@ -3,17 +3,26 @@
package com.fjordtek.bookstore.annotation; package com.fjordtek.bookstore.annotation;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import javax.validation.Constraint; import javax.validation.Constraint;
import javax.validation.Payload; import javax.validation.Payload;
@Documented @Documented
@Constraint(validatedBy = CurrentYearValidator.class) @Constraint(validatedBy = CurrentYearValidator.class)
@Target(value={ElementType.TYPE_USE, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
@Target(
value={
ElementType.TYPE_USE,
ElementType.ANNOTATION_TYPE,
ElementType.CONSTRUCTOR,
ElementType.FIELD,
ElementType.METHOD,
ElementType.PARAMETER
}
)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface CurrentYear { public @interface CurrentYear {


+ 5
- 5
bookstore/src/main/java/com/fjordtek/bookstore/annotation/CurrentYearValidator.java View File

@ -11,13 +11,13 @@ import org.springframework.stereotype.Component;
@Component @Component
public class CurrentYearValidator implements ConstraintValidator<CurrentYear, Integer> { public class CurrentYearValidator implements ConstraintValidator<CurrentYear, Integer> {
private static final int yearNow = Year.now().getValue(); private static final int yearNow = Year.now().getValue();
@Override @Override
public void initialize(CurrentYear year) {
}
public void initialize(CurrentYear yearAnnotation) {
}
@Override @Override
public boolean isValid(Integer year, ConstraintValidatorContext constraintValidatorContext) { public boolean isValid(Integer year, ConstraintValidatorContext constraintValidatorContext) {
return year <= yearNow; return year <= yearNow;


+ 61
- 50
bookstore/src/main/java/com/fjordtek/bookstore/model/Book.java View File

@ -2,27 +2,25 @@
package com.fjordtek.bookstore.model; package com.fjordtek.bookstore.model;
//import java.sql.Timestamp;
//import javax.validation.constraints.PastOrPresent;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMax;
import javax.validation.constraints.DecimalMin; import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Digits; import javax.validation.constraints.Digits;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import javax.validation.constraints.Pattern; import javax.validation.constraints.Pattern;
import javax.validation.constraints.NotNull;
import com.fjordtek.bookstore.annotation.CurrentYear;
import javax.validation.constraints.Size;
import org.springframework.format.annotation.NumberFormat; import org.springframework.format.annotation.NumberFormat;
import org.springframework.format.annotation.NumberFormat.Style; import org.springframework.format.annotation.NumberFormat.Style;
//import java.sql.Timestamp;
//import javax.validation.constraints.PastOrPresent;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import com.fjordtek.bookstore.annotation.CurrentYear;
@Entity @Entity
public class Book { public class Book {
@ -31,23 +29,33 @@ public class Book {
private static final int strMax = 100; private static final int strMax = 100;
// We format length check in Size annotation, not here // We format length check in Size annotation, not here
private static final String regexCommon = "^[a-zA-Z0-9\\-\\s]*$"; private static final String regexCommon = "^[a-zA-Z0-9\\-\\s]*$";
private static final int strIsbnFirstPartMin = 7; private static final int strIsbnFirstPartMin = 7;
private static final int strIsbnFirstPartMax = 7; private static final int strIsbnFirstPartMax = 7;
private static final int strIsbnLastPartMin = 1; private static final int strIsbnLastPartMin = 1;
private static final int strIsbnLastPartMax = 3; private static final int strIsbnLastPartMax = 3;
private static final int strIsbnMin = strIsbnFirstPartMin + strIsbnLastPartMin + 1; private static final int strIsbnMin = strIsbnFirstPartMin + strIsbnLastPartMin + 1;
private static final int strIsbnMax = strIsbnFirstPartMax + strIsbnLastPartMax + 1; private static final int strIsbnMax = strIsbnFirstPartMax + strIsbnLastPartMax + 1;
// We format length and syntax here for ISBN input string // We format length and syntax here for ISBN input string
// 1231234-1 <--> 1231234-123 // 1231234-1 <--> 1231234-123
private static final String regexIsbn = "^[0-9]{" + strIsbnFirstPartMin +
"," + strIsbnFirstPartMax + "}\\-[0-9]{" + strIsbnLastPartMin + "," + strIsbnLastPartMax + "}$";
private static final String regexIsbn = "^[0-9]{" + strIsbnFirstPartMin + "," + strIsbnFirstPartMax + "}" +
"\\-[0-9]{" + strIsbnLastPartMin + "," + strIsbnLastPartMax + "}$";
private static final int yearMin = 1800; private static final int yearMin = 1800;
private static final String minPrice = "0.01"; private static final String minPrice = "0.01";
private static final String maxPrice = "999.99"; private static final String maxPrice = "999.99";
/* For future reference
public static final enum BookDataTypes {
STRING,
BOOLEAN,
INTEGER,
DOUBLE,
LONG
}
*/
//////////////////// ////////////////////
// Primary key value in database // Primary key value in database
@ -56,10 +64,11 @@ public class Book {
strategy = GenerationType.AUTO strategy = GenerationType.AUTO
) )
private long id; private long id;
//////////////////// ////////////////////
// Attributes with hard-coded constraints // Attributes with hard-coded constraints
//////////
@Size( @Size(
min = strMin, max = strMax, min = strMin, max = strMax,
message = "Title length must be " + strMin + "-" + strMax + " characters" message = "Title length must be " + strMin + "-" + strMax + " characters"
@ -72,7 +81,8 @@ public class Book {
message = "Invalid characters" message = "Invalid characters"
) )
private String title; private String title;
//////////
@Size( @Size(
min = strMin, max = strMax, min = strMin, max = strMax,
message = "Author length must be " + strMin + "-" + strMax + " characters" message = "Author length must be " + strMin + "-" + strMax + " characters"
@ -85,13 +95,13 @@ public class Book {
message = "Invalid characters" message = "Invalid characters"
) )
private String author; private String author;
//////////
// TODO: Prefer Timestamp data type // TODO: Prefer Timestamp data type
// @DateTimeFormat(pattern = "yyyy") // @DateTimeFormat(pattern = "yyyy")
// private Timestamp year; // private Timestamp year;
// ... // ...
@NotNull
@Min( @Min(
value = yearMin, value = yearMin,
message = "Minimum allowed year: " + yearMin message = "Minimum allowed year: " + yearMin
@ -99,12 +109,13 @@ public class Book {
@CurrentYear @CurrentYear
private int year; private int year;
//////////
@NotBlank( @NotBlank(
message = "Fill the ISBN code form" message = "Fill the ISBN code form"
) )
@Pattern( @Pattern(
regexp = regexIsbn, regexp = regexIsbn,
message = "Please use syntax: <" +
message = "Please use syntax: <" +
strIsbnFirstPartMin + " integers>-<" + strIsbnFirstPartMin + " integers>-<" +
strIsbnLastPartMin + "-" + strIsbnLastPartMin + "-" +
strIsbnLastPartMax + " integers>" strIsbnLastPartMax + " integers>"
@ -114,11 +125,12 @@ public class Book {
message = "Length must be " + strIsbnMin + "-" + strIsbnMax + " characters" message = "Length must be " + strIsbnMin + "-" + strIsbnMax + " characters"
) )
private String isbn; private String isbn;
//////////
@NumberFormat(style = Style.NUMBER, pattern = "#,###.###") @NumberFormat(style = Style.NUMBER, pattern = "#,###.###")
@Digits( @Digits(
integer = 3, fraction = 2, integer = 3, fraction = 2,
message = "Invalid price, possibly too many decimals"
message = "Invalid price, possibly too many decimals"
) )
@DecimalMin( @DecimalMin(
value = minPrice, message = "Too low price value. Minimum allowed: " + minPrice value = minPrice, message = "Too low price value. Minimum allowed: " + minPrice
@ -131,66 +143,66 @@ public class Book {
//////////////////// ////////////////////
// Attribute setters // Attribute setters
// TODO consider accessibility restrictions? // TODO consider accessibility restrictions?
// NOTE: in default scenario, this is automatically generated // NOTE: in default scenario, this is automatically generated
public void setId(long id) { public void setId(long id) {
this.id = id; this.id = id;
} }
public void setTitle(String title) { public void setTitle(String title) {
this.title = title; this.title = title;
} }
public void setAuthor(String author) { public void setAuthor(String author) {
this.author = author; this.author = author;
} }
public void setYear(int year) { public void setYear(int year) {
this.year = year; this.year = year;
} }
public void setIsbn(String isbn) { public void setIsbn(String isbn) {
this.isbn = isbn; this.isbn = isbn;
} }
public void setPrice(double price) { public void setPrice(double price) {
this.price = price; this.price = price;
} }
//////////////////// ////////////////////
// Attribute getters // Attribute getters
// TODO consider accessibility restrictions? // TODO consider accessibility restrictions?
public long getId() { public long getId() {
return id; return id;
} }
public String getTitle() { public String getTitle() {
return title; return title;
} }
public String getAuthor() { public String getAuthor() {
return author; return author;
} }
public int getYear() { public int getYear() {
return year; return year;
} }
public String getIsbn() { public String getIsbn() {
return isbn; return isbn;
} }
public double getPrice() {
public double getPrice() {
return price; return price;
} }
//////////////////// ////////////////////
// Class constructors // Class constructors
public Book() {} public Book() {}
public Book(String title, String author, int year, String isbn, double price) { public Book(String title, String author, int year, String isbn, double price) {
@ -201,19 +213,18 @@ public class Book {
this.isbn = isbn; this.isbn = isbn;
this.price = price; this.price = price;
} }
//////////////////// ////////////////////
// Class overrides // Class overrides
@Override @Override
public String toString() { public String toString() {
return "id: " + this.id + ", " +
return "[" + "id: " + this.id + ", " +
"title: " + this.title + ", " + "title: " + this.title + ", " +
"author: " + this.author + ", " + "author: " + this.author + ", " +
"year: " + this.year + ", " + "year: " + this.year + ", " +
"isbn: " + this.isbn + ", " + "isbn: " + this.isbn + ", " +
"price: " + this.price;
"price: " + this.price + "]";
} }
// ...
} }

+ 1
- 2
bookstore/src/main/java/com/fjordtek/bookstore/model/BookRepository.java View File

@ -6,10 +6,9 @@ import java.util.List;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
public interface BookRepository extends CrudRepository<Book, Long> { public interface BookRepository extends CrudRepository<Book, Long> {
// Handles both INSERT and UPDATE queries // Handles both INSERT and UPDATE queries
List<Book> findById(String title);
List<Book> findById(String title);
} }

+ 186
- 189
bookstore/src/main/java/com/fjordtek/bookstore/web/BookController.java View File

@ -2,6 +2,13 @@
package com.fjordtek.bookstore.web; package com.fjordtek.bookstore.web;
import java.time.Year;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
@ -10,25 +17,14 @@ import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
import java.time.Year;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import com.fjordtek.bookstore.model.*;
import com.fjordtek.bookstore.model.Book;
import com.fjordtek.bookstore.model.BookRepository;
@Controller @Controller
public class BookController { public class BookController {
/*
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
*/
protected static final String landingPageURL = "index"; protected static final String landingPageURL = "index";
protected static final String bookListPageURL = "booklist"; protected static final String bookListPageURL = "booklist";
protected static final String bookAddPageURL = "bookadd"; protected static final String bookAddPageURL = "bookadd";
@ -41,179 +37,180 @@ public class BookController {
@Autowired @Autowired
private BookRepository bookRepository; private BookRepository bookRepository;
@RequestMapping(
value = bookListPageURL,
method = { RequestMethod.GET, RequestMethod.POST }
)
public String defaultWebFormGet(HttpServletRequest requestData, Model dataModel) {
httpServerLogger.logMessageNormal(
requestData,
bookListPageURL + ": " + "HTTPOK"
);
dataModel.addAttribute("books", bookRepository.findAll());
return bookListPageURL;
}
//////////////////////////////
// ADD BOOK
@RequestMapping(
value = bookAddPageURL,
method = { RequestMethod.GET, RequestMethod.PUT }
)
public String webFormAddBook(
HttpServletRequest requestData,
Model dataModel
) {
httpServerLogger.logMessageNormal(
requestData,
bookAddPageURL + ": " + "HTTPOK"
);
Book newBook = new Book();
dataModel.addAttribute("book", newBook);
if (newBook.getYear() == 0) {
newBook.setYear(Year.now().getValue());
}
return bookAddPageURL;
}
@RequestMapping(
value = bookAddPageURL,
method = RequestMethod.POST
)
public String webFormSaveNewBook(
@Valid @ModelAttribute("book") Book book,
BindingResult bindingResult,
HttpServletRequest requestData
) {
if (bindingResult.hasErrors()) {
httpServerLogger.commonError("Book add: error [" + book.toString() + "]", requestData);
return bookAddPageURL;
}
httpServerLogger.logMessageNormal(
requestData,
bookAddPageURL + ": " + "HTTPOK"
);
bookRepository.save(book);
return "redirect:" + bookListPageURL;
}
//////////////////////////////
// DELETE BOOK
@RequestMapping(
value = bookDeletePageURL + "/{id}",
method = RequestMethod.GET
)
public String webFormDeleteBook(
@PathVariable("id") long bookId,
HttpServletRequest requestData
) {
httpServerLogger.logMessageNormal(
requestData,
bookDeletePageURL + ": " + "HTTPOK"
);
bookRepository.deleteById(bookId);
return "redirect:../" + bookListPageURL;
}
//////////////////////////////
// UPDATE BOOK
@RequestMapping(
value = bookEditPageURL + "/{id}",
method = RequestMethod.GET
)
public String webFormEditBook(
@PathVariable("id") long bookId,
Model dataModel,
HttpServletRequest requestData
) {
httpServerLogger.logMessageNormal(
requestData,
bookEditPageURL + ": " + "HTTPOK"
);
Book book = bookRepository.findById(bookId).get();
dataModel.addAttribute("book", book);
return bookEditPageURL;
}
@RequestMapping(
value = bookEditPageURL + "/{id}",
method = RequestMethod.POST
)
public String webFormUpdateBook(
@Valid @ModelAttribute("book") Book book,
BindingResult bindingResult,
HttpServletRequest requestData
) {
if (bindingResult.hasErrors()) {
httpServerLogger.commonError("Book edit: error [" + book.toString() + "]", requestData);
return bookAddPageURL;
}
httpServerLogger.logMessageNormal(
requestData,
bookEditPageURL + ": " + "HTTPOK"
);
bookRepository.save(book);
return "redirect:../" + bookListPageURL;
}
//////////////////////////////
// REDIRECTS
@RequestMapping(
value = { "/", landingPageURL },
method = RequestMethod.GET
)
@ResponseStatus(HttpStatus.FOUND)
public String redirectToDefaultWebForm() {
return "redirect:" + bookListPageURL;
}
// Other URL requests
@RequestMapping(
value = "*",
method = { RequestMethod.GET, RequestMethod.POST }
)
public String errorWebForm(HttpServletRequest requestData) {
return httpExceptionHandler.notFoundErrorHandler(requestData);
}
@RequestMapping(
value = "favicon.ico",
method = RequestMethod.GET
)
@ResponseBody
public void faviconRequest() {
/*
* We do not offer favicon for this website.
* Avoid HTTP status 404, and return nothing
* in server response when client requests the icon file.
*/
}
//////////////////////////////
// LIST PAGE
@RequestMapping(
value = bookListPageURL,
method = { RequestMethod.GET, RequestMethod.POST }
)
public String defaultWebFormGet(HttpServletRequest requestData, Model dataModel) {
httpServerLogger.logMessageNormal(
requestData,
bookListPageURL + ": " + "HTTPOK"
);
dataModel.addAttribute("books", bookRepository.findAll());
return bookListPageURL;
}
//////////////////////////////
// ADD BOOK
@RequestMapping(
value = bookAddPageURL,
method = { RequestMethod.GET, RequestMethod.PUT }
)
public String webFormAddBook(
HttpServletRequest requestData,
Model dataModel
) {
httpServerLogger.logMessageNormal(
requestData,
bookAddPageURL + ": " + "HTTPOK"
);
Book newBook = new Book();
dataModel.addAttribute("book", newBook);
if (newBook.getYear() == 0) {
newBook.setYear(Year.now().getValue());
}
return bookAddPageURL;
}
@RequestMapping(
value = bookAddPageURL,
method = RequestMethod.POST
)
public String webFormSaveNewBook(
@Valid @ModelAttribute("book") Book book,
BindingResult bindingResult,
HttpServletRequest requestData
) {
if (bindingResult.hasErrors()) {
httpServerLogger.commonError("Book add: error " + book.toString(), requestData);
return bookAddPageURL;
}
httpServerLogger.logMessageNormal(
requestData,
bookAddPageURL + ": " + "HTTPOK"
);
bookRepository.save(book);
return "redirect:" + bookListPageURL;
}
//////////////////////////////
// DELETE BOOK
@RequestMapping(
value = bookDeletePageURL + "/{id}",
method = RequestMethod.GET
)
public String webFormDeleteBook(
@PathVariable("id") long bookId,
HttpServletRequest requestData
) {
httpServerLogger.logMessageNormal(
requestData,
bookDeletePageURL + ": " + "HTTPOK"
);
bookRepository.deleteById(bookId);
return "redirect:../" + bookListPageURL;
}
//////////////////////////////
// UPDATE BOOK
@RequestMapping(
value = bookEditPageURL + "/{id}",
method = RequestMethod.GET
)
public String webFormEditBook(
@PathVariable("id") long bookId,
Model dataModel,
HttpServletRequest requestData
) {
httpServerLogger.logMessageNormal(
requestData,
bookEditPageURL + ": " + "HTTPOK"
);
Book book = bookRepository.findById(bookId).get();
dataModel.addAttribute("book", book);
return bookEditPageURL;
}
@RequestMapping(
value = bookEditPageURL + "/{id}",
method = RequestMethod.POST
)
public String webFormUpdateBook(
@Valid @ModelAttribute("book") Book book,
BindingResult bindingResult,
HttpServletRequest requestData
) {
if (bindingResult.hasErrors()) {
httpServerLogger.commonError("Book edit: error " + book.toString(), requestData);
return bookEditPageURL;
}
httpServerLogger.logMessageNormal(
requestData,
bookEditPageURL + ": " + "HTTPOK"
);
bookRepository.save(book);
return "redirect:../" + bookListPageURL;
}
//////////////////////////////
// REDIRECTS
@RequestMapping(
value = { "/", landingPageURL },
method = RequestMethod.GET
)
@ResponseStatus(HttpStatus.FOUND)
public String redirectToDefaultWebForm() {
return "redirect:" + bookListPageURL;
}
// Other URL requests
@RequestMapping(
value = "*",
method = { RequestMethod.GET, RequestMethod.POST }
)
public String errorWebForm(HttpServletRequest requestData) {
return httpExceptionHandler.notFoundErrorHandler(requestData);
}
@RequestMapping(
value = "favicon.ico",
method = RequestMethod.GET
)
@ResponseBody
public void faviconRequest() {
/*
* We do not offer favicon for this website.
* Avoid HTTP status 404, and return nothing
* in server response when client requests the icon file.
*/
}
} }

+ 20
- 20
bookstore/src/main/java/com/fjordtek/bookstore/web/HttpExceptionHandler.java View File

@ -2,32 +2,32 @@
package com.fjordtek.bookstore.web; package com.fjordtek.bookstore.web;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.ResponseStatus;
@ControllerAdvice @ControllerAdvice
public class HttpExceptionHandler { public class HttpExceptionHandler {
private static final String HTTPNOTFOUND = "Invalid request";
private HttpServerLogger httpServerLogger = new HttpServerLogger();
@ResponseStatus(
value = HttpStatus.NOT_FOUND,
reason = HTTPNOTFOUND
)
// Very simple exception handler (not any sophistication)
@ExceptionHandler(Exception.class)
public String notFoundErrorHandler(HttpServletRequest requestData) {
httpServerLogger.logMessageError(
requestData,
"HTTPNOTFOUND"
);
return "error";
}
private static final String HTTPNOTFOUND = "Invalid request";
private HttpServerLogger httpServerLogger = new HttpServerLogger();
@ResponseStatus(
value = HttpStatus.NOT_FOUND,
reason = HTTPNOTFOUND
)
// Very simple exception handler (not any sophistication)
@ExceptionHandler(Exception.class)
public String notFoundErrorHandler(HttpServletRequest requestData) {
httpServerLogger.logMessageError(
requestData,
"HTTPNOTFOUND"
);
return "error";
}
} }

+ 51
- 51
bookstore/src/main/java/com/fjordtek/bookstore/web/HttpServerLogger.java View File

@ -2,59 +2,59 @@
package com.fjordtek.bookstore.web; package com.fjordtek.bookstore.web;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import javax.servlet.http.HttpServletRequest;
public class HttpServerLogger { public class HttpServerLogger {
private LocalDateTime logTimeStamp;
private void setLogTimeStamp() {
this.logTimeStamp = LocalDateTime.now();
}
private LocalDateTime getLogTimeStamp() {
return this.logTimeStamp;
}
public void logMessageNormal(
HttpServletRequest request,
String HttpRawStatusType
) {
setLogTimeStamp();
System.out.printf(
"%s: HTTP request to '%s' from client %s (%s)\n",
getLogTimeStamp(),
request.getRequestURL(),
request.getRemoteAddr(),
HttpRawStatusType
);
}
public void logMessageError(
HttpServletRequest request,
String HttpRawStatusType
) {
setLogTimeStamp();
System.err.printf(
"%s: Invalid HTTP request to '%s' from client %s (%s)\n",
getLogTimeStamp(),
request.getRequestURL(),
request.getRemoteAddr(),
HttpRawStatusType
);
}
public void commonError(String errorMsg, HttpServletRequest request, String ...strings) {
// Splitting log streams for proper server error logging
System.err.printf("%s: %s - %s\n", getLogTimeStamp(), request.getRemoteAddr(), errorMsg);
for (String dataString : strings) {
System.err.printf("%s\n", dataString);
}
}
private LocalDateTime logTimeStamp;
private void setLogTimeStamp() {
this.logTimeStamp = LocalDateTime.now();
}
private LocalDateTime getLogTimeStamp() {
return this.logTimeStamp;
}
public void logMessageNormal(
HttpServletRequest request,
String HttpRawStatusType
) {
setLogTimeStamp();
System.out.printf(
"%s: HTTP request to '%s' from client %s (%s)\n",
getLogTimeStamp(),
request.getRequestURL(),
request.getRemoteAddr(),
HttpRawStatusType
);
}
public void logMessageError(
HttpServletRequest request,
String HttpRawStatusType
) {
setLogTimeStamp();
System.err.printf(
"%s: Invalid HTTP request to '%s' from client %s (%s)\n",
getLogTimeStamp(),
request.getRequestURL(),
request.getRemoteAddr(),
HttpRawStatusType
);
}
public void commonError(String errorMsg, HttpServletRequest request, String ...strings) {
// Splitting log streams for proper server error logging
System.err.printf("%s: %s - %s\n", getLogTimeStamp(), request.getRemoteAddr(), errorMsg);
for (String dataString : strings) {
System.err.printf("%s\n", dataString);
}
}
} }

Loading…
Cancel
Save