SeamFramework.orgCommunity Documentation

Web Beans: Java Contexts and Dependency Injection

The new standard for dependency injection and contextual state management


Note
I. 컨텍스트 객체 사용
1. Web Beans로 시작하기
1.1. 첫 번째 Web Bean
1.2. Web Bean은 무엇인가요?
1.2.1. API 유형, 바인딩 유형 및 의존성 삽입
1.2.2. 배치 유형
1.2.3. 범위
1.2.4. Web Bean 이름 및 Unified EL
1.2.5. 인터셉터 바인딩 유형
1.3. 어떤 종류의 객체가 Web Beans가 될 수 있을까요?
1.3.1. 심플 Web Beans
1.3.2. 엔터프라이즈 Web Beans
1.3.3. 생산자 방식
1.3.4. JMS 엔드포인트
2. JSF 웹 애플리케이션 예
3. Web Beans, the Reference Implementation of JSR-299
3.1. Using JBoss AS 5
3.2. Using Apache Tomcat 6.0
3.3. Using GlassFish
3.4. numberguess 예제
3.4.1. The numberguess example for Tomcat
3.5. 번역 예제
4. 의존성 삽입
4.1. 바인딩 어노테이션
4.1.1. 멤버와 바인딩 어노테이션
4.1.2. 바인딩 어노테이션의 조합
4.1.3. 바인딩 어노테이션 및 생산자 방식
4.1.4. 기본값 바인딩 유형
4.2. 배치 유형
4.2.1. 배치 유형 활성화
4.2.2. 배치 유형 우선 순위
4.2.3. 배치 유형 예시
4.3. 불만족스러운 의존성 수정
4.4. 클라이언트 프록시
4.5. 프로그램적 lookup에 의해 Web Bean 획득
4.6. 수명 주기 콜백, @Resource, @EJB@PersistenceContext
4.7. InjectionPoint 객체
5. 범위 및 컨텍스트
5.1. 범위 유형
5.2. 내장된 범위
5.3. 컨버세이션 범위
5.3.1. 컨버세이션 경계 설정
5.3.2. 컨버세이션 보급
5.3.3. 컨버세이션 시간 초과
5.4. dependent pseudo-scope
5.4.1. @New 어노테이션
6. 생산자 방식
6.1. 생산자 방식의 범위
6.2. 생산자 방식으로 삽입
6.3. 생산자 방식과 함께 @New 사용
II. 느슨하게 연결된 (loosely-coupled) 방식의 코드 개발
7. 인터셉터
7.1. 인터셉터 바인딩
7.2. 인터셉터 구현
7.3. 인터셉터 활성화
7.4. 멤버와 인터셉터 바인딩
7.5. 여러개의 인터셉터 바인딩 어노테이션
7.6. 인터셉터 바인딩 유형 상속
7.7. @Interceptors 사용
8. 데코레이터
8.1. 위임 속성
8.2. 데코레이터 활성화
9. 이벤트
9.1. 이벤트 옵저버
9.2. 이벤트 생산자
9.3. 옵저버를 동적으로 등록
9.4. 멤버와 이벤트 바인딩
9.5. 여러 이벤트 바인딩
9.6. 트랜잭션 옵저버
III. 가장 강한 타이핑 (strong typing) 사용
10. 스테레오타입 (Stereotypes)
10.1. 스테레오타입에 대한 기본값 범위 및 배치 유형
10.2. 스테레오타입으로 범위 및 유형 제한
10.3. 스테레오타입 용 인터셉터 바인딩
10.4. 스테레오타입과 함께 이름을 기본값으로 지정
10.5. 표준 스테레오타입
11. 특성화
11.1. 특성화 기능 사용
11.2. 특성화 기능의 장점
12. XML을 사용하여 Web Beans 정의
12.1. Web Bean 클래스 명시
12.2. Web Bean 메타데이터 명시
12.3. Web Bean 멤버 명시
12.4. 인라인 Web Beans 명시
12.5. 스키마 사용
IV. Web Beans 및 Java EE 에코시스템
13. Java EE 통합
13.1. Java EE 리소스를 Web Bean으로 삽입
13.2. Servlet에서 Web Bean 호출
13.3. Message-Driven Bean에서 Web Bean 호출
13.4. JMS 엔드포인트
13.5. 패키징 및 배포
14. Web Beans 확장
14.1. Manager 객체
14.2. Bean 클래스
14.3. Context 인터페이스
15. 다음 단계
V. Web Beans Reference
16. Application Servers and environments supported by Web Beans
16.1. Using Web Beans with JBoss AS
16.2. Glassfish
16.3. Tomcat (or any plain Servlet container)
16.4. Java SE
16.4.1. Web Beans SE Module
17. JSR-299 extensions available as part of Web Beans
17.1. Web Beans Logger
17.2. XSD Generator for JSR-299 XML deployment descriptors
A. Web Beans RI를 다른 환경으로 통합
A.1. Web Beans RI SPI
A.1.1. Web Bean 검색
A.1.2. EJB services
A.1.3. JPA services
A.1.4. Transaction Services
A.1.5. The application context
A.1.6. Bootstrap and shutdown
A.1.7. JNDI
A.1.8. 리소스 불러오기
A.1.9. Servlet injection
A.2. 컨테이너와 계약

JSR-299 has recently changed its name from "Web Beans" to "Java Contexts and Dependency Injection". The reference guide still refers to JSR-299 as "Web Beans" and the JSR-299 Reference Implementation as the "Web Beans RI". Other documentation, blogs, forum posts etc. may use the new nomenclature, including the new name for the JSR-299 Reference Implementation - "Web Beans".

You'll also find that some of the more recent functionality to be specified is missing (such as producer fields, realization, asynchronous events, XML mapping of EE resources).

Web Beans (JSR-299) 사양은 애플리케이션을 보다 쉽게 개발하기 위한 Java EE 환경에 대한 서비스 모음을 정의합니다. Web Beans는 JavaBeans 및 Enterprise Java Bean을 포함하여 기존의 Java 구성 요소 유형을 통해 향상된 수명 주기 및 상호 작용 모델을 계층화합니다. 전통적인 Java EE 프로그래밍 모델의 구성 요소로서, Web Beans는 다음과 같은 서비스를 제공합니다:

컨텍스트 수명 주기 관리와 함께 의존성 주입은 다음과 같은 질문을 묻고 대답하는 것에서 생소한 API 사용자를 보호합니다:

Web Bean은 의존하는 다른 Web Beans의 유형 및 시멘틱 만을 지정합니다. 이는 의존하는 다른 Web Bean 클라이언트 또는 스레딩 모델, 실제적인 수명 주기, 구체적 구현 방식을 인식할 필요가 없습니다. 더 나아가 의존하는 Web Bean의 스레딩 모델, 수명 주기, 구체적 구현 방식은 클라이언트에게 영향을 미치지 않고 운용 방식에 따라 달라질 수 있습니다.

이벤트, 인터셉터 및 데코레이터는 이러한 모델에 내제된 느슨하게 연결하는 (loose-coupling) 기능을 강화합니다:

가장 중요하게 Web Beans는 이러한 모든 기능을 타입 안정적 (typesafe) 방식으로 제공합니다. Web Beans는 협력적 객체를 갖추기 위한 방법을 결정하기 위해 문자열 기반의 식별자를 사용하지 않습니다. XML은 옵션으로 남아있어도 거의 사용되지 않습니다. 대신 Web Beans는 바인딩 어노테이션 (binding annotations)이라는 새로운 패턴과 함께 Java 객체 모델에서 이미 사용 가능한 타이핑 정보를 사용하여 Web Beans 및 Web Beans의 의존성, 인터셉터, 데코레이터 및 이벤트 소비자를 함께 묶습니다.

Web Beans 서비스는 일반적으로 Java EE 환경에 있는 다음과 같은 구성 요소의 유형에 적용됩니다:

Web Beans는 통합 지점을 제공하여 차후 Java EE 사양이나 또는 비표준 프레임워크에 의해 지정된 다른 종류의 구성 요소가 Web Beans과 통합되어 Web Beans 서비스의 장점을 취하고 다른 종류의 Web Bean과 상호 작용합니다.

Web Beans는 Seam, Guice, Spring을 포함하여 다수의 기존 Java 프레임워크에 의해 영향을 받았지만 Web Beans은 자체적으로 다음과 같은 고유한 기능을 소유하고 있습니다: Seam 보다 더 타입 안정적, 보다 더 상태 기반적, Spring 보다 덜 XML-중심, Guice 보다 더 웹 및 엔터프라이즈-애플리케이션 사용 가능

보다 중요하게 Web Beans는 Java EE 및 내장 가능한 EJB Lite를 사용할 수 있는 Java SE 환경과 통합된 JCP 표준입니다.

차례

1. Web Beans로 시작하기
1.1. 첫 번째 Web Bean
1.2. Web Bean은 무엇인가요?
1.2.1. API 유형, 바인딩 유형 및 의존성 삽입
1.2.2. 배치 유형
1.2.3. 범위
1.2.4. Web Bean 이름 및 Unified EL
1.2.5. 인터셉터 바인딩 유형
1.3. 어떤 종류의 객체가 Web Beans가 될 수 있을까요?
1.3.1. 심플 Web Beans
1.3.2. 엔터프라이즈 Web Beans
1.3.3. 생산자 방식
1.3.4. JMS 엔드포인트
2. JSF 웹 애플리케이션 예
3. Web Beans, the Reference Implementation of JSR-299
3.1. Using JBoss AS 5
3.2. Using Apache Tomcat 6.0
3.3. Using GlassFish
3.4. numberguess 예제
3.4.1. The numberguess example for Tomcat
3.5. 번역 예제
4. 의존성 삽입
4.1. 바인딩 어노테이션
4.1.1. 멤버와 바인딩 어노테이션
4.1.2. 바인딩 어노테이션의 조합
4.1.3. 바인딩 어노테이션 및 생산자 방식
4.1.4. 기본값 바인딩 유형
4.2. 배치 유형
4.2.1. 배치 유형 활성화
4.2.2. 배치 유형 우선 순위
4.2.3. 배치 유형 예시
4.3. 불만족스러운 의존성 수정
4.4. 클라이언트 프록시
4.5. 프로그램적 lookup에 의해 Web Bean 획득
4.6. 수명 주기 콜백, @Resource, @EJB@PersistenceContext
4.7. InjectionPoint 객체
5. 범위 및 컨텍스트
5.1. 범위 유형
5.2. 내장된 범위
5.3. 컨버세이션 범위
5.3.1. 컨버세이션 경계 설정
5.3.2. 컨버세이션 보급
5.3.3. 컨버세이션 시간 초과
5.4. dependent pseudo-scope
5.4.1. @New 어노테이션
6. 생산자 방식
6.1. 생산자 방식의 범위
6.2. 생산자 방식으로 삽입
6.3. 생산자 방식과 함께 @New 사용

첫 번째 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 Beans 애플리케이션에 있는 주어진 스레드의 경우, Web Bean 범위와 관련된 활성 컨텍스트가 있을 수 있습니다. 이러한 컨텍스트는 스레드에서 유일하거나 (예: 요청 범위일 경우) 또는 특정한 다른 스레드와 공유될 수 있거나 (예: Web Bean이 세션 범위일 경우) 또는 기타 다른 모든 스레드일 수 있습니다 (Web Bean이 애플리케이션 범위일 경우).

