Stateful Session Bean – сессионный
компонент с сохранением состояния в сессии. Состояние компонента сохраняется на
протяжении одной сессии, с которой вы работаете, после окончания сессии
состояние теряется. Применяя аннотацию @Stateful к классу, мы говорим серверу приложений, что
мы описывает бин с сохранением состояния. Давайте поговорим о жизненном цикле Stateful бина, у него может быть 3 состояния: Готов к
обработке, В пассивном состоянии, Не существует. Существуют 4 аннотации для
методов, которые будут вызываться, когда
бин переходит из одного состояния в другое.
Пусть создается новый бин, у него выполняется конструктор, дальше
выполняется метод помеченный аннотацией @PostConstruct и бин помещается в
память. Когда бин долго не используется, то он переходит в пассивное состояние,
т.е. выгружается из памяти во временное хранилище - кэш, при этом выполняется
метод помеченный аннотацией @PrePassivate. Если бин находился в пассивном состоянии и его
метод был вызван клиентской программой, то бин снова подгружается в память и
восстанавливает свое состояние - готов к обработке, при этом будет выполнен
метод с аннотацией @PostActivate. Когда бин уничтожается, то перед этим,
вызывается метод помеченный аннотацией @PreDestroy. Давайте перейдемте к
настройке Stateful
бина
в wildfly, откроем файл настройки JBOSS_HOME/Standalone/configuration/standalone.xml и найдем в нем строки:
<subsystem xmlns="urn:jboss:domain:ejb3:2.0">
<session-bean>
<stateful
default-access-timeout="5000" cache-ref="simple"
passivation-disabled-cache-ref="simple"/>
<singleton
default-access-timeout="5000"/>
</session-bean>
….
<caches>
<cache name="simple"/> <!--
конец обработки --
>
<cache name="distributable"
aliases="passivating clustered" passivation-store-ref="infinispan"/>
</caches>
<passivation-stores>
<passivation-store
name="infinispan" cache-container="ejb"
max-size="10000"/>
</passivation-stores>
….
</subsystem>
….
<subsystem
xmlns="urn:jboss:domain:infinispan:2.0">
…..
<cache-container
name="ejb" aliases="sfsb"
default-cache="passivation"
module="org.wildfly.clustering.ejb.infinispan">
<local-cache
name="passivation" batching="true">
<file-store
passivation="true" purge="false"/>
</local-cache>
<local-cache
name="persistent" batching="true">
<file-store
passivation="false" purge="false"/>
</local-cache>
</cache-container>
….
</subsystem>
По
умолчанию у Stateful
бина
не настроен кэш и он ссылается на заглушку simple для того
чтобы включить кэш нужно заменить название атрибутов на distributable, смотрим на конфиг:
<subsystem
xmlns="urn:jboss:domain:ejb3:2.0">
<session-bean>
<stateful
default-access-timeout="5000" cache-ref="distributable"
passivation-disabled-cache-ref="distributable"/>
<singleton
default-access-timeout="5000"/>
</session-bean>
….
<caches>
<cache name="simple"/>
<cache name="distributable"
aliases="passivating clustered" passivation-store-ref="infinispan"/>
</caches>
<passivation-stores>
<passivation-store
name="infinispan"
cache-container="ejb"
max-size="10000"/>
</passivation-stores>
….
</subsystem>
….
<subsystem
xmlns="urn:jboss:domain:infinispan:2.0">
…..
<cache-container name="ejb"
aliases="sfsb" default-cache="passivation"
module="org.wildfly.clustering.ejb.infinispan">
<local-cache name="passivation"
batching="true">
<file-store
passivation="true" purge="false"/>
</local-cache>
<local-cache
name="persistent" batching="true">
<file-store passivation="false"
purge="false"/>
</local-cache>
</cache-container>
….
</subsystem>
Как мы можем
судить по конфигурации, ejb при пассивации сохраняется в кэше на диске, если
вы перейдете в каталог JBOSS_HOME/Standalone/data/infinispan/ejb/ вы увидите файл кэша где будут сохранятся ваши пассивируемые ejb - jboss_ejb_war.war.dat для моего web приложения. Еще нужно рассказать об одной аннотации, это @Remove. Так как наш экземпляр ejb попадает в кэш и кэш наш ограничен
максимальным размером (max-size="10000"), отсюда следует,
что нужно его чистить от ненужных нам бинов. Чистить можно двумя способами,
вручную вызвав метод помеченный аннотацией @Remove или
настроив метод вытеснения кэша, по умолчанию он выключен. Для того что бы его
включить нужно в конфиге прописать строчку со стратегией вытеснения:
….
<local-cache
“passivation" batching="true">
….
<eviction
strategy="LRU"
max-entries="10000"/>
….
</local-cache>
….
Расскажу о
некоторых параметрах атрибута strategy:
·
Очередь, первым пришел, первым ушел - FIFO.
·
По максимальному времени не использования
объекта кэша, в кэше – LRU.
·
Не используется метод вытеснения, т.е. ручное
вытеснение объекта кэша, из кэша – NONE.
И так закрепим наши знания примером, создадим
EJB бин и JSP страницу, вызывающую метод этого
бина. Создадим Stateful
EJB:
package com.vit;
import org.jboss.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.*;
@Stateful(name="BeanStateful")
public class SessionBean1 {
private
static Logger log = Logger.getLogger(SessionBean1.class.getName());
private
String name;
public
SessionBean1() {
name =
"Hello EJB Bean";
}
public
String getName() {
return
new String(name);
}
public void
setName(String name) {
this.name = name;
}
@PreDestroy
public void
destroyInit(){
log.info(String.format("%s\n","================method
@PreDestroy call================"));
}
@PostConstruct
public void
postConstructInit(){
log.info(String.format("%s\n","================method
@PostConstruct call================"));
}
@PostActivate
public void
postActivate_(){
log.info(String.format("%s\n","================method
@PostActivate call================"));
}
@PrePassivate
public void
prePassivate_(){
log.info(String.format("%s\n","================method
@PrePassivate call================"));
}
@Remove
public void
preRemove(){
log.info(String.format("%s\n","================method
@Remove call================"));
}
}
И код jsp страницы:
<%@ page
contentType="text/html;charset=UTF-8" %>
<%@ page pageEncoding="UTF-8" %>
<%@ page session="false" %>
<%@ page import="com.vit.SessionBean1 "
%>
<%@ page import="javax.naming.Context"
%>
<%@ page
import="javax.naming.InitialContext" %>
<html>
<head>
<title>Home</title>
<meta
http-equiv="Content-Type" content="text/html;
charset=UTF-8"/>
</head>
<body>
<h1>Hello world!</h1>
<%
Context context = new
InitialContext();
SessionBean1 calc1 = (SessionBean1)
context.lookup("java:app/jboss_ejb_war/BeanStateful!com.vit.SessionBean1");
calc1.setName("Hello Session Stateful
Bean!!!");
out.println(calc1.getName());//вывод установленного методом setName значения"Hello Session Stateful
Bean!!!"
calc1.preRemove();
%>
</body>
</html>
Комментариев нет:
Отправить комментарий