Tag Archives: EJB

CDI와 EJB 표준 간의 관계

@Stateful로 선언된 EJB 클래스의 인스턴스의 라이프사이클은 사용자(또는 사용 컴포넌트)가 해당 빈을 명시적으로 종료하기 전까지 지속된다. 하지만 @EJB를 통한 기존의 인젝션 방식으로는 이러한 대화 형식의 정보를 제대로 유지할 수 없는 경우가 발생한다. 다시 말해, EJB는 ‘문맥 정보를 고려하지 않는다’.

어떤 서비스(WAR)에서 외부 요청을 받을 빈을 @Stateless로 선언하고, 해당 빈 내부에서 @Stateful로 선언된 다른 빈을 @EJB로 인젝트 해 사용하는 구조를 생각해보자. 무상태(Stateless) 빈은 매 요청을 받을 때 마다 새롭게 초기화 되고, 이에 따라 해당 빈에 필드로 인젝트 되는 상태 유지(Stateful) 빈 또한 새로운 인스턴스가 할당된다. 이는 @Stateful로 선언된 EJB 빈의 목적과 맞지 않으며, 이를 제대로 관리하기 위해서는 해당 빈에 대한 별도의 문맥 정보(예, 라이프사이클) 관리가 필요하다.

이를 위해, ‘문맥 정보에 대한 지식’을 염두에 둔 인젝션을 가능케하는 기술적 대안으로 CDI를 사용할 수 있다. CDI는 라이프사이클을 몇 가지로 분류(예, 애플리케이션 범위, 요청 범위, 세션 범위 등)해 인젝션 될 객체의 존속 범위를 지정할 수 있다. 즉, 문맥 정보를 바탕으로 빈 객체의 라이프사이클을 관리해준다. 기존에 @EJB를 통해 수행하던 인젝션은 CDI 표준에 따라 @Inject 어노테이션으로 바로 치환해 사용할 수 있다.

이와 같은 CDI와 EJB 간의 상보적 관계는 CDI 표준 문서(다음은 1.1버전 퍼블릭 리뷰 버전)에서 자세히 언급되고 있다. 해당 내용은 다음과 같다.

EJB components may be stateful, but are not by nature contextual. References to stateful component instances must be explicitly passed between clients and stateful instances must be explicitly destroyed by the application.

This specification enhances the EJB component model with contextual lifecycle management.

Any session bean instance obtained via the dependency injection service is a contextual instance. It is bound to a lifecycle context and is available to other objects that execute in that context. The container automatically creates the instance when it is needed by a client. When the context ends, the container automatically destroys the instance.

JSR 346: Contexts and Dependency Injection for JavaTM EE 1.1

CDI는 Java EE 환경에서 의존성 주입을 가능케하는 유용한 도구일 뿐만 아니라, EJB의 한계를 보완해 시너지를 낼 수 있는 도구다. CDI를 효과적으로 적용한다면, 비즈니스 로직을 수행하며 트랜젝션이나 보안 등을 편리하게 관리하도록 해주는 EJB를 더 잘 활용할 수 있다. 혹자들은 CDI만으로 EJB를 대체할 수 있지 않을까 주장하고, 표준화가 이를 염두에 두고 진행된다면 충분히 가능한 이야기이기도 하다. 하지만 EJB의 독립적 책임(트랜젝션이나 보안 등을 고려해 비즈니스 로직을 수행해주는)을 굳이 CDI라는 표준 하나에 밀어 넣는 결정은 불필요한 복잡도를 높일 뿐이 아닌가 생각해본다. 보다 자세한 내용이 필요하다면 Apache TomEE 프로젝트를 이끌고 있는 David Blenvins의 블로그 포스트Adam Bien의 Oracle Technology Network 글을 살펴도록 하자.