HTTP request 시 json 스트링을 서버에 넘겨주고, 서버는 interceptor에서 먼저 HTTP request body에 있는 json 스트링을 읽어와 값에 대한 체크를 진행하는 로직을 개발하고 있었다.
json 스트링 검증 후 spring controller에서 @RequestParam 으로 데이터를 받으려고 할 때 다음과 같은 예외가 발생
java.lang.RuntimeException: java.io.EOFException: No content to map to Object due to end of input
interceptor에서 request body의 데이터를 이미 읽어 들였기 때문에 나오는 증상이다.
시퀀스 다이어그램으로 표현하자면 다음의 4번에 해당하는 부분에서 예외가 발생된다.
인터셉터와 컨트롤러 모두에서 request 의 body 데이터를 읽어 들이고 싶을 때 어떤 방법을 이용해야 할까 고민을 해봤지만 명확한 답을 찾을 수가 없어 KSUG에 질문을 올려 그 해답을 찾을 수 있었다.
해결 방법은 request body 데이터를 저장해 놓는 객체를 생성 후 이를 doFilter로 넘기는 것이였다.
말로 설명하는 것 보다는 코드를 예로 들면 다음과 같다.
## HttpRequestWrapperFilter.java
public class HttpRequestWrapperFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpRequestWrapper requestWrapper = new HttpRequestWrapper(httpServletRequest);
chain.doFilter(requestWrapper, response);
}
## HttpRequestWrapper.java
public class HttpRequestWrapper extends HttpServletRequestWrapper {
private byte[] bodyData;
public HttpRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
InputStream is = super.getInputStream();
bodyData = IOUtils.toByteArray(is);
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream bis = new ByteArrayInputStream(bodyData);
return new ServletImpl(bis);
}
}
class ServletImpl extends ServletInputStream {
private InputStream is;
public ServletImpl(InputStream bis) {
is = bis;
}
@Override
public int read() throws IOException {
return is.read();
}
@Override
public int read(byte[] b) throws IOException {
return is.read(b);
}
}
'프로그래밍' 카테고리의 다른 글
bean 엘리먼트의 parent attribute 사용 (0) | 2014.05.22 |
---|---|
spring util:map 사용 시 key와 value 타입 지정 (0) | 2014.05.17 |
c:import 사용 시 주의사항 (Request method 'POST' not supported) (2) | 2014.05.16 |
Tiles definition 렌더링 전 처리 방법 (ViewPreparer 사용) (0) | 2014.04.30 |
javascript self closing 문제 (2) | 2014.04.16 |
Spring MappingJacksonJsonView modelKey가 하는 역할 (0) | 2014.03.15 |
JUnit private method test (0) | 2014.03.04 |
제너릭 메소드 (0) | 2014.03.01 |