個人EJB學習歷程

http://blog.csdn.net/sinapaper/archive/2004/06/28/28659.aspxphp

http://blog.csdn.net/sinapaper/archive/2004/06/29/29634.aspxhtml

http://blog.csdn.net/sinapaper/archive/2004/06/30/30538.aspxjava

http://blog.csdn.net/sinapaper/archive/2004/07/01/31231.aspxmysql

http://blog.csdn.net/sinapaper/archive/2004/07/05/34109.aspx算法

http://blog.csdn.net/sinapaper/archive/2004/07/05/34202.aspxsql

http://blog.csdn.net/sinapaper/archive/2004/07/14/41058.aspx數據庫

http://blog.csdn.net/sinapaper/archive/2004/07/15/42234.aspxapache

 

爲了力求新的進步,我認爲從今天起開始學習EJB編程。編程

但願各位志同道合的朋友能一塊兒參加進來。設計模式

我選用的參考書是wroxEJB編程指南。這個書有1000多頁,爭取能所有完畢他吧!

 

好了,很少說無用的了。現在開始進入第一章的學習。

 

第一章    Enterprise Javabeans 體系機構。

開始將講了一大堆廢話,從單層體系結構講到了多層體系結構,又講到了N層體系結構。這樣引出了主題(J2EE)。只是這句話翻譯的不錯:其餘需要特別注意的(是)server方資源包含線程,數據庫鏈接,安全、事務等等。定製處理這些資源的基礎結構是至關費勁的。這樣的工做在INTERNET環境中是不可能的。假設你的開發週期僅僅有三個月,可以對數據庫訪問創建鏈接池、對象緩衝區或「精彩的」對象層嗎?

暈!說了一大堆話最終引出了偉大的J2EE。只是要是不知道N層結構的真應該看看!

 

容器:說白了容器就是JAVA程序的執行環境。不知道個人理解是否正確。現在的程度就僅僅能理解到這了。

 

書上說J2EE規範定義了四種容器類型:

1.       小應用程序(APPLET)。

