• 沒有找到結果。

EJB Relationship EJB 系统开发实战录 (2)

N/A
N/A
Protected

Academic year: 2022

Share "EJB Relationship EJB 系统开发实战录 (2)"

Copied!
21
0
0

加載中.... (立即查看全文)

全文

(1)

EJB系统开发实战录(2)

在上期的文章中说明了如何使用JBuilder 开发 CMP 2.x 的 EJB 组件,并 且使用JBuilder 的 EJB Test Client 精灵来快速开发一个测试客户端应用程序 呼叫范例EJB 组件以验证我们开发的 EJB 组件是否能够正确的工作。JBuilder 的EJB Test Client 精灵能够根据开发者定义的 EJB 组件的接口来自动产生完 整的客户端测试程序,是EJB 开发者非常实用的帮手。

在本期的文章中我们将继续加入上期一文中的 Seminar,Instructor 这两 个CMP,并且完成 C MP 之间的关系。读者可以了解到如何建立 EJB 之间的关 系,如何在Java 程序代码中实作这些对应的关系。当然,在本文的最后仍然要 使用EJB Test Client 精灵来确定实作的 EJB 是能够正确工作的。

现在就让我们继续 EJB 组件定义和实作的工作,首先让我们从上期文章中 尚未讨论的其它CMP 对象以及 COM 对象之间的关系开始着手。

EJB Relationship

在现实的世界中许多实体之间都存在有彼此之间特定的关系,例如在本文叙 述的范例中,一个讲师可以教授多个课程,一个教室也可以提供多个课程使用。

在关连数据库(R DBMS)中可以使用关连的机制来描述资料之间的关系,那么在 EJB 模型中是否有任何的机制可以叙述组件之间的关系呢?

由于EJB Entity Bean 的目的之一就是代表 Domain 之中的实体(Entity),

以模型化系统之功能。既然如此那么为 Entity Bean 建立彼此之间的关系以仿 真 Domain 实体的现实关系就是很自然而且成为必要的功能了。在 EJB 1.x 的 规范中并没有定义这种机制,因此在 EJB 1.x 中程序员通常都是自己撰写程序 代码来实作Entity Bean 之间的关连。在 EJB 2.x 规范中,SUN 终于为 EJB 定义了EJB Relationship 让程序员可以在开发 EJB 系统时使用来实作实体之 间的关连关系。

(2)

在EJB 2.x 中 SUN 为 EJB 组件定义了 Local Interface,有有别于原先的 EJB Remote Interface 。Local Interface 顾名思义是使用在本地端的接口,其 目的是提供在同一个JVM 或是同一个 Partition 之中的 EJB 对象能够使用较有 效率的方式进行呼叫。另外一个目的就是为了支持EJB Relationship 的开发,

由于EJB 组件在建立关连时会因为客户端要求建立一个 EJB 组件而连带的因为 EJB Relationship 而建立其它的 EJB 组件,因此为了降低对于执行效率的影 响,因此EJB 2.x 规范要求提供 EJB Relationship 的 EJB 组件必须使用 Local Interface,如此一来 EJB Container 可以使用最有效率的方式来实作并且进行 EJB 组件之间的呼叫。

由于Entity Bean 分为 CMP 和 BMP,因此在提供 EJB Relationship 的 机制也有所不同,CMP 的 EJB 是使用 Deployment Descriptor(DD) 来定义组 件 之 间 的 关 系 ,EJB 组 件 开 发 人 员 使 用 EJB 2.x 提 供 的 EJB Query Language(EJB-QL)来定义 EJB 组件的关连,而 EJB-QL 则是类似 RDBMS 的SQL 语言,使用类似的语法提供开发人员选择符合条件的 EJB 对象。当客户 端存取 CMP 的关连字段特性时,EJB Container 会到 DD 中找到此关连相对 应的 EJB-QL,然后使用此 EJB-QL 从后端数据来源中选择符合条件的资料,

