"Servlet Life Cycle Listeners" 2003/6/26 Tech Tip 에서는 애플리케이션의 특정코드를 실행시키기 위한 서블릿 라이프 사이클 이벤트 리스너 (servlet life cycle event listeners)의 이용방법을 설명하고, 애플리케이션 배포시에, 이를 이용해 애플리케이션 컴포넌트(application components)를 초기화할 수도 있다고 언급하였다. 이번 TechTip은 웹 애플리케이션이 배포될 때, 엔터티 빈의 네트워크를 만들기 위해 ServletContextListener가 사용되는 예를 보여줄 것이다.

서블릿 라이프 사이클 리스너--리뷰

라이프 사이클 리스너는 서블릿 콘테이너 (servlet container)로부터 이벤트들을 받는 이벤트 리스너 클래스(event listener classes)이다. 서블릿 콘테이너는 특정 라이프 사이클 이벤트의 발생을 리스너들에게 알려주는 역할을 하며, 이벤트들은 다음과 같은 일을 한다.

  • 서블릿 콘텍스트와 HTTP 세션의 생성 혹은 파기
  • 서블릿 콘텍스트 애트리뷰트와 HTTP세션 애트리뷰트의 생성, 변경 혹은 제거
  • HTTP세션의 액티베이션과 패시베이션(passivation)
  • HTTP 세션 애트리뷰트에 구속되어 있거나 그렇지 않은 객체에게 알림

웹 애플리케이션은 애플리케이션의 모든 서블릿과 JSP페이지 사이에 공유되는 하나의 ServletContext객체를 갖는다.(분산된 웹 애플리케이션은 각각의 웹 애플리케이션과 자바 버츄얼 머신을 위한 하나의 ServletContext를 갖는다.) 웹 애플리케이션이 배포될 때, 웹 콘테이너는 ServletContext객체를 초기화한다. 만약 웹 애플리케이션의 deployment descriptor가 ServletContextListeners를 선언하면, 콘테이너는 선언된 리스너 순으로 각 리스너의 contextInitialized 메소드를 호출한다. 이 이벤트는 서블릿의 라이프 사이클에서 단 한번만 일어나는데, 이벤트의 발생시점은 웹 애플리케이션의 필터나 서블릿이 초기화되기 전이다. 결과적으로, ServletContextListener.contextInitialized 메소드는 애플리케이션 컴포넌트의 초기화에 사용되는 것이다.

Listeners가 트랜잭션과 트랜잭션 사이를 구별하기(demarcate)위해서 javax.transaction.UserTransaction 인터페이스를 사용할 수는 없다는 것을 기억하자.

샘플 코드

"파인더 메소드와 EJB-QL"은 엔터티 빈의 컬랙션을 식별하기 위해 파인더 메소드 생성 방법을 설명한다. 이 글에서 사용된 예제는 파인더 메소드를 위한 엔터티 빈를 필요로 한다. 따라서 애플리케이션이 배포될 때, 엔터티 빈의 네트워크을 생성할 수 있는 수단이 있어야 한다. 그 수단이라는 것은 ServletContextListener를 통해서 제공된다. 엄밀히 말하자면, 이 팁에서 제공된 샘플 코드는 LoadDataSCL 클래스를 포함하는데, 이 클래스는 ServletContextListenercontextInitialized 메소드가 엔티티 빈의 넥트워크을 생성하도록 ServletContextListener을 구현하는 역할을 한다. 이 메소드는 웹 애플리케이션 아카이브(WAR file)에서 배포되는 XML파일의 컨텐츠에 기반한 빈을 생성한다. LoadDataSCL 클래스의 contextInitialized 메소드를 보자.

   public void contextInitialized(
                             ServletContextEvent sce) {
      ServletContext sc = sce.getServletContext();
      
      System.out.println(
         "contextInitialized: Creating entity beans.");

      DataLoader dl = new DataLoader();
      InputStream is = sc.getResourceAsStream(
                                    "/persondata.xml");
      dl.load(is);

      System.out.println(
          "contextInitialized: Entity beans created.");
   }

이 메소드는 ServletContextEvent 타입의 단일인수(single argument)를 받고, ServletContextEvent는 초기화되는 서블릿 컨텍스트에 레퍼런스를 리턴하는 getServletContext메소드를 포함한다. DataLoader객체는 포맷된 InputStream인 XML로부터 data read를 이용하여 로컬 Person, Address, PhoneNumber 엔터티 빈를 생성한다. 인풋 스트림(input stream)은 getResourceAsStream의 호출에서 양생되었고 애플리케이션 아카이브에 패키지된 XML파일에 스트림을 연다.

애플리케이션의 배포시에, 서블릿 콘테이너는 ServletContext객체를 초기화한 후, LoadDataSCL클래스의 인스턴스를 생성하고 ServletContextEvent객체를 ServletContextEvent에 넘겨준다. 그리고 나서 메소드는 XML파일에 정의된 엔터티 빈의 네트워크을 생성한다. 가령, 사용자가 Reference Implementation에 애플리케이션을 배포시키면, 서버 로그 파일에 다음을 출력한다.

   contextInitialized: Creating entity beans.
   INFO: Document parsed
   contextInitialized: Entity beans created.
   Created Context:/ttaug2003
   Application TTAug2003 deployed.

애플리케이션 배포가 완성되기 전에 초기화 과정이 선행되어야 함을 명심하자. 데이터를 초기화하기 위해서 리스너를 이용하는 것은 웹 리퀘스트가 서비스되기 전에 이미 생성 혹은 초기화 된 객체가 존재한다는 것을 말한다.

이 기법은 엔터티 빈의 네트워크를 생성하는데 유용할 뿐만 아니라, database connections, JMS sessions, Connector 레퍼런스와 같은 웹 컴포넌트들 간에 공유되는 리소스를 서블릿 콘텍스트 리스너(servlet context listener)에 초기화할 때도 사용할 수 있다.

마지막으로 사용자는 웹 애플리케이션의 리소스를 생성하기 위해 다른 타입의 리스너를 이용할 수 있다. 예를 들면, HTTP 세션 애트리뷰트에 상태를 갖는 세션 빈 (가령, 쇼핑카트를 나타내는 것과 같은) 에 대한 레퍼런스를 저장할 수 있다. 그리고 나서 같은 세션 빈 레퍼런스는 같은 세션안의 여러 웹 리퀘스트를 서비스하도록 사용될 수 있다. HTTP 세션 리스너 클래스를 이용해서 확보된 세션 빈 레퍼런스를 HTTP 세션에 저장할 수 있는데, 특정 애플리케이션 서버가 이러한 연산을 수행할 때, 세션 마이그레이션(session migration)과 패시베이션/활성화(passivation/activation)를 적절하게 다루는 역할도 이 클래스의 몫이다.

"Java EE" 카테고리의 다른 글

2003/08/25 14:48 2003/08/25 14:48

TRACKBACK :: http://blog.sdnkorea.com/blog/trackback/264

댓글을 달아 주세요

  1. 박기형  수정/삭제  댓글쓰기

    애플리케이션 초기화하는 방법 알려주셔서 감사합니다.

    2007/09/19 02:17
  2. 박정숙  수정/삭제  댓글쓰기

    좋은 정보 감사해요~

    2007/09/19 06:22
  3. 김복선  수정/삭제  댓글쓰기

    좋은 정보 감사드려요~

    2007/09/19 22:55
[로그인][오픈아이디란?]