From e396a240f2ff486a6925951f9073df00db59ee0e Mon Sep 17 00:00:00 2001 From: Wijit Prajumsook Date: Fri, 22 Nov 2019 12:55:15 +0100 Subject: [PATCH] add project --- demoexception/.gitignore | 31 ++++++++++ demoexception/README.md | 11 ++++ demoexception/pom.xml | 58 +++++++++++++++++++ .../prajumsook/DemoexceptionApplication.java | 13 +++++ .../org/wj/prajumsook/cofig/InitTestData.java | 28 +++++++++ .../prajumsook/controller/BookController.java | 31 ++++++++++ .../java/org/wj/prajumsook/entity/Book.java | 18 ++++++ .../wj/prajumsook/entity/BookRepository.java | 8 +++ .../wj/prajumsook/exception/ApiException.java | 18 ++++++ .../exception/ApiExceptionHandler.java | 48 +++++++++++++++ .../exception/BookNotFoundException.java | 16 +++++ .../exception/CustomerApiException.java | 18 ++++++ .../wj/prajumsook/service/BookService.java | 40 +++++++++++++ .../src/main/resources/application.properties | 1 + .../DemoexceptionApplicationTests.java | 13 +++++ 15 files changed, 352 insertions(+) create mode 100644 demoexception/.gitignore create mode 100644 demoexception/README.md create mode 100644 demoexception/pom.xml create mode 100644 demoexception/src/main/java/org/wj/prajumsook/DemoexceptionApplication.java create mode 100644 demoexception/src/main/java/org/wj/prajumsook/cofig/InitTestData.java create mode 100644 demoexception/src/main/java/org/wj/prajumsook/controller/BookController.java create mode 100644 demoexception/src/main/java/org/wj/prajumsook/entity/Book.java create mode 100644 demoexception/src/main/java/org/wj/prajumsook/entity/BookRepository.java create mode 100644 demoexception/src/main/java/org/wj/prajumsook/exception/ApiException.java create mode 100644 demoexception/src/main/java/org/wj/prajumsook/exception/ApiExceptionHandler.java create mode 100644 demoexception/src/main/java/org/wj/prajumsook/exception/BookNotFoundException.java create mode 100644 demoexception/src/main/java/org/wj/prajumsook/exception/CustomerApiException.java create mode 100644 demoexception/src/main/java/org/wj/prajumsook/service/BookService.java create mode 100644 demoexception/src/main/resources/application.properties create mode 100644 demoexception/src/test/java/org/wj/prajumsook/DemoexceptionApplicationTests.java diff --git a/demoexception/.gitignore b/demoexception/.gitignore new file mode 100644 index 0000000..a2a3040 --- /dev/null +++ b/demoexception/.gitignore @@ -0,0 +1,31 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/** +!**/src/test/** + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ + +### VS Code ### +.vscode/ diff --git a/demoexception/README.md b/demoexception/README.md new file mode 100644 index 0000000..3c6adef --- /dev/null +++ b/demoexception/README.md @@ -0,0 +1,11 @@ +# Spring Boot REST API Exception handling + +### Reference +* Lombok +* MongoDB + +### Hands-on coding +Show how to create custom exception and error message. + + + diff --git a/demoexception/pom.xml b/demoexception/pom.xml new file mode 100644 index 0000000..5782d82 --- /dev/null +++ b/demoexception/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.2.1.RELEASE + + + org.wj.prajumsook + demoexception + 0.0.1-SNAPSHOT + demoexception + Demo project for Spring Boot + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-mongodb + + + org.springframework.boot + spring-boot-starter-web + + + + org.projectlombok + lombok + true + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/demoexception/src/main/java/org/wj/prajumsook/DemoexceptionApplication.java b/demoexception/src/main/java/org/wj/prajumsook/DemoexceptionApplication.java new file mode 100644 index 0000000..72b5673 --- /dev/null +++ b/demoexception/src/main/java/org/wj/prajumsook/DemoexceptionApplication.java @@ -0,0 +1,13 @@ +package org.wj.prajumsook; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoexceptionApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoexceptionApplication.class, args); + } + +} diff --git a/demoexception/src/main/java/org/wj/prajumsook/cofig/InitTestData.java b/demoexception/src/main/java/org/wj/prajumsook/cofig/InitTestData.java new file mode 100644 index 0000000..f55dca0 --- /dev/null +++ b/demoexception/src/main/java/org/wj/prajumsook/cofig/InitTestData.java @@ -0,0 +1,28 @@ +package org.wj.prajumsook.cofig; + +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; +import org.wj.prajumsook.entity.Book; +import org.wj.prajumsook.service.BookService; + +import java.util.UUID; + +@Log4j2 +@Component +@Profile("local") +public class InitTestData implements ApplicationListener { + + @Autowired + private BookService service; + + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + service.deleteAll(); + service.save(new Book(UUID.randomUUID().toString(), "Book Title", "Book author")); + log.info("One book saved"); + } +} diff --git a/demoexception/src/main/java/org/wj/prajumsook/controller/BookController.java b/demoexception/src/main/java/org/wj/prajumsook/controller/BookController.java new file mode 100644 index 0000000..9209eec --- /dev/null +++ b/demoexception/src/main/java/org/wj/prajumsook/controller/BookController.java @@ -0,0 +1,31 @@ +package org.wj.prajumsook.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.wj.prajumsook.entity.Book; +import org.wj.prajumsook.service.BookService; + +import java.util.List; + +@RestController +@RequestMapping("/book") +public class BookController { + + @Autowired + private BookService bookService; + + @GetMapping + public List getAll() { + return bookService.getAll(); + } + + @GetMapping("/{id}") + public Book getBook(@PathVariable(value = "id") String id) { + return bookService.getById(id); + } + + @DeleteMapping("/{id}") + public Book deleteById(@PathVariable(value = "id")String id) { + return bookService.deleteById(id); + } +} diff --git a/demoexception/src/main/java/org/wj/prajumsook/entity/Book.java b/demoexception/src/main/java/org/wj/prajumsook/entity/Book.java new file mode 100644 index 0000000..2ae9daf --- /dev/null +++ b/demoexception/src/main/java/org/wj/prajumsook/entity/Book.java @@ -0,0 +1,18 @@ +package org.wj.prajumsook.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +@Data +@AllArgsConstructor +@NoArgsConstructor +public class Book { + + private String id; + private String title; + private String author; + +} diff --git a/demoexception/src/main/java/org/wj/prajumsook/entity/BookRepository.java b/demoexception/src/main/java/org/wj/prajumsook/entity/BookRepository.java new file mode 100644 index 0000000..2443885 --- /dev/null +++ b/demoexception/src/main/java/org/wj/prajumsook/entity/BookRepository.java @@ -0,0 +1,8 @@ +package org.wj.prajumsook.entity; + +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface BookRepository extends MongoRepository { +} diff --git a/demoexception/src/main/java/org/wj/prajumsook/exception/ApiException.java b/demoexception/src/main/java/org/wj/prajumsook/exception/ApiException.java new file mode 100644 index 0000000..467e534 --- /dev/null +++ b/demoexception/src/main/java/org/wj/prajumsook/exception/ApiException.java @@ -0,0 +1,18 @@ +package org.wj.prajumsook.exception; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ApiException { + + private String code; + private String type; + private String message; + +} diff --git a/demoexception/src/main/java/org/wj/prajumsook/exception/ApiExceptionHandler.java b/demoexception/src/main/java/org/wj/prajumsook/exception/ApiExceptionHandler.java new file mode 100644 index 0000000..fce6173 --- /dev/null +++ b/demoexception/src/main/java/org/wj/prajumsook/exception/ApiExceptionHandler.java @@ -0,0 +1,48 @@ +package org.wj.prajumsook.exception; + +import lombok.extern.log4j.Log4j2; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@Log4j2 +@ControllerAdvice +@RestControllerAdvice +public class ApiExceptionHandler extends ResponseEntityExceptionHandler { + + @ExceptionHandler(BookNotFoundException.class) + public ResponseEntity handleApiException(BookNotFoundException ex) { + logException(ex); + ApiException exception = new ApiException(); + exception.setCode("error-000404"); + exception.setType(HttpStatus.NOT_FOUND.toString()); + exception.setMessage("No book found with id: " + ex.getId()); + CustomerApiException customerApiException = new CustomerApiException(exception); + + return new ResponseEntity<>(customerApiException, HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(Exception.class) + public ResponseEntity handleException(Exception ex) { + logException(ex); + ApiException apiException = new ApiException(); + apiException.setCode("error-000500"); + apiException.setType(HttpStatus.INTERNAL_SERVER_ERROR.toString()); + apiException.setMessage(ex.getMessage()); + + return new ResponseEntity<>(new CustomerApiException(apiException), HttpStatus.INTERNAL_SERVER_ERROR); + } + + private void logException(Throwable t) { + StringBuilder sb = new StringBuilder(); + for(StackTraceElement element : t.getStackTrace()) { + sb.append(element.toString()); + sb.append("\n"); + } + + log.error("ERROR: [\n" + sb.toString() + "]"); + } +} diff --git a/demoexception/src/main/java/org/wj/prajumsook/exception/BookNotFoundException.java b/demoexception/src/main/java/org/wj/prajumsook/exception/BookNotFoundException.java new file mode 100644 index 0000000..2daf47e --- /dev/null +++ b/demoexception/src/main/java/org/wj/prajumsook/exception/BookNotFoundException.java @@ -0,0 +1,16 @@ +package org.wj.prajumsook.exception; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class BookNotFoundException extends RuntimeException { + + private String id; + +} diff --git a/demoexception/src/main/java/org/wj/prajumsook/exception/CustomerApiException.java b/demoexception/src/main/java/org/wj/prajumsook/exception/CustomerApiException.java new file mode 100644 index 0000000..76afc6d --- /dev/null +++ b/demoexception/src/main/java/org/wj/prajumsook/exception/CustomerApiException.java @@ -0,0 +1,18 @@ +package org.wj.prajumsook.exception; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CustomerApiException { + + private ApiException apiException; + +} diff --git a/demoexception/src/main/java/org/wj/prajumsook/service/BookService.java b/demoexception/src/main/java/org/wj/prajumsook/service/BookService.java new file mode 100644 index 0000000..a61aa1b --- /dev/null +++ b/demoexception/src/main/java/org/wj/prajumsook/service/BookService.java @@ -0,0 +1,40 @@ +package org.wj.prajumsook.service; + +import lombok.AllArgsConstructor; +import org.springframework.stereotype.Service; +import org.wj.prajumsook.entity.Book; +import org.wj.prajumsook.entity.BookRepository; +import org.wj.prajumsook.exception.BookNotFoundException; + +import java.util.List; + +@Service +@AllArgsConstructor +public class BookService { + + private BookRepository repository; + + public List getAll() { + return repository.findAll(); + } + + public Book getById(String id) { + return repository.findById(id).orElseThrow(() -> new BookNotFoundException(id)); + } + + public void deleteAll() { + repository.deleteAll(); + } + + public Book save(Book book) { + return repository.save(book); + } + + public Book deleteById(String id) { + Integer.parseInt("xxx"); + Book book = getById(id); + repository.deleteById(book.getId()); + + return book; + } +} diff --git a/demoexception/src/main/resources/application.properties b/demoexception/src/main/resources/application.properties new file mode 100644 index 0000000..4fdd7ad --- /dev/null +++ b/demoexception/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.profiles.active=local diff --git a/demoexception/src/test/java/org/wj/prajumsook/DemoexceptionApplicationTests.java b/demoexception/src/test/java/org/wj/prajumsook/DemoexceptionApplicationTests.java new file mode 100644 index 0000000..ea11f2e --- /dev/null +++ b/demoexception/src/test/java/org/wj/prajumsook/DemoexceptionApplicationTests.java @@ -0,0 +1,13 @@ +package org.wj.prajumsook; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DemoexceptionApplicationTests { + + @Test + void contextLoads() { + } + +}