❗️문제 상황
✉️ 오류 메시지
java.lang.IllegalStateException: 응답이 이미 커밋된 후에는 forward할 수 없습니다.
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:275)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:267)
at org.example.day0819_board_project.controller.board.BoardServlet.doGet(BoardServlet.java:32)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:483)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:663)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:384)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:904)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190)
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
at java.base/java.lang.Thread.run(Thread.java:842)
📃 문제 코드
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Long board_no = Long.valueOf(req.getPathInfo().substring(1));
try {
req.getRequestDispatcher(ROOT + "main/main_before_login.jsp").forward(req, resp);
Board board = boardService.read(board_no);
boardService.addReadCount(board); // 조회수 1 증가 시키기
req.setAttribute("board", board);
req.getRequestDispatcher(ROOT + "board/board.jsp").forward(req, resp); **// 여기서 발생**
} catch (BoardNotFoundException e) {
alertAndRedirect(req, e.getMessage(), req.getContextPath() + "/boards", resp);
} catch (Exception e) {
e.printStackTrace();
}
}
💡 해결 방법
🤔 오류가 발생한 이유
💡 forward()를 한 상태에서 또 다시 forward()를 했기 때문이다.
이는 forward가 아니라 redirect의 경우도 해당된다.
forward()나 sendRedirect()를 하게되면 WAS는 내부적으로 Response Commit을 true로 세팅한다. 그 이유는 forward()나 sendRedirect()를 하게되면 이동한 리소스(JSP나 다른 서블릿)에서 응답을 만들었을 가능성이 높기 때문이다. 그렇기 때문에 WAS는 사전에 별도의 플래그 값을 설정해서 중복해서 응답을 만드는 것을 막는 것이다.
🛠️ 수정
한 서블릿에서 forward나 redirect는 한번만 하자