В этом уроке мы увидим, как активация и пассивация работают в Stateful Java Enterprise Session Bean.
1. Введение
Бины сеансов с сохранением состояния обычно содержат информацию о конкретном клиенте и хранят эту информацию в течение всего сеанса. Однако фактом является то, что клиентские сессии, как правило, активны в течение значительного периода времени, и, конечно, многие клиенты могут быть в сети одновременно. В результате в контейнере EJB необходимо реализовать механизм, который делает возможным высвобождение ресурсов, которые не используются в данный момент и могут быть снова активированы при необходимости.
Пассивация сессионного компонента означает удаление его из Session EJB Cache контейнера и сохранение всей необходимой информации и свойств сессионного компонента в файле. Активация сессионного компонента означает чтение вышеупомянутого файла и восстановление пассивированного сессионного компонента в кэше. Как вы можете себе представить, все поля этого сессионного компонента должны быть Serializable .
В этом примере мы собираемся создать проект EAR и проект EJB, в котором будут размещены наш Session Bean-компонент и динамическое веб-приложение, в котором будет размещен сервлет, тестируя вышеупомянутые свойства пассивации и активации. В качестве нашего контейнера мы будем использовать Eclipse Java EE IDE 4,3 Kepler и Glassfish 4.0.
2. Создайте новый проект корпоративного приложения
Создайте новый проект корпоративного приложения с именем SatefulBeansEAR
В Eclipse IDE выберите «Файл» -> «Новый» -> «Проект корпоративного приложения», заполните форму и нажмите «Готово»:
3. Создайте новый EJB Projet
Создайте новый EJB-проект с именем StatefulEJB. Мы собираемся создать наш сессионный компонент по этому вопросу. Перейдите в File -> New -> EJB Project и заполните форму. Будьте внимательны, выберите «Добавить проект EAR» и выберите « StatefulBeansEAR
» в качестве имени проекта EAR:
Дважды нажмите Next и выберите создание JAR ejb-jar.xml
EJB-клиента, а также создание дескриптора развертывания ejb-jar.xml
:
4. Создайте насыщенный сессионный компонент
Откройте StatefulEJB Project в Project Explorer и в папке ejbModule
создайте новый исходный пакет с именем com.javacodegeeks.enterprise.ejb
. В этом пакете создайте новый интерфейс, который будет локальным представлением EJB:
Passivation.java:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
package com.javacodegeeks.enterprise.ejb; import javax.ejb.Local; import com.javacodegeeks.enterprise.ejb.property.PropertyObject; @Local public interface Passivation { void setPropertyObject(PropertyObject propertyObject); PropertyObject getPropertyObject(); } |
А вот и Session Bean:
PassivationBean.java:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
package com.javacodegeeks.enterprise.ejb; import javax.ejb.PostActivate; import javax.ejb.PrePassivate; import javax.ejb.Stateful; import com.javacodegeeks.enterprise.ejb.property.PropertyObject; @Stateful public class PassivationBean implements Passivation { private PropertyObject myProperty; @Override public void setPropertyObject(PropertyObject propertyObject) { this .myProperty = propertyObject; } @Override public PropertyObject getPropertyObject() { return this .myProperty; } @PrePassivate private void prePassivate(){ // Free resources // ... System.out.println( "Passivating EJB. Property value: " + myProperty.getProperty()); } @PostActivate private void postActivate(){ // Reactivate resources // ... System.out.println( "Activating EJB. Property value: " + myProperty.getProperty()); } } |
В приведенном выше коде:
-
private void prePassivate()
: аннотированный@PrePassivate
— это метод, который выполняется, когда контейнер EJB решает пассивировать этот сессионный компонент. -
private void postActivate()
:@PostActivate
с помощью@PostActivate
это метод, который выполняется, когда контейнер EJB активирует пассивированный сессионный компонент, потому что он снова нужен.
Кроме того, как вы можете видеть, сессионный компонент имеет private PropertyObject myProperty
поле private PropertyObject myProperty
. Это объект, который может содержать информацию для сеанса, для bean-компонента, для ресурсов и любые виды данных, которые могут оказаться полезными.
Поэтому, когда bean-компонент пассивируется, мы хотим, чтобы это свойство также сохранялось и восстанавливалось. Таким образом, он должен быть Serilizable
как мы упоминали во введении. Сказав это, если вы не хотите сохранять это свойство, потому что вам не нужно извлекать этот ресурс при активации бина, вы можете объявить объект переходным, используя аннотацию @Transient
. Для этого объекта я создал новый исходный пакет с именем com.javacodegeeks.enterprise.ejb.property
.
PropertyObject.java:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
package com.javacodegeeks.enterprise.ejb.property; import java.io.Serializable; public class PropertyObject implements Serializable { private static final long serialVersionUID = 1L; private String property; public PropertyObject(String value){ this .property = value; } public String getProperty() { return property; } } |
Итак, это будет окончательная структура EJB-проекта SatefulEJB
:
5. Создайте новый динамический веб-проект
Перейдите в Файл -> Создать -> Динамический веб-проект. Заполните форму и убедитесь, что вы отметили «Добавить проект в EAR» и поместили StatefulBeans EAR в качестве «имени проекта EAR»:
После нажатия «Готово» перейдите в проводник проекта и щелкните правой кнопкой мыши на Project StatefulBeansTest
и перейдите в Свойства-> Сборка развертывания -> Добавить -> Объект -> StatefulEJB:
6. Создайте новый сервлет
Перейдите в веб-проект StatefulBeansTest
и создайте новый MyServlet
именем MyServlet
:
Итак, это будет окончательная структура веб-проекта:
MyServlet.java:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
package com.javacodegeeks.enterprise.servlet; import java.io.IOException; import javax.naming.InitialContext; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.javacodegeeks.enterprise.ejb.Passivation; import com.javacodegeeks.enterprise.ejb.property.PropertyObject; @WebServlet ( "/MyServlet" ) public class MyServlet extends HttpServlet { private static final long serialVersionUID = 1L; public MyServlet() { super (); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println( "Hello from Servlet" ); InitialContext ic; Passivation passivation; String beanCountparam = request.getParameter( "count" ); if (beanCountparam != null ) { int beanCount = Integer.parseInt(beanCountparam); try { ic = new InitialContext(); for ( int i = 0 ; i < beanCount; i++) { passivation = (Passivation) ic .lookup( "java:global/StatefulBeansEAR/StatefulEJB/PassivationBean!" + "com.javacodegeeks.enterprise.ejb.Passivation" ); passivation.setPropertyObject( new PropertyObject( "bean" + i)); request.getSession().setAttribute( "bean" + i, passivation); } } catch (Exception e) { throw new ServletException(e); } } String beanActivationIndex = request.getParameter( "activate" ); if (beanActivationIndex != null ) { try { ic = new InitialContext(); passivation = (Passivation) request.getSession() .getAttribute( "bean" + beanActivationIndex); System.out.println( "TestObject property value: " + passivation.getPropertyObject().getProperty()); } catch (Exception e) { throw new ServletException(e); } } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } } |
В приведенном выше коде при обращении к сервлету он анализирует параметр запроса count
, генерирует компоненты сеанса и сохраняет их в сеансе запроса. Соответственно, если присутствует параметр запроса activate
соответствующий бин извлекается из сеанса.
Совет: Если у вас возникли проблемы с определением имен Portable JNDI для EJB PassivationObject, посмотрите журналы или выходные данные Glassfish при развертывании проекта, и вы обнаружите строку, подобную этой: 2013-12-13T18: 22: 28.598 + 0200 | INFO : EJB5181: Переносимые имена JNDI для объекта EJB PassivationObject: (java: global / StatefulBeans / StatefulEJB / PassivationObject, java: global / StatefulBeans / StatefulEJB / PassivationObject! Com.javacodegeeks.enterprise.ejb.Passivation)
7. Тест
После создания вышеуказанных проектов вы должны запустить StatefulBeansTest
на Glassfish.
Чтобы проверить желаемое поведение, мы должны как-то инициировать пассивацию и активацию определенного сессионного компонента. Чтобы принудительно пассивировать бин Session, мы должны заставить контейнер удалить его из кэша сеанса. По умолчанию Glassfish может содержать не более 512 сессионных компонентов. Таким образом, если мы инициируем запрос на создание 600 бинов, некоторые из них будут в конечном итоге удалены из кэша.
Этот запрос может быть:
1
|
http: //localhost :8080 /StatefulBeansTest/MyServlet ?count=600 |
И вывод в консоли будет:
2013-12-30T22:29:36.978+0200|INFO: Hello from Servlet 2013-12-30T22:29:37.315+0200|INFO: Passivating EJB. Property value: bean31 2013-12-30T22:29:37.329+0200|INFO: Passivating EJB. Property value: bean64 2013-12-30T22:29:37.332+0200|INFO: Passivating EJB. Property value: bean70 2013-12-30T22:29:37.345+0200|INFO: Passivating EJB. Property value: bean98 2013-12-30T22:29:37.390+0200|INFO: Passivating EJB. Property value: bean117 2013-12-30T22:29:37.390+0200|INFO: Passivating EJB. Property value: bean116 2013-12-30T22:29:37.390+0200|INFO: Passivating EJB. Property value: bean115 2013-12-30T22:29:37.394+0200|INFO: Passivating EJB. Property value: bean114 2013-12-30T22:29:37.394+0200|INFO: Passivating EJB. Property value: bean113 2013-12-30T22:29:37.394+0200|INFO: Passivating EJB. Property value: bean112 2013-12-30T22:29:37.397+0200|INFO: Passivating EJB. Property value: bean111 2013-12-30T22:29:37.398+0200|INFO: Passivating EJB. Property value: bean110 2013-12-30T22:29:37.399+0200|INFO: Passivating EJB. Property value: bean109 2013-12-30T22:29:37.402+0200|INFO: Passivating EJB. Property value: bean108 2013-12-30T22:29:37.403+0200|INFO: Passivating EJB. Property value: bean107 . . .
Так что, как вы можете видеть, некоторые компоненты удаляются из кэша и, таким образом, пассивируются. Теперь, чтобы инициировать активацию компонента, мы можем просто запросить получение компонента, который уже пассивирован, например, bean31
.
Этот запрос может быть:
1
|
http: //localhost :8080 /StatefulBeansTest/MyServlet ?activate=31 |
И вывод в консоли будет:
2013-12-30T22:33:48.742+0200|INFO: Hello from Servlet 2013-12-30T22:33:48.744+0200|INFO: Activating EJB. Property value: bean31 2013-12-30T22:33:48.745+0200|INFO: TestObject property value: bean31
Вот и все. Теперь, чтобы убедиться, что сессионные компоненты, которые мы фактически сериализовали на диск, вы можете перейти к Glassfish_installation_folder/glassfish4/glassfish/domains/domain1/session-store
где вы можете увидеть папку, в которой сохранены компоненты:
Скачать проект Eclipse
Это был пример пассивации и активации EJB. Загрузите проект Eclipse этого учебника: EJBPassivationActivation.zip