2.       應用程序客戶容器。(本身覺得就是SWING

3.       WEB容器(SERVLET JSP

4.       EJB容器。

 

看來123都已經掌握了,現在就差4了,因此EJB容器仍是要學習的哦!~

 

書上對EJB寫了個更加深刻的解釋:EJB是個分佈式組件模型,可以開發安全的、可伸縮的、事務性的多用戶組件。簡單的說,EJB是包含業務邏輯的可複用軟件單元。就象JSP可以將應用程序與業務邏輯分開同樣,EJB可以將應用程序邏輯和系統層服務分開,使開發者集中考慮業務問題,而沒必要考慮系統編程。

 

J2EE API

RMI/IIOPRemote Method Invocation類似網絡鏈接使用的一些東西。

JNDIJava Naming and Directory Interface

JDBC:這個不用說了吧?

JAVAMAIL/JAFJAVAMAIL服務,JAF是郵件的附件。

JMSJAVA MESSAGE SERVERJAVA消息服務。

 

設計中爲什麼使用EJB:說了一大堆,我仍是不肯定是爲何。再接着看吧!

 

只是此次我更加的肯定了,原來EJB容器就至關於一個「功能「server,可以把一些業務功能寫在這個裏邊。而後用123來調用咯!(不知道這麼說是否是有點搞笑)。

 

哈哈,個人理解正確了,果真書的第8頁就說了,容器可以當作是執行環境!

 

EJB的容器服務:(這裏的容器服務都是不用編碼,而是容器管理本身實現的啊。不錯)

 

組件池和壽命週期管理:

哈哈,來點白話的,這是我我的理解的,組件池在容器啓動的時候就本身生成了好多的BEAN的實例,假如說是10個吧,這個時候客戶1來了,他就拿了BEAN1,這個時候別人是不能使用BEAN1的,再來了第2個客戶,他不能拿BEAN1了,就僅僅能拿BEAN2了。。。。。。。這個時候客戶11來了,容器發現已經沒有BEAN給他用了,因而就找個現在沒人用的BEAN給他用,但是發現全都在被佔用,沒辦法了,就僅僅好再生成一個給他用了。哈哈,就是這麼簡單,但是有人會問了,這不是越生成越多嗎?不要緊,容器發現生成的BEAN沒人用了,就會本身主動的給刪掉,釋放空間,釋放系統資源嘛!

 

客戶會話管理:

理解鈍化和激活便可了。

鈍化就是把客戶的BEAN狀態保存在池中。

激活就是把客戶的這個BEAN狀態再還給客戶。

 

數據庫鏈接池:

這個好象不用講了吧!數據資源共享!這個名起的COOL B了。

 

事務管理:

事務很是是昂貴啊!

 

驗證和訪問控制:

這個很是easy!

 

 

容器怎樣提供服務:這一部分先不寫,之後再寫,因爲我也不怎麼理解。哈哈

 

EJB類型:*****這但是關鍵的地方。*****

分爲3種類型:

會話BEAN(壽命和所在客戶的會話同樣長啊)

1.       無狀態會話BEAN

2.       狀態會話BEAN

這兩個BEAN很是的重要,但是在第3章纔有講。哈哈,先擱這!

 

實體BEAN

本身理解就好象是數據庫BEAN,就是把數據庫的內容都讀出來放在BEAN裏,也不知道它具體是怎麼讀的,這樣作會不會很是浪費系統資源!???

 

實體BEAN依據同步的不同又可以分爲:

CMP(容器管理的持久性):容器負責BEAN與基礎的數據庫同步。

BMPBEAN管理的持久性):這裏要編程人員負責和基礎數據庫同步!容器在適當的時候調用編程人員寫好的SQL語句!

 

真不明確,爲何已經有CMP了還要出了個BMP,書上是這麼解釋的:

有時需要增長設計的靈活性或在非關係型存儲中支持持久性??這是人話嗎?

還有個例如:EJB規範V1.1僅僅容許實例變量和表格列之間的一對一映射。這樣,使用這個版本號時,假設要在實體BEAN中表示在多個表格中存儲狀態的累計對象,則沒法使用CMP,而要使用BMPEJB2.0規範定影了複雜的查詢語言!仍是很是費解!~~~~只是應該是實用吧!!之後預計就能搞明確!呵呵!~~

 

消息驅動BEAN。第6章講!等着吧!兄弟們~~~~

 

哈哈!看完第一章了。明天再看第2章!

 

 

先說點題外話, bromon說的真有點恐怖,不知道消息來源的真實性,假設真是那樣我想國內的人也不會當即就所有跑去轉用EJB3吧。呵呵,只是仍是要謝謝bromon 個人鐵杵個人針 ,個人第一篇文章最終有人看了,但願愈來愈多的人的增長!J

 

 

第一章    EJB開發

 

EJB的角色:(規定了6種開發和部署的角色)

l         企業BEAN提供者(Enterprise Bean Provider

工做任務例如如下:

1.編寫BEAN的主接口。

2.編寫BEAN的組件接口,聲明應用程序需要的各類業務方法。

3.編寫實現遠程接口中定義的各類業務方法的實現類。

4.編寫部署描寫敘述項。

5.打包。

 

事實上就是編寫EJB的編程人員。至於什麼是主接口,什麼是組件接口,什麼是實現類之後再說吧!先死記吧!

 

l         應用程序彙編者:事實上就是把BEAN提供者寫好的東西組織在一塊兒的人了。沒什麼大用,還號稱是行業專家!(開玩笑了)

 

l         部署者

 

l         系統管理員

 

l         EJB服務提供者,容器提供者(書上是分兩條的,但是我認爲他們應該是同樣的東西,至少臨時是同樣的東西)

 

事實上話說回來了,別的人都不怎麼重要,咱們要作的人就是企業BEAN提供者。

 

開發第一個EJB

高興,最終有個HELLOWORLD了!

你們必定要記住BEAN提供者的那幾個要素啊!很是關鍵的,全是從那幾個要素之間展開的。

 

HELLOWORD的題目是:依據年薪、公積金和所得稅計算每個月的淨收入。(無狀態會話BEAN)。

EJB客戶視圖:

本地客戶:使用本地接口和本地主接口。按引用傳遞值。

遠程客戶:使用遠程接口和遠程主接口。按變量傳遞值。會有java.rmi.RemoteException錯誤。

標準的設計模式是,業務邏輯層的所有訪問使用會話BEAN,這些會話BEAN需要發表遠程接口,使客戶層可以訪問這些會話BEAN。其他實體和無狀態會話BEAN可以當作「實施細節」,僅僅發表本地接口。

 

這是書上原話,你們明確嗎?反正我就僅僅能明確個80%。哈哈~~~再接着來。

 

開發主接口

倒!前邊講了一大堆主接口,現在纔想起來解釋,不知道老外這個書是怎麼寫的。

主接口負責控制BEAN的壽命週期操做:生成,刪除和尋找。主接口是客戶在BEAN中的第一個聯繫點。客戶經過JNDI取得引用。事實上是在部署的時候肯定JNDI的,不着急。

當客戶引用了主接口以後,就可以經過這個接口對BEAN進行下列操做:

l         生成新的實例或者尋找現有的BEAN實例。(本地或者遠程)

l         訪問EJBMetaData接口(遠程)。

l         取得BEAN實例的序列化引用(遠程)。

l         刪除BEAN實例。

l         執行主業務方法。

 

在這個樣例中僅僅使用主接口生成BEAN的新實例。

 

EJB裏定義了本地接口和遠程接口。(EJBHome EJBLocalHome)。這兩個接口的源程序書上有。

 

EJBHome接口中的方法:

getEJBMetaData():返回EJBMetaData接口的引用,取得BEAN信息。(仍是不知道EJBMetaData是什麼東西。查字典是元數據的意思)。

getHomeHandle():返回主對象的句柄。

remove():很是easy,刪除了。哈哈,玩笑,事實上對不一樣BEAN結果不同啦,會話BEAN是將BEAN再放回池中,而實體BEAN則是從數據庫中刪除數據。此次纔對嘛!

 

下邊就是程序了,我先試試程序到底是怎麼回事再給你們講啊!

 

經過本人對書本上演示樣例程序的分析,自我感受書上的演示樣例程序實在是沒有說服力,主要是部署工具出奇的麻煩,在這個JAVA不花錢的年代,怎麼能用J2EE自帶的部署工具,一大堆的配置實在是另人煩躁!呵呵。

說了一大堆,開始進入關鍵議題了,各位聽好了。

 

我選用的是ECLIPSE,這個免費的東西實在作的不錯,在我但是作STRUTS的時候就發現他的好多長處,但是實在遺憾,本人沒實用過JBUILDER,也不知道他們是否是同樣。

 

ECLIPSE有個LOMBOZ的插件,這個插件裏邊包含有所有server的配置方案。可以配置WEB MODEL,和EJB MODEL,這裏邊我選用JBOSSserver吧,因爲據說他也是不要錢的。

 

至於ECLIPSE下JBOSS是怎麼培植,這很是easy,僅僅要上GOOGLE上搜索‘ECLIPSE部署‘就有好多,聯想公司姜巍巍先生就寫了一篇配置,但是你們不要看他的EJB部署,實在是垃圾。依照他說的要想讓剛開始學習的人學會第一個EJB是有難度的!

你們仍是來看個人HELLOWORLD吧!

 

摘自http://www.objectlearn.com/support/docs/firstEJB.jsp

 

事實上我僅僅是幫你們翻譯一下,呵呵。看原文可以上上邊這個網址。

 

好了,很少說廢話了。現在開始。對了,必定要保證你的LOMBOZ和ECLIPSE都已經配置好了啊。

 

1.     新建一個Lomboz J2EE Project,叫"MyFirstEJBProject"。其餘的地方都不要改,NEXT。

2.     而後就能進入這個界面:

 

       

 

看見了吧,在這個的EJB MODULES中加一個新的MODULES,叫mybeans

              而後再選擇TARGET SERVER選項。就是這。

 

 

 

 

 

    選擇咱們剛纔說的已經配置好的JBOSS

 

 

 

3.     好了,現在假設不報錯的話。就點FINISH吧!

4.     第一個EJB模塊已經完畢,它可以給你生成EJB和EJB HOME,但是開發的實現類需要本身寫!下邊就是怎麼寫一個實現類。

5.       

     

 

這副圖能明確吧,但是有人要問了,這個東西哪兒來的?主界面,WINDOW菜單下的PERFERNECE,點他!哈哈,把裏邊有LOMBOZ的全選上就有了。

 

6.OK拉,依照下邊的圖把名字輸上:

 

 

 

 

這個時候FINISH就會生成一個TestSessionBean.java。這個就是生成的實現類了。

 

7.而後就是給這個實現類填加一些方法了。怎麼填呢?別改源碼,行不通,要這麼作:

 

 

 

而後,

 

 

 

這樣就可以增長方法了,千萬別手動加代碼啊,這樣會讓你組件接口找不到你寫的方法!

而後把這個實現類的方法改爲:

public String helloWorld(){

 return "Hello from lomboz!";

}//這個都知道是什麼意思吧

到現在爲止就算咱們已經作出來一個EJB程序了,僅僅只是是缺乏主接口,組件接口的一些東西,但是不要怕,ECLIPSE會給你本身主動生成的。厲害吧?接下來咱們就需要作這麼幾步:

a)     把剛纔寫的這個EJBBEAN增長到EJB中.

b)   生成主接口,組件接口.

