October 2004

Discussion


 


Enterprise JavaBeans(EJB)는 분산 컴포넌트를 작성하기 위해 소개되었다. 등장 시점에는 모든 이슈들과 CORBA의 복잡성을 해결하겠다는 의지를 가지고 있었다. EJB는 몇몇 메이저 버전업을 통하면서 J2EE의 핵심이 되었고, 많은 특징들을 갖춰 나갔다. 초창기부터 많은 개발자들은 EJB에 대한 호감을 가졌고, 큰 고민없이 EJB를 적용한 어플케이션을 개발해 나갔다. 결국 많은 개발자들은 EJB를 사용한 프로젝트가 원만하지 않을 경우, EJB에 책임을 돌리게 되었다.


 


EJB 개발은 결코 쉽지 않으며, 릴리즈 될 때 마다 그 복잡함을 더해 갔다. EJB는 그 복잡성과 무거운 속성 때문에 코끼리에 비유되고 있다. 많은 개발자들은 EJB를 도넛에 입혀진 두터운 설탕 시럽처럼 느끼고 있다. 저탄수화물과 Atkins 다이어트에 열광하고 있는 시대에, EJB expert committee 또한 EJB 개발을 쉽고 간편하게 만들어야 함은 당연하다. EJB 3.0 expert committee는 JavaOne 2004에서 EJB 3.0 Specification의 첫번째 public draft를 발표했을 때 샘플 이미지를 배포 하였다.


 


언뜻 보기에 EJB의 새로운 모델은 꽤 괜찮아 보였따. 이 글에서는 개발자들에게 어필하기 위해 EJB 3.0이 작은 사이즈의 멋진 외양으로 변신하려는 지 알아보련다. 다음 글에서는 EJB 3.0이 퍼시스턴스 모델을 어떻게 간소화 하려는 지 알아 보겠다.


 


Cleaning up the Dirty Laundry


EJB 3.0이 새로이 내놓을 것들을 다루기 전에, 현재의 EJB 모델에서 볼 수 있는 복잡성을 먼저 보도록 하자.





  • 현재 사용되는 EJB 모델은 컴포넌트 인터페이스와 불필요한 몇몇 callback 메소드 구현이 필요하다.


  • 컴포넌트 인터페이스는 EJBObject나 EJBLocalObject를 구현해야 하며, 적잖은 수의 불필요한 Exception 핸들링을 필요로 한다.


  • EJB 모델에 기반한 CMP는 개발과 관리에 더더욱 복잡하다. CMP는 몇가지 기본 원칙들을 준수하지 못하고 있다. 예를 들면 데이터베이스 시퀀스를 사용하는 프라이머리키를 정의하는 것에서 그렇다. 그리고 EJBQL은 아주 제한적이다.


  • EJB 컴포넌트는 그 자체가 OO 처럼 보이지 않는다. 상속이나 다형성을 사용하는데 있어 제약이 있기 때문이다.


  • EJB의 가장 큰 단점은 EJB 컨테이너 밖에서는 EJB 모듈을 테스트 할 수 없다는 점이다. 컨테이너에서의 디버깅 또한 개발자들에겐 공포이다.


  • EJB를 사용한다면 EJB를 룩업하고, 호출해야 하는 복잡한 구조를 알아야 한다. 즉 어플리케이션에서 EJB를 사용만 하기 위해서 최소한 JNDI 정도는 알아야 한다. 

 


Simplifying Developers view


최신 명세로 EJB를 개발한다면 HelloWorldEJB와 같은 간단한 EJB를 개발하는 것이 얼마나 어려운 것인가를 깨닫게 될 것이다. 최소한 두개의 인터페이스와 빈 클래스, 그리고 DD가 필요하다. 대부분의 개발자들은 자신이 왜 이 모든 것을 해야 하는 지 의아해 한다. Oracle JDeveloper, Eclipse 같은 IDE 들이나, Xdoclet은 개발자들을 좀 더 편하게 만들어준다. 그렇더라도 개발자들은 컨테이너에 EJB가 디플로이 될 수 있도록 클래스들을 컴파일 하고, DD를 패키징 하여야 한다. 


 


