stateful session bean和stateless session bean 的根本区别在于它们的生命周期不同,即有状态session bean会一直和固定的客户端保持会话, 即使被钝化;而无状态session bean则完全可以随时(当容器认为客户端结束了会话的时候)删除bean而不需要保持状态。为了验证容器处理两种bean的不同,下面写了一个简单的测试程序来测试。
测试工具及平台: Eclipse JAVA IDE, Sun Application Server 8.
一、首先编写好session bean:
1) 定义远程接口
package mybeans; import java.rmi.RemoteException; import javax.ejb.EJBObject; public interface Count extends EJBObject ... { public int doCount() throws RemoteException;}2) 编写远程主接口
package mybeans; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBHome; public interface CountHome extends EJBHome ... { public Count create() throws RemoteException,CreateException; public Count create(int i) throws RemoteException,CreateException;}3) 编写session bean
package mybeans; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.EJBException; import javax.ejb.SessionBean; import javax.ejb.SessionContext; public class CountBean implements SessionBean ... { public int n=0; public SessionContext ctxt; public int doCount() ...{ n++; return n; } public void ejbCreate() throws RemoteException,CreateException ...{ } public void ejbCreate(int i) throws RemoteException,CreateException ...{ n=i; } public void ejbActivate() throws EJBException, RemoteException ...{ System.out.println("Bean"+n/10+" Acivated."); } public void ejbPassivate() throws EJBException, RemoteException ...{ System.out.println("Bean"+n/10+" Passvated"); } public void ejbRemove() throws EJBException, RemoteException ...{ // TODO Auto-generated method stub } public void setSessionContext(SessionContext ctxt) throws EJBException, RemoteException ...{ // TODO Auto-generated method stub this.ctxt=ctxt; }}
以上便是运行在容器里的EJB程序。
二、部署这个bean
说明:为了测试有状态与无状态会话bean的不同,我们需要分别部署这两个bean。
启动了Sun Application Server 后需要分别进行部署,这里不说明具体过程。两个bean的部署描述文件为:
1) ejb-jar.xml:
<? xml version="1.0" encoding="UTF-8" ?> < ejb-jar xmlns ="http://java.sun.com/xml/ns/j2ee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" version ="2.1" xsi:schemaLocation ="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" > < display-name > CountJar </ display-name > < enterprise-beans > < session > < display-name > CountBean2 </ display-name > < ejb-name > CountBean2 </ ejb-name > < home > mybeans.CountHome </ home > < remote > mybeans.Count </ remote > < ejb-class > mybeans.CountBean </ ejb-class > < session-type > Stateless </ session-type > < transaction-type > Bean </ transaction-type > < security-identity > < use-caller-identity /> </ security-identity > </ session > < session > < display-name > CountBean </ display-name > < ejb-name > CountBean </ ejb-name > < home > mybeans.CountHome </ home > < remote > mybeans.Count </ remote > < ejb-class > mybeans.CountBean </ ejb-class > < session-type > Stateful </ session-type > < transaction-type > Bean </ transaction-type > < security-identity > < use-caller-identity /> </ security-identity > </ session > </ enterprise-beans > </ ejb-jar >2) sun-ejb-jar.xml:
<? xml version="1.0" encoding="UTF-8" ?> <! DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.1 EJB 2.1//EN" "http://www.sun.com/software/appserver/dtds/sun-ejb-jar_2_1-1.dtd" > < sun-ejb-jar > < enterprise-beans > < unique-id > 0 </ unique-id > < ejb > < ejb-name > CountBean </ ejb-name > <jndi-name>CountBean</jndi-name> < pass-by-reference > false </ pass-by-reference > < is-read-only-bean > false </ is-read-only-bean > < refresh-period-in-seconds > -1 </ refresh-period-in-seconds > < cmt-timeout-in-seconds > 0 </ cmt-timeout-in-seconds > < gen-classes /> </ ejb > < ejb > < ejb-name > CountBean2 </ ejb-name > <jndi-name>CountBean2</jndi-name> < pass-by-reference > false </ pass-by-reference > < is-read-only-bean > false </ is-read-only-bean > < refresh-period-in-seconds > -1 </ refresh-period-in-seconds > < cmt-timeout-in-seconds > 0 </ cmt-timeout-in-seconds > < gen-classes /> </ ejb > </ enterprise-beans > </ sun-ejb-jar >注意黑体的部分
三、编写测试程序
测试程序主要思路是利用多线程技术启动3个测试bean,分别进行计数运算,通过观测结果可以得出本文的结论。
package client; import mybeans. * ; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; public class TestCountClient ... { public static void main(String args[]) throws Exception ...{ InitialContext ctxt=new InitialContext(); CountHome countHome=null; countHome=(CountHome)PortableRemoteObject.narrow(ctxt.lookup("CountBean"), CountHome.class); //测试有状态会话bean //countHome=(CountHome)PortableRemoteObject.narrow(ctxt.lookup("CountBean2"), CountHome.class); 测试无状态会话bean Count count=countHome.create(1); Count count2=countHome.create(2); Count count3=countHome.create(3); BeanThread t1=new BeanThread(1,count); BeanThread t2=new BeanThread(2,count2); BeanThread t3=new BeanThread(3,count3); t1.start(); t2.start(); t3.start(); }} class BeanThread extends Thread ... { public int n=0; public Count count=null; public BeanThread(int i, Count c) ...{ n=i; count=c; } public void run() ...{ try...{ for (int i=0;i<10;i++) ...{ System.out.println("The current count"+n+" is: "+count.doCount()); Thread.sleep(10); } } catch (Exception e) ...{ } super.run(); } public synchronized void start() ...{ // TODO Auto-generated method stub super.start(); }}
注意上面的程序,测试两种会话bean需要独立进行。即先注释化掉一种情况然后才能测试另一种。
四、测试结果
1) 测试有状态会话bean时得出的结果如(由于多线程特点,当然结果可能与下面不完全一致):
The current count1 is: 2The current count2 is: 3The current count3 is: 4The current count1 is: 3The current count3 is: 5The current count2 is: 4The current count1 is: 4The current count2 is: 5The current count1 is: 5The current count3 is: 6The current count1 is: 6The current count3 is: 7The current count2 is: 6The current count1 is: 7The current count3 is: 8The current count1 is: 8The current count2 is: 7The current count1 is: 9The current count3 is: 9The current count2 is: 8The current count3 is: 10The current count1 is: 10The current count3 is: 11The current count2 is: 9The current count1 is: 11The current count3 is: 12The current count2 is: 10The current count3 is: 13The current count2 is: 11The current count2 is: 12可以看到:上面的结果显示每个bean尽管执行交替进行,但是它们的状态还是保持的,即上次若是2,下次就是3。
2) 测试无状态会话bean时结果如下(当然也由于多线程的特点,结果很可能和下面不一致):
The current count3 is: 1 The current count1 is: 2 The current count2 is: 3 The current count2 is: 4 The current count3 is: 5 The current count1 is: 1 The current count2 is: 2 The current count1 is: 4 The current count3 is: 3 The current count1 is: 5 The current count2 is: 6 The current count3 is: 7 The current count1 is: 8 The current count2 is: 9 The current count2 is: 10 The current count3 is: 11 The current count1 is: 12 The current count2 is: 14 The current count1 is: 13 The current count3 is: 15 The current count2 is: 16 The current count3 is: 17 The current count1 is: 18 The current count2 is: 19 The current count1 is: 20 The current count3 is: 21 The current count2 is: 22 The current count3 is: 23 The current count1 is: 24 The current count3 is: 25测试结果表明:无状态会话bean确实是无法保持会话状态的。但结果同时还显示了另外一个有趣的现象,即数字很大部分是累加的,这跟容器调度bean的算法是有关的。