Skip to content

Commit

Permalink
refactor: GeneralResponse and i18n
Browse files Browse the repository at this point in the history
  • Loading branch information
oksana-miazina committed May 6, 2024
1 parent aeb6c83 commit 97cd8e4
Show file tree
Hide file tree
Showing 17 changed files with 213 additions and 132 deletions.
11 changes: 9 additions & 2 deletions src/main/java/mate/academy/bookstore/config/I18nConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package mate.academy.bookstore.config;

import java.nio.charset.StandardCharsets;
import java.util.Locale;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
Expand All @@ -8,13 +10,18 @@

@Configuration
public class I18nConfig {
private static final String DEFAULT_BUNDLE_PATH = "classpath:messages";
private static final Locale DEFAULT_LOCALE = Locale.ENGLISH;

@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource
= new ReloadableResourceBundleMessageSource();

messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
messageSource.clearCache();
messageSource.setBasename(DEFAULT_BUNDLE_PATH);
messageSource.setDefaultLocale(DEFAULT_LOCALE);
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name());
return messageSource;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
import lombok.AllArgsConstructor;
import mate.academy.bookstore.dto.BookDto;
import mate.academy.bookstore.dto.BookRequestDto;
import mate.academy.bookstore.response.ResponseHandler;
import mate.academy.bookstore.response.SuccessResponse;
import mate.academy.bookstore.service.BookService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand All @@ -17,32 +20,37 @@
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/api/books")
@AllArgsConstructor
public class BookController {
private final BookService bookService;

@GetMapping
public List<BookDto> getAll() {
return bookService.findAll();
public ResponseEntity<SuccessResponse<List<BookDto>>> getAll() {
return ResponseHandler.getSuccessResponse(
bookService.findAll());
}

@GetMapping("/{id}")
public BookDto getBookById(@PathVariable Long id) {
return bookService.getById(id);
public ResponseEntity<SuccessResponse<BookDto>> getBookById(@PathVariable Long id) {
return ResponseHandler.getSuccessResponse(
bookService.getById(id));
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public BookDto createBook(@Valid @RequestBody BookRequestDto bookDto) {
return bookService.save(bookDto);
public ResponseEntity<SuccessResponse<BookDto>> createBook(@Valid @RequestBody BookRequestDto bookDto) {
return ResponseHandler.getSuccessResponse(
bookService.save(bookDto),
HttpStatus.CREATED);
}

@PutMapping("/{id}")
public BookDto updateBookById(@PathVariable Long id,
public ResponseEntity<SuccessResponse<BookDto>> updateBookById(@PathVariable Long id,
@RequestBody BookRequestDto bookRequestDto) {
return bookService.updateById(id, bookRequestDto);
return ResponseHandler.getSuccessResponse(
bookService.updateById(id, bookRequestDto));
}

@DeleteMapping("/{id}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package mate.academy.bookstore.exception;

import java.util.List;
import mate.academy.bookstore.response.ErrorResponse;
import mate.academy.bookstore.response.ResponseHandler;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.mapping.PropertyReferenceException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class CustomGlobalExceptionHandler {
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<ErrorResponse> handleEntityNotFoundException(
EntityNotFoundException ex) {
return ResponseHandler.getErrorResponse(
ex.getMessage(), HttpStatus.NOT_FOUND);
}

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationExceptions(
MethodArgumentNotValidException ex) {
List<ErrorResponse.Message> errors = ex.getBindingResult().getAllErrors()
.stream()
.map(this::getErrorMessage)
.toList();
return ResponseHandler.getErrorResponse(
errors, HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(PropertyReferenceException.class)
public ResponseEntity<ErrorResponse> handlePropertyReferenceException(
PropertyReferenceException ex) {
return ResponseHandler.getErrorResponse(
ex.getMessage(), HttpStatus.BAD_REQUEST);
}

@ExceptionHandler(DataIntegrityViolationException.class)
public ResponseEntity<ErrorResponse> handleDataIntegrityViolationException(
DataIntegrityViolationException ex) {
return ResponseHandler.getErrorResponse(
ex.getMessage(), HttpStatus.CONFLICT);
}

private ErrorResponse.Message getErrorMessage(ObjectError e) {
String field = null;
if (e instanceof FieldError fieldError) {
field = fieldError.getField();
}
return new ErrorResponse.Message(field, e.getDefaultMessage());
}
}

This file was deleted.

This file was deleted.

This file was deleted.

22 changes: 0 additions & 22 deletions src/main/java/mate/academy/bookstore/handler/ResponseData.java

This file was deleted.

This file was deleted.

18 changes: 18 additions & 0 deletions src/main/java/mate/academy/bookstore/response/ErrorResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package mate.academy.bookstore.response;

import java.util.List;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
public class ErrorResponse extends GeneralResponse {
private List<Message> errors;

public record Message(String field, String message) {
}

public ErrorResponse(List<Message> errors, HttpStatus status) {
super(status);
this.errors = errors;
}
}
21 changes: 21 additions & 0 deletions src/main/java/mate/academy/bookstore/response/GeneralResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package mate.academy.bookstore.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
public abstract class GeneralResponse {
private boolean success;
private int status;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
private Date timestamp;

public GeneralResponse(HttpStatus status) {
this.timestamp = new Date();
this.status = status.value();
this.success = status.is2xxSuccessful();
}
}
32 changes: 32 additions & 0 deletions src/main/java/mate/academy/bookstore/response/ResponseHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package mate.academy.bookstore.response;

import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

public class ResponseHandler {
public static ResponseEntity<ErrorResponse> getErrorResponse(
String message, HttpStatus status) {
return new ResponseEntity<>(
new ErrorResponse(List.of(new ErrorResponse.Message(null, message)), status),
status);
}

public static ResponseEntity<ErrorResponse> getErrorResponse(
List<ErrorResponse.Message> messages, HttpStatus status) {
return new ResponseEntity<>(
new ErrorResponse(messages, status),
status);
}

public static <T> ResponseEntity<SuccessResponse<T>> getSuccessResponse(T data) {
return getSuccessResponse(data, HttpStatus.OK);
}

public static <T> ResponseEntity<SuccessResponse<T>> getSuccessResponse(
T data, HttpStatus status) {
return new ResponseEntity<>(
new SuccessResponse<>(data, status),
status);
}
}
14 changes: 14 additions & 0 deletions src/main/java/mate/academy/bookstore/response/SuccessResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package mate.academy.bookstore.response;

import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
public class SuccessResponse<T> extends GeneralResponse {
private T data;

public SuccessResponse(T data, HttpStatus status) {
super(status);
this.data = data;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package mate.academy.bookstore.service;

public interface LocaleService {
String getMessage(String code);
}
Loading

0 comments on commit 97cd8e4

Please sign in to comment.