再一一的根据得到的数据转换为代表数据的 EJB 组件,最后回传这些组件给客 户端,通常这些EJB 组件是使用 Java 的 Collectio n 类别回传给客户端,接着 客户端就可以从Collection 中取得符合关连或是条件的 EJB 组件。

至于 BMP 型态的 EJB 组件则使用较为传统的方式,由程序员自己撰写程 序代码以及使用内嵌SQL 叙述来实作 EJB 组件之间的关系。当客户端呼叫 BMP 的关连字段特性时,EJB Container 便呼叫 BMP 实作的程序代码来选择符合 条件的EJB 组件。

在本文之中,由于使用的是CMP 型态的组件,因此在稍后讨论这些组件的 实作时,会同时观察EJB 组件的 D D 内容,看看 EJB 的 Container 如何实现 EJB Relationshi p。

实作代表讲师的 EJB 组件

如同上次建立 ROOM 的组件一般,让我们仍然启动 JBuilder 的 EJB Designer,并且点选鼠标右键选择建立 CMP 2.x 的组件,并且为这个组件名称 设定为Instructor,接着如图 1 为此组件建立组件的字段特性,例如 iD,name 等。这些字段特性是在上期中根据 Domain 分析得来的,请参考上期文章的说 明。

(3)

1 使用 JBuilder 的 EJB Designer 设计 Instructor 组件

在图 1 中除了 EJB 组件的 findByPrimaryKey 这个 finder 方法之外,也 定义了另外两个finder 方法,findAll 和 findByName。FindAll 可以回传所有 目前的讲师数据,而 findByName 则可以根据讲师的姓名来搜寻讲师数据。这 两个finder 方法都使用了 EJB-QL 来定义搜寻的条件。这两个 EJB -QL 分别是:

SELECT OBJECT(o) FROM TBLINSTRUCTOR

SELECT OBJECT(o) FROM TBLINSTRUCTOR AS o WHERE o.name = ?1

要在定义 finder 的 EJB-QL ,我们可以在 EJB Designer 中点选 finder 方法,并且在如图2 中的 Query:控件内输入 Query Language。

2 使用 JBuilder 的 EJB Designer 设计 Instructor 组件

(4)

藉由 EJB 2.x 的 Query Language 功能,EJB 的程序员可以很方便的藉 由使用类似SQL 的语法来定义选择组件的条件。由于 EJB-QL 的方便性以及易 于 使 用 , 因 此 连 Microsoft 也 准 备 在 未 来 的 .NET 中 加 入 类 似 的 Query Language 机制。读者如果对 EJB-QL 有兴趣,可以参考 EJB 2.x 规范中对于 EJB-QL 的定义以及语法的叙述。

当我们在 EJB Designer 中定义 finder 方法的 Query Language 后,

JBuilder 便会在 EJB 的 DD 档案中(即 ejb-jar.xml)产生相对的 XML 叙述,例 如下面的程序片段便是由JBuilder 产生的 findByName 的内容。请注意,在这 个query method 中 JBuilder 不但封装了我们定义的 EJB -QL,也定义了此查 询语言使用的动态参数,在稍后的实作程序代码中,客户端可以动态传入查询的 讲师姓名,EJB Container 会自动的把传入的参数值带入此动态参数中,再要 求后端的数据来源执行此Query Language。

<query>

<query-method>

<method-name>findByName</method-name>

<method-params>

<method-param>java.lang.String</method-param>

</method-params>

</query-method>

<ejb-ql>

SELECT OBJECT(o) FROM TBLINSTRUCTOR AS o WHERE o.name = ?1

</ejb-ql>

</query>

观察 EJB Container 的执行行为

现在先让我们看看有了 Instructor 组件之后,如何藉由这个组件在数据库 中新增讲师数据,并且藉由 BES 的 Console 程序来观察 EJB Container 和 Instructor 组件执行的行为。

