搜索文章:

首页  |  Java技术  |  Asp.net  |  Asp编程  |  VC/C++  |  Delphi  |  VB编程

使用 EJBGen:"一个对三个"

开发WebLogic Server上的EJB时,您是否对那些Java文件以及相关的部署描述符感到头痛?很多工具可以帮助您开发bean代码,使用特殊的Javadoc注释来定义其他接口(Home,Remote)中的内容,以及定制出XML部署描述符(ejb-jar.xml,weblogic-ejb-jar.xml)的内容。但使用了这个工具后,您就会立即明白仅用一个Java源文件来表示EJB是多么简洁。

EJBGen 简介
本文中我们将介绍用于生成兼容WebLogic Server 6.1 EJB的工具,即EJBGen,它是由BEA WebLogic架构师Cedric Beust 开发的(http://www.beust.com/cedric/ejbgen)。它可以很容易地添加到你的 WebLogic上的应用中,且是IDE无关的 —— 仅需要在bean类中添加一些Javadoc标签。令人遗憾的是,此工具是不开放源代码的,因为它是由Cedric单独开发的,但是只要您加入邮件列表,就可以与他联系。无论是发出请求还是发现bug,Credric都会在短期内对这些进行处理。如果您需要开放源代码解决方案,则可以使用XDoclet (http://sourceforge.net/projects/xdoclet),它是从JBoss创始人Rickard Oberg所写的EJBDoclet发展而来的。

在本文中,我创建了一组WebLogic Server 6.1上可部署的EJB,表示简单的Order系统。其中有两个实体bean,代表一个订单及它的相关项。将使用EJB 2.0 CMP关系,允许我们从订单EJB对这些项进行访问。我们还有一个会话bean,它操作这些实体bean以便完成工作。

使用EJBGen
 EJBGen允许您将EJB信息放在Javadoc标签中,这些标签嵌入在bean类中。特殊标签格式如下:
         /**          * @ejbgen:tagname attribute = value attribute2 = value2 ...          */


根据标签类型的不同,这些@ejbgen标签或者放在类级别,或者放在方法级别。在类级别,您可以声明EJB的名称、JNDI名称和实体bean的属性。方法级别属性标记给定方法的信息。最常使用的标签是组成Remote或Local接口的方法所使用的标签(使用@ejbgen:remote-method或@ejbgen:local-method)。

         /**          * @ejbgen:remote-method          */          public String viewMaxOrders() {


创建了bean类并且在源码中插入了Javadoc标签之后,可以通过Javadoc客户端运行EJBGen了:

         % javadoc -docletpath /path/to/ejbgen.jar          -doclet EJBGen YourEJBs.java


还有命令行选项可以对EJBGen生成文件的方式进行调整。其中许多选项都使您可以更改不同元素的前缀和后缀。

要生成名为FooRemote.java而不是Foo.java的远程接口,运行以下命令(注意 –remoteSuffix):

         % javadoc -docletpath ejbgen.jar -doclet EJBGen          -remoteSuffix Remote FooEJB.java


EJBGen站点提供了所有命令行选项的文档。

EJBGen 功能
EJBGen 还有以下功能:

·             包含EJB 2.0 全部功能(本地接口/CMP关系/消息驱动bean)

·             生成在WebLogic Server 6+ 上可部署的代码和部署描述符

·             可以生成实体Bean的值对象

·             属性文件:可以在bean类内定义和使用属性。通过{ property name }方式使用属性

·             支持Javadoc标签继承。基本适配器类可以设置标准值,然后实际的bean继承行为以及方法

·             生成ANT构建文件


如果生成ANT构建文件,运行EJBGen后,可以运行

         % ant -buildfile ejbgen-build.xml


可以按如下所示调整变量:

·             ant.buildFileName:buildfile的名称

·             ant.projectName:项目的名称

·             ant.docletPath:ejbgen.jar的路径


创建使用Javadoc标签的会话bean。现在我们看一个实际的例子,先是操作实体bean的会话bean。OrderViewerEJB.java将具有以下方法:

·             viewMaxOrders()返回最大数量的订单,其将是,以显示我们在类级别javadoc注释中对它们的设置 。

·             viewOrders()返回系统中的订单。

·             addOrder(orderId, orderBy, orderName)插入订单条目 。

·             addOrderItem(orderID, itemID, itemName, amount)这将为所给订单插入一项 。

·             deleteOrders()删除所有订单及其中的项 。


类级别定义
在类级别,我们需要定义这是一个会话bean的事实,其相关信息为:JNDI名称;EJB对实体bean的本地引用;和环境entries。

标签:@ejbgen:session
此处仅需要的属性是将bean的名称告诉EJBGen。我们还定义自由内存池中最大数量的bean(WebLogic缓存信息),及默认事务属性将是“Required”。

         /**          * OrderViewer Bean views orders:          *          * @ejbgen:session          * ejb-name = OrderViewer          * max-beans-in-free-pool = 100          * default-transaction = Required          *          * ... other tags ...          */          public class OrderViewerEJB implements SessionBean {


表1中显示了ejbgen:session标签的所有属性。


标签:@ejbgen:jndi-name
这个标签非常重要;它不仅定义JNDI名称,而且EJBGen也通过这个标签知道是否生成远程接口、本地接口,还是这两个接口都生成或都不生成!因为我们想将会话bean公开给远程客户端,所以我们将使用远程属性:

         /**          * OrderViewer Bean views orders:          *          * ... other tags ...          *          * @ejbgen:jndi-name          * remote = ejbgenexamples.OrderViewer          *          * ... other tags ...          */          public class OrderViewerEJB implements SessionBean {


对于本地接口,我们将添加属性“local = local-jndi-name”。

标签:@ejbgen:ejb-local-ref
我们的OrderViewer将使用实体bean说明订单和订单项。EJB 2.0引进了“本地接口”概念,它强迫组件在本地VM中“谈话”,而不越过远程边界。当使用实体bean时,最佳实践是在本地将会话bean(可以远程的)与实体bean一起使用。我们将分别定义对两个实体bean的本地引用(清单1)。

 清单1

         /**          * OrderViewer Bean views orders:          *          * ... other tags ...          *          * @ejbgen:ejb-local-ref          * home = ejbgenexamples.OrderLocalHome          * local = ejbgenexamples.OrderLocal          * jndi-name = ejbgenexamples.OrderLocalHome          * name = ejb/OrderHome          * type = Entity          *          * @ejbgen:ejb-local-ref          * home = ejbgenexamples.OrderItemLocalHome          * local = ejbgenexamples.OrderItemLocal          * jndi-name = ejbgenexamples.OrderItemLocalHome          * name = ejb/OrderItemHome          * type = Entity          *          * ... other tags ...          */          public class OrderViewerEJB implements SessionBean {


使用这些本地引用,我们可以通过查询“java: comp/env/ <name>”来查询OrderLocal Home,从而获得对Home接口的访问权:

         OrderLocalHome orderHome = (OrderLocalHome) new          InitialContext().lookup("java:/comp/env/ejb/Order-Home");


要使用远程接口引用EJB,使用@ejbgen:ejb-ref标签。

标签:@ejbgen:env-entry
要定义环境entries,使用ejbgen:env-entry标签。我们将定义环境条目保持最大数量订单的整数值:

         /**          * OrderViewer Bean views orders:          *          * ... other tags ...          *          * @ejbgen:env-entry          * name = maxOrders          * type = java.lang.Integer          * value = 10          *          * ... other tags ...          */          public class OrderViewerEJB implements SessionBean {


注意,类型必须给完整的(比如是java. lang.Integer,而不是Integer)。

方法级别定义
我们想对远程客户端将可以使用的所有方法进行标记。或者,您还可以使用方法的事务属性的值(即覆盖我们在类级别定义的默认值)和单独的级别。这里我们标记addOrder()方法:

         /**          * Add an order          *          * @ejbgen:remote-method          */          public void addOrder(Integer id, String orderBy, String name)


我们将看到实体bean将标记它们的方法@ejbgen:local-method。现在我们就完成了会话bean的创建!

创建OrderItem实体Bean
使用实体bean与使用会话bean相似。其中包括几个不同的类级别标签;我们将标签容器应该管理的字段及主键。将生成OrderItem实体,其包括三个字段 – itemid、itemname和itemamount – 这些字段将是持久的。

数据库表还将包含ORDER_ID,这是Order实体中的外键(稍后讨论)。现在我们将忽略OrderItem将与Order有关系这个事实。

类级别定义
在类级别,我们将定义实体定义、JNDI名称和实体finder签名,并且创建数据库中的表。

标签:@ejbgen:entity
像会话bean一样,我们需要定义实体bean的名称,可以定义诸如默认事务值等属性。我们还需要定义数据库中表的名称、主键类别和要使用的数据源:

         /**          * @ejbgen:entity          * ejb-name = OrderItemEJB          * data-source-name = orderPool          * table-name = OrderItems          * prim-key-class = java.lang.Integer          * default-transaction = Required          *          * ... other tags ...          */          public abstract class OrderItemEJB implements EntityBean {


表2中显示了ejbgen:entity标签的所有属性。



标签:@ejbgen:jndi-name
这个标签与会话相同,但是因为我们使用实体,所以将仅创建本地接口:

         /**          * ... other tags ...          *          * @ejbgen:jndi-name          * local = ejbgenexamples.OrderItemLocalHome          *          * ... other tags ...


标签@ejbgen:finder
每个finder方法都必须有一个ejbgen:finder标签。您必须指定方法签名,包括您可能要抛出的任何例外。而且,还要给出您希望使用的EJB Query Language语句。我们将定义findItemsByName()方法,它检索具有所给名称的每一项: 

         /**          * @ejbgen:finder          * signature = "Collection findItemsByName(String name)"          * ejb-ql = "WHERE name = ?1"


标签@ejbgen: create-default-dbms-tables
如果进行开发,可以使WebLogic创建数据库表:

         * @ejbgen:create-default-dbms-tables


方法级别定义
所有抽象的get()方法都必须标记为容器管理的持久字段,我们提供列名映射。必须标记为主键,而且如果要想能够从组件接口调用这些方法,我们还必须对接口进行标记(远程或本地)。下面是OrderItem的主键:

         /**          * @ejbgen:cmp-field column = id          * @ejbgen:local-method          * @ejbgen:primkey-field          */          public abstract Integer getId();          public abstract void setId(Integer id);


创建Order实体bean并将其与OrderItem相关联
WebLogic Server 6.1 支持EJB 2.0关系,其他许多J2EE服务器没有这个功能。然而,WebLogic Server6.1没有部署描述符工具来部署CMP关系实体(XML必须手动操作),所以我们将使用EJBGen的功能来完成此项工作。

我们将有一个一对多的关系,在这个关系中一个订单可以有多个关联项。在订单EJB中,我们能够通过getItems()获得订单的集合,从集合中我们可以通过OrderLocal getOrder()返回订单。像定义这些抽象的方法,我们需要在每一类中配置ejbgen:relation标签(Order-EJB和OrderItemEJB)。创建这个关系的步骤如下所示:

1.           OrderItem配置ejbgen:relation标签

2.           OrderItem创建容器管理的关系

3.           Order配置ejbgen:relation标签

4.           Order创建容器管理的关系


OrderItem:配置 ejbgen
relation 标签
此项是关系中“多”的一方。关系双方共享同一名称,target-ejb是要使用此关系的bean的名称。因为我们有target-ejb属性,您可以将所有关系标签放入一个EJB bean类中。因为多重属性,我们将告诉EJBGen这些相关的外键列和映射到容器管理的关系的字段。删除订单时,我们希望相关的订单项能自动删除,这样就有了cascade-delete选项的需求:

         * @ejbgen:relation          * multiplicity = many          * name = OrderCanHaveMultipleItems          * target-ejb = OrderItemEJB          * fk-column = order_id          * cmr-field = order          * cascade-delete = True


OrderItem:创建容器管理的关系
我们可以从订单EJB中的订单对象得到此订单。标记CMR字段并将其声明为本地方法:

         /**          * @ejbgen:cmr-field          * @ejbgen:local-method          */          public abstract OrderLocal getOrder();          public abstract void setOrder(OrderLocal order);


Order:配置ejbgenrelation标签
此Order是关系中“一”的一方。此关系必须有相同的关系名称:

         * @ejbgen:relation          * multiplicity = one          * name = OrderCanHaveMultipleItems          * target-ejb = OrderEJB


Order创建容器管理的关系
因为一个订单有许多返回值,我们使用OrderItems的集合:

         /**          * @ejbgen:cmr-field          * @ejbgen:local-method          */          public abstract Collection getItems();          public abstract void setItems(Collection items);


如果您曾经使用过CMP关系,您可能已经多少感到厌烦了。然而通过EJBGen创建CMP关系相当容易。我从来不想手动构建关系的XML。我想使用GUI构建关系,或者可以使用EJBGen。要想进一步使用EJBGen,可以使用能够构建EJBGen可识别类的GUI。请查看免费软件Middlegen (http://boss.bekk.no/boss/middlegen/)。

部署系统
现在我们有三个Java源文件:OrderEJB.java、OrderItemEJB.java和OrderViewerEJB.java。从这些文件我们将使用EJBGen生成接口和XML部署描述符。下面的build脚本将打包一个ejb-jar文件:

         javadoc -docletpath c:\ejbgen\ejbgen.jar          -doclet EJBGen ejbgenexamples\Order*EJB.java          cd ejbgenexamples          javac -classpath %CLASSPATH%;.. *.java          cd ..          mv *.xml META-INF          jar cvf c:\bea\wlserver6.1\config\          mydomain\applications\ejbgen.jar *


在运行应用程序前,我们必须先在应用服务器(WebLogic Server)上配置数据源,注意既“orderPool”。清单2显示了客户端的main()方法,其添加、查看、然后删除订单。

 清单 2

         public static void main(String[] args) throws Exception {          Context ic = getInitialContext();            OrderViewerHome home = (OrderViewerHome)          ic.lookup("ejbgenexamples.OrderViewer");          OrderViewer v = home.create();            System.out.println("Add Order");          v.addOrder(new Integer(1), "Dion", "Books");          v.addOrderItem(new Integer(1), new Integer(1),          "EJB v3", 36.55f);          v.addOrderItem(new Integer(1), new Integer(2),          "Mastering EJB", 45.95f);            System.out.println("The Max Orders: " + v.viewMaxOrders());            System.out.println("Display Orders:\n" + v.viewOrders() );            System.out.println("Delete Orders");          v.deleteOrders();          }


结束语
我们了解了使用EJBGen为WebLogic Server 6.1开发EJB的方法。此工具使我们可以每个EJB的生成仅使用一个文件来完成,而不需要开发三个Java文件和多个相关的部署描述符。它是一个非常简洁的预处理系统 —— 甚至还有可以生成EJBGen可识别代码的其他工具!

相关文章:
© 2006   www.java-asp.net