哈哈,过了一个轻松的周末,又要开始写东西咯。
周末本来也想写,可是还是觉得玩有意思,姑且放几天假。
上次讲的是无状态会话BEAN。
好象还是有点不明白为什么要分无状态和状态会话BEAN这两种BEAN,不过不要紧,看完状态会话BEAN的程序就能明白了。对了,还有一点要说的。我周五那天搞了一天的ECLIPSE3,听说他出新版本了,所以赶紧下载试验试验,他在里边新加了功能叫EJB EDITOR,这个东西不错,有好多新东西。可是唯一另我费解的是为什么用他CREATE CLIENT TEST PROGRAMM的时候却总是报错!所以还是比较的烦躁的!也不知道是ECLIPSE的毛病还是我机器自己运行环境的毛病,大家也试试然后告诉我啊!
我的这个状态会话BEAN还是用ECLIPSE2.1写的拉。
我先把程序写给大家,然后再分析吧,我好象是那种喜欢先看程序然后再看理论的人。不知道是不是有人和我一样。
这是客户端的实现程序:
package com.test.session;
import javax.ejb.*;
/**
* @ejb.bean name="Stateful"
* jndi-name="StatefulBean"
* type="Stateful"
*
*--
* This is needed for JOnAS.
* If you are not using JOnAS you can safely remove the tags below.
* @jonas.bean ejb-name="Stateful"
* jndi-name="StatefulBean"
*
*--
**/
public abstract class StatefulBean implements SessionBean {
/**
* @ejb.create-method
* view-type="remote"
**/
public void ejbCreate(double amout) throws CreateException{
this.amout=amout;
}
/**
* @ejb.interface-method
* view-type="remote"
**/
public void addFunds(double amout){
this.amout+=amout;
}
/**
* @ejb.interface-method
* view-type="remote"
**/
public void withdrawFunds(double amout){
this.amout-=amout;
}
/**
* @ejb.interface-method
* view-type="remote"
**/
public double getBalance(){
return this.amout;
}
double amout;
}
对了,ejbCreate(double amout)方法是在BEAN生成过程中,容器调用ejbCreate(double amout)方法的。
就好象是初始化的方法一样。
还有你一定要确保在主接口中有个Create(double amout)方法和ejbCreate(double amout)对应啊!这段是必须的,如果不明白的话,赶紧找资料。你这个ejbCreate(double amout)方法在新建的时候要选择CREATE哦!
在把客户端的测试程序给你们:
package com.testing.client;
import java.rmi.RemoteException;
import java.util.Hashtable;
import javax.ejb.CreateException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.swing.JFrame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.text.*;
import com.test.session.*;
/**
* @author sy
*
* 更改所生成类型注释的模板为
* 窗口 > 首选项 > Java > 代码生成 > 代码和注释
*/
public class testStateful extends JFrame implements ActionListener{
public testStateful(){
super("fund manger");
}
private com.test.session.StatefulHome getHome() throws NamingException {
return (com.test.session.StatefulHome) getContext().lookup(
com.test.session.StatefulHome.JNDI_NAME);
}
private InitialContext getContext() throws NamingException {
Hashtable props = new Hashtable();
props.put(
InitialContext.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
props.put(InitialContext.PROVIDER_URL, "jnp://127.0.0.1:1099");
// This establishes the security for authorization/authentication
// props.put(InitialContext.SECURITY_PRINCIPAL,"username");
// props.put(InitialContext.SECURITY_CREDENTIALS,"password");
InitialContext initialContext = new InitialContext(props);
return initialContext;
}
public void CreateFund() {
try {
myBean = getHome().create(1000);
//--------------------------------------
//This is the place you make your calls.
//System.out.println(myBean.callYourMethod());
} catch (RemoteException e) {
e.printStackTrace();
} catch (CreateException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
}
public void testBean() {
buildGUI();
addWindowListener(new WindowAdapter(){public void WindowClosing(WindowEvent evt){System.exit(0);}});
CreateFund();
addFund.addActionListener(this);
withdraw.addActionListener(this);
currencyFomat=NumberFormat.getCurrencyInstance();
try{
String currency=currencyFomat.format(myBean.getBalance());
status.setText(msg+currency);
}catch(Exception e){}
pack();
show();
}
public void actionPerformed(ActionEvent e){
String str=amout.getText();
try{
if(e.getSource()==addFund){
myBean.addFunds(Double.parseDouble(str));
currencyFomat=NumberFormat.getCurrencyInstance();
strBar=currencyFomat.format(myBean.getBalance());
status.setText(msg+strBar);
}
if(e.getSource()==withdraw){
myBean.withdrawFunds(Double.parseDouble(str));
currencyFomat=NumberFormat.getCurrencyInstance();
strBar=currencyFomat.format(myBean.getBalance());
status.setText(msg+strBar);
}
}catch(Exception ex){}
}
public void buildGUI(){
GridBagLayout gl=new GridBagLayout();
GridBagConstraints gc=new GridBagConstraints();
Container container=getContentPane();
container.setLayout(gl);
gc.fill=GridBagConstraints.BOTH;
JLabel label=new JLabel("enter amout");
gl.setConstraints(label,gc);
container.add(label);
gc.gridwidth=GridBagConstraints.REMAINDER;
gl.setConstraints(amout,gc);
container.add(amout);
gl.addLayoutComponent(addFund,gc);
container.add(addFund);
gl.addLayoutComponent(withdraw,gc);
container.add(withdraw);
status=new JLabel(msg);
gl.addLayoutComponent(status,gc);
container.add(status);
}
double balance=100;
JTextField amout=new JTextField(10);
JButton addFund=new JButton("add funds");
JButton withdraw=new JButton("withdraw funds");
String msg="current funds is:";
String strBar="0";
JLabel status;
Stateful myBean;
NumberFormat currencyFomat;
public static void main(String[] args) {
testStateful test = new testStateful();
test.testBean();
}
}
看出来门道了吗?我终于知道为什么这个要叫做:状态会话BEAN了。因为,因为。。。。。哈哈,他有个amout变量,这个完全是EJB内部的变量,在EJB容器中保存!而和那个无状态会话BEAN不一样的地方就是,无状态会话BEAN是在客户端保存数据。很大的区别!这就是问题的关键!也不知道你们看懂了没有!反正我觉得真的很明显。
下边这个是我在IBM文章库里找的一副图,感觉不错,完全讲明白了状态BEAN是怎么回事拉:
这些是些讲解,和书上的差不多,省得我打字了。
有状态会话 Bean 生命周期:
Bean 在下列情况下被回收: 超时 (无论是激活的或钝化的) 被调用 remove() Passivation 是根据 Least-Recently-Used 算法 Activation 由对 Bean 的方法调用产生 afterBegin()
beforeCompletion()
afterCompletion()
方法仅对实现 SessionSynchronization 接口的 Bean 有效 在一个事务环境下,调用的方法必需具有相同的事务类型 OK,状态会话BEAN就是这么回事。应该是很简单的东西,完全可以理解。