现在让我们回到上期文章中的客户端应用程序,并且在main 函式中加入一 行程序代码来呼叫建立 Instructor 组件的函式,下面即是修改后的客户端应用 程序,读者可以看到在main 函式中呼叫了 CreateInstructorInfos() 函式。

public static void main(String[] args) { /*

//第 1 期的客户端程序代码

client.create("教室 1", 30);

client.create("教室 2", 35);

(5)

client.create("教室 3", 20);

client.create("大会议室", 120);

client.create("小会议室", 40);

client.executeFindAll();

*/

//第 2 期的客户端程序代码 CreateInstructorInfos();

}

CreateInstructorInfos 建立了 InstructorTestClient 对象来连结 EJB Container 之中的 Instructor,并且呼叫 InstructorTestClient 的 Create 方 法直接建立4 个 Instructor 组件。

static void CreateInstructorInfos() {

try {

long lID = 1;

InstructorTestClient instructorClient = new InstructorTestClient();

instructorClient.create(lID++, "利瓦伊", "1111-1111",

"[email protected]");

instructorClient.create(lID++, "庄永璋", "2222-2222",

"[email protected]");

instructorClient.create(lID++, "李匡正", "3333-3333",

"[email protected]");

instructorClient.create(lID, "张铭期", "5555-5555",

"[email protected]");

}

catch(Exception e) {

e.printStackTrace();

} }

InstructorTestClient 则是位于另外一个 java 档案的类别,它首先建立 Context,再呼叫 lookup 方法,藉由 JNDI ,以 Instructor 组件注册的名称来 搜寻Instructor 组件。在 lookup 成功执行之后,客户端便可以取得 Instructor 的RemoteHome 接口。

(6)

package praticalejbprogramming;

import javax.naming.*;

import javax.rmi.PortableRemoteObject;

import java.util.*;

public class InstructorTestClient {

private InstructorRemote instructorRemote = null;

private InstructorRemoteHome instructorRemoteHome = null;

public InstructorTestClient() {

GetInstructorHome();

}

void GetInstructorHome() {

try {

//get naming context

Context ctx = new InitialContext();

//look up jndi name

Object ref = ctx.lookup("InstructorRemote");

//cast to Home interface

instructorRemoteHome = (InstructorRemoteHome)

PortableRemoteObject.narrow(ref, InstructorRemoteHome.class);

}

catch(Exception e) { e.printStackTrace();

} }

public InstructorRemote create(long iD, String name, String phone, String eMail)

{ try

(7)

{

instructorRemote = instructorRemoteHome.create(iD, name, phone, eMail);

}

catch(Exception e) {

e.printStackTrace();

}

return instructorRemote;

}

public InstructorRemoteHome GetInstructorRemoteHome() {

return instructorRemoteHome;

} }

在取得了 Instructor 的 RemoteHome 接口之后,便可以呼叫其中的 Create 方法来建立 Instructor 组件,此时在客户端便会相对应的建立代表远程 Instructor 组件的 stub 对象。InstructorTestClient 的 Create 方法便是执行 刚 才 叙 述 的 这 些 动 作 , 因 此 客 户 端 应 用 程 序 可 以 便 可 以 很 方 便 的 呼 叫 InstructorTestClient 的 Create 方法来建立远程 Instructor 组件。

现在让我们重新编译这个 JBuilder 项目,再重新分发编译后的 EAR 档案 到BES 之中。由于 BES 5.x 提供了 Hot-Deploy 功能,因此 EJB 程序员可以 直接再次布署包含EJB 组件的 EAR 档案,而无需先暂停 EJB Server。接着启 动BES 的 Console 程序,以 admin 密码登录,开启 standard partition 之后,

我们可以在其中找到刚才分发的Instructor 组件。让我们点选画面右边的 State 页次,再点选线状图图标来观察客户端应用程序尚未执行前的Instructor 组件,

