在本教程中,我们将了解状态Java企业会话Bean中激活和钝化的工作方式。
1.简介
有状态会话Bean通常保存有关特定客户端的信息,并在整个会话中保存该信息。 但是,事实是,客户端会话往往会在相当长的时间内保持活动状态,当然,许多客户端可以同时在线。 结果,EJB容器有必要实现一种机制,该机制使释放在给定时刻不使用的资源成为可能,并且可以在需要时再次激活它。
钝化会话Bean意味着将其从容器的会话EJB缓存中删除,并将会话Bean的所有必要信息和属性存储在文件中。 激活会话Bean意味着读取上述文件并在缓存中恢复已钝化的会话Bean。 就像您想象的那样,该会话bean的所有字段都必须可序列化 。
在这个示例中,我们将创建一个EAR项目和一个EJB项目,它们将托管我们的Session Bean,以及一个动态Web应用程序,它将托管Servlet,并测试上述钝化和激活属性。 我们将使用Eclipse Java EE IDE 4,3 Kepler和Glassfish 4.0作为容器。
2.创建一个新的企业应用程序项目
创建一个名为SatefulBeansEAR
的新企业应用程序项目。在Eclipse IDE中,选择File-> SatefulBeansEAR
> Enterprise Application Project并填写表单,然后单击Finish:
3.创建一个新的EJB Projet
创建一个名为StatefulEJB的新EJB项目。 我们将基于此创建会话bean。 转到文件->新建-> EJB项目并填写表单。 注意选择“ Add EAR Project”,然后选择“ StatefulBeansEAR
”作为EAR项目名称:
单击下一步两次,然后选择创建EJB客户端JAR以及生成ejb-jar.xml
部署描述符:
4.创建一个令人满意的会话Bean
在Project Explorer中打开StatefulEJB Project,并在ejbModule
文件夹中创建一个名为com.javacodegeeks.enterprise.ejb
的新源包。 在该程序包中,创建一个新的Interface,它将是EJB的本地视图:
Passivation.java:
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();
}
这是会话Bean:
PassivationBean.java:
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容器决定以钝化该会话bean要执行的方法。 -
private void postActivate()
具有注释@PostActivate
-
是EJB容器由于再次需要而激活钝化会话Bean时要执行的方法。
此外,如您所见,会话bean有一个private PropertyObject myProperty
字段。 这个对象可以包含有关会话,Bean,资源以及任何有用的数据的信息。
因此,当钝化bean时,我们希望也必须保存和恢复此属性。 因此,正如我们在引言中提到的,它必须是可Serilizable
的。 话虽如此,如果您不想存储此属性,因为您不希望在激活Bean时检索该资源,则可以使用@Transient
注解声明对象瞬态。 我为此对象创建了一个名为com.javacodegeeks.enterprise.ejb.property
的新源程序包。
PropertyObject.java:
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.创建一个新的动态Web项目
转到文件->新建->动态Web项目。 填写表单,并确保选中“将项目添加到EAR”,然后将StatefulBeans EAR作为“ EAR项目名称”:
单击“完成”后,转到项目资源管理器,然后右键单击项目StatefulBeansTest
然后转到“属性”->“部署程序集”->“添加”->“项目”->“ StatefulEJB”:
6.创建一个新的Servlet
转到StatefulBeansTest
Web项目并创建一个名为MyServlet
的新Servlet:
因此,这将是Web项目的最终结构:
MyServlet.java:
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 {
}
}
在上面的代码中,访问Servlet时,它将解析count
查询参数,生成count
会话bean并将其存储到请求会话中。 因此,如果存在activate
查询参数,则从会话中检索相应的bean。
提示: 如果您在确定EJB PassivationObject的可移植JNDI名称时遇到麻烦,请在部署项目时查看Glassfish的日志或输出,您会发现类似以下内容的行: 2013-12-13T18:22:28.598 + 0200 | INFO :EJB5181:EJB PassivationObject的便携式JNDI名称:(java:global / StatefulBeans / StatefulEJB / PassivationObject,java:global / StatefulBeans / StatefulEJB / PassivationObject!com.javacodegeeks.enterprise.ejb.Passivation)
7.测试
创建上述项目后,您必须在Glassfish上运行StatefulBeansTest
。
为了测试所需的行为,我们必须以某种方式触发特定会话bean的钝化和激活。 为了强制Session Bean被钝化,我们必须使容器将其从Session缓存中删除。 默认情况下,Glassfish最多可以托管512个会话bean。 因此,如果我们触发请求创建600个bean的请求,那么其中的一些bean最终将被从缓存中删除。
该请求可以是:
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
.
.
.
因此,您可以看到一些Bean已从缓存中删除并因此被钝化。 现在触发bean的激活,我们可以简单地请求检索已被钝化的bean,例如bean31
。
该请求可以是:
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
而已。 现在可以确信我们实际上已将会话Bean序列化到了光盘,您可以转到Glassfish_installation_folder/glassfish4/glassfish/domains/domain1/session-store
,在其中您可以实际看到保存Bean的文件夹:
下载Eclipse项目
这是有关EJB钝化和激活的示例。 下载本教程的Eclipse项目: EJBPassivationActivation.zip
翻译自: https://www.javacodegeeks.com/2013/08/ejb-passivation-and-activation-example.html