paulwong

Entity Bean(2)

四、Entity bean的實作

 

在上一節我們簡略地介紹了entity bean的生命週期的各種狀態與相關的life-cyclecall back方法,在本節中我們則要以實際的程式碼說明CMPBMP在實作這些life-cyclecall back方法時的異同與值得注意之處。但無論是CMP beanBMP bean,開發人員都必須提供下列檔案:

1.       Bean class

Bean class必須視其為CMPBMP,宣告或實作其屬性的getter/setter方法、call back方法、與home interface相應的life-cycle方法。

2.       Primary key

Entity beanprimary key的類型必須是任何繼承或實作java.io.Serializable的物件或class。如果primary key field是基本類型或複合型的primary key,則我們必須提供另外的class檔將其包裹起來使用。

3.       Home interface

我們必須在Home interface上定義與entity bean生命週期有關的life-cycle方法,如create()findBy()等方法。

4.       Component interface

我們在這裡定義client端所能使用的business方法。

5.       Deployment descriptor(部署描述子)

我們在此設定與entity bean及其背景服務有關的訊息。

CMP bean

EJB 1.1規格書中,CMPBMP都是concrete classes,但在EJB 2.0規格書中,則將CMP規定為abstract classes。開發人員必須將bean class宣告為abstract,並為每一個定義在部署描述子中與資料庫欄位對應的CMP field,宣告抽象的getter/setter方法。在部署階段,部署工具會產生abstract classsubclass以實作這些抽象的getter/setter方法,以及其他life-cyclecall back方法。以下是相關的部署描述子、bean class以及interface的範例。:

Code 1Deployment Descriptor(ejb-jar.xml) Fragment for Member Entity Bean(CMP)

10     <entity>

11             <display-name>MemberEJB</display-name>

12             <ejb-name>MemberEJB</ejb-name>

13             <local-home>com.eland.ejb.MemberLocalHome</local-home>

14                         <local>com.eland..ejb.MemberLocal</local>

15                         <home>com.eland.ejb.MemberRemoteHome</home>

16                         <remote>com.eland.ejb.MemberRemote</remote>

17                         <ejb-class>com.eland.ejb.MemberBean</ejb-class>

18                         <persistence-type>Container</persistence-type>

19                         <prim-key-class>java.lang.String</prim-key-class>

20                         <reentrant>False</reentrant>

21                         <cmp-version>2.x</cmp-version>

22                         <abstract-schema-name>Member</abstract-schema-name>

23                         <cmp-field>

24                                <description>Primary key</description>

25                                <field-name>userid</field-name>

26                         </cmp-field>

27                         <cmp-field>

28                                <description></description>

29                                <field-name>username</field-name>

30                         </cmp-field>

31                         <cmp-field>

32                                <description></description>

33                                <field-name>password</field-name>

34                         </cmp-field>

35                         <query>Implemetation of QL</query>

36                         <primkey-field>userid</primkey-field>

36     </entity>

Code 2Entity Bean Implementation for Member Entity Bean(CMP)

1      package    com.eland.ejb;

2

3      import       javax.ejb.*;

4      import      javax.naming.*;

5

6      public abstract class MemberBean implements EntityBean {

7

8              private EntityContext context;

9

10             // virtual persistence fields

11             public abstract String getUserid();

12             public abstract void setUserid();

13

14             public abstract String getUsername();

15             public abstract void setUsername();

16

17             public abstract String getPassword();

18             public abstract void setPassword();

19

20             // container callback methods

21             public String ejbCreate(String userid, String username, String password)

22                     throws CreateException {

23                     setUserid(userid);

24                     setUsername(username);

25                     setPassword(password);

26                     return null;

27             }

28

29             public void postCreate(String userid, String username, String password)

30                     throws CreateException {

31             }

32

33             public void setEntityContext(EntityContext ctx) {

34                     context = ctx;

35             }

36

37             public void unsetEntityContext() {

38                     context = null;

39             }

40

41             public void ejbRemove() {}

42             public void ejbActivate() {}

43             public void ejbPassavate() {}

44             public void ejbLoad() {}

45             public void ejbStore() {}

46     }

Code 3Local Component Interface for Member Bean

1      package    com.eland.ejb;

2

3      import       javax.ejb.*;

4

5      public interface MemberLocal extends EJBLocalObject {

6              public String getUserid();

7              public String getUsername();

8                             public String getPassword();

9                             public void remove();

9      }