동일한 컨텍스트에서 실행되는 클라이언트 (예: 기타 다른 Web Bean)는 동일한 Web Bean의 인스턴스를 보게 됩니다. 하지만 다른 컨텍스트에서 실행되는 클라이언트는 다른 인스턴스를 보게 됩니다.

컨텍스트 모델의 큰 장점 중 하나는 상태 유지 Web Beans가 서비스처럼 다루어지게 하는 것입니다! 클라이언트는 사용되는 Web Bean의 수명 주기 관리 자체를 고려하거나, 또는 수명 주기가 무엇인지를 알 필요가 없습니다. Web Beans는 메세지를 전달하여 상호작용하고 Web Bean 구현은 자신의 상태에 따른 수명 주기를 정의합니다. Web Beans는 다음과 같은 이유로 느슨하게 연결되어 있습니다:

하나의 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는 사용자 정의 클래스 또는 인터페이스입니다. (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장. 의존성 삽입 에서 다루겠습니다.

JavaBeans, EJB 및 기타 다른 Java 클래스가 Web Beans이 될 수 있음을 살펴보았습니다. 하지만, 정확히 어떤 종류의 객체가 Web Beans인가요?

사양에서는 모든 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장. 생산자 방식 에서 생산자 방식에 관해 보다 자세하게 다룹니다.

이러한 웹 애플리케이션의 예를 살펴봅시다. JSF를 사용하는 애플리케이션의 사용자 로그인/로그아웃을 구현할 것입니다. 먼저, 로그인시 입력한 사용자 이름 및 암호를 보유하기 위해 Web Bean을 정의합니다:

@Named @RequestScoped

public class Credentials {
        
    private String username;
    private String password;
    
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    
}

Web Bean은 다음과 같은 JSF 형식에서 로그인 프롬프트로 바운딩됩니다:

<h:form>

    <h:panelGrid columns="2" rendered="#{!login.loggedIn}">
        <h:outputLabel for="username"
>Username:</h:outputLabel>
        <h:inputText id="username" value="#{credentials.username}"/>
        <h:outputLabel for="password"
>Password:</h:outputLabel>
        <h:inputText id="password" value="#{credentials.password}"/>
    </h:panelGrid>
    <h:commandButton value="Login" action="#{login.login}" rendered="#{!login.loggedIn}"/>
    <h:commandButton value="Logout" acion="#{login.logout}" rendered="#{login.loggedIn}"/>
</h:form
>

현재 로그인 사용자에 관한 정보를 관리하는 Web Bean 세션 범위에 의해 실제 작업이 완료되어 다른 Web Beans에 User 엔티티를 노출시킵니다:

@SessionScoped @Named

public class Login {
    @Current Credentials credentials;
    @PersistenceContext EntityManager userDatabase;
    private User user;
    
    public void login() {
            
        List<User
> results = userDatabase.createQuery(
           "select u from User u where u.username=:username and u.password=:password")
           .setParameter("username", credentials.getUsername())
           .setParameter("password", credentials.getPassword())
           .getResultList();
        
        if ( !results.isEmpty() ) {
           user = results.get(0);
        }
        
    }
    
    public void logout() {
        user = null;
    }
    
    public boolean isLoggedIn() {
       return user!=null;
    }
    
    @Produces @LoggedIn User getCurrentUser() {
        return user;
    }
}

@LoggedIn은 바인딩 어노테이션입니다:

@Retention(RUNTIME)

@Target({TYPE, METHOD, FIELD})
@BindingType
public @interface LoggedIn {}

기타 다른 Web Bean은 현재 사용자를 쉽게 삽입할 수 있습니다:

public class DocumentEditor {


    @Current Document document;
    @LoggedIn User currentUser;
    @PersistenceContext EntityManager docDatabase;
    
    public void save() {
        document.setCreatedBy(currentUser);
        docDatabase.persist(document);
    }
    
}

이러한 예가 Web Bean 프로그래밍 모델의 맛을 보는 계기가 되었으면 합니다. 다음 부분에서는 Web Beans 의존성 삽입에 대해 자세히 살펴보겠습니다.

The Web Beans is being developed at the Seam project. You can download the latest developer release of Web Beans from the the downloads page.

Web Beans comes with a two deployable example applications: webbeans-numberguess, a war example, containing only simple beans, and webbeans-translator an ear example, containing enterprise beans. There are also two variations on the numberguess example, the tomcat example (suitable for deployment to Tomcat) and the jsf2 example, which you can use if you are running JSF2. To run the examples you'll need the following:

  • the latest release of Web Beans,

  • JBoss AS 5.0.1.GA, or

  • Apache Tomcat 6.0.x, and

  • Ant 1.7.0.

You'll need to download JBoss AS 5.0.1.GA from jboss.org, and unzip it. For example:

$ cd /Applications
$ unzip ~/jboss-5.0.1.GA.zip

Next, download Web Beans from seamframework.org, and unzip it. For example

$ cd ~/
$ unzip ~/webbeans-$VERSION.zip

다음으로, JBoss가 위치해 있는 곳을 Web Beans에게 알려야 합니다. jboss-as/build.properties를 편집하고 jboss.home 속성을 설정합니다. 예:

jboss.home=/Applications/jboss-5.0.1.GA

To install Web Beans, you'll need Ant 1.7.0 installed, and the ANT_HOME environment variable set. For example:

$ unzip apache-ant-1.7.0.zip
$ export ANT_HOME=~/apache-ant-1.7.0

Then, you can install the update. The update script will use Maven to download Web Beans automatically.

$ cd webbeans-$VERSION/jboss-as
$ ant update

이제, 첫번째 예제를 배치할 준비가 되었습니다!

작은 정보

The build scripts for the examples offer a number of targets for JBoss AS, these are:

  • ant restart - exploded 형식으로 예제를 배치합니다

  • ant explode - 배치 버전을 다시 시작하지 않고 exploded 예제를 업데이트합니다

  • ant deploy - 압축된 jar 포맷으로 예제를 배치합니다

  • ant undeploy - 서버에서 예제를 제거합니다

  • ant clean - 예제를 지웁니다

numberguess 예제를 배치하려면:

$ cd examples/numberguess
ant deploy

Start JBoss AS:

$ /Application/jboss-5.0.0.GA/bin/run.sh

작은 정보

If you use Windows, use the run.batscript.

애플리케이션이 배치되면 http://localhost:8080/webbeans-numberguess에서 살펴보시기 바랍니다!

Web Beans includes a second simple example that will translate your text into Latin. The numberguess example is a war example, and uses only simple beans; the translator example is an ear example, and includes enterprise beans, packaged in an EJB module. To try it out:

$ cd examples/translator
ant deploy

애플리케이션이 배치되면 http://localhost:8080/webbeans-translator에 가보십시오!

You'll need to download Tomcat 6.0.18 or later from tomcat.apache.org, and unzip it. For example:

$ cd /Applications
$ unzip ~/apache-tomcat-6.0.18.zip

Next, download Web Beans from seamframework.org, and unzip it. For example

$ cd ~/
$ unzip ~/webbeans-$VERSION.zip

Next, we need to tell Web Beans where Tomcat is located. Edit jboss-as/build.properties and set the tomcat.home property. For example:

tomcat.home=/Applications/apache-tomcat-6.0.18

작은 정보

The build scripts for the examples offer a number of targets for Tomcat, these are:

  • ant tomcat.restart - deploy the example in exploded format

  • ant tomcat.explode - update an exploded example, without restarting the deployment

  • ant tomcat.deploy - deploy the example in compressed jar format

  • ant tomcat.undeploy - remove the example from the server

  • ant tomcat.clean - clean the example

To deploy the numberguess example for tomcat:

$ cd examples/tomcat
ant tomcat.deploy

Start Tomcat:

$ /Applications/apache-tomcat-6.0.18/bin/startup.sh

작은 정보

If you use Windows, use the startup.batscript.

애플리케이션이 배치되면 http://localhost:8080/webbeans-numberguess에서 살펴보시기 바랍니다!

numberguess 애플리케이션에서 1에서 100사이의 숫자를 알아내기 위해 주어진 10 번을 시도하게 됩니다. 각각 시도한 후 숫자가 너무 높은지 또는 너무 낮은지를 알려주게 됩니다.

numberguess 예제는 여러 Web Beans, 설정 파일, Facelet JSF 페이지로 구성되어 있으며, war로 패키지되어 있습니다 설정 파일부터 시작합시다.

예제에 해당하는 모든 설정 파일은 WEB-INF/에 위치해 있으며, 이는 소스 트리에 있는 WebContent에 저장되어 있습니다. 먼저, faces-config.xml을 사용하여, Facelets를 사용할 JSF를 알려주게 됩니다:


<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="1.2"
              xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
    
    <application>
        <view-handler
>com.sun.facelets.FaceletViewHandler</view-handler>
    </application>

</faces-config
>

여기에는 빈 web-beans.xml 파일이 있어, 이는 Web Beans 애플리케이션으로 애플리케이션을 표시합니다.

마지막으로, web.xml 파일이 있습니다:

Let's take a look at the Facelet view:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:s="http://jboss.com/products/seam/taglib">

  <ui:composit(1)ion template="template.xhtml">
    <ui:define name="content">
       <h1
>Guess a number...</h1>
       <h:form(2) id="NumberGuessMain">
          <div style="color: red">
             <h:messages id="messages" globalOnly="false"/>
             <h:outputText id="Higher" value="Higher!" rendered="#{game.number gt game.guess and game.guess ne 0}"/>
             <h:outputText id="Lower" value="Lower!" rendered="#{game.number lt game.guess and game.guess ne 0}"/>
          </div>
   
          <div(3)>
             I'm thinking of a number between #{game.smallest} and #{game.biggest}.
             You have #{game.remainingGuesses} guesses.
          </div>
     
          <div>
             Y(4)our guess: 
             <h:inputText id="inputGuess" 
                          value="#{game.guess}" 
                          required="true" 
                          size="3" 
              (5)            disabled="#{game.number eq game.guess}">
                <f:validateLongRange maximum="#{game.biggest}" 
                                     minimum="#{game.smallest}"/>
             <(6)/h:inputText>
            <h:commandButton id="GuessButton"  
                             value="Guess" 
                             action="#{game.check}" 
                             disabled="#{game.number eq game.guess}"/>
          </div>
          <div>
            <h:commandButton id="RestartButton" value="Reset" action="#{game.reset}" immediate="true" />
          </div>
       </h:form>
    </ui:define>
  </ui:composition>
</html
>
1

Facelets is a templating language for JSF, here we are wrapping our page in a template which defines the header.

2

There are a number of messages which can be sent to the user, "Higher!", "Lower!" and "Correct!"

3

As the user guesses, the range of numbers they can guess gets smaller - this sentance changes to make sure they know what range to guess in.

4

This input field is bound to a Web Bean, using the value expression.

5

A range validator is used to make sure the user doesn't accidentally input a number outside of the range in which they can guess - if the validator wasn't here, the user might use up a guess on an out of range number.

6

And, of course, there must be a way for the user to send their guess to the server. Here we bind to an action method on the Web Bean.

예제에는 4 개의 클래스가 존재합니다, 첫 번째 두 개는 바인딩 유형입니다. 먼저, 임의의 숫자를 삽입하기 위해 사용되는 @Random 바인딩 유형이 있습니다:

@Target( { TYPE, METHOD, PARAMETER, FIELD })

@Retention(RUNTIME)
@Documented
@BindingType
public @interface Random {}

삽입될 수 있는 최대 번호 삽입하기 위해 사용되는 @MaxNumber 바인딩 유형도 있습니다:

@Target( { TYPE, METHOD, PARAMETER, FIELD })

@Retention(RUNTIME)
@Documented
@BindingType
public @interface MaxNumber {}

Generator 클래스는 생산자 방식을 통해 임의의 숫자를 생성해야 할 책임이 있습니다. 또한 이는 생산자 방식을 통하여 가능한 최대 숫자를 나타냅니다:

@ApplicationScoped

public class Generator {
   
   private java.util.Random random = new java.util.Random( System.currentTimeMillis() );
   
   private int maxNumber = 100;
   
   java.util.Random getRandom()
   {
      return random;
   }
   
   @Produces @Random int next() { 
      return getRandom().nextInt(maxNumber); 
   }
   
   @Produces @MaxNumber int getMaxNumber()
   {
      return maxNumber;
   }
}

Generator는 애플리케이션 범위로 되어 있음을 발견하실 것입니다; 따라서 매번 다른 임의 숫자를 갖지 않게 됩니다.

애플리케이션에 있는 마지막 Web Bean은 Game 범위 세션입니다.

@Named 어노테이션이 사용되므로 JSF 페이지에서 EL을 통해 bean을 사용할 수 있음을 인지하실 것입니다. 마지막으로 생성자 삽입을 사용하여 임의의 숫자로 게임을 초기화합니다. 물론, 게임 플레이어에게 언제 게임에어 이겼는지를 알려주어야 하므로, FacesMessage로 피드백을 제공합니다.

package org.jboss.webbeans.examples.numberguess;



import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.webbeans.AnnotationLiteral;
import javax.webbeans.Current;
import javax.webbeans.Initializer;
import javax.webbeans.Named;
import javax.webbeans.SessionScoped;
import javax.webbeans.manager.Manager;
@Named
@SessionScoped
public class Game
{
   private int number;
   
   private int guess;
   private int smallest;
   private int biggest;
   private int remainingGuesses;
   
   @Current Manager manager;
   
   public Game()
   {
   }
   
   @Initializer
   Game(@MaxNumber int maxNumber)
   {      
      this.biggest = maxNumber;
   }
   public int getNumber()
   {
      return number;
   }
   
   public int getGuess()
   {
      return guess;
   }
   
   public void setGuess(int guess)
   {
      this.guess = guess;
   }
   
   public int getSmallest()
   {
      return smallest;
   }
   
   public int getBiggest()
   {
      return biggest;
   }
   
   public int getRemainingGuesses()
   {
      return remainingGuesses;
   }
   
   public String check()
   {
      if (guess
>number)
      {
         biggest = guess - 1;
      }
      if (guess<number)
      {
         smallest = guess + 1;
      }
      if (guess == number)
      {
         FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
      }
      remainingGuesses--;
      return null;
   }
   
   @PostConstruct
   public void reset()
   {
      this.smallest = 0;
      this.guess = 0;
      this.remainingGuesses = 10;
      this.number = manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random
>(){});
   }
   
}