c)      把他部署到server上.

d)     寫一個客戶程序來實驗他.

EASY吧!真的很是EASY啊!

8.這是a)那一步,把他增長到EJB中。就是剛纔咱們在EJB MODULES中創建的那個EJB。

 

 

9.各位觀衆,現在你們以最快的速度把這個界面找到。

 

 

而後作這個操做:

 

 

這個操做就是完畢任務b)的任務。

 

10.OK了,現在開始作c)了,就是把剛纔寫好的EJB部署到server上,依照下邊兩個圖來作。

 

 

 

 

找控制檯,看看你的部署成功不成功,要是成功的話。就可以作d)了。不成功的話,再來一遍!要是還不成功的話。找我吧。

 

11.現在咱們就要寫一個客戶程序來實驗他了,真是興奮啊!

先又一次創建一個JAVA項目,這樣才幹顯示出EJB的功能嘛。

 

 

新創建的項目叫這個名MyEjbClientProject,事實上隨便叫什麼名了。

NEXT進下一頁的時候一個要在PROJECT裏邊把咱們剛纔作的MyEJBClientProject給加上啊!不然白作了。

 

而後在NEW 菜單下找這個ITEMCREATE AN EJB TEST CLIENT。點上。

 

12.這麼配置。這個事實上根本都不用說。

 

 

