#spring

본 글은 Spring 4.3.12의 레퍼런스 문서 에서 @ControllerAdvice@ExceptionHandler 관련 부분을 번역한 글입니다. 부족한 해석이 있다면 피드백 부탁드리겠습니다.

Advising controllers with @ControllerAdvice and @RestControllerAdvice

@ControllerAdvice 애노테이션은 클래스패스 스캐닝을 통해서 자동으로 검출되어지는 구현 클래스를 허용하는 컴포넌트 애노테이션이다. MVC 네임스페이스와 MVC 자바 설정을 사용하면 자동으로 활성화된다.
@ControllerAdvice 선언이 되어 있는 클래스는 @ExceptionHandler@InitBinder, @ModelAttribute 가 선언된 메소드들을 포함한다. 그리고 이 메소드들은 자신들이 선언되어 있는 컨트롤러 계층 구조와는 반대 방향으로 @RequestMapping 메소드들에 적용될 것이다.
기본적으로 @RestControllerAdvice@ExceptionHandler 메소드가 @ResponseBody 로 결과를 반환하고자 하는 곳에 대신 사용할 수 있다.
@ControllerAdvice@RestControllerAdvice 둘 다 컨트롤러들 중에서 일부만 대상으로 삼을 수 있다.

Read More

Spring MVC Test

  • Spring MVC 컨트롤러와의 상호작용 테스트를 위한 테스팅 프레임워크
  • 웹 환경을 목킹하기 위해서 Servlet API Mock 객체를 제공
    • MockHttpServletRequest - 자바의 HttpServletRequest mock
    • MockHttpServletResponse - 자바의 HttpServeltRequest mock
  • DispatcherServlet
    • 요청들은 Spring MVC의 DistpatcherServelt을 통해서 경로를 찾아감

Read More

이미 일년도 넘은 내용이지만 에버노트에서 꺼내보면서 이것 저것 정리도 해볼겸 RequestBody의 내용을 로그로 남기고 싶다. 에 이어서 좀 더 관련 내용을 적어보았다. filter 를 이용해서 request body 를 로그로 찍어보자.

우선 문자열과 input stream 의 편리한 처리를 위해서 다음과 같이 의존성을 추가한 다음에 진행하였다.

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>

Read More

다음은 최초에 제가 가졌던 니즈입니다.

  1. POST 방식으로 호출되는 http request의 payload를 로그로 남기고 싶다.
  2. controller 내부에서 한땀 한땀 로그로 남기는 방법 말고 다른 방법으로 남겨보고 싶다.

스프링 프레임워크 위에서 비즈니스 로직을 구현하고 있지만, 스프링 기반의 프로젝트의 구조에 관심을 이제서야 조금씩 가지다 보니 새롭고 좋네요. 한번도 완독해본적 없는 토비의 스프링이나 스프링 인 액션을 찬찬히 다시 한번 봐야겠습니다. 올해는 꼭 성공하면 좋겠네요.

일단 서비스가 돌아가고 있는 프로젝트의 소스 코드를 쭉 훑어보았습니다. 우선 기존에 쌓이고 있는 로그를 읽어가며 역으로 소스코드를 따라 들어가보았습니다. config 관련된 클래스들을 별도의 패키지에서 관리하고 있는데요. WebMvcConfigurationSupport 클래스를 상속받은 ServletApplicationContextConfig 가 있고, HandlerInterceptorAdapter 를 상속하여 구현한 인터셉터들이 있네요. 구현된 인터셉터들은 ServletAppliationContextConfig 내에서 등록하여 사용하고 있었습니다. 인터셉터의 내부에서 HttpRequest의 내용을 간략하게 남기고 있는 것을 보아하니, 별도의 인터셉터 클래스를 만들어 주어 request의 body를 찍어주게 하면 될 것 같은 느낌을 받았습니다.

스트림을 읽어들인 다음 문자열로 변환 시킨 후 로그로 남기도록 구현하였습니다. HandlerInterceptorAdapter 를 상속하여 만든 ApiLoggingInterceptor 클래스의 afterCompletion() 메소드에 이쁘게 로그를 찍어주도록 만들었습니다. 기쁜 마음으로 톰캣 인스턴스를 띄우고, http request를 하나 날려보았습니다. 찍히길 기대했던 로그는 안찍히고 다른 로그가 올라오네요. 별거 아니라고 생각하며 기쁜 마음으로 서버 로그가 찍히길 기다렸는데, 이미 스트림이 닫혀있다는 예외 메시지만 출력되었습니다. 다음과 같이요.

Read More

DummyEntity라는 엔티티가 있다고 해보겠습니다. 특별한 건 없고, modifiedAt 이라는 필드에 @PreUpdate 어노테이션이 선언되어 있습니다.

1
2
3
4
5
6
7
8
// DummyEntity.javascript
private String description;
private Date modifiedAt;

@PreUpdate
public void preUpdate() {
modifiedAt = new Date();
}

아래의 DummyServiceImpl 제가 짠 소스 코드 입니다. 문제가 있는 소스 코드입니다. 회사 코드가 유출되면 안되니 간단하게 바꾸었습니다. 엔티티를 조회한 다음, 엔티티의 특정 필드의 값을 수정하여 변경 사항을 저장한 후에 큐로 이벤트를 발행할 때, modifiedAt 에는 변경이 이루어진 시간을 세팅하여 전달하고 싶었습니다.

Read More

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×