EJB(Enterprise JavaBeans™) 1.0 스펙에서 소개되고
EJB 3.0 스펙에 의해 크게 단순화된 stateful 세션 Bean에
대한 Bean 구현 클래스를 작성할 수 있습니다.
Stateful Bean은 수명 중에 단일 클라이언트가 사용할 것이며
이를 호출하고 있는 클라이언트와의 대화 상태를 유지하는
세션 Bean의 한 유형입니다.
이 태스크 정보
Stateful 세션 Bean은 인터페이스 없음
로컬 보기(EJB 3.1의 새 기능), 비즈니스 로컬, 비즈니스 원격, EJB 2.1
로컬, EJB2.1 원격 클라이언트 보기를 가질 수 있습니다. 한 가지
예를 들면, 클라이언트가 온라인 쇼핑 세션 중에 카트에
항목을 추가하는 장바구니가 있습니다.
다음 예는 기본 stateful 세션 Bean을 보여줍니다.
package com.ibm.example;
public interface ShoppingCart {
void addToCart (Object o);
Collection getContents();
}
package com.ibm.example;
@Stateful
public class ShoppingCartBean implements ShoppingCart {
private ArrayList contents = new ArrayList();
public void addToCart (Object o) {
contents.add(o);
}
public Collection getContents() {
return contents;
}
}
다른 엔터프라이즈 Bean 유형과 마찬가지로
어노테이션을 사용하는 것보다 배치 디스크립터에서 stateful 세션
Bean에 대한 메타데이터를 선언할 수도 있습니다. 예를 들면,
<?xml version="1.0"?>
<ejb-jar
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/ejb-jar_3_1.xsd"
version="3.1">
<enterprise-beans>
<ejb-name>ShoppingCartBean</ejb-name>
<business-local>com.ibm.example.ShoppingCart</business-local>
<ejb-class>com.ibm.example.ShoppingCartBean</ejb-class>
<session-type>Stateful</session-type>
</enterprise-beans>
</ejb-jar>
- 지정되지 않은 보안 컨텍스트 및 지정되지 않은 트랜잭션
컨텍스트에서 실행함을 이해하면서 초기화 및 제거 메소드를
코드화하십시오. 초기화 중 인스턴스가 작성되고
종속성 주입이 발생하며 PostConstruct 라이프사이클 인터셉터 콜백이
호출됩니다. 원격 메소드가 호출될 때 PreDestroy 라이프사이클
인터셉터 콜백이 stateful 세션 Bean에 대해 호출됩니다.
또한 수동 상태에 있는 중에 stateful 세션 Bean이 제한시간
초과하는 경우 또는 Bean에 대한 메소드 호출 중에
예기치 않은 예외가 발생하고 Bean이 버려지는 경우 PreDestroy
라이프사이클 인터셉터 콜백이 호출되지 않음을 기억하십시오.
- Stateful 세션 Bean이 직렬화 가능하지 않은 상태를 포함하는
경우 PrePassivate 및 PostActivate 메소드를 사용하십시오. 컨테이너는
트랜잭션 또는 현재 실행 중인 메소드 요청에 나열되지 않을 때는
언제든지 stateful 세션 Bean 인스턴스를 수동화할 수 있습니다.
Stateful 세션 Bean 인스턴스는 모든 상태 데이터를 직렬화하여
수동 상태로 이동됩니다. 임의의 상태 데이터가 직렬화하지
않는 경우 컨테이너가 stateful 세션 Bean 인스턴스를
버립니다.
- Stateful 세션 Bean의 상태 데이터가 트랜잭션 롤백 후에
재설정되어야 하는 경우 선택적인 javax.ejb.SessionSynchronization
인터페이스 구현을 고려하십시오. Stateful 세션 Bean의
상태 데이터는 트랜잭션이 아니며 트랜잭션 롤백의 결과로
초기 상태로 자동으로 재설정되지 않습니다. javax.ejb.SessionSynchronization
인터페이스의 afterCompletion 메소드를 구현하여
stateful 세션 Bean 인스턴스가 스스로 초기 또는
일관된 상태로 재설정할 수 있습니다.
- 동시 클라이언트 요청을 방지하거나 메소드가 인스턴스 잠금이
부여되길 기다리는 기간을 제한하려면 @AccessTimeout 표기법을
사용하십시오. 기본적으로 컨테이너는 동시 클라이언트 요청을
허용하지만, stateful 세션 Bean 인스턴스에 대한 멀티스레드 액세스를
막기 위해 모든 메소드 호출 및 컨테이너 호출 콜백을 직렬화합니다.
이 동작은 싱글톤 세션 Bean에 대한 쓰기 잠금을 갖는 컨테이너
관리 동시성을 사용하는 것과 비슷합니다. 그러나 싱글톤 세션 Bean과는
달리, stateful 세션 Bean은 Bean 관리 동시성을 사용하도록 구성될
수 없으며 잠금 유형을 변경할 수 없습니다. Stateful 세션 Bean에
대한 액세스 제한시간 값만 수정할 수 있습니다. 다음 코드 예는 동시 클라이언트 요청을 방지하는
동시 액세스 제한시간 값을 갖는 stateful 세션 Bean을
보여줍니다.
package com.ibm.example;
@Stateful
public class ShoppingCartBean implements ShoppingCart {
private ArrayList contents = new ArrayList();
@AccessTimeout( value=0 )
public void addToCart (Object o) {
contents.add(o);
}
public Collection getContents() {
return contents;
}
}
package com.ibm.example;
@Stateful
public class ShoppingCartBean implements ShoppingCart {
private ArrayList contents = new ArrayList();
@AccessTimeout( value=0 )
public void addToCart (Object o) {
contents.add(o);
}
public Collection getContents() {
return contents;
}
}
어노테이션이 제공되지 않는 경우
기본 동작은 잠금이 부여될 때까지 대기하는 것입니다. 클라이언트가
잠금이 부여되길 기다리는 기간에 대한 시간 제한은 없습니다. 클래스
레벨에서 코드화된 것이 없기 때문에 클래스의 모든 메소드에
부여되는 잠금에 대해 대기 시간 제한이 없습니다. @AccessTimeout
어노테이션이 사용되고 컨테이너가 지정된 제한 시간 내에 잠금을
부여할 수 없는 경우 javax.ejb.ConcurrentAccessTimeoutException
예외가 클라이언트에서 발생합니다. @AccessTimeout 어노테이션은
@AccessTimeout 어노테이션과 동일한 클래스에서 선언되는 메소드에만
적용됩니다. 주어진 클래스에 대해 @AccessTimeout 어노테이션에 대한
메타데이터는 클래스 상속 트리의 더 높은 클래스에서 상속될
수 없습니다.
-1의 액세스 제한시간 값은 동시 메소드 호출이
Bean 인스턴스에 대한 액세스를 무한정 차단함(기본값)을
표시합니다. 0의 액세스 제한시간 값은 동시 메소드 호출이
허용되지 않음을 표시합니다. javax.ejb.ConcurrentAccessException 예외는
동시성이 발견될 때 발생합니다. 또한 모든 양의 값은 메소드가
계속할 수 있을 때까지 기다릴 시간을 표시합니다.
Java™ EE 6 이전에는
stateful 세션 Bean에 대해 지원되는 유일한 동시성 동작은
-1(동시성 없음)의 액세스 제한시간입니다. Java EE 6 스펙이
기본 동작을 변경했으므로, 이전의 기본 동작을 제공하는 시스템 특성이
지원됩니다. com.ibm.websphere.ejbcontainer.EE5Compatibility 시스템 특성에 대한
자세한 정보는 EJB 컨테이너 시스템 특성을 참조하십시오.
또한 XML 배치 디스크립터를
사용하여 @AccessTimeout 어노테이션을 지정할 수 있으며,
XML 배치 디스크립터를 사용하는 경우 @AccessTimeout
어노테이션의 메타데이터는 무시됩니다. 다음 예제는 XML
배치 디스크립터를 사용하여 이전 예제와 동일한 메타데이터를
지정합니다.
<session>
<ejb-name>ShoppingCartBean</ejb-name>
<concurrent-method>
<method>
<method-name>addToCart</method-name>
</method>
<access-timeout>
<timeout>0</timeout>
<unit>Milliseconds</unit>
</access-timeout>
</concurrent-method>
</session>
- 동시성 methodType의 XML 코딩은 컨테이너 트랜잭션 메소드 요소에
대해 XML을 작성하기 위해 EJB 스펙에 아웃라인된 세 가지의
스타일을 따른다는 것을 인지하는 것이 중요합니다. 세 가지
스타일은 다음과 같습니다. 스타일 1은 특수 메소드 이름 *를 사용하여
액세스 제한시간 값을 지정된 Bean에 대한 모든 비즈니스 메소드에
적용합니다.
<!-- Example: Style 1 -->
<concurrent-method>
<method>
<method-name>*</method-name>
</method>
<access-timeout>
<timeout>2000</timeout>
<unit>Milliseconds</unit>
</access-timeout>
</concurrent-method>
스타일 2는
특정 이름을 가진 비즈니스 메소드에 대해 참조하고 이를 지정된 액세스 제한시간 값을
지정하는 데 사용됩니다. 메소드 이름이 오버로드(다중 메소드에 동일한
이름의 다른 메소드 서명이 있음)되는 경우 이 이름의 모든 메소드에
지정된 액세스 제한시간 값이 있습니다.
<!-- Example: Style 2 -->
<concurrent-method>
<method>
<method-name>businessMethod</method-name>
</method>
<access-timeout>
<timeout>2000</timeout>
<unit>Milliseconds</unit>
</access-timeout>
</concurrent-method>
스타일 3은 주어진 메소드 이름과 일치하고 나열된 메소드
매개변수와 일치하는 메소드 서명을 가진 다른 메소드를
참조하는 데 사용됩니다. 스타일 3이 스타일 1 및
스타일 2 모두에 우선합니다.
<!-- Example: Style 3 -->
<concurrent-method>
<method>
<method-name>businessMethod</method-name>
<method-params>
<method-param>long</method-param>
<method-param>int</method-param>
</method-params>
</method>
<access-timeout>
<timeout>2000</timeout>
<unit>Milliseconds</unit>
</access-timeout>
</concurrent-method>
스타일 1
XML이 액세스 제한시간 값을 정의하는 데 사용되는 경우, Bean의 모든
@AccessTimeout 어노테이션은 메소드 레벨 1이 대신 사용되기 때문에
무시됩니다.
- 사용한 어노테이션에 대한 상속 규칙을
이해해야 합니다.
- Stateful 세션 Bean은 재진입 불가하며, 이것은 stateful 세션 Bean
메소드가 그 자신을 다시 호출함을 의미합니다. stateful 세션 Bean에
대한 재진입 호출이 작성되는 경우, 액세스 제한시간 값과 상관없이
javax.ejb.ConcurrentAccessTimeoutException 예외가 클라이언트에서 발생합니다.
예외가 호출자에 의해 처리되지 않는 경우 이 예외의
결과로 stateful 세션 Bean이 삭제되지 않으며
롤백용 트랜잭션을 표시하지 않습니다.