Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ Dependency Development Repository for Spring Beginners
![Java version](https://img.shields.io/badge/Java%20version-17-orange)

## Package
- ### [Api-Payload](https://github.com/projectnamul/beginner/tree/develop/api-payload)
Dependency for Unified response and error handler settings that will use at initial project settings
- ### [api-payload-core](https://github.com/projectnamul/beginner/tree/develop/api-payload-core)
This module offer Error Handling module to make unified response about several exceptions.

127 changes: 101 additions & 26 deletions api-payload-core/README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,74 @@
# Api Payload
The module to unify response you can use DefaultResponse or your custom response
# api-payload-core
You can make and use class to make response about several exceptions.

## Default
### How to add ExceptionAdvice with DefaultResponse
---

## Content of Table
[1. Classes & Interfaces](#classes-and-interfaces)

[2. How to use](#how-to-use)

[2 - 1. Default](#default)

[2 - 2 Custom](#custom)

----

## Classes and Interfaces
Descriptions of classes and Interfaces

### BaseResponse
- This interface is just response type which you want to send to client. You can make type of server response with implementing this interface. Make a response class and declare variable you want to contain in response.

### BaseErrorCode
- This interface returns data that needs a response. After creating a response type with the BaseResponse interface, extend the BaseErrorCode interface to create an interface that can return the data that needs a response that you created. Then, implement other interfaces with the interface you implemented with BaseErrorCode.

### FailureResponseWriter
- This interface responds with throwable (Exception) and BaseErrorCode. Implement to return BaseResponse using BaseErrorCode's method and Throwable.

### AdditionalExceptionHandler
- This interface performs additional logic except for generating response by implementing this interfaace. Like logging, send discord or alarm... etc.
> If you add it to ErrorCodeExceptionHandler with ErrorCodeExceptionHandlerConfigurer, you must control consistency problem. Because it runs asynchronously in ErrorCodeExceptionHandler's handle method.

### WebRequest & WebResponse
- This interface offer some method can use in AdditionalExceptionHandler. You can implement it yourself or use a class already implemented from another module.

### ErrorCodeExceptionHandler
- Based on the transmitted exception, this class finds the appropriate BaseErrorCode, generates responses, and asynchronously executes additional logic. It also provides a way to find the right BaseErrorCode for Throwable.

### ErrorCodeExceptionHandlerConfigurer
- This class make ErrorCodeExceptionHandler with several methods. Developer can set ErrorCodeExceptionHandler with this class by using classes that developer created.

### ServerApplicationException
- This class is just exception class that contain BaseErrorCode. Developer can make another exception class by extending it. Also, It can get cause(Throwable) for stacktrace

---

## How to use
### Default
Just add one config file.

Because `DefaultResponseWriter` is already registered in Bean, If you have not registered class which implement that `FailureResponseWriter` interfaces to bean

```java
@Configuration
public class ExceptionAdviceConfig {
public class ErrorHandlerConfig {

@Bean
ExceptionAdvice<DefaultBaseErrorCode> defaultExceptionAdviceConfigurer(
public ErrorCodeExceptionHandler<DefaultBaseErrorCode> errorCodeExceptionHandler(
FailureResponseWriter<DefaultBaseErrorCode> failureResponseWriter,
List<AdditionalExceptionHandler<DefaultBaseErrorCode>> additionalExceptionHandlers
List<AdditionalExceptionHandler<DefaultBaseErrorCode>> additionalExceptionHandlerList
) {
return new DefaultExceptionAdviceConfigurer(failureResponseWriter)
.addAdditionalExceptionHandlers(additionalExceptionHandlers)
ErrorCodeExceptionHandlerConfigurer<DefaultBaseErrorCode> configurer = new ErrorCodeExceptionHandlerConfigurer<>(failureResponseWriter);
return configurer
.addServerApplication(DefaultResponseErrorCode.BAD_REQUEST)
.addGlobalException(DefaultResponseErrorCode.INTERNAL_SERVER_ERROR)
.addAdvice(CustomException.class, CustomErrorCode.CUSTOM_ERROR_CODE)
// ...
.addAdditionalExceptionHandlers(additionalExceptionHandlerList)
.build();
}

}
```

Expand All @@ -38,17 +87,39 @@ public class TestController {
}
```

or
```java
@GetMapping("/success")
public BaseResponse success() {
return successResponseWriter.onSuccess(DefaultResponseSuccessCode.OK, "Success");
}
```

> ⚠️ Setting the return value to BaseResponse may prevent the Swagger's response format from appearing properly.

### How to add AdditionalExceptionHandler
You can add additional logic with implementing AdditionalExceptionHandler and add it to bean.

```java
@Slf4j
@Component
public class ExceptionAdviceLoggingHandler implements AdditionalExceptionHandler<DefaultBaseErrorCode> {
public class LogAdditionalHandler implements AdditionalExceptionHandler<DefaultBaseErrorCode> {

@Override
public void doHandle(HttpServletRequest request, HttpServletResponse response, Exception e, DefaultBaseErrorCode code) {
log.warn("Error occur: class: {}, message: {}", e.getClass(), code.getMessage());
public void doHandle(WebRequestWrapper webRequestWrapper, WebResponseWrapper webResponseWrapper, Throwable e, DefaultBaseErrorCode defaultBaseErrorCode) {
log.info("""
Cookie: {},
URI: {},
Header: {},
Method: {},
Address: {},
UserAgent: {},
""",
webRequestWrapper.getCookie("JSESSIONID"),
webRequestWrapper.getRequestURI(),
webRequestWrapper.getHeader("content-type"),
webRequestWrapper.getMethod(),
webRequestWrapper.getRemoteAddress().get(),
webRequestWrapper.getUserAgent().get());

}
}
```
Expand Down Expand Up @@ -85,15 +156,17 @@ public class ArticleService {
}
```

---

## Custom
### How to make your custom response

You can make custom response by implementing BaseResponse, BaseErrorCode and FailureResponseWriter.

1. Make custom BaseResponse
2. Make custom BaseErrorCode
3. Make custom FailureResponseWriter
4. Register your custom Writer in bean and implement custom BaseErrorCode
1. Make custom response class with BaseResponse
2. Make custom interface with BaseErrorCode. It has several method which you need to create response
3. Make custom FailureResponseWriter with BaseResponse, BaseErrorCode which you implemented.
4. Register your custom Writer in bean and create ErrorCodeExceptionHandler with Configurer.

> Use BaseResponse to make frame of the response and expand the BaseErrorCode to define the data needed to generate the response as a method. Using the expanded BaseErrorCode, Implement the FailureResponseWriter which creates the response. Then, If you implement the Custom BaseErrorCode class and pass it to ServerApplicationException, the ExceptionAdvice can make Response and return it.

Expand Down Expand Up @@ -138,7 +211,7 @@ You implement `CustomResponseFailureWriter` to make CustomResponse with CustomBa
public class CustomFailureResponseWriter implements FailureResponseWriter<CustomBaseErrorCode> {

@Override
public BaseResponse onFailure(Exception e, CustomBaseErrorCode code) {
public BaseResponse onFailure(Throwable e, CustomBaseErrorCode code) {
return new CustomResponse<>(code.getHttpStatus(), code.getMessage(), null);
}
}
Expand All @@ -165,21 +238,23 @@ public enum CustomErrorCode implements CustomBaseErrorCode {
}
```


#### Config

```java

@Configuration
public class ExceptionAdviceConfig {
@Bean
ExceptionAdvice<CustomBaseErrorCode> defaultExceptionAdviceConfigurer(
ErrorCodeExceptionHandler<CustomBaseErrorCode> customErrorCodeExceptionHandler(
FailureResponseWriter<CustomBaseErrorCode> failureResponseWriter,
List<AdditionalExceptionHandler<CustomBaseErrorCode>> additionalExceptionHandlers
) {
return new ExceptionAdviceConfigurer<>(failureResponseWriter)
.withDefault(CustomErrorCode.ERROR, CustomErrorCode.BAD_ERROR)
.addAdditionalExceptionHandlers(additionalExceptionHandlers)
ErrorCodeExceptionHandlerConfigurer<CustomBaseErrorCode> configurer = new ErrorCodeExceptionHandlerConfigurer<>(failureResponseWriter);
return configurer
.addServerApplication(CustomErrorCode.ERROR)
.addGlobalException(CustomErrorCode.BAD_ERROR)
.addAdvice(CustomNotFoundException.class, CustomErrorCode.NOT_FOUND)
// ...
.addAdditionalExceptionHandlers(additionalExceptionHandlerList)
.build();
}
}
Expand All @@ -196,7 +271,7 @@ public class ArticleService {

@Transactional(readonly = true)
public Article findArticle(Long articleId){
return articleRepository.findById(articleId).orElseThrow(() -> new ServerApplicationException(CustomErrorCode.NOT_FOUND));
return articleRepository.findById(articleId).orElseThrow(() -> new CustomException(CustomErrorCode.NOT_FOUND));
}
}
```
Expand Down
18 changes: 18 additions & 0 deletions api-payload-webmvc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# api-payload-webmvc

It is a dependency that helps users easily use functions in a Spring MVC environment by using it as 'api-payload-core'.


## Classes

### HttpServletWebRequestWrapper
- A class that implements WebRequestWrapper's method using HttpServletRequest. It makes it easy to change and use HttpServletRequestWrapper to WebRequestWrapper through a constructor or static method.

### HttpServletWebResponseWrapper
- A class that implements WebResponseWrapper's method using HttpServletResponse. It makes it easy to change and use HttpServletResponse to WebResponseWrapper through a constructor or static method.

### HttpServletErrorCodeExceptionHandlerConfigurer
- This class implements the ErrorCodeExceptionHandlerConfigurer, which supports methods that make it easy to add errors that usually occur in the Dispatcher Servlet environment.

### ExceptionRestControllerAdvice
- RestControllerAdvice is a class implemented using ErrorCodeExceptionHandler that helps developers add it through Bean rather than directly. If it needs to be modified, you can override it. Of course, you can implement it yourself without using it.