EJB 3.0은 복잡성에 대응하기 위해 다음과 같이 하고 있다.




  • 인터페이스와 DD의 필요성을 제거하고, metadata annotation을 사용하여 컨테이너에 의해 생성될 수 있도록 한다.


  • EJB로 보통의 자바 클래스를 사용하고, EJB를 위한 보통의 비즈니스 인터페이스를 사용한다.

 


Metadata Annotations


EJB 3.0은 metadata annotaion에 큰 의존을 하고 있다. metadata annotaion은 JSR 175에서 표준화되었고, J2SE 5.0에서 채텍될 것이다. Annotaion은 XDoclet과 유사한 attribute 기반 프로그래밍의 한 종류이다. 사전 컴파일이 필요한 XDoclet과 달리, annotaion은 클래스 안에서 컴파일 시점에 자바 컴파일러에 의해 컴파일 된다. (@Retention이 설정되었을 때이다.) 개발자 관점에서 보자면, annotation은 public과 같은 제한자이며, 클래스, 필드, 메소드, 변수, 로컬변수, 생성자, enumeration, 패키지에서 사용될 수 있다. Annotation은 attribute를 자바 소스에 기술해서 사용한다. Attribute는 코드 생성, 문서화, 비즈니스 레베 보안 향상과 같은 특정 서비스나 런타임 시의 특정 비즈니스 로직 등이 있다. J2EE 1.5 (5.0)의 목표는 annotaion을 사용하여 개발 과정을 보다 간소화 하는 것이고, 결국에는 annotation이 필수 요소가 되도록 하는 것이다. Annotation은 다음처럼 @ 로 표시되어 진다.    

 @Author("Debu Panda") @Bean public class MySessionBean  

EJB 3.0의 목표는 개발 과정을 간소화 하는 것이다. 이를 위해서 인터페이스와 같은 몇몇 산출물을 생성하기 위해 metadata annotation을 사용하고, DD 대신에 annotaion을 사용한다.


 


 


Using POJOs and POJIs


전통적으로, 자바빈즈와 인터페이스는 종종 POJO와 POJI로 간주된다. EJB 클래스는 이제 POJO와 POJI와 유사해 질 것이다. 홈 인터페이스와 같은 불필요한 객체는 곧 제거될 것이다.


 


개발자는 javax.ejb 패키지에 있는 EJB 인터페이스(SessionBean, EntityBean, MessageDrivenBean)를 구현하거나, 빈 구현 클래스에 있는 annotaion을 사용해야 한다. 빈 클래스에 annotate를 달기 위해 Stateless, Stateful, MessageDriven, Entity 들 중 하나를 사용할 수 있다. 예를 들면 HelloWorld란 stateless EJB를 만든다면, 다음과 같이 EJB를 정의한다.

@Remote @Stateless public class HelloWorldBean { 
public String sayHello(String s) {
System.out.println("Hello: "+s;
}
}

리모트, 또는 로컬과 같은 EJB를 위한 인터페이스는 EJBOBject, 또는 EJBLOcalObject를 구현할 필요가 없다. EJB를 위한 비즈니스 인터페이스를 제공하거나, 빈 클래스에서 인터페이스를 구현하거나, 디플로이 하는 동안 생성되면 된다. 인터페이스는 Entity Bean에서는 옵션이지만, SessionBean과 MessageDrivenBean에서는 반드시 필요하다. 세션 빈에서 인터페이스를 구현하지 않는다면, 빈 인터페이스는 자동으로 생성할 것이다. 생성된 인터페이스는 빈 클래스에 사용된 annotation에 따라 로컬이거나, 리모트가 된다. 위의 코드를 보면, HelloWorld 빈을 위해 리모트 인터페이스를 생성하도록 @Remote 가 사용되었음을 알 수 있다. 필요할 경우, 리모트와 로컬 인터페이스를 모두 생성할 수 있다.  


 


위의 예제를 보면, 인터페이스 정의와 콜백 메소드를 구현 등의 EJB 컴포넌트를 만들기 위한 일련의 작업들이 더 이상 개발자의 몫이 아님을 알 수 있다.


 


생성된 인터페이스의 이름은 빈 구현 클래스의 이름으로과 연관되어 만들어진다. 생성된 인터페이스들은 개발자들에겐 더할 나위없이 적합한 것들이다. 하지만 Oracle JDeveloper와 같은 IDE에서 이러한 것들을 생성해 주는 것만큼의 효용을 볼 수는 없었다.   


 


이번 Draft에선 클라이언트에서 EJB를 룩업하기 위해 필요한 것이 무엇인지가 명확하지 않다. 그리고 EJB를 호출하기 위해 필요한 인터페이스들을 어떻게 해야 할 지에 관해서도 막연하기만 하다. 아래 열거한 이유들 때문에 난 생성된 인터페이스를 사용하는 것을 지지하지 않는다. 






