SeamFramework.orgCommunity Documentation
첫 번째 Web Bean 작성을 시작해 보시겠습니까? 혹은 어떤 종류의 Web Beans 사양을 통해 도약하게 될 지를 의아해 하거나 의심하고 계실 수 도 있겠군요! 한 가지 좋은 정보는 여러분은 이미 수백개의 혹은 수천개의 Web Beans을 이미 작성 및 사용하고 계셨다는 것입니다. 아마 여러분은 처음으로 작성하신 Web Beans를 기억하지 못하고 계실 수 도 있습니다.
특정한 예외 상항에서 매개 변수가 없는 것을 허용하는 생성자와 함께하는 모든 Java 클래스는 Web Bean으로 이에는 모든 JavaBean이 포함됩니다. 이에 더하여 모든 EJB 3-스타일 세션 빈도 Web Bean입니다. 물론 매일 작성하셨던 JavaBeans 및 EJB는 Web Beans 사양에 의해 정의된 새로운 서비스의 장점을 취할 수 없지만, Web Beans으로서 기존 코드를 변경하지 않고 이 모든 것을 사용하실 수 있습니다 기타 다른 Web Beans로의 삽입, Web Beans XML 설정 기능을 통한 설정, 인터셉터 및 데코레이터 추가 등
다양한 애플리케이션에서 오랫동안 사용해 온 두 개의 Java 클래스를 갖고 있다고 가정합시다. 첫 번째 클래스는 문자열을 문장 목록으로 구문 분석합니다:
public class SentenceParser {
public List<String
> parse(String text) { ... }
}
두 번째 클래스는 하나의 언어에서 다른 언어로 문장을 번역할 수 있는 외부 시스템에 대한 무상태 세션 빈 프론트엔드입니다:
@Stateless
public class SentenceTranslator implements Translator {
public String translate(String sentence) { ... }
}
여기서 Translator
는 로컬 인터페이스입니다:
@Local
public interface Translator {
public String translate(String sentence);
}
불행하게도 전체 텍스트 문서를 번역하는 기존 클래스가 없으므로, 이러한 작업을 실행하는 Web Bean을 작성합시다:
public class TextTranslator {
private SentenceParser sentenceParser;
private Translator sentenceTranslator;
@Initializer
TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) {
this.sentenceParser = sentenceParser;
this.sentenceTranslator = sentenceTranslator;
}
public String translate(String text) {
StringBuilder sb = new StringBuilder();
for (String sentence: sentenceParser.parse(text)) {
sb.append(sentenceTranslator.translate(sentence));
}
return sb.toString();
}
}
인스턴스를 Web Bean, Servlet 또는 EJB로 삽입하여 TextTranslator
인스턴스를 얻을 수 있습니다:
@Initializer
public setTextTranslator(TextTranslator textTranslator) {
this.textTranslator = textTranslator;
}
다른 방법으로 Web Beans 관리자 방식을 직접 호출하여 인스턴스를 획득할 수 있습니다:
TextTranslator tt = manager.getInstanceByType(TextTranslator.class);
하지만 잠시 기다려주십시오: TextTranslator
는 매개 변수 없는 생성자를 갖지 않습니다! 그래도 이것이 Web Bean입니까? 클래스가 @Initializer
라고 어노테이션된 생성자를 갖고 있을 경우 매개 변수 없이 생성자를 갖지 않는 클래스는 Web Bean이 될 수 있습니다.
예상하셨듯이, @Initializer
어노테이션은 의존성 삽입을 사용하여 실행하기 위한 무엇인가를 갖고 있습니다! @Initializer
는 생성자 또는 Web Bean 방식에 적용될 수 있으며, Web Bean을 인스턴스화할 때 Web Bean 관리자에게 생성자 또는 Web Bean 방식을 호출할 것을 지시합니다. Web Bean 관리자는 기타 다른 Web Beans를 생성자 또는 방식의 매개 변수에 삽입하게 됩니다.
시스템 초기화시 Web Bean 관리자는 각각의 삽입 지점을 만족시키는 하나의 Web Bean이 존재하도록 이를 유효화해야 합니다. 예에서 사용 가능한 Translator
구현이 없을 경우 SentenceTranslator
EJB가 배치되지 않는 다면 Web Bean 관리자는 UnsatisfiedDependencyException
을 넘기게 됩니다. 하나 이상의 Translator
를 구현할 수 있을 경우, Web Bean 관리자는 AmbiguousDependencyException
을 넘기게 됩니다.
정확하게 Web Bean은 무엇인가요?
Web Bean은 비지니스 로직이 들어 있는 애플리케이션 클래스입니다. Web Bean은 Java 코드에서 직접 불러오거나 또는 Unified EL을 통해 불러올 수 있습니다. Web Bean은 트랜젝션 리소스에 액세스할 수 있습니다. Web Beans 사이에서의 종속성은 Web Bean 관리자에 의해 자동으로 관리됩니다. 대부분의 Web Beans은 상태 유지 (stateful) 및 컨텍스트 기반입니다. Web Bean 수명 주기는 항상 Web Bean 관리자에 의해 관리됩니다.
두 번째 내용으로 돌아가 봅시다. "컨텍스트화"된다는 의미는 정확하게 무엇입니까? Web Beans가 상태 유지 세션 빈이면, 보유하고 있는것이 어떤 빈 인스턴스인가가 문제입니다. 무상태 구성 요소 모델 이나 (예: 무상태 세션 빈) 또는 singleton 구성요소 모델 (예: ervlets 또는 singleton 빈)과는 다르게 Web Bean의 다른 클라이언트는 다른 상태에 있는 Web Bean을 보게 됩니다. 클라이언트-가시성 상태는 클라이언트가 참조하고 있는 Web Bean의 인스턴스가 무엇인가에 의존합니다.
하지만, 무상태 또는 싱글턴 모델과 같으나 상태 유지 세션 빈 과는 다르게, 클라이언트는 인스턴스의 수명 주기를 명시적으로 생성 또는 파괴하여 제어하지 못합니다. 대신, Web Bean의 범위는 다음 사항을 결정합니다:
각각의 Web Bean 인스턴스의 수명 주기
어떤 클라이언트가 특정 Web Bean 인스턴스의 참조를 공유할 것인지
Web Beans 애플리케이션에 있는 주어진 스레드의 경우, Web Bean 범위와 관련된 활성 컨텍스트가 있을 수 있습니다. 이러한 컨텍스트는 스레드에서 유일하거나 (예: 요청 범위일 경우) 또는 특정한 다른 스레드와 공유될 수 있거나 (예: Web Bean이 세션 범위일 경우) 또는 기타 다른 모든 스레드일 수 있습니다 (Web Bean이 애플리케이션 범위일 경우).
동일한 컨텍스트에서 실행되는 클라이언트 (예: 기타 다른 Web Bean)는 동일한 Web Bean의 인스턴스를 보게 됩니다. 하지만 다른 컨텍스트에서 실행되는 클라이언트는 다른 인스턴스를 보게 됩니다.
컨텍스트 모델의 큰 장점 중 하나는 상태 유지 Web Beans가 서비스처럼 다루어지게 하는 것입니다! 클라이언트는 사용되는 Web Bean의 수명 주기 관리 자체를 고려하거나, 또는 수명 주기가 무엇인지를 알 필요가 없습니다. Web Beans는 메세지를 전달하여 상호작용하고 Web Bean 구현은 자신의 상태에 따른 수명 주기를 정의합니다. Web Beans는 다음과 같은 이유로 느슨하게 연결되어 있습니다:
잘 정의된 공개 API를 통해 상호 작용하므로
수명 주기는 완전하게 연결 해제되므로
하나의 Web Bean을 동일한 API를 구현하고 다른 Web Bean 구현에 영향을 미치지 않고 다른 수명 주기 (다른 범위)를 갖는 다른 Web Bean으로 대체할 수 있습니다. 사실, 4.2절. “배치 유형 ”에서 살펴보실 수 있듯이 Web Beans는 배치시 Web Bean 구현을 덮어쓰기하기 위한 정교한 기능을 정의합니다.
모든 Web Bean 클라이언트가 Web Beans가 될 수 없음에 유의합니다. Servlets 또는 Message-Driven Beans와 같은 본래 삽입 가능한 컨텍스트 객체가 아닌 객체는 삽입에 의해 Web Beans에 참조를 획득할 수 있습니다.
보다 공식적으로 spec에 따르면:
Web Bean은 다음과 같은 것으로 구성되어 있습니다:
(비어 있지 않은) API 유형 모음
(비어 있지 않은) 바인딩 어노테이션 유형 모음
범위
배치 유형
Web Bean 이름 (옵션 사항)
인터셉터 바인딩 유형 모음
Web Bean 구현
이러한 용어가 Web Bean 개발자에게 무엇을 의미하는 살펴봅시다.
주로 Web Beans는 의존성 삽입을 통해 다른 Web Beans에 참조를 획득합니다. 삽입된 속성은 삽입될 Web Bean을 만족시키는 "계약"을 지정합니다. 계약에는 다음과 같은 내용을 지정합니다:
API 유형
바인딩 유형 모음
API는 사용자 정의 클래스 또는 인터페이스입니다. (Web Bean이 EJB 세션 빈일 경우, API 유형은 @Local
인터페이스이거나 또는 bean-class 로컬 보기입니다.) 바인딩 유형은 클라이언트-가시성 시멘틱을 나타내는 것으로 API의 일부 구현에 의해 만족됩니다.
바인딩 유형은 @BindingType
으로 어노테이션된 사용자 정의 어노테이션에 의해 나타납니다. 예를 들어, 다음과 같은 삽입 지점은 PaymentProcessor
API 유형 및 @CreditCard
바인딩 유형을 갖습니다:
@CreditCard PaymentProcessor paymentProcessor
바인딩 유형이 삽입 지점에 명확하게 지정되어 있지 않을 경우, 기본값 바인딩 유형@Current
가 사용됩니다.
각각의 삽입 지점의 경우, Web Bean 관리자는 계약을 만족시키는 (API를 구현하고 모든 바인딩 유형을 갖는) Web Bean을 검색하여 이를 삽입합니다.
다음과 같은 Web Bean은 @CreditCard
바인딩 유형을 갖고 PaymentProcessor
API 유형을 구현합니다. 따라서 이는 예시 삽입 지점에 삽입될 수 있습니다:
@CreditCard
public class CreditCardPaymentProcessor
implements PaymentProcessor { ... }
Web Bean이 바인딩 유형 모음을 명확히 지정하지 않을 경우, 이는 기본값 바인딩 유형인 @Current
라는 하나의 바인딩 유형을 갖습니다.
Web Beans는 정교하지만 직관적인 해상도 알고리즘을 정의하여 특정 계약을 만족시키는 하나 이상의 Web Bean이 있을 경우 컨테이너가 무엇을 해야할 지를 결정하는 것을 돕습니다. 보다 자세한 내용은 4장. 의존성 삽입 에서 다루겠습니다.
배치 유형은 배치 시나리오에 의해 Web Beans을 구분하게 합니다. 배치 유형은 특정 배치 시나리오를 나타네는 어노테이션으로, 예를 들어 @Mock
, @Staging
, @AustralianTaxLaw
가 있습니다. 시나리오에 배치되어야 할 Web Beans에 어노테이션을 적용합니다. 배치 유형은 단일 설정행을 사용하여 전체 Web Beans 모음이 상황에 따라 배치되게 합니다.
다수의 Web Beans는 배기본값 배치 유형 @Production
을 사용하므로, 이러한 경우 배치 유형을 명확하게 지정할 필요가 없습니다. 예에서 모든 Web Bean 트리는 @Production
배치 유형을 갖습니다.
테스트 환경에서, SentenceTranslator
Web Bean을 "모의 객체"로 교체하고자 합니다:
@Mock
public class MockSentenceTranslator implements Translator {
public String translate(String sentence) {
return "Lorem ipsum dolor sit amet";
}
}
MockSentenceTranslator
및 기타 다른 Web Bean 어노테이션 @Mock
을 사용해야 함을 나타내기 위해 테스트 환경에서 @Mock
배치 유형을 활성화할 수 있습니다.
4.2절. “배치 유형 ”에서 이러한 유일하고 강력한 기능에 관해 자세히 살펴 보겠습니다.
범위는 Web Bean의 수명 주기및 인스턴스의 가시성을 정의합니다. Web Beans 컨텍스트 모델은 확장 가능하고, 임의의 범위를 수용합니다. 하지만, 특정 중요 범위는 사양으로 내장되어 있으며, Web Bean 관리자가 제공합니다. 범위는 어노테이션 유형에 의해 나타납니다.
예를 들어, 웹 애플리케어션은 세션 범위 Web Beans을 갖을 수 있습니다:
@SessionScoped
public class ShoppingCart { ... }
세션 범위 Web Bean의 인스턴스는 사용자 세션으로 바운딩되어 세션 컨텍스트에서 실행되는 모든 요청에 의해 공유됩니다.
기본값으로, Web Beans는 dependent pseudo-scope라는 특정 범위에 속합니다. 이러한 범위를 갖는 Web Beans는 삽입되어야할 객체의 순수한 의존적 객체이며 수명주기는 객체의 수명주기로 바운딩됩니다.
5장. 범위 및 컨텍스트 에서 범위에 대해 보다 자세하게 다루겠습니다.
Web Bean은 이름을 갖을 수 있으며, Unified EL 표현식에서 사용될 수 있습니다. Web Bean의 이름을 지정하는 것은 쉽습니다:
@SessionScoped @Named("cart")
public class ShoppingCart { ... }
이제 JSF 또는 JSP 페이지에서 쉽게 Web Bean을 사용할 수 있습니다:
<h:dataTable value="#{cart.lineItems}" var="item"> .... </h:dataTable >
Web Bean 관리자기 이름을 기본값으로 하게 하는 것이 보다 수월합니다:
@SessionScoped @Named
public class ShoppingCart { ... }
이러한 경우, 이름 기본값은 shoppingCart
가 됩니다 첫번째 문자가 소문자로 된 수식어가 붙지않는 클래스 이름.
Web Beans는 EJB beans 뿐 만 아니라 일반 Java 클래스에 대해 EJB 3에 의해 정의된 인터셉터 기능을 지원합니다. 이에 더하여, Web Beans는 바인딩 인터셉터, EJB beans 및 기타 다른 Web Beans에 새로운 접근 방식을 제공합니다.
@Interceptors
어노테이션의 사용을 통해 인터셉터 클래스를 직접 지정할 수 있습니다:
@SessionScoped
@Interceptors(TransactionInterceptor.class)
public class ShoppingCart { ... }
하지만, 인터셉터 바인딩 유형을 통해 인터셉터 바인딩을 돌려 놓는 것이 보다 좋습니다:
@SessionScoped @Transactional
public class ShoppingCart { ... }
JavaBeans, EJB 및 기타 다른 Java 클래스가 Web Beans이 될 수 있음을 살펴보았습니다. 하지만, 정확히 어떤 종류의 객체가 Web Beans인가요?
Web Beans 사양은 다음과 같을 경우 구체적 Java 클래스가 심플 Web Bean이라고 말합니다:
EJB, Servlet 또는 JPA 엔티티와 같이 EE 컨테이너 관리 기반 구성요소가 아닐 경우,
비-정적인 내부 클래스가 아닐 경우,
매개 변수화된 유형이 아닐 경우,
매개 변수 없는 생성자나 또는 @Initializer
어노테이션된 생성자를 갖을 경우,
따라서, 거의 모든 JavaBean은 심플 Web Bean이 됩니다.
심플 Web Bean에 의해 직접적 또는 간접적으로 구현되는 모든 인터페이스는 API 유형의 심플 Web Bean입니다. 클래스 및 상위클래스도 API 유형이 됩니다.
사양에서는 모든 EJB 3 스타일 세션 및 singleton beans가 EJB 3 엔터프라이즈 Web Beans라고 말합니다. Message driven beans는 Web Beans이 아닙니다 다른 객체에 삽입되도록 되어있지 않기 때문 하지만 이는 의존성 삽입 및 인터셉터를 포함한 대부분의 Web Beans 기능의 장점을 취할 수 있습니다.
와일드카드 유형 매개 변수 또는 유형 변수를 갖지 않는 엔터프라이즈 Web Bean의 모든 로컬 인터페이스 및 이의 상위인터페이스는 엔터프라이즈 Web Bean의 API 유형입니다. EJB bean이 bean 클래스 로컬 보기를 갖고 있을 경우 bean 클래스 및 이의 모든 상위 클래스도 API 유형입니다.
상태유지 세션 빈은 매개 변수가 없는 제거 방식이나 @Destructor
로 어노테이션된 삭제 방식을 명시해야 합니다. Web Bean 관리자는 수명 주기의 마지막에 상태 유지 세션 빈 인스턴스를 파괴하기 위해 이러한 방식을 호출합니다. 이러한 방식은 엔터프라이즈 Web Bean의 파괴자 방식이라고 합니다.
@Stateful @SessionScoped
public class ShoppingCart {
...
@Remove
public void destroy() {}
}
그러면 언제 심플 Web Bean 대신 엔터프라이즈 Web Bean을 사용해야 할까요? 다음과 같이 EJB에 의해 제공되는 고급 엔터프라이즈 서비스가 필요할 때 마다 사용하면 됩니다:
메소드-수준 트랜젝션 관리 및 보안
동시성 관리
상태 유지 세션 빈 용 인스턴스 레벨 수동화 및 무상태 세션 빈 용 인스턴스 풀링
원격 및 웹 서비스 호출
타이머 및 비동기 방식
엔터프라이즈 Web Bean을 사용해야 합니다. 이러한 것이 전혀 필요하지 않을 경우, 심플 Web Bean도 잘 실행될 것입니다.
다수의 Web Beans (세션 또는 애플리케이션 범위 Web Bean 포함)은 동시 액세스에서 사용 가능합니다. 따라서, EJB 3.1에 의해 제공되는 동시성 관리는 아주 유용합니다. 대부분의 세션 및 애플리케이션 범위 Web Beans는 EJB이어야 합니다.
Web Beans는 중량의 리소스에 참조를 보유하고 있거나 EJB @Stateless
/@Stateful
/@Singleton
모델에 의해 정의된 고급 컨테이너 관리 수명주기로 부터의 내부적 상태 장점을 수동화 및 인스턴스 풀링 지원과 함께 보유하고 있어야 합니다.
마지막으로, 메서드-수준 트랜젝션 관리, 메서드-수준 보안, 타이머, 원격 방식 또는 비동기 방식은 명백하게 필요합니다.
심플 Web Bean으로 시작하고, @Stateless
, @Stateful
, @Singleton
어노테이션을 추가하여 EJB로 변환합니다.
생산자 방식은 현재 컨텍스트에 인스턴스가 존재하지 않을 때 Web Bean의 인스턴스를 획득하기 위해 Web Bean 관리자에 의해 호출되는 방식입니다. 생산자 방식은 인스턴스를 Web Bean 관리자가 관리하게 두지 않고 애플리케이션이 인스턴스 절차를 완전히 제어하게 합니다. 예:
@ApplicationScoped
public class Generator {
private Random random = new Random( System.currentTimeMillis() );
@Produces @Random int next() {
return random.nextInt(100);
}
}
생산자 방식 결과는 기타 다른 Web Bean과 같이 삽입됩니다.
@Random int randomNumber
방식 반환 유형 및 직접적이나 간접적으로 확장/구현하는 모든 인터페이스 API 유형의 생산자 방식입니다. 반환 유형이 클래스일 경우 모든 상위클래스도 API 유형이 됩니다.
일부 생산자 방식은 명시적 파괴를 요청하는 객체를 반환합니다:
@Produces @RequestScoped Connection connect(User user) {
return createConnection( user.getId(), user.getPassword() );
}
이러한 생산자 방식은 폐지 방식과 일치하게 정의될 수 있습니다:
void close(@Disposes Connection connection) {
connection.close();
}
이러한 폐지 방식은 요청 마지막에 Web Bean 관리자에 의해 자동으로 호출됩니다.
6장. 생산자 방식 에서 생산자 방식에 관해 보다 자세하게 다룹니다.
마지막으로, JMS 큐 또는 토픽은 Web Bean이 될 수 있습니다. Web Beans는 큐 및 토픽에 메세지를 전달하기 위해 필요한 모든 다양한 JMS 객체의 수명주기 관리에 있어서 개발자에게 단조로움을 완화시킵니다. 13.4절. “JMS 엔드포인트 ”에서 JMS 엔드포인트를 다루게 됩니다.