IBM Korea Skip to main content
       IBM 홈    |  제품 & 서비스  |  고객지원 & 다운로드  |  회원가입  

EJB best practices :동적 delegate
Java reflection을 이용하여 보다 일반적인 business delegate 구현하기

Level: Intermediate

Brett McLaughlin
작가/편집자, O'Reilly and Associates
2002년 11월

Column iconbusiness delegate 클래스는 엔터프라이즈 자바 디자인에 놀라운 유연성을 부여했지만 애플리케이션의 모든 세션에 business delegate를 코딩하는 일은 여간 성가신 일이 아닐 수 없다. 이 글을 통해, 좀더 일반적인 버전의 business delegate 클래스인 동적 delegate를 만드는 방법을 배워보자.

이전 글 에서, business delegate 클래스(Business Interface 패턴과 혼동하지 말 것!)를 사용하여 EJB 컴포넌트에 액세스 하는 방법을 이야기했다. business delegate 클래스를 클라이언트와 EJB 코드 사이에 삽입함으로서 EJB 구조와 비지니스 로직에서 애플리케이션의 웹 티어를 분리할 수 있었다.

이러한 유형의 디자인을 보는 한 가지 방법은 이것이 얼마나 일반적인가 하는 관점에서 보는 것이다. 비지니스 로직과 기술적 기능이 긴밀하게 연결된 애플리케이션을 시작하면서 우리는 점차적으로 다른 레이어들의 애플리케이션을 분리하고 그들의 상호의존성을 완화시키기 위해 다양한 기술을 사용하기 시작했다. 이렇게 함으로서 애플리케이션의 기반 구조가 일반적일수록 시간이 흐르면서 결국 더욱 강력하고 관리가 쉬워진다는 것을 알게 된다.

이 글에서 일반적인 디자인 이라는 개념을 이어갈 것이다. 현재 business delegate 구현의 한계를 검토한 다음 훨씬 일반적이어서 덜 강직되어있는 business delegate 클래스의 구현을 만들어서 이러한 한계를 극복하는 방법을 보여주겠다.

business delegate class: 리프레셔(refresher)
Library 빈 인터페이스용 business delegate 클래스 참조.

대부분의 LibraryDelegate 클래스는 원래의 Library 빈에 있는 메소드들이 단지 중복된 것이다. LibraryDelegateinit(), destroy(), 구조체 메소드를 추가하고 그런다음 이러한 메소드들을 사용하여 Library 빈으로 태스크들을 위임한다(delegate). 이렇게 해서 delegate은 웹 티어와 엔터프라이즈 빈 사이의 버퍼 역할을 하는 것이다. 원래 빈의 비지니스 인터페이스 참조.

메소드의 확산
이러한 접근방식의 문제는 많은 세션 빈들이 10개, 20개 또는 그 이상의 메소드를 가지고 있다는 것을 고려하기 전까지 명확해지지 않는다. 사실 50개 이상의 메소드를 가진 세션빈을 발견하는 것은 흔한일이다. 빈의 비지니스 인터페이스가 빈의 모든 메소드를 포함해야 하기 때문에 business delegate 클래스가 그럴 수 있다. 이것은 확산된 코드이고 에러의 양산지이다.

타이핑 속도가 빠르다구요?
EJB 컴포넌트 작업을 할 때, 원격 인터페이스, 비지니스 인터페이스, 구현 클래스, business delegate 등을 넘나들면서 많은 메소드들이 중복된다. 손으로 일일이 메소드를 입력하는 것 보다, 에디터 윈도우와 IDE 사이에서 "자르기(cut)" 와 "붙이기(paste)" 라는 좋은 방법이 있다. 하지만 조심해라. 메소드를 손으로 입력하는 것 만큼이나 Option+V 또는 Control+V를 누르는 것도 실수가능성이 높다. 게다가 메소드를 추가할 때 에러의 기회가 된다. 메소드가 정확히 입력되고 의도한 대로 "자르기(cut)" 와 "붙이기(paste)"가 정확히 되었다는 것을 두번 정도 확인하면 장수하게 될 것이다. :)

확산되는 것 이외에도 변경 요소를 고려해야한다. Delegate 클래스는 모든 빈의 메소드들을 중복시키고 빈들은 시간이 지나면 어쩔 수 없이 변경되기 때문에 새로운 메소드를 Delegate에 추가하는데 많은 시간을 할애하게 된다. 새로운 코드를 재컴파일하고 테스트 해야함은 두말할 나위 없다.

이 자체는 그다지 큰 문제가 아니다. 하지만 business delegate 클래스를 사용하여 비지니스와 구현 로직을 기술 인프라에서 추출하는 것으로 시작했으며 이 경우 EJB 컴포넌트라는 것을 고려해보라. 원격 인터페이스를 변경이 business delegate을 변경을 수반한다면 우리의 business delegate은 기반 컴포넌트에 묶인다.

여기 더 좋은 방법이 있다.