Code 4Local Home Interface for Member Bean

1      package    com.eland.ejb;

2

3      import       javax.ejb.*;

4

5      public interface MemberLocalHome extends EJBLocalHome {

6              public MemberLocal create(String userid, String username, String password)

7                      throws CreateException;

8              public MemberLocal findByPrimaryKey(String userid)

9                            throws FinderException;

1                    public Collection findByName(String name)

10                        throws FinderException;

11         }

Code 5Remote Component Interface for Member Bean

1             package    com.eland.ejb;

2              

3             import       javax.ejb.EJBObject;

4             import       java.rmi.RemoteException;

5              

6             public interface MemberRemote extends EJBObject {

7                    public String getUsername() throws RemoteException;

8                    public void setUsername(String name) throws RemoteException;

9                    public String getPassword() throws RemoteException;

10                public void setPassword(String pw) throws RemoteException;

11                public void remove() throws RemoteException;

12         }

Code 6Remote Home Interface for Member Bean

2             package    com.eland.ejb;

3              

4             import       javax.ejb.EJBHome;

5             import       javax.ejb.CreateException;

6             import       javax.ejb.FinderException;

7             import       java.rmi.RemoteException;

8             import       java.util.Collection;

9              

10         public interface MemberRemoteHome extends EJBHome {

11                public MemberRemote create(String userid, String username, String password)

12                        throws RemoteException, CreateException;

13                public MemberRemote findByPrimaryKey(String id)

14                        throws RemoteException, FinderException;

15                public Collection findByName(String name)

16                        throws RemoteException, FinderException;

17         }

在編寫CMP bean的程式碼時需要注意幾件事:

1.       Entity beanbean class必須實作javax.ejb.EntityBeanhome interfacecomponent interface則必須分別繼承javax.ejb.EJBLocalHomejavax.ejb.EJBLocalObject;如果有remote home interfaceremote interface,則必須分別繼承javax.ejb.EJBHomejavax.ejb.EJBObject

2.       Bean class中必須宣告與所有定義在部署描述子中的CMP fields相應的getter/setter方法。

3.       Bean class中的ejbCreate()方法與ejbPostCreate()方法必須成對出現,並接受相同的參數傳入。

4.       Bean class中可以有多對ejbCreate()方法與ejbPostCreate()方法,bean class中有幾對ejbCreate()方法與ejbPostCreate()方法,home interface上就必須有幾個create()方法,並且傳入的參數要一致。

5.       Home interface中必須要有findByPrimaryKey()方法,但bean class裡不必有相應的方法,實作部分於部署階段由部署工具產生。除了findByPrimaryKey()方法以外的findBy()方法,則必須在部署描述子中宣告與其對應<query>標籤與QL語法,我們將在下期介紹QL語法的使用。

6.       Home interface上所有create()方法必須宣告丟出CreateExceptionfindBy()方法必須丟出FinderException。所有remote interface上的方法必須宣告丟出RemoteException

7.       開發人員不需實作CMP bean class中的call back方法。而在屬於life-cycle方法的ejbCreate()方法中只需要初始化CMP fields即可。

BMP bean

前面提到,BMP bean將資料保存的責任交由開發人員負責,因此開發人員必須在BMP beanbean class中實作存取資料庫的程式碼,而這些程式碼主要就是寫在所謂的call backlife-cycle方法中。實作這些程式碼的目的在於在適當時機對entity bean與資料庫裡的資料作同步化的動作,但何時是適當的時機則由EJB Container視系統狀況而定。以下是BMP bean的部署描述子、bean class的範例。由於CMP beanBMP beaninterfaces並無規格上的分別,因此BMP beaninterface部分請參考前面CMP bean interfaces的範例(Code 3Code 6)

Code 7Deployment Descriptor(ejb-jar.xml) Fragment for Member Entity Bean(BMP)

10         <entity>

11                <display-name>MemberEJB</display-name>

12                 <ejb-name>MemberEJB</ejb-name>

13                <local-home>com.eland.ejb.MemberLocalHome</local-home>

14                <local>com.eland..ejb.MemberLocal</local>

15                <home>com.eland.ejb.MemberRemoteHome</home>

16                <remote>com.eland.ejb.MemberRemote</remote>