FINISH以後就能看見這個類:TestClient.java

改動這種方法

public void testBean() {

            try {

                  com.testing.session.TestSession

                        myBean = getHome().create();

                  //--------------------------------------

                  //This is the place you make your calls.

                  System.out.println(myBean.helloWorld());

            } catch (RemoteException e) {

                  e.printStackTrace();

            } catch (CreateException e) {

                  e.printStackTrace();

            } catch (NamingException e) {

                  e.printStackTrace();

            }

      }

OKSAVE而後執行!!!!成功!!!

 

 

 

 

 

OK,一個最簡單的EJB完畢。最終可以進入到第三章了啊!

 

前邊的程序好用吧,我認爲比書上寫的麻煩的程序強多了,因此仍是得用工具的。

最終有了點EJB方面的成就,趁熱打鐵,現在當即就看第三章。

 

第一章           開發會話BEAN

你們都知道了,會話BEAN又分爲狀態會話BEAN和無狀態會話BEAN

書上總結了他們的共同點是:

1.      二者均可實現javax.ejb.SessionBean接口,所以具備一樣的容器回調。容器回調?現在中國的翻譯啊!

2.      二者都表示生成BEAN的客戶的專用資源。

3.      二者都可以構造一個進程或一個任務模型

4.      二者都可以更新共享數據,但不象實體BEAN中同樣表示共享數據。