동적 delegate
해결책은 dynamic delegate인데 이것은 Java reflection을 사용한다. delegate으로 하드코딩된 비지니스 메소드를 갖는 대신 목표 EJB 컴포넌트의 원격 인터페이스상에서 delegate이 메소드를 동적으로 호출하도록 한다. 이것은 원격 인터페이스에서 완벽한 디커플링(decoupling)이 가능하다. 빈의 비지니스 또는 원격 인터페이스에 메소드를 추가한다고 해서 이에 따른 business delegate을 변경할 필요가 없다. 동적 delegate을 이용하면 기술 인프라 변경도 쉬워진다. 원격 인터페이스와 EJB 기술에서 Java Data Objects (JDO)같은 다른 기술로 마이그레이션 할 때 단지 delegate의 init() 메소드만 변경하면 된다. 다른 모든 메소드 호출은 빈의 인터페이스를 통해 계속적으로 위임된다. 변경에 따른 추가작업은 없다. Listing 1은 Library business delegate의 동적 버전이다:

Listing 1. Library 빈을 위한 business delegate

package com.ibm.library;

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.CreateException;
import javax.naming.NamingException;

public class LibraryDelegate implements ILibrary {
  private ILibrary library;
  private Map availableMethods;
  
  public LibraryDelegate() {
    init();
  }
    
      public void init() {
        // Look up and obtain our session bean
        try {
          LibraryHome libraryHome =
            (LibraryHome)EJBHomeFactory.getInstance().lookup(
              "java:comp/env/ejb/LibraryHome", LibraryHome.class);
          library = libraryHome.create();
            
          // Get the methods available for use in proxying
          availableMethods = new HashMap();
          Method[] methods = ILibrary.class.getMethods();
          for (int i=0; i<methods.length; i++) {
            availableMethods.put(methods[i].getName(),
              methods[i]);
          }
        } catch (NamingException e) {
          throw new RuntimeException(e);
        } catch (CreateException e) {
          throw new RuntimeException(e);
        } catch (RemoteException e) {
          throw new RuntimeException(e);
        }
      }  
          
      // All the hard-coded methods are removed
      public Object 
        invoke(Object proxy, Method method, Object[] args)
        throws Throwable{
        
        try {
          // See if this is init() or destroy()
          if (method.getName().equals("init")) {
            init();
            return null;
          } else if (method.getName().equals("destroy")) {
            destroy();
            return null;
          } else {
            Method method = 
              (Method)availableMethods.get(method.getName());
            
            // See if we found anything
            if (method != null) {
              return method.invoke(library, args);
            } else {
              throw new 
                NoSuchMethodException("The Library does not " +
                "support the  " + method.getName() +" method.");
            }
          } 
        } catch (InvocationTargetException e) {
          // We don't support throwing RuntimeExceptions from EJBs 
          // directly
          if (e.getTargetException() instanceof RemoteException) {
            throw new RuntimeException(e);
            } else {
              throw e.getTargetException();
            }
          }
        }
        
        public void destroy() {
          // In this case, do nothing
        }
      }

동적 delegate은 delegate, 빈, 비지니스 인터페이스 사이의 커플링 문제를 훌륭하게 해결한다. 하지만 이것은 완벽한 솔루션도 최상의 솔루션도 아니다. 이러한 접근방식은 무한한 유연성을 제공해주지만 퍼포먼스에 대해서 희생을 해야한다. 자바 reflection은 빠르지 않다. 따라서 invoke()를 호출하고 결과를 얻게되기까지 상당한 시간이 걸린다. 이전 팁에서 설명했던 정적 business delegate은 좀 더 빠른 솔루션이기는 하지만 비지니스와 기술 레이어가 지나치게 커플링된다. 따라서 두 가지 옵션을 고려할 때 디자인이나 퍼포먼스에 따른 선택이 되어야한다. 동적 delegate은 전체 퍼포먼스 보다는 애플리케이션 디자인이 더 중요할 경우 선택하면 좋다. business delegate은 퍼포먼스가 더욱 중요한 요소가 될 때 최상의 선택이 된다.

참고자료

목 차:
business delegate class: 리프레셔(refresher)
메소드의 확산
동적 delegate
참고 자료
필자 소개
기사에 대한 평가
관련 dW 링크:
EJB best practices series
Best practices in EJB exception handling
Subscribe to the developerWorks newsletter
US 원문 읽기
Also in the Java zone:
Tutorials
Tools and products
Code and components
Articles
필자소개
Photo of Brett McLaughlinBrett McLaughlin은 현재 자바 및 관련 기술을 이용하여 애플리케이션 기반구조 구현을 전문적으로 수행하고 있다. Brett은 Java Apache 프로젝트인 Turbine의 공동 창립자이다.
이 기사에 대하여 어떻게 생각하십니까?

정말 좋다 (5) 좋다 (4) 그저그렇다 (3) 수정보완이 필요하다(2) 형편없다 (1)

  회사소개  |  개인정보 보호정책  |  법률  |  문의