17                <ejb-class>com.eland.ejb.MemberBean</ejb-class>

18                <persistence-type>Bean</persistence-type>

19                <prim-key-class>java.lang.String</prim-key-class>

20                <reentrant>False</reentrant>

21                <resource-ref>

22                        <description>DataSource for the Test database</description>

23                        <res-ref-name>jdbc/TestDB</res-ref-name>

24                        <res-type>javax.sql.DataSource</res-type>

25                        <res-auth>Container</res-auth>

26                </resource-ref>

27         </entity>

Code 8Entity Bean Implementation for Member Entity Bean(BMP)


1      package    com.eland.ejbl

2     

3      import       javax.naming.*;

4      import       javax.ejb.*;

5      import       java.rmi.RemoteException;;

6      import       java.sql.*;

7      import       javax.sql.DataSource;

8      import       java.util.*;

9     

10         public class MemberBean implements EntityBean {

11             private String userid;

12             private String username;

13                         private String password;

14                          

15                         public EntityContext context;

16                          

17                         public String getUsername() {

18                                return username;

19                         }

20                         public void setUsername(String name) {

21                                username = name;

22                         }

23                         public String getPassword() {

24                                return password;

25                         }

26                         public void setPassword(String pw) {

27                                password = pw;

28                         }

29                          

30                         public String ejbCreate(String userid, String username, String password)

31                                throws CreateException {

32                                this.userid = userid;

33                                this.username = username;

34                                this.password = password;

35                               

36                                Connection con = null;

37                                PreparedStatement ps = null;

38                                try {

39                                        con = this.getConnection();

40                                        ps = con.prepareStatement(

41                                                “insert into Member(userid, username, password) values(?,?,?)”);

42                                        ps.setString(1, userid);

43                                        ps.setString(2, username);

44                                        ps.setString(3, password);

45                                        if(ps.executeUpdate() != 1) {

46                                                throw new CreateException(“Failed to add member to database”);

47                                        }

48                                        return userid;

49                                } catch(SQLException se) {

50                                        throw new EJBException(se);

51                                } finally {

52                                        try {

53                                                if(ps != null) ps.close();

54                                                if(con != null) con.close();

55                                        } catch(SQLException se) {

56                                                se.printStackTrace();

57                                        }

58                                }

59                          

60                                public void ejbPostCreate(String userid, String username, String password) {

61                                       

62                                }

63                          

64                                public String ejbFindByPrimaryKey(String primaryKey) throws FinderException {

65                                        Connection con = null;

66                                        PreparedStatement ps = null;

67                                        ResultSet result = null;

68                                        try {

69                                                con = this.getConnection();

70                                                ps = con.prepareStatement(“select userid from Member where userid=?”);

71                                                ps.setString(1, primaryKey);

72                                                result = ps.executeQuery();

73                                                if(!result.next()) {

74                                                        throw new ObjectNotFoundException(

75                                                                “Cannot find member with userid = ” + primaryKey);

76                                                }

77                                        } catch(SQLException se) {

78                                                throw new EJBException(se);

79                                        } finally {

80                                                try {

81                                                        if(result != null) result.close();

82                                                        if(ps != null) ps.close();

83                                                        if(con != null) con.close();

84                                                } catch(SQLException se) {

85                                                        se.printStackTrace();

86                                                }

87                                        }

88                                        return primaryKey;

89                                }

90                          

91                                public Collection ejbFindByName(String username) throws FinderException {

92                                        Connection con = null;

93                                        PreparedStatement ps = null;

94                                        ResultSet result = null;

95                                        try {

96                                                con = this.getConnection();

97                                                ps = con.prepareStatement();

98                                                “select userid from Member where username=?”);

99                                                ps.setString(1, username);

100                                             result = ps.executeQuery();

101                                             Vector keys = new Vector();

102                                             while(result.next()) {

103                                                     keys.addElement(result.getObject(“userid”));

104                                             }

105                                             return keys;

106                                      } catch(SQLException se) {

107                                             throw new EJBException(se);

108                                     } finally {

109                                             try {

110                                                     if(result != null) ps.close();

111                                                     if(ps != null) ps.close();

112                                                     if(con != null) con.close();

113                                             } catch(SQLException se) {

114                                                     se.printStackTrace();

115                                             }

116                                     }

117                             }

118                            

119                             public void setEntityContext(EntityContext ctx) {

120                                      context = ctx;

121                             }

122                       

123                             public void unsetEntityContext() {

124                                     context = null;

125                             }

126                            

127                             public void ejbActivate() {}

128                             public void ejbPassavate() {}

129                       

130                             public void ejbLoad() {

131                                     String primaryKey = (String)context.getPrimaryKey();

132                                     Connection con = null;

133                                     PreparedStatement ps = null;

134                                     ResultSet result = null;

135                                     try {

136                                             con = this.getConnection();

137                                             ps = con.prepareStatement();

138                                             “select userid, username, password from Member where userid=?”);

139                                             ps.setString(1, primaryKey);

140                                             result = ps.executeQuery();

141                                             if(result.next()) {

142                                                     userid = primaryKey;

143                                                     username = result.getString(“username”);

144                                                     password = result.getString(“password”);

145                                             }

146                                     } catch(SQLException se) {

147                                             throw new EJBException(se);

148                                     } finally {

149                                             try {

150                                                     if(result != null) ps.close();

151                                                     if(ps != null) ps.close();

152                                                     if(con != null) con.close();

153                                             } catch(SQLException se) {

154                                                     se.printStackTrace();

155                                             }

156                                     }

157                             }