如图 3 所示。从图 3 我们可以发现此时 Instructor 组件的确尚未由 EJB Container 建立。

(8)

3 客户端应用程序尚未执行前Console 观察到的情形

现在回到JBuilder 中执行客户端应用程序来建立 Instructor 组件,在客户 端应用程序执行完毕之后,再让我们回到 Console 程序,此时我们会看到类似 图 4 的画面,从 Console 的 Monitor 中我们看到在客户端应用程序呼叫 RemoteHome 建立 4 个 Instructor 组件后,在后端的 EJB Container 果然显 示了此时在EJB Container 的内存中建立了 4 个 Instructor 组件。

(9)

4 客户端应用程序执行后Console 观察到的情形

在客户端应用程序执行完毕之后,如果我们使用 JDataStore 的 Explorer 来检视资料表,那么可以发现 Instructor 组件已经正确的在数据表中产生了正 确的数据了。

5 Instructor 组件在数据库中建立了4 笔数据

从上面的讨论中可以发现,藉由JBuilder 的 EJB Designer 程序员可以快 速的开发EJB 组件,而 BES 的 Console 程序不但可以让程序员分发和布署 EJB 组件,也可以监督和调校EJB 组件,非常的方便。

(10)

实作代表课程的 EJB 组件

在说明如何建立 ROOM 以及 Instructor 组件之后,接着的 Seminar 和 Attendee 组件的实作方式也是一样的,我们都是使用 EJB Designer 来定义这 两个组件,并且定义其中的字段特性和finder 方法,读者现在可以自己试试看。

图6 显示的便是继续使用 EJB Designer 设计 Seminar 和 Attendee 的画面。

6 使用 EJB Designer 设计 Seminar 和 Attendee 组件

当然,读者要记得在设计完 EJB 组件之后,必须指定每一个 CMP 对应的 资料表,这个动作可以在EJB Designer 中设定 EJB 组件的 Table Name 特性 值即可,此时 JBuilder 会自动的在 EJB 的叙述档案 ejb-borland.xml 中定义 EJB 组件和数据来源之间的对应,之后加载 EJB 组件的 EJB Server 便会根据 这个档案定义的内容来系结EJB 组件和数据表。

定义和实作 EJB 组件之间的关系

建立了 Domain 之中代表实体的 EJB 组件之后,下一个工作便是为这些 EJB 组件定义会实际发生的关系。定义 EJB Relationship 除了可以仿真实际 的企业规则之外,程序员也能够藉由EJB Relationship 从一个 EJB 组件轻易 的取得和这个 EJB 组件系结的 EJB 组件 这可以大幅减少应用程序员需要撰写 的程序代码。不过天下没有白吃的午餐,有好处也一定会有它的缺点,在稍后我 们会说明使用EJB Relationship 可能会造成的问题。

(11)

使用 JBuilder 来定义 EJB Relationship 是非常容易的事情,JBuilder 的EJB Designer 不但可允许程序员使用拖曳的方式定义 EJB Relationship , 更能够在 EJB 组件中产生正确的程序代码。要定义 EJB Relationship ,我们 可以如图7 在 EJB Designer 中点选 Add 菜单中的 Relationship 子菜单在 EJB 组件中定义EJB Relationship 。

在选择了Relationship 子菜单后,EJB Designer 便会显示一个线条,让 程序员使用拖曳的方式定义此组件和目的组件之间的关系,程序员只需要拖曳此 线条到另外一个EJB 组件上,EJB Designer 便会在这两个组件之间显示联机 并且在EJB 组件之中产生关连字段以代表建立的关系。

7 使用 EJB Designer 定义 EJB 组件之间的关系

在EJB Designer 建立了 EJB 组件之间的关系字段之后,程序员可以点选 此关系字段来设定 EJB Relationship 的其它必要特性,例如关系的方向性,