  • 생성된 인터페이스의 이름은 빈 이름으로부터 생성된다.


  • EJB에서 인터페이스로 내보내고 싶지 않은 어떤 메소드가 있을 수 있지만, 기본적으로 모든 메소드들이 생성된 인터페이스에 내보내 질 것이다.


  • 클라이언트 측에서는 EJB를 호출하기 위한 EJB가 필요하다.

Removing need for Callback methods


 


EJB 2.1과 그 이전 릴리스에서는 몇몇 라이프 사이클과 관련한 메소드의 구현이 반드시 필요했다. 라이프 사이클 메소드로는 ejbPassivate, ejbActivate, ejbLoad, ejbStore 등이 있다. 이런 것들이 필요없는 EJB들도 모두 구현해야 했다. 예를 들면 무상태 세션 빈에서 ejbPassivate는 필요가 없다. 빈 클래스에서 이 메소드를 구현하기 전까지는 전혀 사용되지 않는 것이다. 그래서 EJB 3.0에서 이러한 라이프 사이클 메소드들은 옵션으로 되어 있다. EJB에서 어떤 콜백 메소드를 구현했을 때에만 컨테이너가 그 메소드를 호출할 것이다.


 


단 하나의 예외는 Stateful 세션 빈의 ejbRemove 메소드이다. Stateful 세션빈의 비즈니스 메소드에서 Remove annotation을 사용하여 표시한다. Remove annotation은 표시된 메소드를 정상, 또는 비정상 종료한 후에 Stateful 세션빈이 제거될 수 있도록 컨테이너에게 알려주는 역할을 한다. 예를 들면 Stateful 세션빈 인스턴스의 checkOut 메소드가 실행된 후 제거될 수 있도록 다음과 같이 기술하면 된다.

@Stateful public class Cart { 
... ...
@Remove public void checkOut() {
...
}
}

Annotations vs. deployment descriptors


상기한 바와 같이, EJB에서 DD 대신에 annotation이 쓰이게 될 것이다. DD에서 각 attribute의 기본 값은 설정되어 있으며, 개발자들은 기본 값 이외의 다른 값을 필요로 하지 않는 한 특별히 기술하지 않았다. 이것들은 빈 클래스 자체에서 annotation을 사용하여 기술될 것이다. EJB 3.0 스펙에는 개발자가 사용할 수 있는 metadata annotaion set을 정의되어 있다. metadata annotation에는 bean type, type of interfaces, resource references, transaction attributes, security 등이 있다. 간단한 예로 특정 EJB를 위한 resource reference를 쓰고 싶다면, 다음과 같이 한다.



@Resource(name="jdbc/OracleDS", resourceType="javax.sql.DataSource")


Oracle, BEA, IBM 과 같은 J2EE 벤더들은 벤터 자체의 DD에서 쓰이는 attribute를 위한 annotaion 들을 추가할 것이다. 그리고 개발자들은 DD를 사용하지 않기 위해서 추가된 annotation들을 사용할 것이다. 개발자들에겐 아주 흥미있는 소식이 될 것이다. 왜냐하면 그들이 꽤나 귀찮아 하던 xml 디스크립터들이 사라지기 때문이다. 하지만 몇가지 문제점은 있다. Annotation을 받아 들이기 전에 좀 더 주의할 필요가 있다.




  • 아무 곳에서나 구동할 수 있는 장점이 퇴색할 수 있다. EJB가 벤더에 종속된 DD를 사용한다면, 다른 벤더에 적용하기 위해 EJB를 컴파일하고 패키징하는 작업을 새로 해주어야만 한다. 


  • DD는 EJB 모듈에 대한 정보를 제공한다. 그래서 EJB 내부를 들여다 보지 않아도 assembler와 deployer에게 EJB 모듈에 관한 정보를 알 수 있도록 해준다. DD는 각 디플로이먼트 단위로 필요하다. 만약 descriptor가 사용될 수 없거나, 디플로이먼트가 끝날 때까지 생성되지 않는다면 개발자들에겐 또 하나의 난관이 될 것이다.


