Spring
json error stack trace print 여부 커스텀 프로퍼티
ybs
2021. 11. 22. 01:16
반응형
먼저 application.yml 에 원하는 커스텀 프로퍼티를 추가한다. 보통 deploy phase 에 따라 다르게 설정된다.
response:
print-stack-trace: true
다음으로 /resources/META-INF/spring-configuration-metadata.json 파일에 프로퍼티에 대한 메타데이터를 추가한다.
{
"groups": [
{
"name": "response",
"type": "com.toy.config.ResponseProperties",
"sourceType": "com.toy.config.ResponseProperties"
}
],
"properties": [
{
"name": "response.print-stack-trace",
"type": "java.lang.Boolean",
"description": "에러 스택 트레이스.",
"sourceType": "com.toy.config.ResponseProperties"
}
]
}
다음으로 application.yml 에 설정된 값이 맵핑될 ResponseProperties 를 추가한다.
package com.toy.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@ConfigurationProperties(prefix = "response")
@ConstructorBinding
@Getter
@RequiredArgsConstructor
public class ResponseProperties {
private final boolean printStackTrace;
}
다음으로 ConfigurationPropertiesScan 애노테이션을 추가한다.
@ConfigurationPropertiesScan(basePackages = "com.toy.config")
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
...
}
다음으로 JsonConfig 에서 빈으로 만드는 ObjectMapper 에서 ResponseProperties 를 활용한다.
@Configuration
public class JsonConfig {
@Bean
ObjectMapper jacksonObjectMapper(ResponseProperties responseProperties) {
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper
.registerModule(
// HTTP 응답에 에러 StackTrace 포함 여부
new ProblemModule().withStackTraces(responseProperties.isPrintStackTrace())
);
}
}
cf) RFC7807 application/problem+json 구현체로 zalando problem 을 사용했다.
<dependency>
<groupId>org.zalando</groupId>
<artifactId>problem-spring-web</artifactId>
<version>0.26.2</version>
</dependency>
마지막으로 ExceptionHandler에서 ProblemBuilder 를 통해 Problem을 만들어 처리한다. 설명을 위해 편의상 ProblemHandling 을 컨트롤러에서 직접 implements 했지만 GlobalExceptionHandler 를 따로 만들고 거기서 implements 하는게 좋다.
@RestController
public class TestController implements ProblemHandling {
...
@ExceptionHandler(Exception.class)
public ResponseEntity<Problem> handle(NativeWebRequest request, Exception ex) {
ProblemBuilder builder = Problem.builder()
.withTitle(Status.BAD_REQUEST.getReasonPhrase())
.withStatus(Status.BAD_REQUEST)
.withDetail("wrong request param")
.with("name", "ybs")
.withType(URI.create("https://yangbongsoo.tistory.com"));
return create(ex, builder.build(), request);
}
}
cf) 예외가 발생했을 때 response body는 아래와 같다.
{
"type": "https://yangbongsoo.tistory.com",
"title": "Bad Request",
"status": 400,
"detail": "wrong request param",
"stacktrace": [
"org.zalando.problem.ProblemBuilder.build(ProblemBuilder.java:83)",
...
],
"name": "ybs"
}
반응형