Multiplicity 等。例如图 8 显示的便是 ROOM 组件和 Seminar 组件之间的关 系,在图中显示的Relationship properties 对话盒中我们便可以设定关系的方 向性和 Multiplicity ,Navigability 等的特性值。

读者可以依照上期文章中分析的Bean 关系图在 EJB Designer 中定义不同 EJB 组件之间的关系。

(12)

8 EJB Designer 允许程序员定义 EJB Rela tionship 之间的 Multiplicity 以及 Navigability

在定义了EJB Relationship 之后,我们接着必须定义 EJB 组件对应的数 据表之间键值的关系,这样可以产生相对的XML 叙述内容,让 EJB Server 能 够自动产生正确的 Query Language 来提供 EJB 系结的功能。同样的 EJB Designer 也体贴的为程序员提供拖曳的方式来定义数据表关系,并且产生 XML 叙述内容。例如图9 便是定义 ROOM 组件的 ROOM 数据表和 Seminar 组件的 tblSeminar 数据表之间是以 ROOM.NAME 和 tblSeminar.RoomName 这两 个字段进行系结关系的,程序员只需要使用鼠标在这两个字段间拉一个连结线,

其它的工作就会由EJB Designer 自动的完成。

(13)

9 EJB Designer 允许程序员使用拖曳的方式定义EJB 组件之间关连的字段

在我们于图 9 完成了 ROOM 和 Seminar 之间定义的关连之后,EJB Designer 便会于 ejb-borland.xml 档案中产生如下的 EJB Relationship 关系 的叙述内容,EJB Server 在执行时期便会根据这个内容来系结相关的 EJB 组 件。读者可以花一些时间看看下面的内容,会发现其中封装了EJB Relationship 之间所有的信息。

<ejb-relation>

<ejb-relation-name>seminar-instructor</ejb-relation-name>

<ejb-relationship-role>

<description>seminar</description>

<ejb-relationship-role-name>SeminarRelationshipRole</ejb-relationship -role-name>

<multiplicity>Many</multiplicity>

<relationship-role-source>

<description>seminar</description>

<ejb-name>Seminar</ejb-name>

</relationship-role-source>

<cmr-field>

<description>instructor</description>

<cmr-field-name>instructor</cmr-field-name>

(14)

</cmr-field>

</ejb-relationship-role>

<ejb-relationship-role>

<description>instructor</description>

<ejb-relationship-role-name>InstructorRelationshipRole</ejb-relations hip-role-name>

<multiplicity>One</multiplicity>

<relationship-role-source>

<description>instructor</description>

<ejb-name>Instructor</ejb-name>

</relationship-role-source>

<cmr-field>

<description>seminar</description>

<cmr-field-name>seminar</cmr-field-name>

<cmr-field-type>java.util.Collection</cmr-field-type>

</cmr-field>

</ejb-relationship-role>

</ejb-relation>

除了两个组件之间的关系之外,EJB Designer 甚至允许程序员使用多个数 据 表 来 定 义 EJB Relationship 。最好的范例便是在我们的范例系统中,

Attendee 和 Seminar 之 间 的 的 连 结 关 连 我 们 是 使 用 第 3 个 数 据 表 Appointment 来代表的。因此在定义 Seminar 和 Attendee 组件之间的关系时,

我们可以如图10 一般,在两个资料表之间加入另外一个 Cross-Table 来代表系 结的关系。程序员可以在图 9 中点选『Add Corss Table』按钮加入第 3 个系 结资料表,图 10 显示的就是使用三个资料表 tblSeminar,tblAppointment 和tblAttendee 来定义 Seminar 和 Attendee 之间的 EJB Relationship 。

(15)

10 EJB Designer 允许程序员使用拖曳的方式定义多个EJB 组件之间关连的字段

在我们使用EJB Designer 定义了所有 CMP 之间的关系之后,便可以看到 类似图11 的画面,此时在拥有 EJB Relationship 的 CMP 组件之间都会显示 连结线条以及相关的EJB Relationship 字段特性。

