Error Process
에러가 발생함
var ticket = ticketJpaRepository.findByLectureIdAndEmployeeId(command.getLectureId(),
command.getEmployeeId());
if (ticket != null && ticket.isPresent()) {
throw new SimpleLogicException("이미 수강신청 하였습니다.");
}
var ticket = ticketJpaRepository.findByLectureIdAndEmployeeId(command.getLectureId(),
command.getEmployeeId());
if (ticket != null && ticket.isPresent()) {
throw new SimpleLogicException("이미 수강신청 하였습니다.");
}
Explain
RestControllerWithEnvelopPattern Annotation
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@RestController
public @interface RestControllerWithEnvelopPattern {
}
- @Documented : @RestControllerWithEnvelopPattern Annotation을 사용한 코드를 JavaDoc으로 만들 때, JavaDoc에 포함시킬지 여부를 결정
- @Inherited : 상속을 통해서 서브클래스에도 Annotation을 전달할지 여부를 결정
RestControllerAdvice
RestControllerAdvice란 @ControllerAdvice와 @ResponseBody가 결합된 Annotation이다.
- @ControllerAdvice : @ExceptionHandler, @ModelAttribute, @InitBinder 가 적용된 메서드들에 AOP를 적용해 Controller 단에 적용하기 위해 고안된 어노테이션이라고 한다.
- @ResponseBody : 자바객체를 HTTP 요청의 Body 내용으로 매핑하여 클라이언트로 전송하는 어노테이션이라고 한다.
즉, ExceptionHandler, ModelAttribute, InitBinder에 AOP를 적용하여 Controller 단에 적용하고, 그 결과를 HTTP 요청의 Body 내용으로 매핑하여 클라이언트로 전송하는 어노테이션이다.
intrastructure.web.common.dto.ApiResponseWrappingResponseBodyAdvisor.java
@RestControllerAdvice(annotations = {RestControllerWithEnvelopPattern.class})
public class ApiResponseWrappingResponseBodyAdvisor implements ResponseBodyAdvice<Object> {
private static final Logger LOG =
LoggerFactory.getLogger(ApiResponseWrappingResponseBodyAdvisor.class);
private Type getGenericType(MethodParameter returnType) {
if (HttpEntity.class.isAssignableFrom(returnType.getParameterType())) {
return ResolvableType.forType(returnType.getGenericParameterType())
.getGeneric()
.getType();
} else {
return returnType.getGenericParameterType();
}
}
@Override
public boolean supports(
MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
Type type =
GenericTypeResolver.resolveType(
getGenericType(returnType), returnType.getContainingClass());
if (returnType.getExecutable().getName().toUpperCase().contains("HEALTH")) { // healthCheck
return false;
}
if (Void.class.getName().equals(type.getTypeName())) {
return false;
}
return !converterType.isAssignableFrom(ByteArrayHttpMessageConverter.class)
&& !converterType.isAssignableFrom(ResourceHttpMessageConverter.class);
}
@Override
public Object beforeBodyWrite(
Object body,
MethodParameter returnType,
MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request,
ServerHttpResponse response) {
HttpStatus responseStatus =
HttpStatus.valueOf(
((ServletServerHttpResponse) response).getServletResponse().getStatus());
if (Objects.isNull(body)) {
return responseStatus.isError()
? ApiResponseGenerator.fail()
: ApiResponseGenerator.success();
}
var apiResponse =
responseStatus.isError()
? ApiResponseGenerator.fail(body)
: ApiResponseGenerator.success(body);
LOG.trace("[ApiResponse] {}", apiResponse);
if (selectedConverterType.isAssignableFrom(StringHttpMessageConverter.class)) {
try {
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
return JsonUtils.toJson(apiResponse);
} catch (JsonUtils.JsonEncodeException jpe) {
throw new ApiResponseJsonProcessingException(jpe);
}
}
return apiResponse;
}
}