跳到导航
BEA Dev2Dev Oracle and BEA
首页 资源中心 dev2dev学堂 在线技术论坛 User Group CodeShare
dev2dev 首页 > 资源中心 > 技术文章
使用 EJBGen:"一个对三个"

时间:2004-04-06
作者:Dion Almaer
浏览次数:
本文关键字:EJBEJBGen部署编译
文章工具
推荐给朋友 推荐给朋友
打印文章 打印文章
开发WebLogic Server上的EJB时,您是否对那些Java文件以及相关的部署描述符感到头痛?很多工具可以帮助您开发bean代码,使用特殊的Javadoc注释来定义其他接口(HomeRemote)中的内容,以及定制出XML部署描述符(ejb-jar.xmlweblogic-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单独开发的,但是只要您加入邮件列表,就可以与他联系。无论是发出请求还是发现bugCredric都会在短期内对这些进行处理。如果您需要开放源代码解决方案,则可以使用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的属性。方法级别属性标记给定方法的信息。最常使用的标签是组成RemoteLocal接口的方法所使用的标签(使用@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.buildFileNamebuildfile的名称

·             ant.projectName:项目的名称

·             ant.docletPathejbgen.jar的路径


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

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

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

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

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

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


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

标签:@ejbgen:session
此处仅需要的属性是将bean的名称告诉EJBGen。我们还定义自由内存池中最大数量的beanWebLogic缓存信息),及默认事务属性将是“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实体,其包括三个字段 – itemiditemnameitemamount – 这些字段将是持久的。

数据库表还将包含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-EJBOrderItemEJB)。创建这个关系的步骤如下所示:

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.javaOrderItemEJB.javaOrderViewerEJB.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();
         }


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

 作者简介
Dion Almaer是Middleware Company (www.middleware-company.com) 的首席技术专家,该公司是国内领先的EJB/J2EE和B2B技术培训机构之一。Middleware Company还构建和维护一流的在线J2EE社区TheServerSide.com。
dot dot dot

dot
  作者其它文章
您对本文的评价
您对这篇文章的看法如何?
太棒了!5分 不错啊 4分 一般般 3分 有待提高 2分 不好 1分

   
相关产品