(16)

11 EJB Designer 定义之完整范例 EJB Relationship 架构图

当程序员使用EJB Designer 定义 EJB Relationship 后,JBuidler 会在 EJB 组件中产生相关的程序代码。例如我们定义了 Seminar 组件和 Room 组件 之间是多对1,而 Seminar 和 Attendee 之间是多对多的关系,JBuidler 便在 Seminar 的 Bean Instance 中产生了如下的程序代码:

public abstract praticalejbprogramming.Room getRoom();

public abstract praticalejbprogramming.Instructor getInstructor();

public abstract java.util.Collection getAttendee();

由于Seminar 和 Room 是多对 1,因此 JBuilder 产生的 getRoom 方法回 传 Room 样例,代表此课程使用的教室。Seminar 和 Attendee 是多对多,因 此 getInstructor 回传的是代表参加此 Seminar 的所有学员,所以 JBuild er 产生了回传封装所有学员的Collection 对象。

再次观察 EJB Container 的执行行为

在继续下一步的实作之前,让我们再次的使用 Seminar 对象来测试是否可 以正确的工作,并且加入前面讨论的Instructor 组件,以 finder 方法来系结建 立的Seminar 组件以及新增到 tblSeminar 数据表的数据。

首先在客户端应用程序中如同建立 Instructor 组件一样,同样的建立一个 CreateSeminarInfos 函式来建立 Seminar 组件。

CreateSeminarInfos();

在 CreateSeminarInfos 函式中使用和前面讨论的 InstructorTestClient 类别类似的技巧建立 SeminarTestClient 对象,再藉由 SeminarTestClient 对象的Create 方法来建立 Seminar 组件。由于 Seminar 组件需要设定它连结 的 Room 组件以及 Instructor 组件,因此 CreateSeminarInfos 函式建立 InstructorTestClient 对象,再藉由 InstructorTestClient 对象取得代表远程 Instructor 组 件的 RemoteHome 接口,最后呼叫 RemoteHome 接口的 findByPrimaryKey 来搜寻系结到此 Seminar 组件的 Instructor 组件,对于 Room 组件也是使用类似的方法。I