번역 예제는 입력하신 아무 문장을 가져가 이를 라틴어로 번역합니다.

번역 예제는 ear로 작성되며, EJB가 들어있게 됩니다. 따라서, 문장 구조가 numberguess 예보다 훨씬 복잡합니다.

먼저, webbeans-translator-ear 모듈에 있는 ear aggregator를 살펴봅시다. Maven은 자동으로 application.xml을 생성합니다:


<plugin>
   <groupId
>org.apache.maven.plugins</groupId>
   <artifactId
>maven-ear-plugin</artifactId>
   <configuration>
      <modules>
         <webModule>
            <groupId
>org.jboss.webbeans.examples.translator</groupId>
            <artifactId
>webbeans-translator-war</artifactId>
            <contextRoot
>/webbeans-translator</contextRoot>
         </webModule>
      </modules>
   </configuration>
</plugin
>

url (http://localhost:8080/webbeans-translator)을 제공하는 컨텍스트 경로를 설정합니다.

작은 정보

Maven을 사용하여 이러한 파일을 생성할 경우, META-INF/application.xml이 필요합니다:


<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_5.xsd"
             version="5">
  <display-name
>webbeans-translator-ear</display-name>
  <description
>Ear Example for the reference implementation of JSR 299: Web Beans</description>
  
  <module>
    <web>
      <web-uri
>webbeans-translator.war</web-uri>
      <context-root
>/webbeans-translator</context-root>
    </web>
  </module>
  <module>
    <ejb
>webbeans-translator.jar</ejb>
  </module>
</application
>

Next, lets look at the war. Just as in the numberguess example, we have a faces-config.xml (to enable Facelets) and a web.xml (to enable JSF) in WebContent/WEB-INF.

텍스트를 번역하데 facelet이 사용됩니다. numberguess 예제에서와 같이 양식으로된 템플릿이 있습니다 (간결하게 하기 위해 여기서는 생략됨):


<h:form id="NumberGuessMain">
            
   <table>
      <tr align="center" style="font-weight: bold" >
         <td>
            Your text
         </td>
         <td>
            Translation
         </td>
      </tr>
      <tr>
         <td>
            <h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80" />
         </td>
         <td>
            <h:outputText value="#{translator.translatedText}" />
         </td>
      </tr>
   </table>
   <div>
      <h:commandButton id="button" value="Translate" action="#{translator.translate}"/>
   </div>
   
</h:form
>

사용자는 왼쪽 텍스트 부분에 텍스트를 입력할 수 있으며, 번역하기 버튼을 누르면 오른쪽에 번역 결과가 나타나게 됩니다.

마지막으로, ejb 모듈인 webbeans-translator-ejb를 살펴봅시다. src/main/resources/META-INF에는 Web Beans가 들어 있는 것으로 아카이브를 표시하기 위해 사용되는 빈 web-beans.xml이 있습니다.

가장 흥미로운 코드 부분은 마지막을 위해 남겨두겠습니다! 프로젝트에는 두 개의 심플 beans인 SentenceParserTextTranslator와 두 개의 엔터프라이즈 beans인 TranslatorControllerBeanSentenceTranslator가 있습니다. 이제 Web Bean에 관해 보다 많이 알고 계실 것이므로, 가장 중요한 부분만 여기서 다루겠습니다.

SentenceParserTextTranslator는 beans에 의존하며, TextTranslator는 생성자 초기화를 사용합니다:

public class TextTranslator { 

   private SentenceParser sentenceParser; 
   private Translator sentenceTranslator; 
   
   @Initializer
   TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) 
   { 
      this.sentenceParser = sentenceParser; 
      this.sentenceTranslator = sentenceTranslator;

TextTranslator는 무상태 세션빈으로 (로컬 비지니스 인터페이스와 함께), 완전한 번역기를 개발할 수는 없지만, 잘 작동하고 있습니다!

마지막으로, UI 기반 제어기가 있어, 이는 사용자로 부터 텍스트를 수집하여 번역기에 이를 보냅니다. 이는 요청 범위, 이름, 상태 유지 세션빈으로 번역기에 삽입되어 있습니다.

@Stateful

@RequestScoped
@Named("translator")
public class TranslatorControllerBean implements TranslatorController
{
   
   @Current TextTranslator translator;

bean은 페이지에 있는 모든 영역에 대해 getter 및 setter를 갖습니다.

이는 상태 유지 세션 빈이므로, 제거 방식을 갖고 있어야 합니다:

   @Remove

   public void remove()
   {
      
   }

Web Beans 관리자는 bean이 삭제될 때 제거 방식을 호출하게 됩니다; 이러한 경우 요청 마지막에 호출하게 됩니다.

That concludes our short tour of the Web Beans examples. For more on Web Beans , or to help out, please visit http://www.seamframework.org/WebBeans/Development.

버그 수정, 새로운 기능 작성, 예세 작성, 참조 가이드 번역과 같이 모든 영역에서 도움이 필요합니다.

Web Beans는 의존성 삽입에 대한 세 가지 주요 메카니즘을 지원합니다:

생성자 매개 변수 삽입:

public class Checkout {

        
    private final ShoppingCart cart;
    
    @Initializer
    public Checkout(ShoppingCart cart) {
        this.cart = cart;
    }
}

초기화 방식 매개 변수 삽입:

public class Checkout {

        
    private ShoppingCart cart;
    @Initializer 
    void setShoppingCart(ShoppingCart cart) {
        this.cart = cart;
    }
    
}

직접적 영역 삽입:

public class Checkout {


    private @Current ShoppingCart cart;
    
}

Web Bean 인스턴스가 먼저 인스턴스화되었을 경우 의존성 삽입이 발생합니다.

  • 먼저, Web Bean 관리자는 Web Bean 생성자를 호출하여 Web Bean 인스턴스를 획득합니다.

  • 다음으로, Web Bean 관리자는 Web Bean의 삽입된 모든 영역의 값을 초기화합니다.

  • 그 후, Web Bean 관리자는 Web Bean의 모든 초기화 방식을 호출합니다.

  • 마지막으로 Web Bean의 @PostConstruct 방식이 호출됩니다.

EJB가 Web Bean 관리자가 아닌 EJB 컨테이너에 의해 인스턴스화된 이래 생성자 매개변수 삽입은 EJB beans을 지원하지 않습니다.

기본값 바인딩 유형 @Current가 적용되었을 경우 생성자의 매개 변수 및 초기화 방식에서는 명시적으로 어노테이션할 필요가 없습니다. 하지만 삽입된 영역에는 반드시 바인딩 유형을 지정해야 하며, 언제 기본값 바인딩 유형을 적용할 지도 지정해야 합니다. 영역에 바인딩 유형이 지정되어 있지 않을 경우, 이는 삽입되지 않게 됩니다.

생산자 방식은 매개 변수 삽입을 지원합니다:

@Produces Checkout createCheckout(ShoppingCart cart) {

    return new Checkout(cart);
}

마지막으로 옵저버 방식 (9장. 이벤트 에서 살펴보게됨), 폐지 방식 및 소멸자 방식 모두는 매개 변수 삽입을 지원합니다.

Web Beans 사양은 타입 안정적 해상도 알고리즘이라는 절차를 정의하여, Web Bean 관리자가 삽입 지점에 삽입하기 위해 Web Bean을 인식할 때 이를 따르게 됩니다. 이러한 알고르짐은 처음에는 복잡하게 보이지만, 일단 이를 이해하면, 이는 다소 직관적입니다. 타입 안정적 해상도는 시스템 초기화시에 실행되어, 관리자는 사용자에 과한 정보를 즉각적으로 알게되며 Web Bean의 의존성에 만족하지 않을 경우, UnsatisfiedDependencyException 또는 AmbiguousDependencyException을 넘기게 됩니다.

이러한 알고리즘은 여러 Web Beans를 허용하여 동일한 API 유형을 구현하기 위한 것입니다:

  • 또는 클라이언트가 바인딩 어노테이션을 사용하여 필요한 구현 사항을 선택하게 합니다,

  • 애플리케이션 개발자가 클라이언트로 변경하지 않고 배치 유형을 활성화 또는 비활성화하여 특정 시스템에 어떤 구헌이 적합할 지를 선택하게 합니다.

  • 하나의 API 구현이 클라이언트에 변경하지 않고 배치 유형 우선 순위를 사용하여 배치시 다른 동일한 API 구현을 덮어쓰기하게 합니다.

Web Beans 관리자가 어떻게 Web Bean을 삽입할 지를 결정하는 방법에 대해 살펴봅시다.

특정 API 유형을 구현하는 하나 이상의 Web Bean이 있을 경우, 삽입 지점은 바인딩 어노테이션을 사용하여 어떤 Web Bean이 삽입되어야 할 지를 지정할 수 있습니다. 예를 들어, PaymentProcessor의 두 가지 구현이 있을 수 있습니다:

@PayByCheque

public class ChequePaymentProcessor implements PaymentProcessor {
    public void process(Payment payment) { ... }
}
@PayByCreditCard

public class CreditCardPaymentProcessor implements PaymentProcessor {
    public void process(Payment payment) { ... }
}

여기서 @PayByCheque@PayByCreditCard는 바인딩 어노테이션입니다:

@Retention(RUNTIME)

@Target({TYPE, METHOD, FIELD, PARAMETER})
@BindingType
public @interface PayByCheque {}
@Retention(RUNTIME)

@Target({TYPE, METHOD, FIELD, PARAMETER})
@BindingType
public @interface PayByCreditCard {}

클라이언트 Web Bean 개발자는 바인딩 어노테이션을 사용하여 정확히 어떤 Web Bean이 삽입되어야 하는 지를 지정합니다.

영역 삽입 사용:

@PayByCheque PaymentProcessor chequePaymentProcessor;

@PayByCreditCard PaymentProcessor creditCardPaymentProcessor;

초기화 방식 삽입 사용:

@Initializer

public void setPaymentProcessors(@PayByCheque PaymentProcessor chequePaymentProcessor, 
                                 @PayByCreditCard PaymentProcessor creditCardPaymentProcessor) {
   this.chequePaymentProcessor = chequePaymentProcessor;
   this.creditCardPaymentProcessor = creditCardPaymentProcessor;
}

생성자 삽입 사용:

@Initializer

public Checkout(@PayByCheque PaymentProcessor chequePaymentProcessor, 
                @PayByCreditCard PaymentProcessor creditCardPaymentProcessor) {
   this.chequePaymentProcessor = chequePaymentProcessor;
   this.creditCardPaymentProcessor = creditCardPaymentProcessor;
}

모든 Web Beans는 배치 유형을 갖습니다. 각각의 배치 유형은 시스템의 일부 배치에 조건부로 설치되어야 하는 Web Beans 모음을 인식합니다.

예를 들어, @Mock라는 배치 유형을 정의할 수 있으며, 이는 시스템이 통합적인 테스트 환경 내에서 실행될 때 설치되어야 하는 Web Beans를 인식합니다:

@Retention(RUNTIME)

  @Target({TYPE, METHOD})
  @DeploymentType
  public @interface Mock {}

지불 절차를 처리하기 위한 외부적 시스템과 상호 작용하는 일부 Web Bean이 있다고 가정합시다:

public class ExternalPaymentProcessor {

        
    public void process(Payment p) {
        ...
    }
    
}

이러한 Web Bean이 배치 유형을 명시적을 지정하지 않고 있으므로, 이는 기본값 배치 유형 @Production을 갖게 됩니다.

통합 또는 단위 테스트를 위해 외부적 시스템은 속도가 느리거나 또는 사용 불가능합니다. 따라서 모의 객체를 생성할 수 있습니다:

@Mock 

public class MockPaymentProcessor implements PaymentProcessor {
    @Override
    public void process(Payment p) {
        p.setSuccessful(true);
    }
}

하지만 Web Bean 관리자가 특정 배치에 어떤 구현을 사용할 지를 어떻게 결정할까요?

관심을 기울이셨다면, Web Bean 관리자가 어떤 구현 — ExternalPaymentProcessor 또는 MockPaymentProcessor — 을 선택할 지를 어떻게 결정하는지에 대해 궁금해 하셨을 것입니다. 관리자기 이러한 삽입 지점에 이르렀을 때 무엇이 발생할 지를 고려합니다:

@Current PaymentProcessor paymentProcessor

PaymentProcessor 계약을 만족하는 두 개의 Web Beans가 있습니다. 삽입 지점에서 바인딩 어노테이션은 소스로 하드-코드화되어 있으므로, 명확하게 하기 위해 바인딩 어노테이션을 사용할 수 없으며, 관리자가 배치시 결정할 수 있게 하기를 원합니다!

이러한 문제의 해결책은 각각의 배치 유형이 다른 우선 순위를 갖게 하는 것입니다. 배치 유형의 우선 순위는 web-beans.xml에 나타나는 순서에 의해 결정됩니다. 예에서 @Mock@Production 보다 나중에 나타나므로 보다 높은 우선 순위를 갖습니다.

하나 이상의 Web Bean이 삽입 지점에 의해 지정된 계약 (API 유형 및 바인딩 어노테이션)에 만족할 수 있음을 관리자가 발견할 때 마다, 이는 Web Beans의 관련된 우선 순위를 고려합니다. 하나의 Web Bean이 다른 것 보다 높은 우선 순위를 갖을 경우, 삽입될 보다 높은 우선 순위의 Web Bean을 선택합니다. 예에서, 통합 테스트 환경 (실제적으로 원하는 환경)에서 실행할 때 Web Bean 관리자는 MockPaymentProcessor를 삽입하게 됩니다.

이러한 기능을 오늘날의 관리자 구조와 비교하는 것은 흥미로운 일입니다. 다양한 "경량"의 컨테이너는 classpath에 있는 클래스의 조건부 배치를 허용하지만, 배치될 클래스는 명시적, 개별적이어하며, 설정 코드나 일부 XML 설정 파일에 나열되어 있어야 합니다. Web Beans는 XML을 통한 Web Bean 정의 및 설정을 지원하지만 복잡한 설정을 필요로 하지 않는 대부분의 경우, 배치 유형은 전체 Web Beans 설정이 단일 XML 행으로 활성화되게 합니다. 동시에, 코드를 검색하는 개발자는 어떤 배치 시나리오를 Web Bean이 사용할 지를 쉽게 인식할 수 있습니다.

삽입된 Web Bean 클라이언트는 Web Bean 인스턴스에 직접적인 참조를 유지하지 않습니다.

요청 범위로 바운딩된 Web Bean으로의 직접 참조를 보유하고 있는 애플리케이션 범위에 바운딩된 Web Bean을 가정해 봅시다. 애플리케이션 범위에 바운딩된 Web Bean은 다른 많은 요청 사이에서 공유됩니다. 하지만, 각각의 요청은 요청 범위로 바운딩된 Web Bean의 다른 인스턴스를 확인해야 합니다!

이제 애플리케이션 범위로 바운딩된 Web Bean으로의 직접 참조를 보유하고 있는 세션 범위에 바운딩된 Web Bean을 가정해 봅시다. 때때로 세션 컨텍스트는 메모리를 보다 효과적으로 사용하기 위해 디스크 순서대로 나열됩니다. 하지만, 애플리케이션 범위로 바운딩된 Web Bean 인스턴스는 세션 범위로 바운딩된 Web Bean과 함께 나열되어서는 안됩니다!

따라서, Web Bean은 기본값 범위 @Dependent를 갖지 않는 한, Web Bean 관리자는 프록시 객체를 통해 삽입된 모든 참조를 Web Bean으로 돌려 놓아야 합니다. 이러한 클라이언트 프록시는 방식 호출을 받는 Web Bean 인스턴스가 현재 컨텍스트와 관련된 인스턴스임을 확인해야 할 책임이 있습니다. 또한 클라이언트 프록시는 Web Beans가 삽입된 다른 Web Beans를 귀납적으로 나열하지 않고 디스크 순서대로 나열한 세션 컨텍스트와 같은 컨텍스트로 바운딩되게 합니다.

Java 언어의 한계로 인해, 일부 Java 유형은 Web Bean 관리자에 의해 프록시될 수 없습니다. 따라서, 삽입 지점 유형이 프록시될 수 없을 경우 Web Bean 관리자는 UnproxyableDependencyException을 던지게 됩니다.

다음과 같은 Java 유형은 Web Bean 관리자에 의해 프록시될 수 없습니다:

UnproxyableDependencyException을 수정하기 쉽습니다. 간단하게 삽입된 클래스에 매개 변수가 없는 생성자를 추가하고, 인터페이스를 소개하거나, 삽입된 Web Bean의 범위를 @Dependent로 변경합니다.

애플리케이션은 삽입에 의해 Manager 인터페이스의 인스턴스를 획득할 수 있습니다:

@Current Manager manager;

Manager 객체는 프로그램적으로 Web Bean 인스턴스의 획득을 위한 방식 모음을 제공합니다.

PaymentProcessor p = manager.getInstanceByType(PaymentProcessor.class);

바인딩 어노테이션은 AnnotationLiteral 도우미 클래스를 하부클래스화하여 지정될 수 있으며, 그렇지 않으면 Java에서 어노테이션 유형을 인스턴스화하기 어렵습니다.

PaymentProcessor p = manager.getInstanceByType(PaymentProcessor.class, 

                                               new AnnotationLiteral<CreditCard
>(){});

바인딩 유형이 어노테이션 멤버를 갖을 경우, AnnotationLiteral의 임의의 하부클래스를 사용할 수 없습니다 — 대신 named 하부 클래스를 생성해야 합니다:

abstract class CreditCardBinding 

    extends AnnotationLiteral<CreditCard
> 
    implements CreditCard {}
PaymentProcessor p = manager.getInstanceByType(PaymentProcessor.class, 

                                               new CreditCardBinding() { 
                                                   public void value() { return paymentType; } 
                                               } );

특정 종류의 의존성 객체가 있습니다 — @Dependent 범위와 함께 Web Beans — 객체 또는 이는 실행 가능하게 되기 위해 삽입되는 삽입 지점에 관해 알아야 합니다. 예:

@Dependent 범위와 함께 Web Bean은 InjectionPoint 인스턴스를 삽입하고 해당 삽입 지점에 관련된 메타데이트를 액세스합니다.

다음 예를 살펴봅시다. 다음과 같은 코드는 프로그램을 리팩토링하기에 취약하고 장황합니다:

Logger log = Logger.getLogger(MyClass.class.getName());

이와 같이 현명한 생산자 방식은 로그 범주를 명시적으로 지정하지 않고 JDK Logger를 삽입하게 합니다:

class LogFactory {


   @Produces Logger createLogger(InjectionPoint injectionPoint) { 
      return Logger.getLogger(injectionPoint.getMember().getDeclaringClass().getName()); 
   }
}

이제 다음을 작성할 수 있습니다:

@Current Logger log;

확신하시지 않습니까? 그러시다면 여기에 두 번째 예제가 있습니다. HTTP 매개 변수를 삽입하려면, 바인딩 유형을 정의해야 합니다:

@BindingType

@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface HttpParam {
   @NonBinding public String value();
}

다음과 같이 삽입 지점에서 이러한 바인딩 유형을 사용할 수 있습니다:

@HttpParam("username") String username;

@HttpParam("password") String password;

다음의 생산자 방식은 다음과 같이 작업합니다:

class HttpParams


   @Produces @HttpParam("")
   String getParamValue(ServletRequest request, InjectionPoint ip) {
      return request.getParameter(ip.getAnnotation(HttpParam.class).value());
   }
}

HttpParam 어노테이션의 value() 멤버는@NonBinding.을 어노테이션하므로 Web Bean 관리자에 의해 무시됨에 유의하시기 바랍니다.

Web Bean 관리자는 InjectionPoint 인터페이스를 구현하는 내장된 Web Bean을 제공합니다:

public interface InjectionPoint { 

   public Object getInstance(); 
   public Bean<?> getBean(); 
   public Member getMember(): 
   public <extends Annotation
> T getAnnotation(Class<T
> annotation); 
   public Set<extends Annotation
> getAnnotations(); 
}

지금까지 범위 유형 어노테이션의 여러 가지 예를 살펴보았습니다. Web Bean의 범위는 Web Bean 인스턴스의 수명주기를 결정합니다. 또한 범위는 어떤 클라이언트가 어떤 Web Bean 인스턴스를 참조하게 할 지를 결정합니다. Web Beans 사양에 따라 범위는 다음을 결정합니다:

  • 범위와 함께 Web Bean의 새로운 인스턴스가 생성될 시기

  • 범위와 함께 Web Bean의 기존 인스턴스가 제거될 시기

  • 삽입된 어떤 참조가 범위와 함께 Web Bean 인스턴스를 참조하는 지

예를 들어, Web Bean 세션 범위가 있을 경우, CurrentUser, 동일한 HttpSession 컨텍스트에서 호출되는 모든 Web Beans는 동일한 CurrentUser 인스턴스를 확인하게 됩니다. 이러한 인스턴스는 세션에서 CurrentUser가 처음으로 필요할 때 자동으로 생성되고 세션이 끝나면 자동으로 삭제됩니다.

Web Beans 컨버세이션 범위는 시스템 사용자와 관련된 상태를 보유하고 있는 전통 세션 범위와 유사하며, 서버에 여러 가지 요청을 보냅니다. 하지만, 세션 범위와 다르게 컨버세이션 범위는 다음과 같은 사항을 갖습니다:

컨버세이션은 사용자 관점에서의 작업 단위, 작업 내용을 나타냅니다. 컨버세이션 컨텍스트는 현재 사용자가 작업하고 있는 것과 관련된 상태를 유지합니다. 사용자가 동시에 여러가지 작업을 실행하고 있을 경우, 여러 개의 컨버세이션이 있게 됩니다.

컨버세이션 컨텍스트는 JSF 요청 시 활성화되어 있습니다. 하지만 대부분의 컨버세이션은 요청 마지막에 삭제됩니다. 컨버세이션이 여러 가지 요청을 통해 상태를 유지해야 할 경우, 장기 실행 컨버세이션으로 요청되어야 합니다.

Web Beans는 JSF 애플리케이션에 있는 컨버세이션 수명 주기를 제어하기 위한 내장된 Web Bean을 제공합니다. 이러한 Web Bean은 삽입에 의해 획득될 수 있습니다:

@Current Conversation conversation;

장기 실행 컨버세이션으로의 최근 요청과 관련된 컨버세이션을 활성화하려면, 애플리케이션 코드에서 begin() 방식을 호출합니다. 현재 요청의 마지막에 삭제를 위해 장기 실행 컨버세이션 컨텍스트를 스케줄하려면 end()를 호출합니다.

다음의 예에서, 컨버세이션 범위 Web Bean은 관련 된 컨버세이션을 제어합니다:

@ConversationScoped @Stateful

public class OrderBuilder {
    private Order order;
    private @Current Conversation conversation;
    private @PersistenceContext(type=EXTENDED) EntityManager em;
    
    @Produces public Order getOrder() {
        return order;
    }
    public Order createOrder() {
        order = new Order();
        conversation.begin();
        return order;
    }
    
    public void addLineItem(Product product, int quantity) {
        order.add( new LineItem(product, quantity) );
    }
    public void saveOrder(Order order) {
        em.persist(order);
        conversation.end();
    }
    
    @Remove
    public void destroy() {}
    
}

Web Bean은 Conversation API를 사용하여 수명 주기를 제어할 수 있습니다. 하지만 일부 다른 Web Beans는 다른 객체에 완전히 의존하는 수명 주기를 갖습니다.

네 가지 내장된 범위에 더하여, Web Beans는 dependent pseudo-scope라는 기능을 특징으로 합니다. 이는 범위 유형을 명시하지 않는 Web Bean에 대한 기본값 범위입니다.

예를 들어, Web Bean에는 @Dependent 범위 유형이 있습니다:

public class Calculator { ... }

Web Bean의 삽입 지점이 의존적 Web Bean을 해결할 때, 의존적 Web Bean의 새로운 인스턴스는 처음으로 Web Bean이 초기화될 때 마다 생성됩니다. 의존적 Web Beans의 인스턴스는 다른 Web Bean 사이에서나 또는 다른 삽입 지점 간에 공유되지 않습니다. 이는 일부 다른 Web Bean 인스턴스에 대해 의존적 객체입니다.

의존하는 인스턴스가 삭제되면 의존적 Web Bean 인스턴스가 삭제됩니다.

클래스 또는 EJB bean이 일부 다른 범위 유형과 함께 Web Bean으로 명시되어 있어도, Web Beans는 Java 클래스 또는 EJB bean의 의존적 인스턴스를 쉽게 획득할 수 있게 합니다.

생산자 방식은 Web Bean 관리자가 애플리케이션 대신 인스턴스 객체에 응답할 때 발생할 수 있는 특정한 한계를 극복할 수 있게 합니다. Web Beans이 아닌 객체를 Web Beans 환경으로 통합하기 위한 가장 쉬운 방법이 있습니다. (12장. XML을 사용하여 Web Beans 정의 에서 두번째 방법에 대해 살펴보겠습니다.)

spec에 의하면:

A Web Beans producer method acts as a source of objects to be injected, where:

  • the objects to be injected are not required to be instances of Web Beans,

  • the concrete type of the objects to be injected may vary at runtime or

  • the objects require some custom initialization that is not performed by the Web Bean constructor

For example, producer methods let us:

  • expose a JPA entity as a Web Bean,

  • expose any JDK class as a Web Bean,

  • define multiple Web Beans, with different scopes or initialization, for the same implementation class, or

  • vary the implementation of an API type at runtime.

In particular, producer methods let us use runtime polymorphism with Web Beans. As we've seen, deployment types are a powerful solution to the problem of deployment-time polymorphism. But once the system is deployed, the Web Bean implementation is fixed. A producer method has no such limitation:

@SessionScoped

public class Preferences {
    
    private PaymentStrategyType paymentStrategy;
    
    ...
    
    @Produces @Preferred 
    public PaymentStrategy getPaymentStrategy() {
        switch (paymentStrategy) {
            case CREDIT_CARD: return new CreditCardPaymentStrategy();
            case CHEQUE: return new ChequePaymentStrategy();
            case PAYPAL: return new PayPalPaymentStrategy();
            default: return null;
        } 
    }
    
}

Consider an injection point:

@Preferred PaymentStrategy paymentStrat;

This injection point has the same type and binding annotations as the producer method, so it resolves to the producer method using the usual Web Beans injection rules. The producer method will be called by the Web Bean manager to obtain an instance to service this injection point.

.

위의 코드에 한 가지 문제가 있을 수 있습니다. CreditCardPaymentStrategy 구현은 Java new 연산자를 사용하여 인스턴스화됩니다. 애플리케이션에 의해 직접 인스턴스화된 객체는 의존성 삽입의 장점을 취할 수 없으며 인터셉터를 갖지 못합니다.

이러한 방식을 원하지 않을 경우, 의존성 삽입을 생산자 방식으로 사용하여 Web Bean 인스턴스를 획득할 수 있습니다:

@Produces @Preferred @SessionScoped

public PaymentStrategy getPaymentStrategy(CreditCardPaymentStrategy ccps,
                                          ChequePaymentStrategy cps,
                                          PayPalPaymentStrategy ppps) {
    switch (paymentStrategy) {
        case CREDIT_CARD: return ccps;
        case CHEQUE: return cps;
        case PAYPAL: return ppps;
        default: return null;
    } 
}

CreditCardPaymentStrategy가 요청 범위 Web Bean이면 어떻게 합니까? 이럴 경우 생산자 방식은 현재 요청 범위 임스턴스를 세선 범위로 "활성화되게" 됩니다. 이는 버그입니다! 요청 범위 객체는 세션이 종료되기 전 Web Bean 관리자에 의해 삭제되지만, 객체에 대한 참조는 세션 범위에 "남아 있게" 됩니다. 이러한 오류는 Web Bean 관리자에 의해 검출되지 않으므로 생산자 방식에 Web Bean 인스턴스를 반환할 경우 각별히 주의하시기 바랍니다!

이러한 버그를 해결할 수 있는 세 가지 방법이 있습니다. CreditCardPaymentStrategy 구현 범위를 변경할 수 있지만, Web Bean의 클라이언트에 영향을 미칠 수 있습니다. 보다 나은 방법으로 생산자 방식의 범위를 @Dependent 또는 @RequestScoped로 변경하는 것입니다.

하지만 보다 일반적인 방법은 특별한 @New 바인딩 어노테이션을 사용하는 것입니다.

Web Beans의 첫번째 주요 기능은 느슨한 연결 (loose coupling)입니다. 이러한 느슨한 연결 기능을 실행하기 위한 세가지 방식은 이미 알려져 있습니다:

이러한 기술로 클라이언트 및 서버의 느슨한 연결을 활성화할 수 있습니다. 클라이언트는 더이상 API 구현으로 바운딩할 수 없으며, 서버 객체의 수명주기를 관리할 수 없습니다. 이러한 접근으로 상태 유지 객체가 서비스하는 것 처럼 상호 작용하게 합니다.

느슨한 연결로 시스템이 보다 동적으로 되게 할 수 있습니다. 시스템은 잘 정의된 방식에서의 변경 사항에 대응할 수 있습니다. 위에 나열된 기능을 변함없이 제공하기 위한 이전의 프레임워크는 타입 안정성을 희생하여 이를 실행하였습니다. Web Beans는 타입 안정적 방식에서의 느슨한 연결을 실행하기 위한 첫번째 기술입니다.

Web Beans는 느슨한 연결 기능을 촉진하기 위해 세 가지 중요한 기능을 추가로 제공합니다:

먼저 인터셉터에 대해 살펴봅시다.

Web Beans는 EJB 3.0의 기본 인터셉터 구조를 재사용하여, 두 가지 방향으로 기능을 확장합니다:

  • Web Bean에는 세션 beans 만이 아니라 인터셉터도 있을 수 있습니다.

  • Web Beans는 Web Beans에 인터셉터를 바인딩하기 위해 보다 복잡한 어노테이션 기반 방식을 특징으로 합니다.

EJB 사양은 두 종류의 인터셉션 지점을 정의합니다:

  • 비지니스 방식 인터셉터

  • 수명주기 콜백 인터셉터

비지니스 방식 인터셉터는 Web Bean 클라이언트에 의해 Web Bean 방식 호출에 적용됩니다:

public class TransactionInterceptor {

    @AroundInvoke public Object manageTransaction(InvocationContext ctx) { ... }
}

수명 주기 콜백 인터셉터는 컨테이너에 의해 수명 주기 콜백 호출에 적용됩니다:

public class DependencyInjectionInterceptor {

    @PostConstruct public void injectDependencies(InvocationContext ctx) { ... }
}

인터셉터 클래스는 수명 주기 콜백 및 비지니스 방식 모두를 차단할 수 있습니다.

인터셉터는 유형 시스템에 직교 되어 있는 문제를 분리하고 캡쳐하는 강력한 방법입니다. 인터셉터는 모든 Java 유형 호출을 차단할 수 있습니다. 이는 트랜젝션 관리 및 보안과 같은 기술적 문제를 해결하는데 유용합니다. 하지만, 본래 인터셉터는 차단한 이벤트의 실제적 시멘틱을 인식하지 않습니다. 따라서, 인터셉터는 비지니스 관련 문제를 분리하기 위한 도구로는 적합하지 않습니다.

역으로 기능하는 것이 데코레이터입니다. 데코레이터는 특정 Java 인터페이스에 대해서만 호출을 차단하며, 인터페이스에 부착된 모든 시멘틱을 인식합니다. 이는 일부 비지니스 문제를 모델화하기 위해 데코레이터를 완벽한 도구로 만듭니다. 또한 데코레이터는 인터셉터의 일반적 기능을 갖지 않습니다. 데코레이터는 여러 이질적 유형을 초월하는 기술적 문제를 해결할 수 없습니다.

어카운트를 나타내는 인터페이스가 있다고 가정합니다:

public interface Account {

    public BigDecimal getBalance();
    public User getOwner();
    public void withdraw(BigDecimal amount);
    public void deposit(BigDecimal amount);
}

시스템에서 여러 다른 Web Beans는 Account 인터페이스를 구현합니다. 하지만, 일반적인 법적 요구조건이 있으며, 모든 종류의 어카운트의 경우, 대용량 트랜젝션은 특정 로그로 시스템에 의해 기록되어야 합니다. 이는 데코레이터의 뛰어난 작업 기능입니다.

데코레이터는 심플 Web Bean으로 유형을 구현하고 @Decorator를 어노테이션합니다.

@Decorator

public abstract class LargeTransactionDecorator 
        implements Account {
    
    @Decorates Account account;
    
    @PersistenceContext EntityManager em;
    
    public void withdraw(BigDecimal amount) {
        account.withdraw(amount);
        if ( amount.compareTo(LARGE_AMOUNT)
>0 ) {
            em.persist( new LoggedWithdrawl(amount) );
        }
    }
    
    public void deposit(BigDecimal amount);
        account.deposit(amount);
        if ( amount.compareTo(LARGE_AMOUNT)
>0 ) {
            em.persist( new LoggedDeposit(amount) );
        }
    }
    
}

기타 다른 심플 Web Beans와 다르게, 데코레이터는 추상클래스일 수 도 있습니다. 데코레이터된 인터페이스의 특정 방식에 대해 데코레이터가 특별히 해야할 것이 없을 경우, 이 방식을 구현하실 필요가 없습니다.

Web Beans 이벤트 통지 기능은 Web Beans가 완전 연결 해제 방식으로 상호 작용하게 합니다. 이벤트 생산자는 이벤트를 제기한 후 Web Bean 관리자에 의해 이벤트 옵저버로 전달합니다. 이러한 기본적인 스키마는 옵저버/옵저버 패턴과 유사하게 들이지만, 몇 가지 다른 부분이 있습니다:

  • 이벤트 생산자만 옵저버에서 연결 해제되는 것이 아니라; 옵저버도 생산자에서 완전하게 연결 해제됩니다.

  • 옵저버는 "선택자" 조합을 지정하여 이벤트 통지 모음의 범위를 좁힙니다.

  • 옵저버는 바로 통지하거나 또는 현재 트랜젝션이 끝날때 까지 이벤트 전송이 지연되도록 지정할 수 있습니다.

이벤트 생산자는 삽입을 통해 이벤트 통지 객체를 갖을 수 있습니다:

@Observable Event<Document

> documentEvent

@Observable 어노테이션은 @Dependent 범위 및 @Standard 배치 유형, Web Bean 관리자에 의해 제공되는 구현으로 Web Bean을 정의합니다.

생산자는 Event 인터페이스의 fire() 방식을 호출하여 이벤트를 제기하고, 이벤트 객체를 전달합니다:

documentEvent.fire(document);

이벤트 객체는 와일드카드 유형 매개변수나 또는 유형 변수가 없는 Java 클래스의 인스턴스가 될 수 도 있습니다. 이벤트는 다음과 같은 사항을 갖는 모든 옵저버 방식에 전달됩니다:

Web Bean 관리자는 모든 옵저버 방식을 호출하여, 이벤트 매개 변수 값으로 이벤트 객체를 전달합니다. 옵저버 방식이 예외 처리를 넘기게 될 경우, Web Bean 관리자는 옵저버 방식 호출을 중단하고 예외 처리는 fire() 방식에 의해 다시 넘기게 됩니다.

"선택자"를 지정하려면, 이벤트 생산자가 이벤트 바인딩 유형을 fire() 방식에 전달해야 합니다:

documentEvent.fire( document, new AnnotationLiteral<Updated

>(){} );

Java에서 실행하기 어려웠던 도우미 클래스 AnnotationLiteral은 바인딩 유형 인라인을 인스턴스화할 수 있게 합니다.

이벤트는 모든 옵저버 방식으로 전달됩니다:

다른 방법으로 이벤트 바인딩은 이벤트 통지 삽입 지점을 어노테이션하여 지정될 수 도 있습니다:

@Observable @Updated Event<Document

> documentUpdatedEvent

이러한 Event 인스턴스를 통해 해제된 모든 이벤트는 어노테이션된 이벤트 바인딩을 갖습니다. 이벤트는 모든 옵저버 방식에 전달됩니다:

트랜잭션 옵저버는 이벤크가 제기된 트랜잭션의 완료 단계 이전 또는 이후 동안 이벤트 통지를 받습니다. 예를 들어, 다음과 같은 옵저버 방식은 트랜잭션이 Category 크리를 성공적으로 업데이트했을 경우에만 애플리케이션 컨텍스트에서 캐시된 쿼리 결과 모음을 새로고침해야 합니다:

public void refreshCategoryTree(@AfterTransactionSuccess @Observes CategoryUpdateEvent event) { ... }

세 가지 종류의 트랜잭션 옵저버가 있습니다:

트랜잭션 옵저버는 Web Beans와 같은 상태 유지 객체 모델에서 아주 중요합니다. 이는 단일 원자성 트랜잭션보다 오래 지속되기 때문입니다.

애플리케이션 범위에 있는 JPA 쿼리 결과 모음을 캐시했다고 가정합니다:

@ApplicationScoped @Singleton

public class Catalog {
    @PersistenceContext EntityManager em;
    
    List<Product
> products;
    @Produces @Catalog 
    List<Product
> getCatalog() {
        if (products==null) {
            products = em.createQuery("select p from Product p where p.deleted = false")
                .getResultList();
        }
        return products;
    }
    
}

때때로 Product는 생성 또는 삭제됩니다. 이러한 상황이 발생하면, Product 카탈로그를 새로고침해야 합니다. 하지만, 이러한 새로 고침을 실행하기 전 트랜젝션이 성공적으로 완료할 때 까지 기다리셔야 합니다!

Product를 생성 및 삭제하는 Web Bean은 이벤트를 제기할 수 있습니다, 예:

@Stateless

public class ProductManager {
    @PersistenceContext EntityManager em;
    @Observable Event<Product
> productEvent;
    public void delete(Product product) {
        em.delete(product);
        productEvent.fire(product, new AnnotationLiteral<Deleted
>(){});
    }
    
    public void persist(Product product) {
        em.persist(product);
        productEvent.fire(product, new AnnotationLiteral<Created
>(){});
    }
    
    ...
    
}

Catalog는 트랜잭션을 성공적으로 완료한 후에 이벤트를 옵저버할 수 있습니다:

@ApplicationScoped @Singleton

public class Catalog {
    ...
    
    void addProduct(@AfterTransactionSuccess @Observes @Created Product product) {
        products.add(product);
    }
    
    void addProduct(@AfterTransactionSuccess @Observes @Deleted Product product) {
        products.remove(product);
    }
    
}

Web Beans의 두번째 주요 기능은 강한 타이핑 (strong typing)입니다. Web Bean의 의존성, 인터셉터, 데코레이터에 관한 정보 및 이벤트 생산자에 대한 이벤트 소비자에 관한 정보는 컴파일러에 의해 사용할 수 있는 타입 안정적 Java 구성 요소에 들어 있습니다.

Web Beans 코드에서 문자열 기반 식별자를 보실 수 없습니다. 그 이유는 프레임워크가 — "관례에 의한 설정"이라고 부르는 — 기본값 규칙을 사용하여 이를 숨기려하기 때문이 아니라 시작할 수 있는 문자열이 없기 때문입니다!

이러한 접근 방식의 장점은 어떤 IDE도 특정 도구 없이 자동 완성, 검증, 리팩토링을 제공할 수 있습니다. 이에는 다른 부수적인 장점도 있습니다. 이름 대신 어노테이션을 통해 객체, 이벤트, 인터셉터를 인식하고자 할 경우 이것이 나타나 코드의 시맨틱 레벨을 해제할 수 있습니다.

Web Beans는 개념을 모델로 하는 어노테이션을 개발하게 합니다. 예:

다음과 같은 복합적인 명칭을 사용하는 대신

어노테이션은 다시 사용할 수 있습니다. 이는 시스템의 연관 없는 부분의 일반적인 기능을 설명하는데 사용되며, 코드를 이해하고 범주화하는데 사용될 수 있습니다. 이는 일반적인 문제를 일반적인 방식으로 해결하는데 도움을 주며, 코드를 보다 더 이해하고 읽고 쓸 수 있게 합니다.

Web Beans의 전형적인 역할은 이러한 기능에 한 단계 더 나아갑니다. 전형적인 역할은 애플리케이션 구조에서의 일반적인 역할을 모델로 합니다. 이는 범위, 인터셉터 바인딩, 배치 유형 등과 같은 다양한 역할의 속성으로 다시 사용 가능한 단일 패키지로 캡슐화합니다.

심지어 Web Beans XML 메타데이터는 강하게 타이핑됩니다! XML 용 컴파일러가 없으므로 Web Beans는 XML 스키마의 장점을 취해 XML에 나타나는 Java 유형 및 속성을 유효하게 합니다. 어노테이션이 Java 코드를 읽고 쓸 수 있게 하는 것 처럼 이러한 접근은 XML을 보다 더 읽고 쓸 수 있게 합니다.

이제 Web Beans의 보다 고급 기능에 대해 알아볼 준비가 되었습니다. 이러한 기능은 코드를 보다 쉽게 유효화하고 이해 가능하게 하기 위해 존재하는 것임을 명심하시기 바랍니다. 대부분 이러한 기능을 사용할 필요가 없지만 이를 보다 효과적으로 사용할 경우, 이러한 기능에 감사하게 될 것입니다.

Web Beans 사양에 따라:

여러 시스템에서, 아키텍처 패턴을 사용하여 Web Bean 역할을 반복하는 모음을 생산합니다. 스테레오타입은 프레임워크 개발자가 이러한 역할을 인식하고 중앙 위치에서의 역할과 함께 Web Beans의 일반적인 메타데이터를 명시하게 합니다.

스테레오타입은 다음의 조합을 캡슐화합니다:

  • 기본값 배치 유형

  • 기본값 범위 유형

  • Web Bean 범위에서의 제한,

  • 특정 유형을 Web Bean이 구현하거나 확장하기 위한 요구 사항

  • 인터셉터 바인딩 어노테이션 모음

스테레오타입은 스테레오타입이 있는 모든 Web Beans이 Web Bean 이름을 기본값으로 하도록 지정할 수 도 있습니다.

Web Bean은 0 또는 하나 이상의 스테레오타입을 명시할 있습니다.

스테레오타입은 Java 어노테이션 유형입니다. 이러한 스테레오타입은 일부 MVC 프레임워크에서 작업 클래스를 인식합니다:

@Retention(RUNTIME)

@Target(TYPE)
@Stereotype
public @interface Action {}

Web Bean에 어노테이션을 적용하여 스테레오타입을 사용합니다.

@Action 

public class LoginAction { ... }

이미 Web Beans 의존성 삽입 모델은 배치시 API 구현을 덮어쓰기 하게 합니다. 예를 들어, 다음과 같은 엔터프라이즈 Web Bean은 제품에서 API PaymentProcessor 구현을 제공합니다:

@CreditCard @Stateless

public class CreditCardPaymentProcessor 
        implements PaymentProcessor {
    ...
}

staging 환경에서, 다른 Web Bean을 사용하여 PaymentProcessor 구현을 덮어쓰기 합니다:

@CreditCard @Stateless @Staging

public class StagingCreditCardPaymentProcessor 
        implements PaymentProcessor {
    ...
}

StagingCreditCardPaymentProcessor를 사용하여 실행하려는 작업은 특정 시스템 배치에 AsyncPaymentProcessor를 완전 교체하는 것입니다. 여기서 배치 유형 @Staging은 기본값 배치 유형 @Production 보다 높은 우선 순위를 갖게 되므로 클라이언트는 다음과 같은 삽입 지점을 사용하게 됩니다:

@CreditCard PaymentProcessor ccpp

StagingCreditCardPaymentProcessor 인스턴스를 받고자 합니다.

불행하게도 여기에는 몇 가지 함정이 있습니다:

  • 높은 우선 순위의 Web Bean은 덮어쓰기하려는 Web Bean의 모든 API 유형을 구현할 수 없습니다.

  • 높은 우선 순위의 Web Bean은 덮어쓰기하려는 Web Bean의 모든 바인딩 유형을 명시할 수 없습니다.

  • 높은 우선 순위의 Web Bean은 덮어 쓰기하려는 Web Bean과 동일한 이름을 갖을 수 없습니다.

  • 덮어쓰기하려는 Web Bean은 생산자 방식, 폐지 방식 또는 옵저버 방식을 명시할 수 있습니다.

이러한 경우, 덮어 쓰기하려는 Web Bean은 런타임시 호출 가능해야 합니다 따라서, 덮어쓰기는 다소 개발자 오류를 초래하는 경우가 있습니다.

Web Beans는 특성화라는 특별 기능을 제공하여, 개발자들이 이러한 함정에 빠지지 않도록 돕습니다. 특성화 기능은 처음에는 조금 난해하게 보이지만, 익숙해 지면 사용하기 쉬우며 제공되는 추가 보안 기능에 만족하실 것입니다.

지금까지 어노테이션을 사용하여 명시된 여러 가지 Web Beans의 예를 살펴보았습니다. 하지만 Web Bean을 정의하기 위해 어노테이션을 사용할 수 없는 경우가 종종 있습니다:

  • 구현 클래스가 일부 기존 라이브러에서 비롯되었을 경우,

  • 동일한 구현 클래스를 갖는 다수의 Web Beans이 있을 경우

이러한 경우, Web Beans는 두 가지 옵션을 제공합니다:

  • 생산자 방식 작성 또는

  • XML을 사용하여 Web Bean 명시

다수의 프레임워크는 XML을 사용하여 Java 클래스 관련 메타테이터를 제공합니다. 하지만, Web Beans는 다양한 접근 방법을 사용하여 Java 클래스 이름, 영역, 방식을 대부분의 다른 프레임워크에 지정합니다. XML 요소 및 속성의 문자열 값으로 클래스 및 멤버 이름을 작성하는 대신, Web Beans는 XML 요소 이름으로 클래스 또는 멤버 이름을 사용하게 합니다.

이러한 접근 방법의 장점은 XML 문서에서 스펠링 오류가 나타나지 않게 하는 XML 스키마를 작성할 수 있다는 것입니다. 컴파일된 Java 코드에서 XML 스키마를 자동으로 생성하기 위한 도구를 만들 수 도 있습니다. 또는 통합된 개발 환경은 중간 생성 단계를 거치지 않고 동일한 검증을 실행할 수 있습니다.

Web Beans의 세 번째 기능은 통합 기능입니다. Web Beans는 다른 기술과 일제히 작동하도록 고안되어, 애플리케이션 개발자가 다른 기술을 함께 사용하게 합니다. 이는 Java EE 에코시스템의 일부분을 형성하여 새로운 에코시스템에 대해 기존 프레임워크와 기술로의 기능 통합 및 휴대용 확장의 기초가 됩니다.

EJB가 JSF 페이지에 직접 바운딩되게 하여 Web Beans이 어떻게 EJB 및 JSF를 통합하였는지를 살펴보았습니다. 이는 단지 시작에 불과합니다. Web Beans는 비지니스 프로세스 관리 엔진, 기타 다른 웹 프레임워크, 제삼자 구성 요소 모델과 같은 다른 기술을 다양화하기 위해 동일한 잠재적 기능을 제공합니다. Java EE 플랫폼은 Java 애플리케이션 개발에 사용되는 모든 기술을 표준화할 수 없지만, Web Beans는 Java EE 환경 내에 있는 플랫폼의 일부분에 속하지 않는 기술을 보다 쉽게 사용할 수 있게 합니다.

Web Beans을 사용하는 애플리케이션에서 Java EE 플랫폼의 장점을 최대한으로 활용하는 방법에 대해 살펴보겠습니다. 또한 Web Beans에 휴대용 확장을 지원하기 위해 제공되는 SPI 설정에 대해서도 간략하게 살펴보겠습니다. 이러한 SPI 기능을 직접 사용할 필요가 없을 수 도 있지만, 만약 필요할 경우 이러한 기능한 기능이 있다는 것을 알아두시면 좋습니다. 가장 중요하게 제삼자 확장 기능을 사용할 때 마다 이러한 기능의 장점을 간접적으로 활용할 수 있습니다.

Web Beans는 Java EE 환경으로 완전 통합됩니다. Web Beans는 Java EE 리소스 및 JPA 지속성 컨텍스트로 액세스합니다. 이는 JSF 및 JSP 페이지에서 Unified EL 표현식으로 사용될 수 있습니다. 이는 Web Beans가 아닌 Servlets 및 Message-Driven Beans와 같은 일부 객체로 삽입될 수 도 있습니다.

JMS를 사용하여 메세지를 전송하는 것은 다소 복잡할 수 있습니다. 이는 다수의 다른 개체를 처리해야 하기 때문입니다. 큐의 경우 Queue, QueueConnectionFactory, QueueConnection, QueueSession QueueSender를 갖습니다. 토픽의 경우 Topic, TopicConnectionFactory, TopicConnection, TopicSession, TopicPublisher를 갖습니다. 이러한 각각의 객체는 자체적으로 수명 주기 및 스레딩 모델을 갖고 있습니다.

Web Beans는 이러한 모든 것을 처리합니다. 여기서 처리해야 할 사항은 web-beans.xml에 있는 큐 또는 토픽을 명명하고 관련된 바인딩 유형 및 연결 팩토리를 지정하는 것입니다.


<Queue>
    <destination
>java:comp/env/jms/OrderQueue</destination>
    <connectionFactory
>java:comp/env/jms/QueueConnectionFactory</connectionFactory>
    <myapp:OrderProcessor/>    
</Queue
>

<Topic>
    <destination
>java:comp/env/jms/StockPrices</destination>
    <connectionFactory
>java:comp/env/jms/TopicConnectionFactory</connectionFactory>
    <myapp:StockPrices/>    
</Topic
>

이제 큐의 경우 Queue, QueueConnection, QueueSession, QueueSender를 삽입할 수 있고, 토픽의 경우 Topic, TopicConnection, TopicSession TopicPublisher를 삽입할 수 있습니다.

@OrderProcessor QueueSender orderSender;

@OrderProcessor QueueSession orderSession;
public void sendMessage() {
    MapMessage msg = orderSession.createMapMessage();
    ...
    orderSender.send(msg);
}
@StockPrices TopicPublisher pricePublisher;

@StockPrices TopicSession priceSession;
public void sendMessage(String price) {
    pricePublisher.send( priceSession.createTextMessage(price) );
}

삽입된 JMS 객체의 수명주기는 Web Bean 관리자에 의해 전적으로 관리됩니다.

Web Beans는 다른 기술과의 통합, 확장, 프레임워크에 대한 플랫폼이 되기 위한 것입니다. 따라서, Web Beans는 Web Beans로의 휴대용 확장에 대한 개발자의 사용을 위해 SPI 모음을 노출합니다. 예를 들어, 다음과 같은 종류의 확장은 Web Beans 개발자에 의해 구상되었습니다.

  • 비지니스 프로세스 관리 엔진과의 통합

  • Spring, Seam, GWT, Wicket과 같은 제삼자 프레임워크와의 통합

  • Web Beans 프로그래밍 모델을 기반으로 하는 새로운 기술

Web Beans 확장의 중심은 Manager 객체입니다.

Manager 인터페이스는 Web Beans, 인터셉터, 데코레이터, 옵저버 및 컨텍스트를 프로그램적으로 획득하여 등록할 수 있게 합니다.

public interface Manager

{
   public <T
> Set<Bean<T
>
> resolveByType(Class<T
> type, Annotation... bindings);
   public <T
> Set<Bean<T
>
> resolveByType(TypeLiteral<T
> apiType,
         Annotation... bindings);
   public <T
> T getInstanceByType(Class<T
> type, Annotation... bindings);
   public <T
> T getInstanceByType(TypeLiteral<T
> type,
         Annotation... bindings);
   public Set<Bean<?>
> resolveByName(String name);
   public Object getInstanceByName(String name);
   public <T
> T getInstance(Bean<T
> bean);
   public void fireEvent(Object event, Annotation... bindings);
   public Context getContext(Class<? extends Annotation
> scopeType);
   public Manager addContext(Context context);
   public Manager addBean(Bean<?> bean);
   public Manager addInterceptor(Interceptor interceptor);
   public Manager addDecorator(Decorator decorator);
   public <T
> Manager addObserver(Observer<T
> observer, Class<T
> eventType,
         Annotation... bindings);
   public <T
> Manager addObserver(Observer<T
> observer, TypeLiteral<T
> eventType,
         Annotation... bindings);
   public <T
> Manager removeObserver(Observer<T
> observer, Class<T
> eventType,
         Annotation... bindings);
   public <T
> Manager removeObserver(Observer<T
> observer,
         TypeLiteral<T
> eventType, Annotation... bindings);
   public <T
> Set<Observer<T
>
> resolveObservers(T event, Annotation... bindings);
   public List<Interceptor
> resolveInterceptors(InterceptionType type,
         Annotation... interceptorBindings);
   public List<Decorator
> resolveDecorators(Set<Class<?>
> types,
         Annotation... bindings);
}

삽입을 통해 Manager 인스턴스를 얻을 수 있습니다:

@Current Manager manager

Bean 추상 클래스의 인스턴스는 Web Beans를 나타냅니다. 애플리케이션에 있는 모든 Web Bean에 해당하는 Manager 객체로 등록된 Bean 인스턴스가 있습니다.

public abstract class Bean<T> {

    
    private final Manager manager;
    
    protected Bean(Manager manager) {
        this.manager=manager;
    }
    
    protected Manager getManager() {
        return manager;
    }
    
    public abstract Set<Class> getTypes();
    public abstract Set<Annotation> getBindingTypes();
    public abstract Class<? extends Annotation> getScopeType();
    public abstract Class<? extends Annotation> getDeploymentType(); 
    public abstract String getName();
    
    public abstract boolean isSerializable();
    public abstract boolean isNullable();
    public abstract T create();
    public abstract void destroy(T instance);
    
}

Web Beans 사양 (심플 Web Beans 및 엔터프라이즈 Web Beans, 생산자 방식 및 JMS 엔드포인트)에 의해 정의된 것 이상으로 새로운 종류의 Web Beans을 지원하기 위해 Bean 클래스를 확장하고 Manager.addBean()를 호출하여 인스턴스를 등록할 수 있습니다. 예를 들어, Bean 클래스를 사용하여 Web Beans에 주입된 다른 프레임워크에 의해 관리되는 객체를 허용하게 할 수 있습니다.

Web Beans 사양에 의해 정의되는 두 개의 Bean 하부 클래스가 있습니다: InterceptorDecorator.

Web Beans is the reference implementation of JSR-299, and is used by JBoss AS and Glassfish to provide JSR-299 services for Java Enterprise Edition applications. Web Beans also goes beyond the environments and APIs defined by the JSR-299 specification and provides support for a number of other environments (such as a servlet container such as Tomcat, or Java SE) and additional APIs and modules (such as logging, XSD generation for the JSR-299 XML deployment descriptors).

If you want to get started quickly using Web Beans with JBoss AS or Tomcat and experiment with one of the examples, take a look at 3장. Web Beans, the Reference Implementation of JSR-299. Otherwise read on for a exhaustive discussion of using Web Beans in all the environments and application servers it supports, as well the Web Beans extensions.

Web Beans can be used in Tomcat 6.0.

Web Beans should be used as a web application library in Tomcat. You should place webbeans-tomcat.jar in WEB-INF/lib. webbeans-tomcat.jar is an "uber-jar" provided for your convenience. Instead, you could use its component jars:

You also need to explicitly specify the Tomcat servlet listener (used to boot Web Beans, and control its interaction with requests) in web.xml:

<listener>
   <listener-class
>org.jboss.webbeans.environment.servlet.Listener</listener-class>
</listener
>

Tomcat has a read-only JNDI, so Web Beans can't automatically bind the Manager. To bind the Manager into JNDI, you should add the following to your META-INF/context.xml:

<Resource name="app/Manager" 
          auth="Container"
          type="javax.inject.manager.Manager"
          factory="org.jboss.webbeans.resources.ManagerObjectFactory"/>

and make it available to your deployment by adding this to web.xml:

<resource-env-ref>
  <resource-env-ref-name>
    app/Manager
  </resource-env-ref-name>
  <resource-env-ref-type>
    javax.inject.manager.Manager
  </resource-env-ref-type>
</resource-env-ref>

Tomcat only allows you to bind entries to java:comp/env, so the Manager will be available at java:comp/env/app/Manager

Web Beans also supports Servlet injection in Tomcat. To enable this, place the webbeans-tomcat-support.jar in $TOMCAT_HOME/lib, and add the following to your META-INF/context.xml:

<Listener className="org.jboss.webbeans.environment.tomcat.WebBeansLifecycleListener" />

Apart from improved integration of the Enterprise Java stack, Web Beans also provides a state of the art typesafe, stateful dependency injection framework. This is useful in a wide range of application types, enterprise or otherwise. To facilitate this, Web Beans provides a simple means for executing in the Java Standard Edition environment independently of any Enterprise Edition features.

When executing in the SE environment the following features of Web Beans are available:

To make life easy for developers Web Beans provides a special module with a main method which will boot the Web Beans manager, automatically registering all simple Web Beans found on the classpath. This eliminates the need for application developers to write any bootstrapping code. The entry point for a Web Beans SE applications is a simple Web Bean which observes the standard @Deployed Manager event. The command line paramters can be injected using either of the following:

@Parameters List<String

> params;
@Parameters String[] paramsArray; // useful for compatability with existing classes

Here's an example of a simple Web Beans SE application:

@ApplicationScoped

public class HelloWorld
{
    @Parameters List<String
> parameters;
    public void printHello( @Observes @Deployed Manager manager )
    {
        System.out.println( "Hello " + parameters.get(0) );
    }
}

Web Beans SE applications are started by running the following main method.

java org.jboss.webbeans.environments.se.StartMain <args

>

If you need to do any custom initialization of the Web Beans manager, for example registering custom contexts or initializing resources for your beans you can do so in response to the @Initialized Manager event. The following example registers a custom context:

public class PerformSetup

{
    public void setup( @Observes @Initialized Manager manager )
    {
        manager.addContext( ThreadContext.INSTANCE );
    }
}

현재 Web Beans RI는 JBoss AS 5에서만 실행됩니다; RI를 기타 다른 EE 환경 (예를 들어 Glassfish와 같은 다른 애플리케이션 서버)으로 통합, 또는 servlet 컨테이너로 통합 (예: Tomcat), 또는 내장된 EJB3.1 구현과 통합하는 것은 쉽습니다. Appendix에서 필요한 절차에 대해 간략하게 살펴보겠습니다.

The Web Beans SPI is located in webbeans-spi module, and packaged as webbeans-spi.jar. Some SPIs are optional, if you need to override the default behavior, others are required.

SPI에 있는 모든 인터페이스는 데코레이터 패턴을 지원하고 Forwarding 클래스를 제공합니다.

Web Beans RI는 컨테이너로 EJB3 bean 검색을 위임하므로 EJB3 어노테이션을 검색하거나 ejb-jar.xml을 파싱할 필요가 없습니다. 애플리케이션에 있는 각각의 EJB의 경우 EJBDescriptor를 검색해야 합니다:

public interface EjbServices

{
   
   /**
    * Gets a descriptor for each EJB in the application
    * 
    * @return The bean class to descriptor map 
    */
   public Iterable<EjbDescriptor<?>> discoverEjbs();
public interface EjbDescriptor<T

> {
   
   /**
    * Gets the EJB type
    * 
    * @return The EJB Bean class
    */
   public Class<T
> getType();
   /**
    * Gets the local business interfaces of the EJB
    * 
    * @return An iterator over the local business interfaces
    */
   public Iterable<BusinessInterfaceDescriptor<?>
> getLocalBusinessInterfaces();
   
   /**
    * Gets the remote business interfaces of the EJB
    * 
    * @return An iterator over the remote business interfaces
    */
   public Iterable<BusinessInterfaceDescriptor<?>
> getRemoteBusinessInterfaces();
   
   /**
    * Get the remove methods of the EJB
    * 
    * @return An iterator over the remove methods
    */
   public Iterable<Method
> getRemoveMethods();
   /**
    * Indicates if the bean is stateless
    * 
    * @return True if stateless, false otherwise
    */
   public boolean isStateless();
   /**
    * Indicates if the bean is a EJB 3.1 Singleton
    * 
    * @return True if the bean is a singleton, false otherwise
    */
   public boolean isSingleton();
   /**
    * Indicates if the EJB is stateful
    * 
    * @return True if the bean is stateful, false otherwise
    */
   public boolean isStateful();
   /**
    * Indicates if the EJB is and MDB
    * 
    * @return True if the bean is an MDB, false otherwise
    */
   public boolean isMessageDriven();
   /**
    * Gets the EJB name
    * 
    * @return The name
    */
   public String getEjbName();
   
   
}

EjbDescriptor는 쉽게 알 수 있어야 하며 EJB 사양에 정의되어 있음으로 관련된 메타데이터를 반환해야 합니다. 이러한 두 가지 인터페이스에 더하여, 로컬 비지니스 인터페이스를 나타내는 BusinessInterfaceDescriptor가 있습니다. (EJB 인스턴스를 검색하는데 사용되는 인터페이스 클래스 및 jndi 이름을 캡슐화)

The resolution of @EJB and @Resource is delegated to the container. You must provide an implementation of org.jboss.webbeans.ejb.spi.EjbServices which provides these operations. Web Beans passes in the javax.inject.manager.InjectionPoint the resolution is for, as well as the NamingContext in use for each resolution request.

The Web Beans RI must delegate JTA activities to the container. The SPI provides a couple hooks to easily achieve this with the TransactionServices interface.

public interface TransactionServices

{
   /**
    * Possible status conditions for a transaction. This can be used by SPI
    * providers to keep track for which status an observer is used.
    */
   public static enum Status
   {
      ALL, SUCCESS, FAILURE
   }
   /**
    * Registers a synchronization object with the currently executing
    * transaction.
    * 
    * @see javax.transaction.Synchronization
    * @param synchronizedObserver
    */
   public void registerSynchronization(Synchronization synchronizedObserver);
   /**
    * Queries the status of the current execution to see if a transaction is
    * currently active.
    * 
    * @return true if a transaction is active
    */
   public boolean isTransactionActive();
}

The enumeration Status is a convenience for implementors to be able to keep track of whether a synchronization is supposed to notify an observer only when the transaction is successful, or after a failure, or regardless of the status of the transaction.

Any javax.transaction.Synchronization implementation may be passed to the registerSynchronization() method and the SPI implementation should immediately register the synchronization with the JTA transaction manager used for the EJBs.

To make it easier to determine whether or not a transaction is currently active for the requesting thread, the isTransactionActive() method can be used. The SPI implementation should query the same JTA transaction manager used for the EJBs.

API의 외부 구현에서의 올바른 기능을 실행하게 하기 위해 Web Beans RI이 컨테이너에 위치하게 해야 할 여러 요구 사항이 있습니다

Classloader 분리

Web Beans RI를 다수의 애플리케이션의 운용을 지원하는 환경으로 통합할 경우, 각각의 Web Beans 애플리케이션에 대한 클래스로더 분리를 자동으로 또는 사용자 설정을 통해 반드시 활성화해야 합니다.

Servlet listener and filters

Web Beans를 Servlet 환경으로 통합할 경우, Servlet을 사용하는 각각의 Web Beans 애플리케이션에 대해 자동으로 또는 사용자 설정을 통해 org.jboss.webbeans.servlet.WebBeansListener를 Servlet 청취자로 등록해야 합니다.

If you are integrating the Web Beans into a JSF environment you must register org.jboss.webbeans.servlet.ConversationPropagationFilter as a Servlet listener, either automatically, or through user configuration, for each Web Beans application which uses JSF. This filter can be registered for all Servlet deployment safely.

Session Bean 인터셉터

Web Beans를 EJB 환경으로 통합하고자 할 경우 엔터프라이즈 beans를 사용하는 각각의 Web Beans 애플리케이션 용으로 모든 EJB 애플리케이션에 대해 EJB 인터셉터로서 org.jboss.webbeans.ejb.SessionBeanInterceptor를 자동으로 또는 사용자 설정을 통해 등록해야 합니다.

The webbeans-core.jar

If you are integrating the Web Beans into an environment that supports deployment of applications, you must insert the webbeans-core.jar into the applications isolated classloader. It cannot be loaded from a shared classloader.