  • DD는 EJB 모듈에서 툴에 의해 EJB를 정의하도록 사용되어져 왔다. 그래서 DD는 다른 컨테이너로의 전환에 아주 유용하게 사용되어져 왔다. EJB 3.0도 DD에서 annotation을 오버라이드 할 수 있는 방법을 제공한다. 하지만 annotation을 오버라이딩하는 부분은 Draft에서 빠져있는 상태이다.  

DD를 제거하게 된다면 새로운 개발자들에겐 보다 쉽게 느껴질 것이다. 그러나 주의하지 않는다면 관리적인 측면에서 새로운 암초로 등장할 수도 있을 것이다.


 


 


Simplifying Container Managed Persistence


CMP 엔티티 빈은 EJB 3.0에서 개발자들을 감탄시킬 수 있을 만큼의 대대적인 정비가 이루어 지고 있다. 복잡하고 무거운 엔티티 빈을 싫어하는 개발자들은 TopLink나 Hibernate 같은 Persistence 프레임웍은 J2EE 어플리케이션을 위한 퍼시스턴스 프레임웍을 애용하고 있다. EJB 3.0은 CMP를 간편하게 하기 위해 TopLink나 Hibernate 같은 경량 퍼시스턴스 모델을 적용하고 있어 개발자들을 기대하게 만들고 있다. 엔티티 빈을 위한 플랜을 훑어 보자. 그리고 다른 아티클에서 퍼시스턴스 향상에 관한 세부적인 내용을 다시 다루겠다.  


 


엔티티 빈은 POJO로 다시 태어났다. 그리고 엔티티 빈에 필수였던 컴포넌트 인터페이스는 필요없다. 이제 엔티티 빈은 상속과 다형성을 지원하는 순수한 오브젝트의 모습이 될 것이다.


 


Following is the source code for an entity bean:

@Entity public class Employee { 
private Long empNo;
private String empName;
private Address address;
private Hashmap projects = new Hashmap();
private Double salary;

@Id(generate=SEQUENCE) public Long getEmpNo() {
return empNo;
}

protected void setEmpNo(Long empNo) {
this.empNo = empNo;
}


public String getEmpName() {
return EmpName;
}
 public void setEmpName(String EmpName) { 
this.EmpName = EmpName;
}
 @Dependent public Address getAddress() { 
return address;
}
 public void setAddress(Address address) { 
this.address = address;
}
 public Set getProjects() { 
return projects;
}
 public void setProjects(Set projects) { 
this.projects = projects;
}
 public Double getSalary() { 
return salary;
}
 public void setSalary(Double salary) { 
this.salary = salary;
}
....
}

코드를 보면, 빈 클래스가 보통의 엔티티 빈과 같은 추상 클래스가 아닌 보통 클래스란 것을 알 수 있을 것이다.  


 


EJB QL에서 쿼리 능력 향상, 엔티티 빈에서의 SQL 질의 지원 등 몇가지 향상된 기능이 추가 되었다. 새로운 EntityManager API(Hibernate, TopLink의 Session API의 단순화된 버전과 유사)는 엔티티 빈을 조작하기 위해 제안되었다. (예: creattion, removal, finding of entity beans)


 


다음에 나올 아티클에서 제안된 CMP 엔티티 빈에 관해 더 상세히 보겠다.


 


 


Simplifying Client View for EJBs


EJB를 사용하는 건 EJB가 어플리케이션에 들어 있다 하더라도 매우 복잡하다. J2EE 1.4와 EJB 3.0 스펙은 EJB를 바라보는 클라이언트 측을 보다 더 단순화시켜 놓았다.


 


지금은 EJB를 사용하고 싶을 경우 DD에서 ejb-ref나 ejb-local-ref를 정의해 놓아야 한다. 예를 들어 HelloWorld EJB를 호출하고 싶다면, 보통 다음과 같은 방법으로 EJB를 호출하게 된다.


 


먼저 EJB 레퍼런스를 DD에 등록한다.

 
HelloWorldEJB
Session
hello.HelloWorldHome
hello.HelloWorld

다음 처럼 EJB를 lookup 한다. 빈 인스턴스의 EJB 룩업과 생성을 위한 예외를 명시적으로 처리해 주어야 한다.

try { 
Context context = new InitialContext();
HelloWorldHome helloHome =
(HelloWorld)PortableRemoteObject.narrow(
context.lookup("java:comp/env/ejb/HelloWorldEJB"),
HelloWorldHome.class);
HelloWorld hello = helloHome.create();
....
} catch(RemoteException e) {
System.err.println("System/communication error: " + e.getMessage());
} catch(NamingException e) {
System.err.println("Communication error: " + e.getMessage());
} catch(CreateException e) {
System.err.println("Error creating EJB instance: " + e.getMessage());
}

다른 방법으로 EJB 3.0은 EJB를 룩업하고 호출할 수 있는 setter injection을 쓰는 방안을 제공한다.


 


다음은 다른 EJB에서 setter injection을 사용하여 HelloWorldEJB를 호출하는 방법이다.

@Inject private void setSessionContext(SessionContext ctx) { 
this.ctx = ctx
}
...
myHello = (HelloWorld)ctx.lookup("java:comp/env/ejb/HelloWorldEJB");

코드를 보면 setSessionContext 메소드에 @Inject가 붙어 있다. @Inject는 이 메소드가 dependency injection에 사용됨을 나타내는 것이다. @Inject 처리된 메소드는 EJB의 있는 메소드가 호출되기 전 EJBContext를 세팅할 때 호출된다.


 


HelloWorld 세션빈을 inject 하기 위해서 @EJB public HelloWorld myHello 처럼 해도 된다. 이렇게 하면 HelloWorld 빈 인스턴스가 myHello에 inject 된다.


 


dependency injection은 DataSource, JMS, Mail, Web Service 같은 타입의 environment나 resource reference 를 룩업하기 위해 사용할 수도 있다.


 


 


Testability Usability Outside Container


EJB 개발자들의 가장 주요한 관심사는 EJB 개발이 복잡하다는 것 뿐만 아니라, 테스트가 쉽지 않다는 점에도 있다. EJB 컨테이너는 EJB를 개발하고 테스트 하는데 반드시 필요하다. 그래서 개발자는 테스트를 수행할 배포 플랫폼에 익숙해야만 한다. 이 부분은 많은 엔터프라이즈 개발자들에게 주요한 이슈가 아닐 수도 있다. 그렇지만 다양한 벤더를 지원해야 하는 ISV들에는 이슈가 된다. 그들은 다양한 환경에서의 동작을 보증하기 위해 그들의 EJB 테스팅을 수행해야 하기 때문이다. EJB 3.0 스펙은 컨테이너 외부에서의 테스팅 기능 제공을 약속하고 있다. 그러나 아직 Draft 스펙에는 누락되어 있다.


 


 


Conclusion


packing, assembly, API 등 많은 정보가 누락되긴 했지만, EJB 3.0에 담긴 제안들은 엔터프라이즈 자바 개발자들에겐 매우 환영할 만한 것들이다. 제안들로 인해 개발자들에게 부여되었던 복잡성을 컨테이너 벤더들에게 넘겨버리게 되므로 확실히 단순화 될 것이다. 컨테이너 벤더들이 이것들을 어떻게 구현할지, 엔터프라이즈 어플리케이션을 개발할 때 EJB 3.0을 보다 수월하게 할 수 있는 방법들을 볼 수 있게 될 것이다.  


 


References and further reading



 


Author Bio


Debu Panda is a principal product manager of Oracle Application Server development team, where he focuses his efforts on the EJB container and Transaction Manager. He has more than 13 years of experience in the IT industry and has published articles in several magazines and has presented at many technology conferences. His J2EE-focused weblog can be found at http://radio.weblogs.com/0135826/.



PRINTER FRIENDLY VERSION 
 

Posted by 아름프로
BLOG main image

카테고리

분류 전체보기 (539)
이야기방 (19)
토론/정보/사설 (16)
IBM Rational (9)
U-IT (0)
SOA/WS/ebXML (110)
개발방법론/모델링 (122)
J2SE (34)
J2EE (60)
DataBase (39)
Open Projects (30)
BP/표준화 (50)
Apache Projects (15)
Web/보안/OS (22)
Tools (7)
AJAX/WEB2.0 (1)
Linux/Unix (1)
영어 (0)
비공개방 (0)

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

달력

«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

글 보관함

Total :
Today : Yesterday :