static void CreateSeminarInfos() {

Calendar gmtCal = Calendar.getInstance(TimeZone.getDefault());

gmtCal.set(2002, Calendar.SEPTEMBER, 24, 9, 0, 0);

seminarStartTime = gmtCal.getTime();

gmtCal.set(2002, Calendar.SEPTEMBER, 24, 17, 0, 0);

seminarFinishTime = gmtCal.getTime();

(17)

long lID = 1;

try {

InstructorTestClient instructorClient = new InstructorTestClient();

InstructorRemoteHome instructorRemoteHome = instructorClient.GetInstructorRemoteHome();

InstructorRemote instructorRemote =

instructorRemoteHome.findByPrimaryKey(new InstructorPK(1));

RoomTestClient1 client = new RoomTestClient1();

RoomRemote room = client.findByPrimaryKey("教室 1");

SeminarTestClient seminarClient = new SeminarTestClient();

SeminarRemote seminarRemote = seminarClient.create(lID++, "EJB 程 序设计实战课程", seminarStartTime, seminarFinishTime, 0, 0, "", 1);

seminarRemote.setRoomName(room.getName());

seminarRemote.setInstructorID(instructorRemote.getID());

seminarRemote = seminarClient.create(lID++, "CORBA 程序设计实战课程

", seminarStartTime, seminarFinishTime, 0, 0, "", 1);

instructorRemote = instructorRemoteHome.findByPrimaryKey(new InstructorPK(4));

seminarRemote.setRoomName(room.getName());

seminarRemote.setInstructorID(instructorRemote.getID());

seminarRemote = seminarClient.create(lID++, "JSP/Servlet 程序设计实 战课程", seminarStartTime, seminarFinishTime, 0, 0, "", 2);

room = client.findByPrimaryKey("教室 2");

instructorRemote = instructorRemoteHome.findByPrimaryKey(new InstructorPK(2));

seminarRemote.setRoomName(room.getName());

seminarRemote.setInstructorID(instructorRemote.getID());

seminarRemote = seminarClient.create(lID++, "Web Service 程序设计实 战课程", seminarStartTime, seminarFinishTime, 0, 0, "", 2);

instructorRemote = instructorRemoteHome.findByPrimaryKey(new InstructorPK(3));

seminarRemote.setRoomName(room.getName());

(18)

seminarRemote.setInstructorID(instructorRemote.getID());

}

catch(Exception e) {

e.printStackTrace();

} }

由于在前面实作Instructor 组件时,我们也定义了 findByName 的方法,

因此在上面的程序代码中我们也可以使用 findByName 来搜寻讲师组件,如此 做似乎比较符合正常的使用习惯,而不是使用讲师代号来搜寻讲师组件。下面就 是如何使用findByName 的片断程序代码:

nstructorRemote instructorRemote = instructorRemoteHome.findByName("利瓦伊");

现在我们可以重新打包包含EJB 组件的 EAR 档案并且再次的分发到 BES 之中,准备让新的客户端应用程序呼叫使用。图 12 显示了在成功分发 EJB 组 件之后,Console 程序显示的 EJB 组件以及在客户端应用程序执行后 EJB Server 果然建立了 4 个 Seminar 组件。

12 Console 程序观察到客户端建立了 4 个 Seminar 对象

(19)

由于客户端应用程序也使用了 Instructor 组件,因此现在如果我们观察 Instructor 组件的状态,会发现类似如图 11 的情形,BES 会 Cache 住客户端 使用 Instructor 组件,以增加执行效率。这也显示了 BES 的确提供了 Object Pooling 的能力。

13 Console 程序也观察到 EJB Container 开始 Cache Seminar 组件使用的 Instructor 组件

它们可以正确工作吗?

在修改过的客户端应用程序执行完毕之后,Seminar 组件应该会如图 14 正 确的在tblSeminar 数据表中新增 4 笔课程数据,在这些数据中也应该会正确的 包含连结到 Room 和 Instructor 的字段数据。到了这里我们已经完成了三个 CMP 组件以及组件之间的关系。

14 Seminar 组件也正确的在数据表中建立了4 笔数据

(20)

最后让我们回头讨论一下在前面使用 JNDI 名称搜寻 EJB 组件时,应该在 lookup 方法中使用什么名称?事实上当程序员使用 JBuilder 设计 EJB 组件 时,可以自己定义EJB 组件的 JNDI 注册名称,或是使用 B E S 的 Console 来 设定EJB 组件的 JNDI 注册名称。如果程序员没有自己定义 EJB 组件的 JNDI 注册名称,那么JBuilder 在内定上会自动帮助程序员设定 JNDI 注册名称。

要查询或是得知EJB 组件的 JNDI 注册名称非常的简单,在 EJB 组件分发 之后,程序员可以在 Console 程序的 cosnaming 服务中看到所有目前 EJB 组 件以及CORBA 组件的注册名称,例如图 15 就显示了这些信息。由于 BES 的 JNDI 是使用 CORBA 的 Naming Service 来实作的,因此 BES 的 Console 能 够同时管理EJB 以及 CORBA 组件,非常的有威力又方便。

15 使用 Console 的 cosnamimg 服务可以检视所有注册的EJB 组件注册的JNDI 名称

从图15 中可以看到 Instructor 组件的注册名称是 InstructorRemote,这 就 是 为 什 么 在 前 面 InstructorTestClient 类 别 中 于 lookup 方 法 中 使 用 InstructorRemote 做为搜寻 Instructor 组件的名称了。同理如果读者自己实 作SeminarTestClient 类别,那么使用来搜寻 Seminar 组件的注册名称当然就 是图15 中的 SeminarRemote 了。

还缺少什么?

如果读者仔细观察前面讨论的内容,会发现Seminar,Instructor 等的 CMP 对象几乎只包含了字段特性,简单的 Finder 方法,连结的数据表以及 CMP 之 间的关连而已。而且CMP 许多的功能都是由 EJB Container 提供的,或是使 用 DD 来叙述的,即使是 D D 也是由 EJB Container 自动产生的。到目前为止 虽然我们已经能够藉由 EJB 组件处理数据,但是 CMP 组件本身并没有什么实

(21)

作程序代码。所有的企业逻辑,即如何建立CMP 并且搜寻和异动数据等,都是 在客户端的程序代码中撰写的。

虽然这样做仍然可以达成系统的功能,但是如此实作不但让客户端的程序代 码非常的复杂,也失去了使用 EJB 组件模型的意义。为什么呢?简单的说,在 这样的实作之下,客户端几乎和后端的组件模型以及数据库纲要 (Database Schema)系结得太紧密,一旦数据库纲要或是组件模型改变,那么客户端的程序 代码一定需要修改。此外客户端必须了解所有后端的细节,这对于撰写客户端应 用程序,需要进行大量生产(Mass Production) 客户端解决方案的应用是非常不 利的。

在下一期的文章中将介入Session Bean 以及 Design Pattern ,让 Ses sion Bean 封装企业程序代码,并且使用 Design Pattern 来解决许多的问题。读者 将可以了解到Session Bean 的功能,并且学习如何使用 Design Pattern 来增 加系统的功能和可维护性。

结论

在开发系统时建立组件之间的关系几乎是一定会进行的工作,EJB 2.x 定义 了EJB Relationship 来帮助 EJB 开发人员实作组件关系,让开发时程可以大 幅的缩减并且增加可靠性。从文章中读者可以了解藉由 JBuilder 的 EJB Designer 功能,我们可以轻易且快速的定义并且完成 EJB 组件之间关系定义的 工作,JBuilder 的 EJB Designer 会自动的产生正确的 DD 内容并且封装在 EAR 之中再分发到 EJB Server 内。

虽然EJB Relationship 是很方便的功能,但是开发人员在使用时仍然必须 留意,因为不正确的使用EJB Relationship 功能将会让 EJB Container 建立 许多的 EJB Instance ,占据内存以及浪费 CPU 的计算资源。因此开发人员在 使用Finder 方法或是 Select 方法定义 EJB Relationship 时,应该尽量使用较 严格的条件,而不要使用宽松的条件来系结EJB 组件,以增加系统的效率。

參考文獻

相關文件

此行文字的特別意義,是讓 MATLAB 藉由 lookfor 指令 搜尋並顯示此函式用途。.. 語法:

sort 函式可將一組資料排序成遞增 (ascending order) 或 遞減順序 (descending order)。. 如果這組資料是一個行或列向量,整組資料會進行排序。

It is well known that second-order cone programming can be regarded as a special case of positive semidefinite programming by using the arrow matrix.. This paper further studies

「僅僅靠事件的順序本身並不能構成情節。」「因

Key concepts :personal growth (family roles) , family relationship, family problems, social welfare system, interpersonal relationship, communication among family members,

(1999), “Relationship Marketing and Data Quality Management," SAM Advanced Management Journal, Vol. (2004), “The Role of Multichannel Integration in Customer

由於 Android 作業系統的開放性和可移植性,它可以被用在大部分電子產品 上,Android 作業系統大多搭載在使用了 ARM 架構的硬體設備上使裝置更加省電

值得一提的是,Add-in 在 Inventor 運行時會自動加載的特性是一個非常實用的功 能。使用者可以在執行 Inventor 前選擇所需要加載的 Add-in,而沒有選擇的