158                            

159                             public void ejbStore() {

160                                     Connection con = null;

161                                     PreparedStatement ps = null;

162                                     try {

163                                             con = this.getConnection();

164                                             ps = con.prepareStatement();

165                                             “update Member set username=?, password=? where userid= ?”);

166                                             ps.setString(1, username);

167                                             ps.setString(2, password);

168                                             ps.setString(3, userid);

169                                             if(ps.executeUpdate() != -1) {

170                                                     throw new EJBException(“ejbStore”);

171                                             }

172                                     } catch(SQLException se) {

173                                             throw new EJBException(se);

174                                     } finally {

175                                             try {

176                                                     if(ps != null) ps.close();

177                                                     if(con != null) con.close();

178                                             } catch(SQLException se) {

179                                                     se.printStackTrace();

180                                             }

181                                     }

182                             }

183                       

184                             public void ejbRemove() {

185                                     Connection con = null;

186                                     PreparedStatement ps = null;

187                                     try {

188                                             con = this.getConnection();

189                                             ps = con.prepareStatement(“delete from Member where userid=?”);

190                                             ps.setString(1, userid);

191                                             result = ps.executeQuery();

192                                             if(ps.executeUpdate() != -1) {

193                                                     throw new EJBException(“ejbRemove”);

194                                             }

195                                     } catch(SQLException se) {

196                                             throw new EJBException(se);

197                                     } finally {

198                                             try {

199                                                     if(ps != null) ps.close();

200                                                     if(con != null) con.close();

201                                             } catch(SQLException se) {

202                                                     se.printStackTrace();

203                                             }

204                                     }

205                             }

206                       

207                             private Connection getConnection() throws SQLException {

208                                     try {

209                                             Context jndiCntx = new InitialContext();

210                                             DataSource ds = (DataSource)jndiCntx.lookup(“java:comp/env/jdbc/TestDB”);

211                                             return ds.getConnection();

212                                     } catch(NamingException ne) {

213                                             throw new EJBException(ne);

214                                     }

215                             }

216                      }

在編寫BMP bean的程式碼時需要注意下列事項:

1.       BMP bean的部署描述子裡的<persistence-type>標籤的值為Bean,並且沒有宣告<container-managed><cmp-version><abstract-schema-name><cmp-field><relationship-field>等專屬CMP bean的標籤。

2.       我們可以在部署描述子裡宣告查詢資料庫時所需的DataSource訊息,然後在BMP beanbean class中實作取得資料庫連線的方法(Code 8line 207-215),以便在各call backlife-cycle方法中直接取用。

3.       call back方法中所實作的程式碼分別屬於四種存取資料庫的基本語法:INSERTSELECTUPDATEDELETE

4.       ejbCreate()方法裡面的是INSERT語法(Code 8line 30-58),當client端呼叫home interface上的create()方法時,EJB Container會呼叫bean class中相應的ejbCreate()方法,以新增一筆資料。

