2011년 5월 23일 월요일

Simplifying EJB development with EJB 3.0

Simplifying EJB development with EJB 3.0

(이 글의 원문은 http://www.theserverside.com/articles/article.tss?l=SimplifyingEJB3 입니다. 이 글은 역자의 의역으로 원문보다 못한 내용이 많음을 알려드립니다.)

개요
EJB는 분산 컴포넌트 구성을 위해서 도입되었다. EJB가 처음 대두될 때 이것은 CORBA의 복잡성과 모든 문제점의 해결을 약속했었다. EJB는 몇 번의 중요한 개정으로 많이 비대해졌다.
초기에 대부분의 개발자들은 어떠한 이해도 없이 맹목적으로 EJB을 사랑하고 자신의 어플리케이션에 사용해왔고 많은 개발자들이 EJB의 사용으로 그들의 프로젝트가 잘 계획되지 않을 때 EJB을 비난했다.
새로운 EJB 스펙이 발표될 때 마다 그것은 더 복잡해지고 그것의 개발은 더욱 어려워지고 있었다. 결국 EJB의 복잡성과 덩치는 코끼리에 비교되었다.
EJB3.0 expert 위원회는 경량 모델의 단순한 구조의 EJB 3.0 스펙을 발표하게 되었다.

문제점의 해결
우리는 EJB 3.0에 관하여 이야기 하기 전에 현재 EJB모형안의 복잡성을 살펴봐야 할것이다.
  • 현재의 EJB모델은 몇몇의 인터페이스의 생성과 불필요한 몇몇의 callback 메소드 구현을 요구한다.
  • 컴포넌트 인터페이스는 EJBObject, EJBLocalObject의 구현과 많은 불필요한 예외 핸들링을 요구한다.
  • EJB 배치 기술자는 복잡하고 어렵다.
  • CMP(container managed persistence) EJB 모델의 기본이 되었지만 개발과 관리하기에 지나치게 복잡하다. EJBQL은 database의 sequence의 사용과 primary key 정의 등에 있어 매우 제한적이다.
  • EJB 컴포넌트는 상속과 polymorphism 사용을 제한하여 객체지향적으로 보이지 않는다.
  • EJB의 중요한 결점중의 하나인 EJB 컨테이너 외부에서의 테스트를 할 수 없는 것과 컨테이너 안의 EJB을 디버깅 할수 없는 것은 개발자에겐 악몽으로 여겨진다.
  • 우리는 EJB을 사용하려면 우리의 어플리케이션안에 JNDL의 상세한 항목을 알고있어야 한다.


개발자 관점을 단순하게..
만일 우리가 가장 최근 스펙의 EJB을 기준으로 “HelloWorldEJB”와 같은 단순한 EJB을 개발한다고 하더라도 결코 쉬운일이 아니다. 우리는 적어도 두개의 인터페이스, 하나의 bean클래스 그리고 배치기술자(deployment descriptor)을 필요로 하게된다. 개발자의 대부분은 내가 왜 이짓을 해야하는지 생각하게 될것이다. 물론 IDE개발툴을 사용하면 생성, 패키징, 배포까지 도움을 많이 받을수 있지만 말이다.
EJB 3.0은 복잡성을 이야기한다.
- 인터페이스와 배치기술자의 제거가 필요하고 이것은 metadata 주석의 사용으로 컨테이너가 생성해줄것이다.
- EJB을 일반 자바 클래스와 인터페이스로 사용

메타데이터 주석
EJB 3.0 메타데이터 주석에 많이 의존한다. 메타테이터 주석은 JSR 175에 의해 표준화 되었고 J2SE 5.0의 일부분이다. 주석은 XDoclet의 속성 지향 프로그램밍의 종류와 유사하다.
XDoclet의 전편집(pre-compilation)를 요구하는것과 다르게 주석은 컴파일시에 자바 컴파일러에 의해 클래스 안에서 컴파일된다. 개발자 관점에서 보면, 주석은 class, field, method, parameter, 지역변수, 생성자, enumeration, 패키지에서 사용할 수 있는 public 과 같은 수식어구이다. 우리는 code 생성, code 문서화 또는 런타임 동안 비즈니스-레벨 보안 이나 특별한 비즈니스 로직 강화 같은 특별한 서비스를 제공하기 위해 속성을 기술하기위해 자바코드에 주석을 사용할 수 있다.
J2EE 1.5(5.0)의 목표는 주석을 통한 개발의 단순화이다. 다음은 “@”의 주석 예이다.
@Author("Debu Panda")
@Bean
Public class MySessionBean


EJB 3.0의 목적은 개발을 쉽게이고 이를 위해 interface와 같은 몇몇 아티팩트, 배치기술자를 대신에 메타데이터 주석을 사용하게된다.

Using POJOs and POJIs
JavaBeans 와 interface은 POJO(Plain Old Java Objects)와 POJI(Plain Old Java Interface)와 비교된다. EJB class와 interface는 POJO와 POJI을 닮을 것이다. 그리고 Home 인터페이스 같은 불필요한 구성요소는 제거 될 것 입니다.
개발자는 java.ejb 패키지에 정의된 EJB 인터페이스(SessionBean, EntityBean, MessageDrivenBean) 또는 bean 클래스의 주석을 사용 중 하나를 구현하게 될것이다. 우리는 bean 클래스에 Stateless, Stateful, MessageDriven, Entity 중에 하나를 주석으로 사용할것이다.
HelloWorld EJB을 stateless로 정의
@Remote
@Stateless public class HelloWorldBean {
public String sayHello(String s) {
System.out.println("Hello: "+s);
}
}


EJB의 remote, local 인터페이스 EJBObject와 EJBLocalObject을 구현하지 않아도 된다. 우리는 비스니스 인터페이스를 bean클래스에서 인터페이스를 구현하거나 배치 동안에 그것이 생성되어 제공할수 있다.
인터페이스는 Entity Bean에서는 옵션이지만 SessionBean, MessageDrivenBean에서는 필수 사항이다. 만일 우리가 Session Bean에서 인터페이스를 구현하지 않으면 자동으로 생성될것이다.
이 두가지 인터페이스는 우리가 bean 클래스에 작성한 주석에 의해 remote, local 중에 하나로 생성된다.
위의 예를 보면 HelloWorldBean에서 “@Remote” 주석을 사용했기 때문에 remote인터페이스가 생성될 것 이다. 필요하다면 remote, local 모두를 생성 할수 도 있다.
예를 보면 인터페이스 정의와 callback메소드 정의가 없어 매우 간결히 코드가 작성됨을 알수 있다. 생성된 인터페이스의 이름은 bean 클래스의 이름에서 파생된다.

Removing need for Callback methods
EJB 2.1까지 ejbPassivate, ejbActivate, ejbLoad, ejbStore 등 EJB 생명주기에 관계된 메서드 구현이 필요했다. 하지만 ejbPassivate메서드가 stateless Sessioin Bean에서 필요없는 것처럼 모든 메서드가 모든 EJB에 필요한 것은 아니다. EJB 3.0 생명주기에 관련된 메서드를 옵션으로 지정함으로 일반적인 자바 클래스를 닮았다. 만일 우리가 어떤 callback메서드를 구현한다면 Container는 그때만 그 메서드를 실행 할것이다.
유일한 예외는 statefull Session bean에서 ejbRemove 메소드이다. 우리는 statefull Session bean 비즈니스 메서드에 “Remove” 하는 주석을 사용할수 있다. 우리가 이 주석을 사용하면 컨데이너에게 이 주석인 포함된 메서드를 실행하고 Stateful Session bean의 인스턴스를 삭제 하라는 힌트를 주는것이다.
@Stateful public class Cart {
...
...
@Remove public void checkOut() {
...
}
}


Annotations vs. deployment descriptors
앞으로는 EJB에서 deployment descriptor가 더 이상 사용되지 않고 주석이 사용될 것 이다. deployment descriptor에 각 속성의 기본값이 지정 되어있고 그 기본값을 원하지 않는 개발자는 이 속성을 지정하지 않는다. bean클래스 안에 주석을 사용하여 지정 할수 있다.
EJB 3.0 스펙은 bean 타입의 개발자를 위해 메타데이터 주석의 셋을 정의하고 있다. 예를 들어 EJB에서 특별한 자원을 원한다면 다음과 같이 정의 할수 있다.
@Resource(name="jdbc/OracleDS", resourceType="javax.sql.DataSource")


배치 기술자를 제가한 것이 새로운 개발자에게는 편할수도 있을 것이다. 하지만 주석의 사용에 있어서는 주의가 갚어야 하며, 주석을 관리하는 것 자체가 악몽이 되지도 모른다.

Simplifying Container Managed Persistence
EJB 3.0은 TopLink, Hibernate의 단순한 CMP(container managed persistence)와 같은 경량 persistence 모델을 채택하였다. Entity 빈은 POJO 로 다시 태어났고 interface가 더 이상 요구되지 않는다. 또, Entity Bean은 상속과 다형성(polymorphism)을 지원하는 pure object로 가 되었다.
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;
}
....
}
위 code을 보면 CMP가 더 이상 abstract class가 아니라 concrete class임을 발견할 수 있다.(EJB 2.1 스펙에서 CMP는 abstract class 이다.)
Entity bean에서 EJB QL, SQL 쿼리의 지원을 위해 몇 가지 개선이 있었다.