NND,說了這麼多的共同點,說實話,我一點都不知道他說的是什麼意思?爲何要這麼專業??:(

 

只是不一樣點但是很是清楚:

狀態會話BEAN可以在客戶訪問之間保存數據,而無狀態則不可以!

 

管他呢,從樣例上找切入點。

 

無狀態會話BEAN的一個簡單樣例是計算數字,數字可以隨意複雜,但是僅僅在客戶程序中存放。哦!是這樣啊,事實上就至關沒有SESSION拉,但是好象還不能這麼說,姑且先這麼理解。

 

好拉,此次我決定採用書上的樣例,書上的樣例至關於一個BANK的系統!誇張,事實上就是加減數字的BEAN

 

這樣,咱們仍是用(三)裏邊講的方法來部署他:

記得是一個無狀態會話BEAN的樣例啊。

新建一個實現類,個人是這麼寫的:

 

 

 

package com.testing.fund;

 

import javax.ejb.SessionBean;

 

/**

 * @ejb.bean name="FundManger"

 *  jndi-name="FundMangerBean"

 *  type="Stateless"

 *

 *--

 * This is needed for JOnAS.

 * If you are not using JOnAS you can safely remove the tags below.

 * @jonas.bean ejb-name="FundManger"

 *  jndi-name="FundMangerBean"

 *

 *--

 **/

 

public abstract class FundMangerBean implements SessionBean {

 

/**

 * @ejb.interface-method

 *  view-type="remote"

**/

public double add(double b,double a){

    b=b+a;

 return b;

}

/**

 * @ejb.interface-method

 *  view-type="remote"

**/

public double withdraw(double b,double a){

    b=b-a;

 return b;

}

}

 

 

要記得這裏邊的ADD和WITHDRAW方法不是手動加上的啊,是用WIZARD的啊。要是不會的話,看個人(三)去!!!!

 

而後依照(三)裏邊的方法部署到JBOSS上邊去!

 

一切成功的話,仍是依照(三)的方法寫一個實現類!個人是這樣寫的,和書上有點不同,只是實現方法是全然同樣的!

 

 

 

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.*;

import java.awt.*;

import java.awt.event.*;

import java.text.*;

import com.testing.fund.FundManger;

 

public class FundTest extends JFrame implements ActionListener{

   

    public FundTest(){

       super("fund manger");

    }

 

    private com.testing.fund.FundMangerHome getHome() throws NamingException {

       return (com.testing.fund.FundMangerHome) getContext().lookup(

           com.testing.fund.FundMangerHome.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 testBean() {

      

       buildGUI();

      

       addWindowListener(new WindowAdapter(){public void WindowClosing(WindowEvent evt){System.exit(0);}});

       CreateFund();

       addFund.addActionListener(this);

       withdraw.addActionListener(this);

       currencyFomat=NumberFormat.getCurrencyInstance();

       String currency=currencyFomat.format(0);

       status.setText(msg+currency);

      

       pack();

       show();

    }

   

    public void actionPerformed(ActionEvent e){

       String str=amout.getText();

      

       try{

           if(e.getSource()==addFund){

              balance=(double)myBean.add(balance,Double.parseDouble(str));

              currencyFomat=NumberFormat.getCurrencyInstance();

              strBar=currencyFomat.format(balance);

              status.setText(msg+strBar);

           }

           if(e.getSource()==withdraw){

              balance=(double)myBean.withdraw(balance,Double.parseDouble(str));

              currencyFomat=NumberFormat.getCurrencyInstance();

              strBar=currencyFomat.format(balance);

              status.setText(msg+strBar);

           }         

          

       }catch(Exception ex){}

    }

 

 

 

    public void CreateFund(){

      

 

       try {

            myBean = getHome().create();

 

           //--------------------------------------

           //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 static void main(String[] args) {

       FundTest test = new FundTest();

       test.testBean();

 

    }

   

    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;

   

    FundManger myBean;

   

    NumberFormat currencyFomat;

   

}

 

執行爲JAVA 應用程序!成功了!界面例如如下:

 

現在來想一想爲何是無狀態會話BEAN了,事實上這個EJB就至關於一個簡單的應用程序後臺數據處理器!你的所有數據記錄信息所有都在前臺了,也就是上邊這個界面上邊。

 

OK,下節課就是狀態會話BEAN了。

 

哈哈,過了一個輕鬆的週末,又要開始寫東西咯。

週末原本也想寫,但是仍是認爲玩有意思,姑且放幾天假。

 

上次講的是無狀態會話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就是這麼回事。應該是很是easy的東西,全然可以理解。

 

 

 

呵呵,你們看見了那個總回我帖子的QUGHOST了嗎?他是個人好朋友。

他有好多的搞笑故事,我和他商議了一下,準備把他的搞笑經歷發在個人一個新版塊裏,但是不知道他容許不容許。

 

OK,話歸正傳。我當即就要把第三章結束了,事實上第三章的會話BEAN5就已經講完了,但是這裏邊另外一個很是關鍵的東西,那就是序列化。

 

序列化 (Serialization)

  • Java 序列化機制可以將整個對象的狀態輸出到一個流上
  • 對象可以再從其原始狀態又一次構建回來

事實上很是easy了,就是把某個對象的所有東西都輸出到一個文件上。這裏也可以是別的東西。好多。

而後當你還想用他的時候,就再在這個文件上把這個對象的狀態等等的一些信息所有找回來。

 

真正發生了什麼

  • Bean 的實例沒有被序列化
    假設 Bean 實例自己被序列化,當它被又一次構建時一個新的實例需要被建立這就丟失了實例池的意義
  • Bean 的狀態被序列化
    每一個屬性需要被單獨考慮

什麼會被序列化?

  • 一個可序列化 (serializable) 的對象
  • 一個 null
  • 對特定不可序列化對象的直接引用:
    • 一個 Bean home remote 接口的引用
    • SessionContext 的引用
  • 對不可序列化部分的直接引用的序列化
    • 容器必需對不可序列化的 EJB 在鈍化時保存它們的 remote home 接口
    • 或許依賴於 Java java.io.ObjectOutputStream java.io.ObjectInputStream 中的對象替換技術來實現

部分序列化

  • 構成狀態的每樣屬性必需是可序列化的
  • 所有屬性的內容必需包含可序列化的值
  • Helper
  • 不然容器可以選擇在鈍化時回收該 Bean 實例

 

這些全是我從IBM抄下來的。但願對你們理解序列化有幫助。

 

把個人程序也給大家吧,我用的仍是那個狀態會話BEAN的那個EJB

 

/*

 * 建立日期 2004-7-5

 *

 * 更改所生成文件模板爲

 * 窗體 > 首選項 > Java > 代碼生成 > 代碼和凝視

 */

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 com.test.session.*;

 

import java.io.*;

import javax.ejb.Handle;

 

 

/**

 * @author sy

 *

 * 更改所生成類型凝視的模板爲

 * 窗體 > 首選項 > Java > 代碼生成 > 代碼和凝視

 */

public class HandleTest {

 

    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 testBean() {

 

        try {

            com.test.session.Stateful myBean = getHome().create(1000);

           

            //System.out.println("adding 1000");

           

            myBean.addFunds(1000);

           

            System.out.println("adding 1000");

           

            System.out.println("Now Account is:"+myBean.getBalance());

           

            myBean.withdrawFunds(100);

           

            System.out.println("withdrawing 100");

           

            System.out.println("Now Account is:"+myBean.getBalance());

           

            System.out.println("saving Handle");

           

            saveHandle(myBean);

           

            System.out.println("saving success");

           

            myBean=null;

           

            System.out.println("loading Handle");

           

            myBean=loadHandle();

           

            System.out.println("loading success");

           

           

           

            System.out.println("Now Account is:"+myBean.getBalance()+",withdrawing 100");

           

            myBean.withdrawFunds(100);

           

            System.out.println("Now Account is:"+myBean.getBalance());

           

 

            //--------------------------------------

            //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 static void main(String[] args) {

        HandleTest test = new HandleTest();

        test.testBean();

 

    }

   

    private static void saveHandle(Stateful mybean){

        try{

            FileOutputStream fos=new FileOutputStream("symic");

            ObjectOutputStream out=new  ObjectOutputStream(fos);

           

            out.writeObject(mybean.getHandle());

           

            out.close();

        }catch(Exception e){}

    }

   

    private static Stateful loadHandle(){

        try{

            FileInputStream fis =new FileInputStream("symic");

            ObjectInputStream in =new ObjectInputStream(fis);

           

            Handle handle=(Handle)in.readObject();

           

            Stateful mybean=(Stateful)handle.getEJBObject();

           

            in.close();

           

            return mybean;

        }catch(Exception x){}

        return null;

    }

}

 

事實上很是easy,看個人程序就好,而後找找SYMIC文件,看看他裏邊寫了些什麼東西。哈哈~~~~

 

說點別的,我近期發現原來ITLAY真的是個不錯的國家。但是好象在中國根本就沒有機會去吧!

ITaly ,SHopper's DEstinatiON!

 

在他那買東西很是合適啊!據說PRADA,AMANI在那有很是多TAX REBATE的店啊,僅僅有國內的一半價錢,並且東西全是最TOP 的CLASS。

 

真想去啊~~~~~~~~~~

 

ITALY MY DREAM-PRADISE!

 

呵呵!~~~

 

最終可以又出新東西了。上個禮拜一直沒忙,公司帶咱們出去HAPPY了。只是現在水好涼,不能下水。纔下去兩分鐘瞬間就被凍上來了。特別的冷。

 

恩,言歸正傳。我一直在看CMP,實體BEAN,但是發現要弄好ENTITYBEAN首先要作的是知道怎麼配置server,我找到了一篇配置JBOSSserver的指南,認爲不錯,就在這給你們SHARE一下。

http://www.uml.org.cn/j2ee/j2ee121505.htm

JBoss3.07的配置

    這裏需要對JBoss進行配置的地方有兩處,一處爲JBoss的日誌信息選項,使得咱們從此在部署EJB時可以獲得關於部署的具體信息;另外一處爲JBoss中的數據源,使得咱們可以使用容器持久化管理的EntityBean對數據庫中的數據進行操做。

    (1)首先咱們講述日誌信息選項的更改,進入JBoss所在文件夾下的server/default/conf文件夾,找到文件log4j.xml,將其用文本編輯器打開,將屬性做例如如下改動:

改動一:

 

  < category name="org.jboss" >

    < priority value="INFO" / >

  < / category >

 

改動爲:

 

  < category name="org.jboss" >

    < priority value="INFO" / >

  < / category>

改動二:

 

 

  < appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender" >

    < param name="Threshold" value="INFO" / >

    < param name="Target" value="System.out" / >

改動爲:

  < appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">

    < param name="Threshold" value="DEBUG"/>

    < param name="Target" value="System.out"/>

將這些屬性進行改動以後,當咱們部署CMP EntityBean的時候將能看見JBoss針對所部署的CMP EntityBean本身主動產生的SQL插入語句與CMP EntityBean中包含的EJB-QL語句;並且在EntityBean被使用時發生的SQL查詢語句。

(2)接着咱們講述數據源的配置,第一步:咱們進入JBoss的文件夾下的docs/examples/jca文件夾,用文本編輯器打開mysql-service.xml,將當中的部份內容做例如如下改動:

< attribute name="JndiName">MySqlDS(數據源名稱)< / attribute>

< attribute name="ManagedConnectionFactoryProperties">

< properties>

< config-property name="ConnectionURL" type="java.lang.String" >jdbc:mysql://localhost:3306/resultmanager

 

(數據庫URL)

       

< / config-property>

< config-property name="DriverClass" type="java.lang.String" >com.mysql.jdbc.Driver

(數據庫驅動程序)

< / config-property>

< config-property

name="UserName" type="java.lang.String">DataBase(數據庫用戶)

< / config-property>

< config-property

name="Password" type="java.lang.String" >

sailing(數據庫用戶密碼)

< / config-property>

< / properties>

< /attribute>

 

將改動好的內容保存後,複製mysql-service.xml文件至JBoss文件夾下server/default/deploy 文件夾,此時deploy文件夾中的文件例如如下圖所看到的:

第二步,咱們將含有MySQL JDBC 2.0.14驅動程序的jar文件拷貝到JBoss安裝文件夾的server/default/lib文件夾下,此時lib文件夾中的文件例如如下圖所看到的:

現在咱們已經完畢了前期的配置工做,接下來咱們將講述CMP EntityBean的開發。

你們先依照以上的方法把JBOSS配置好,而後作好準備,咱們要開始CMP了,是數據庫的東西啊!!!

 

這個禮拜發生了好多事情啊。因此一直沒有時間寫。只是好多人問我怎麼不寫了啊?我是要寫的,現在就開始寫。(五)裏邊有個弟兄問個人IBM的站點在哪兒,個人收藏夾被DEL了,在GOOGLE上找了很久也沒找到,等我找到了,再發上去!

 

只是我之後會把我所有引用網址都給打上去。

 

好了,現在進入個人第4章咯。

開發EJB1.1實體BEAN,好象關於EJB實體BEAN還要分版本號的,只是現在我也不清楚爲何分版本號。

因爲數據庫BEAN這個地方的部署我也沒有搞清楚,因此我找了LOMBOZ上邊有個演示樣例程序,我們先把這個實驗好了,而後再照書作,OK?

 

摘自:http://www.objectlearn.com/support/docs/cmp.jsp

 

1-9步和我曾經寫的同樣,是怎樣創建J2EE項目的,這在我曾經的我文章裏有寫。

從第10步開始寫吧:

現在選中CMP這一項。 而後打上你本身中意的名字和包名,作NEXT。

而後就會進入到CMP這個界面了:事實上這個界面一看就知道是怎麼回事:

 

寫上表名,加上字段,一切簡單的OK了。記得啊,這裏DATASOURCE必定要和表裏邊的字段同樣。

還有相應的數據類型。可以加好多的字段,但是這個樣例裏邊就給了兩個字段,咱們也姑且用他這兩個字段。

對對了,還有就是設置一個PRIMARY KEY。搞定。FINISH。

 

這個時候ECLIPSE會本身就把你剛纔創建的AddressBean給打開。

而後你照着這個樣例改代碼,事實上不講爲何這麼改你們也都能明確:

package com.testing.cmp;

import javax.ejb.EntityBean;

/**
* @ejb.bean name="Address"
* jndi-name="AddressBean"
* type="CMP"
* primkey-field="name"
* schema="addressSchema"
* cmp-version="2.x"
*
* @ejb.persistence
* table-name="address"
*
* @ejb.finder
* query="SELECT OBJECT(a) FROM addressSchema as a"
* signature="java.util.Collection findAll()"
*
**/

public abstract class AddressBean implements EntityBean {

...

 

Modify the ejbCreate and ejbPostcreate methods to accepts two parameters:

/**
* The ejbCreate method.
*
* @ejb.create-method
*/

public java.lang.String ejbCreate(String name, String phone)
     throws javax.ejb.CreateException {
        setName(name);
        setPhone(phone);
        return null;
}

/**
* The container invokes this method immediately after it calls ejbCreate.
*
*/

public void ejbPostCreate(String name, String phone) throws javax.ejb.CreateException {
}

必須改POST和CREATE方法的內容啊。等下再告訴大家爲何要這樣作,對了,他裏邊還都幫你寫好了

setName();

setPhone();方法。直接用就行了。

 

而後SAVE,把剛纔寫的BEAN加到EJB裏邊,就是用J2EE->Add Ejb to Modules ,而後選擇你剛纔創建的EJB就行了。

 

下邊是最討厭的東西了,就是寫個EJBDOCLET,演示樣例給的是要改ejbGenerate.xmlNND,我根本就沒有這個文件,後來查了好多的資料,才知道,原來他那個是舊版本號,鬱悶~~~~~~舊版本號還要往上貼。

 

咱們3.X要改的是xdoclet.xml這個文件,這個文件保證有,你們找到以後就能看見,他裏邊有好多種配置server的數據庫的XML,我用的是JBOSS,因此就改這塊了。

< jboss

            version="3.0"

            unauthenticatedPrincipal="nobody"

            xmlencoding="UTF-8"

            destdir="${ejb.dd.dir}"

            validatexml="false"

            datasource="java:/MySqlDS"

            datasourcemapping="mySQL"

            preferredrelationmapping="PLEASE_MODIFY_THIS"

/ >

 

對了對了,講到這我找到了文章也不錯,是個小J寫的。給大家地址:
http://nemuneko.com/jboss/lomboz_cmp.html

因爲我近期在學日語,因此能看明確點,看不明確的就看圖理解咯~~~~~

 

注意啊,這裏是最關鍵的地方,我認爲,多是因爲我比較的笨。呵呵。

 

這裏的MySqlDS是我在(7)裏邊寫的在JBOSS裏邊配置的DEFUALT DATASOUCE,對了,我依照7裏邊寫的把mysql-service.xml這個配置文件放的位置好象不可以,我查了很久才找到,原來是你的EJB部署到哪一個文件夾下,這個mysql-service.xml文件就要跟着放到那個文件夾下,我機器上的是:D:/jboss-3.0.8/server/default/deploy

這個文件夾。最後就是把你的DB DRIVER放在和這個文件夾相應的LIB裏邊。

我機器上是這個:

D:/jboss-3.0.8/server/default/lib

 

我用的是Mysql 的driver,沒有問題的。

 

這樣配置就應該是沒問題了。

對了,把建表的語句也給大家:create table address ( name varchar(40) , phone varchar(40));

 

而後SAVE你的XDOCLET.XML。作GENERATE EJB FILES,和DEPLOY。

假如你成功的話,就能看見這麼一段的輸出:

 

22:50:11,031 INFO [MainDeployer] Starting deployment of package: mybeans.jar
22:50:11,302 INFO [EjbModule] Creating
22:50:11,342 INFO [EjbModule] Deploying Address
22:50:11,392 INFO [EjbModule] Created
22:50:11,392 INFO [EjbModule] Starting
22:50:11,822 INFO [Address] Table 'ADDRESS' already exists
22:50:11,842 INFO [EjbModule] Started
22:50:11,842 INFO [MainDeployer] Deployed package: mybeans.jar

 

必定要看輸出啊!很是關鍵的地方。

 

這樣就完畢了咱們的EJB CMP的BEAN了。再寫個CLIENT測試他就OK了。

 

把個人CLIENT程序給大家。

 

public void testBean() {

            try {
                Address address = getHome().create("John Smith", "+212 223 4455");
                Collection all = getHome().findAll();
                Iterator it = all.iterator();
                while (it.hasNext()) {
                    Address element = (Address) it.next();
                    System.out.println("Name:" +
                        element.getName() + " Phone: " +element.getPhone() );
                 }

            } catch (Exception e) {

                  e.printStackTrace();

            }

      }

IMPORT本身記得加啊~哈哈。

執行,成功!!!!!!

 

下次又的寫些理論上的東西,說實話,我最討厭理論的東西,因爲看上去真的很是頭大!~~

 

 

 

http://nemuneko.com/jboss/lomboz_cmp.html

 

下邊這段文字是在CN-JAVA下COPY過來的。(http://www.cn-java.com/target/news.php?news_id=2174)

1、entity Bean 表明了以持久存儲機制保存的一個實體,一般爲一個DB。客戶機經過entity beanremote接口訪問它,實現該remote接口的對象被稱爲EJB對象。每一個
entity
對象都有一個標識符。
Entity Bean
的特徵:持久的(分爲BMPCMP),容許共享訪問,並且有一個主鍵。
2、編寫規則:
 
 1.(1)實現EntityBean的接口。
  (2).類定義爲PUBLIC
  (3).類不能定義爲abstract final
  (4).實現finaler方法(僅用於BMP)
  (5).實現商業方法。
(6).
含有一個空構造器。
(7).
不能實現finalize方法。
 2.ejbCreate應知足的規則:
  (1).訪問控制修飾符必須爲public
(2).
返回類型必爲主鍵(僅對於BMP)
(3).
參數必須爲僉的JAVA RMI類型。
(4).
方法修飾符不能爲finalstatic
(5).throws
子句可以包含CreateException以及應用程序中指定的其餘異常。
3.ejbPostCreate:
每一個ejbCreate必須相應一個ejbPostCreate方法,一般爲空。
(1).
參數的數量和類型必與相應ejbCreate方法匹配。
(2).
訪問控制修飾符必須爲public
(3).
方法修飾符不能爲final static
(4).
返回類型必須爲void
(5).throws
子句包含CreateException以及應用程序中指定的其餘Exception
  4.ejbRemove方法:當EJB客戶調用此方法時,將刪除DB中該實體的狀態或EntityBean
    被一個DB刪除直接移走。
  5.ejbLoad方法:利用DB刷新實體變量。
   ejbStore方法:將變量寫到DB中。
這兩個方法用於同步與存貯在DB中的值所相應的EntityBean實體變量。
  6.finder方法的規則:
(1).
必須ejbFindByPrimaryKey方法。
(2).finder
方法務必須以ejbFind爲前綴。
(3).
訪問控制修飾符必須爲public
(4).
方法修飾符不能爲final static
(5).
參數必須是合法的Java RMI類型。
(6).
返回類型必須爲主鍵或主鍵的集合。
(7).throws
子句包含FinderException以及應用程序中指定的其餘Exception
  7.商業方法
(1).
方法名不能與EJB結構定義的方法名衝突。
(2).
訪問控制修飾必爲public.
(3).
方法修飾不能final static
(4).
參數必須爲合法的Java RMI類型。
.Home接口的編寫規則:
1.Create
方法的編寫規則:
(1).
它與enterprise Bean類中相應的方法同樣,含有一樣的參數。
(2).
返回Remote接口類型。
(3).throws
子句包含相應的ejbCreate ejbPostCreate方法的異常。
2.finder
講法的編寫規則:
(1).Remote
接口中的每一個方法必須與enterpriseBean類中的方法匹配。
(2).
每一個方法命名規則與enterprise Bean類中的方法的命名規則同樣。
(3).
參數和返回類型必須是合法的Java RMI類型。
(4).throws
子句包含RemoteException

相關文章
相關標籤/搜索