5.       client端呼叫home interface上的findBy()方法時,EJB Container會呼叫bean class中相應的ejbFindBy()方法。ejbFindBy()方法分兩種:一種是以primary key為搜尋條件的ejbFindByPrimaryKey()方法,它回傳符合搜尋條件的EJB Object referenceclient(Code 8line 64-89);另一種則是以entity bean的屬性為搜尋條件的ejbFindBy()方法,它回傳內含符合搜尋條件的EJB ObjectCollection(Code 8line 91-117)。兩種方法內部都實作了SELECT語法。

6.       所有findBy()方法都必須在BMP bean class中實作存取資料庫的程式碼,這點有別於開發CMP bean時無須在CMP bean class中實作任何findBy()方法。

7.       另外一個實作SELECT語法的call back方法是ejbLoad()方法(Code 8line 130-157),我們已經知道EJB Container會在Activation過程中呼叫這個方法,以便就先前在Passivation過程中寫回資料庫的資料,將其最新狀態寫回新的bean instance,以繼續服務client端的請求。

8.       相對地,在ejbStore()方法(Code 8 line 159-182)中的UPDATE語法則可以在Passivation過程中將bean instance內的資料寫回資料庫。我們可以說,EJB Container主要就是利用ejbLoad()ejbStore()這對方法,並且視系統當時的狀況,在entity bean與資料庫之間作資料同步的動作。

9.       最後,當client端呼叫interface上的remove方法時,EJB Container會呼叫bean class中的remove()方法,執行其中的DELETE語法,以刪除資料庫內的資料。

10.   entity bean的生命週期中,EJB Container雖然也會呼叫ejbActivate()ejbPassivate()setEntityContext()unsetEntityContext()方法,但這些方法只供EJB Containerentity nean溝通與生命週期有關的的各種狀態用,不建議在這些方法中實作存取資料庫的程式碼。

11.   開發人員必須實作BMP beanbean class上各屬性的getter/setter方法(Code 8line 17-28),並公開至component interface上供client端呼叫使用。

五、Client端如何使用entity bean

Entity beanclient端可以是JSPservletjava applicationsession bean等。不論是哪一種client端,使用entity bean時首先要做的是利用JNDI service找到entity beanhome interface,然後呼叫home interface上的create()方法,若沒有例外丟出,home interface會回傳代表component interfacereference。由於我們將bean class中的business方法公開至component interface上,因此我們可以呼叫component interfacepublic方法,即可使用entity bean。對client而言,只看得到home interfacecomponent interface。以下是client端尋找與呼叫entity bean的範例:

Code 9Client local lookup of home interface

3      import       javax.naming.*;

10                InitialContext ctx = new InitialContext();

11                Object objHome = ctx.lookup(“java:comp/env/ejb/MemberHome”);

12                MemberLocalHome home = (MemberLocalHome)objHome;

以上是呼叫local home interface的範例。

Code 10Client remote lookup of remote home interface

3             import       javax.naming.*;

4             import       javax.rmi.PortableRemoteObject;

10                InitialContext ctx = new InitialContext();

11                Object objHome = ctx.lookup(“java:comp/env/ejb/MemberHome”);

12                MemberRemoteHome home =

13                  (MemberRemoteHome)PortableRemoteObject.narrow(objHome, MemberRemoteHome.class);

以上是呼叫remote home interface的範例。取得home interface reference後,再呼叫home interface上的create()方法,得到component interface reference,如下例所示:

Code 11Creating an entity bean

14                String userid = “123”;

15                MemberLocal member = home.create(userid);

如果要尋找既存的資料,則可呼叫home interface上的findByPrimaryKey()方法:

Code 12Finding an existing entity bean

14              String userid = “123”;

15              MemberLocal member = home.findByPrimaryKey(userid);

取得component interface後,我們就可以透過component interface使用bean classbusiness方法:

Code 13Using an entity bean

16              String username = member.getUsername();

17              String password = request.GetParameter(“password”);

18              member.setPassword(password);

30                         member.remove();

參考資料

1. Richard Monson-Haefel ---- Enterprise JavaBeans, 3rd Edition, O’reilly, 2001

2. Ueli Wahli, Wouter Denayer, Lars Schunk, Deborah Shaddon, Martin Weiss ---- EJB 2.0 Development with WebSphere Studio Application Developer, 1st Edition, IBM/Redbooks, 2003

posted on 2008-12-04 11:32 paulwong 阅读(483) 评论(0)  编辑  收藏 所属分类: J2EE


只有注册用户登录后才能发表评论。


网站导航: