업무를 하며 Jetty를 켰을 때 평소처럼 URL을 입력했는데 메인 페이지가 나오지 않고 에러 페이지가 나왔다.
이 웹 애플리케이션 파일(Jar 형식)을 윈도우 환경에서 실행하면 문제가 없는데 리눅스(CentOS)환경에서 실행하면 문제가 나타났다.
우선 HTTP 500에러는 Internal Server Error를 나타내는데 에러 내용 그대로 서버에 문제가 있다는 것이다.
HTTP ERROR 500
에러 페이지에 출력된 에러 메시지를 보니 Caused by와 함께 상세 내용이 나와있었다.
java.lang.ClassNotFoundException: org.apache.jsp.index_jsp 클래스 파일이 없다는것인데 이 페이지는 내가 만든 것이 아니다.
에러코드 원본
Problem accessing /. Reason:
Server Error
Caused by:
org.apache.jasper.JasperException: java.lang.ClassNotFoundException: org.apache.jsp.index_jsp
at org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:176)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:375)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340)
at org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:108)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:199)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:74)
at org.eclipse.jetty.servlet.DefaultServlet.sendWelcome(DefaultServlet.java:598)
at org.eclipse.jetty.servlet.DefaultServlet.doGet(DefaultServlet.java:484)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:159)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:74)
at ws.WebSocketServletCast.service(WebSocketServletCast.java:56)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:837)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689)
at org.eclipse.jetty.servlets.CrossOriginFilter.handle(CrossOriginFilter.java:308)
at org.eclipse.jetty.servlets.CrossOriginFilter.doFilter(CrossOriginFilter.java:262)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: org.apache.jsp.index_jsp
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at org.apache.jasper.servlet.JasperLoader.loadClass(JasperLoader.java:131)
at org.apache.jasper.servlet.JasperLoader.loadClass(JasperLoader.java:62)
at org.apache.tomcat.SimpleInstanceManager.newInstance(SimpleInstanceManager.java:51)
at org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:171)
... 64 more
Caused by:
java.lang.ClassNotFoundException: org.apache.jsp.index_jsp
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at org.apache.jasper.servlet.JasperLoader.loadClass(JasperLoader.java:131)
at org.apache.jasper.servlet.JasperLoader.loadClass(JasperLoader.java:62)
at org.apache.tomcat.SimpleInstanceManager.newInstance(SimpleInstanceManager.java:51)
at org.apache.jasper.servlet.JspServletWrapper.getServlet(JspServletWrapper.java:171)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:375)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340)
at org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:108)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:199)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:74)
at org.eclipse.jetty.servlet.DefaultServlet.sendWelcome(DefaultServlet.java:598)
at org.eclipse.jetty.servlet.DefaultServlet.doGet(DefaultServlet.java:484)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:845)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:583)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:566)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:159)
at org.eclipse.jetty.server.Dispatcher.forward(Dispatcher.java:74)
at ws.WebSocketServletCast.service(WebSocketServletCast.java:56)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:837)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1689)
at org.eclipse.jetty.servlets.CrossOriginFilter.handle(CrossOriginFilter.java:308)
at org.eclipse.jetty.servlets.CrossOriginFilter.doFilter(CrossOriginFilter.java:262)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:225)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1676)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:581)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:226)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1180)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:511)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1112)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:134)
at org.eclipse.jetty.server.Server.handle(Server.java:524)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:319)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:253)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:273)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:95)
at org.eclipse.jetty.io.SelectChannelEndPoint$2.run(SelectChannelEndPoint.java:93)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.executeProduceConsume(ExecuteProduceConsume.java:303)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.produceConsume(ExecuteProduceConsume.java:148)
at org.eclipse.jetty.util.thread.strategy.ExecuteProduceConsume.run(ExecuteProduceConsume.java:136)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:671)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:589)
at java.lang.Thread.run(Thread.java:748)
서버 설정이 무언가 잘못돼서 Jetty 서버가 내부적으로 사용하는 것들을 제대로 읽지 못하는 듯했다.
내가 조치한 방법은 가장 마지막에 정리했다.
구글링으로 네 가지 방법을 찾아서 테스트해봤다.
첫 번째 방법. 서버의 크론잡 스케줄러 확인 및 Jetty 버전 업그레이드
질문에 달린 답글은 Jetty가 실행될 때 JSP 파일들을 컴파일해서 잠시 /tmp 경로에 저장하는데 서버에 /tmp 경로를 삭제하는 cron잡(스케줄러)가 있는 경우 이 컴파일 된 코드를 찾을 수 없어서 HTTP 500 에러가 발생할 수 있다고 한다.
Jetty 버전을 올리는걸 권장했지만 내가 사용중인 환경은 이미 Jetty 9버전이므로 맞지 않는 내용이었다.
1. 링크 : Bug 356187 - java.lang.ClassNotFoundException: org.apache.jsp.index_jsp
두 번째 방법. 라이브러리 파일 추가
JSP 실행 에러를 검색하면서 찾은 내용인데 이것도 나의 상황과는 맞지 않았다.
주요 내용은 Jetty에서 사용하는 모듈들의 버전과 그 외 라이브러리들의 버전이 맞지 않는다는 내용이다.
1. 링크 : JSP compilation error on jetty-9.3.3
2. 링크 : jsp-support-in-jetty-9-3
세 번째 방법. java policy 추가
이런 저런 것들을 테스트하다가 현재 개발중인 프로그램의 로그 경로를 부모 디렉토리의 절대경로를 입력했을 때만 문제가 발생한다는걸 알아챘다.
특정 경로에서만 발생하는 문제여서 Jetty의 어떤 동작 방식과 연관이 있을거라 생각하고 Jetty의 기능을 찾아보다가 알게된 내용이다.
Java를 이용해서 Jetty가 실행될 때 JVM의 보안 설정들을 선택할 수 있다고 한다.
이것도 시도해봤지만 내가 찾던 답은 아니라서 패스
1. 링크 : Jetty/Feature/Secure Mode
네 번째 방법. web.xml 수정하기
지금 개발중인 웹 애플리케이션에는 'http://{IP}:{PORT}'형태로 웹애플리케이션에 접속할 때 /index.jsp 경로의 파일 내용을 읽고 실행하는 로직이 포함되어 있다. 그래서 이 index.jsp를 처리하는것만 우회하면 괜찮지 않을까해서 시도한 방법이다.
자바 웹 애플리케이션을 개발할 때 web.xml(deployment descriptor, 배포 서술자)파일에 필요한 정보들을 입력해준다. 이 web.xml의 내용 중 '<welcome-file-list>'이 있는데 이 태그는 context path없이 url을 입력해서 서비스에 접근할 때 기본적으로 어떤 파일로 리다이렉트 할 지 알려준다. 설정된 값이 여러개가 있을 경우 첫 번째 입력된 것부터 접근을 시도하고, 파일이 없으면 그 다음, 그 다음 순서로 접근한다. 다 시도해봐도 없는 경우 에러 페이지를 보여준다.
<web-app>
...
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
...
</web-app>
이 설정값이 내가 개발하는 웹 애플리케이션에서는 index.jsp가 1순위로 설정되어 있었기 때문에 이것을 index.html로 바꾸고 기존 로직을 자바스크립트로 실행하도록 수정했다. 결론은 이것도 답이 아니었다.
1. 링크 : web.xml에 대한 내용
결론
아직도 정확히 무엇이 원인인지 찾지 못했다.
그래도 로그 경로를 jetty의 웹 부모 디렉토리 절대경로로 입력했을 때만 문제가 발생한다는 점은 특정되었기 때문에 로그 경로 설정시 유의해야한다고 전달했다.
개발하는 프로그램이 커지다보니 살짝 건드렸을 때 어디가 터질지 알 수가 없다. TDD 개발방법론 같은걸 도입하면 이런 문제를 줄일 수 있다고하는데, 코드가 아닌 인프라가 문제일경우엔 어떻게 해야할까...? 생각이 많아진다.
'Study > Java' 카테고리의 다른 글
[Java] 정규표현식을 이용한 파일구분자 바꾸기 (0) | 2021.03.22 |
---|---|
자바 웹 프로젝트 디렉토리 구성 (0) | 2021.01.08 |
Iterator 와 For-each 비교 (4) | 2020.12.20 |
Oracle JDBC 예제 코드(PrepareStatement) (0) | 2020.11.11 |
자바스크립트로 서블릿 요청(Request)하기 (0) | 2020.11.11 |