Simplifying Client View for EJBs
어플리케이션에 많은 EJB들이 뭉뚱그려져 있다면 EJB을 lookup하고 실행하는데 개발자는 매우 복잡함을 느낄 것이다. J2EE 1.4과 EJB 3.0은 이 작업을 단순하게 바꾸어 놓았다.
만일 우리가 EJB을 사용하고 싶다면 그 방법은 deployment descriptor에 “ejb-ref” 또는 “ejb-local-ref”을 정의해서 lookup 하고 실행하는 것이다.
deployment descriptor에 EJB references 정의
<ejb-ref>
<ejb-ref-name>HelloWorldEJB</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>hello.HelloWorldHome</home>
<remote> hello.HelloWorld</remote>
</ejb-ref>


LookUp과 실행
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());
}


다음은 setter injection을 사용한 EJB 사용방법이다.
@Inject private void setSessionContext(SessionContext ctx)
{
this.ctx = ctx
}
...
myHello = (HelloWorld)ctx.lookup("java:comp/env/ejb/HelloWorldEJB");


injection된 메서드는 EJB의 비즈니스 메소드가 실행되기 전에 컨테이너에 의해서 EJBContext에 설정된다.

Conclusion
- EJB 어플리케이션에 주석을 달수 있는 메타데이터 주석의 정의가 추가되었다. 메타데이터 주석들은 개발자의 작업을 쉽게하고, 개발자가 작성해야 하는 프로그램의 수를 줄여주고, 개발자가 EJB 배치 디스크립터를 작성할 필요가 없게 해준다.
- 기존의 JNDI 접근은 메타데이터 주석, injection 을 이용한 간단한 LookUp메커니즘을 사용한다.
- Enterprise Java Bean은 자바 Object나 자바 Bean과 유사해 진다.
- 세션빈과 엔티티빈에서 EJB 인터페이스가 없어진다.
- CMP를 사용하는 엔티티빈의 객체/관계 맵핑을 위한 자바 메타데이터 주석이 포함된다.
- 상속과 다형성을 포함하는 도메인 모델링 지원.
- Standard SQL과 함께 벤더에서 지원하는 쿼리도 지원한다.
- CallBack 인터페이스 구현의 제약이 없어진다.
- 컨테이터 없이 테스트 할수 있는 환경을 제공

댓글 없음:

댓글 쓰기

ETL 솔루션 환경

ETL 솔루션 환경 하둡은 대용량 데이터를 값싸고 빠르게 분석할 수 있는 길을 만들어줬다. 통계분석 엔진인 “R”역시 하둡 못지 않게 관심을 받고 있다. 빅데이터 역시 데이터라는 점을 볼때 분산처리와 분석 그 이전에 데이터 품질 등 데이...