|
|
翻译:Smiling_Sundoc:王锦全 Sun Java System Studio IDE中的EJB构建器使你能开发消息驱动bean(Message-Driven Beans),这类bean能支持一个应用客户端的异步处理过程。本章将讨论创建和处理消息驱动bean的过程。这些bean的事务通常由EJB容器来管理,但如果你愿意,你可以自己提供事务管理代码。 采用消息驱动bean有以下几个原因:
但消息驱动bean并不总是正确的选择。例如在下列情况中其他方式可能会工作的更好:
关于更多利弊,请参见理解消息驱动Bean。 该IDE提供了一个向导来让你创建一个消息驱动bean所需要的一个单独的bean类。因为一个消息驱动bean只是从一个客户端提出消息并用它们开始其他的bean处理,所以不需要其他的接口类。向导会自动执行创建一个消息驱动bean所需的许多任务,而你需要用IDE的源码编辑器和属性页来完成创建任务。 编写消息驱动bean时你还有本章没有说明的一些选项。虽然Sun ONE Studio IDE被设计用来帮你做许多编码工作,但该IDE还灵活地支持那些选项并把决定权留给你。要获得更多信息,参见列在开始之前的相关资源,或者可以参考编写企业bean方面的众多优秀教材中的一本。
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
表 7-1 在容器管理和bean管理的事务间作出决定 |
||
|
问题 |
容器管理的事务(BMP) |
Bean管理的事务(BMP) |
|
事务的管理者 |
容器自己是事务管理者。 |
你利用JTA自己写代码管理事务。这可以包含用于其他资源如JDBC的事务。 |
|
事务边界的设定 |
EJB容器根据Java2平台企业版规范来决定何时开始和提交一个事务。 |
程序员显示地编写事务边界来获得对事务更细化的控制。 |
|
事务时效 |
消息驱动bean在同一个事务中接收一个消息并执行它的业务方法。 |
事务直到该消息驱动bean收到消息之后才开始。 |
|
问题处理 |
容器会回滚该事务并通知该bean这一消息。 |
该消息驱动bean根据你生成该bean后指明的通知模式来做出响应。 |
关于这些选项的更多信息,参见书构建J2EE应用中关于事务的那一章。
本章剩下的部分将介绍如何创建每种消息驱动bean和开发中要考虑的问题。
EJB构建器向导会自动执行创建你的消息驱动bean所需的一个bean类的许多任务。要定义一个消息驱动bean,按以下步骤执行:
1. 选择或创建一个包含该bean的包。
2. 利用EJB构建器向导生成你的消息驱动bean的基本结构。
3. 完成onMessage方法体,并且如果需要,完成setMessageDrivenContext和ejbCreate方法。
这些基本步骤随后会详细解释。
完成本章讲述的步骤之后你必须给你完成的bean的属性页中添加信息以便它可以同其他bean交互、查找它的资源、以及监听相应的消息。这些关于准备把你完成的bean用于一个应用中的步骤会在第8章讨论。
如果你需要创建一个包来保存你的消息驱动bean,选择一个文件系统,单击鼠标右键并选择“New Java Package”
当你准备要创建一个消息驱动bean时,按以下步骤执行:
bean
在EJB构建器的“Message-Driven Bean Name”和“Properties”面板中命名你的消息驱动bean并决定如何管理该bean可能执行的事务。缺省值是容器管理的事务,但如果你愿意,你可以在该bean类中提供所有事务管理代码。
做出你的选择后你可以单击“Finish”。(或者你可以单击“Next”以打开你可以为你的消息驱动bean指明一个既存的bean类的面板。这之后你再单击“Finish”。)
你新建的消息驱动bean会显示在IDE对象管理器中的“Filesystems”面板中。该bean的基本结构(它的基本bean类和两个组件方法)已经被该EJB构建器自动生成了。
图 7-1 展示了一个典型的消息驱动bean是如何在对象管理器的“Filesystems”面板中显示的。
图 7-1 一个典型的消息驱动bean的缺省类和方法

在显示的两个主要结点中,一个是逻辑结点(用一个bean图标表示)一个表示其实际的类(用一个类图标表示)。在逻辑结点上进行你的所有编辑工作。该bean的两个主要结点接下来会说明。
“Classes”结点包含bean类的代码,它包括了这些方法。 “Create Method”结点指向了初始化你的消息驱动bean的代码。“OnMessage Method”结点指向收到一个消息时要调用的那个方法。
当你展开你的消息驱动bean包下面的两个结点时,你能看到图7-2那样的视图。
图 7-2 一个典型消息驱动bean的对象管理器详细视图

向导会自动在每个消息驱动bean中放入某些缺省的方法:一个创建方法、一个onMessage方法、以及两个生命期方法。如表7-2所示,该创建方法ejbCreate与其他类型企业bean工作的很类似,但onMessage方法是一个新且不同的方法。
|
表 7-2 一个消息驱动bean类中ejbCreate和onMessage方法的目的 |
|
|
方法 |
目的 |
|
ejbCreate |
该方法在需要的时候初始化该bean |
|
onMessage |
这一方法打开该消息驱动bean收到的消息、决定用它做什么、以及处理它。 |
向导还添加了表7-3描述的缺省的生命期方法.
|
表 7-3 一个消息驱动bean类中缺省生命期方法的目的 |
|
|
方法 |
目的 |
|
setMessageDrivenContext |
该方法在ejbCreate方法之前调用,它把该消息驱动bean同一个context对象关联。 |
|
ejbRemove |
该方法在该消息驱动bean实例刚被删除时调用,它释放不再用到的资源。在一个简单的消息驱动bean中这一方法可能根本用不到。 |
要完成你的消息驱动bean,执行以下步骤:
简单的消息驱动bean不需要 ejbCreate 和 ejbRemove 方法。但如果确实需要,那么ejbCreate方法可以用来分配资源而ejbRemove可以释放那些资源。
单击对象管理器中逻辑bean结点下的bean组件来打开源码编辑器完成其他工作。
附录A 探讨了修改你的企业bean的最佳方式,以及当你采用其他方式时可能会遇到的错误和异常。作为一条总的原则,你应该通过逻辑结点而不是单独的类结点来工作,利用bean的属性页(property sheets)或定制对话框(Customizer dialog box)来编辑方法,以及使用IDE的源码编辑器(Source Editor)来完成或编辑所有通过这些对话框访问不到的bean代码。
你的消息驱动bean的一个实例在某一时刻只能处理一个消息,并且该bean只能有一个onMessage方法。下面是一个完整方法的例子。
public void onMessage(Message inMessage)
{ TextMessage msg = null;
try
{ if (inMessage instanceof TextMessage)
{ msg = (TextMessage) inMessage;
System.out.println("MESSAGE BEAN: Message " +
"received: " + msg.getText());
}
else { System.out.println("Message of wrong type: " +
inMessage.getClass().getName());
}
} catch (JMSException e)
{ System.err.println("MessageBean.onMessage: " +
"JMSException: " + e.toString());
context.setRollbackOnly();
} catch (Throwable te)
{ System.err.println("MessageBean.onMessage: " +
"Exception: " + te.toString());
}
}
|
setMessageDrivenContext方法在一个域中保存消息驱动上下文并且构造非持久性域。如果需要,你可以用这一方法来分配独立于该bean对象且在整个bean生命期中都会保持的资源。这些资源可能包括一个队列连接(queue-connection)或者主题连接工厂(topic-connection factory)。
缺省地,EJB构建器向导会生成把消息驱动上下文赋给一个叫做coontext的非持久性域的代码。通常,你不需要再给生成的方法加什么东西。但是,如果你确实需要完成它,拷贝生成的context代码到实例变量中。如:
|
表 7-4 一个setMessageDrivenContext 方法的例子 |
public void setMessageDrivenContext(javax.ejb.MessageDrivenContext aContext ) {
this.context=context;
}
|
除需要其他几步工作为该bean用于其最终环境作准备外,你的消息驱动bean现在已经完成了。你必须在属性页中指明下述信息:
如果你的消息驱动bean将从一个客户端那里接收消息并且你打算把你的bean发布到J2EE引用实现应用服务器(reference implementation application server,RI)上,你必须在该bean的属性页中的“J2EE RI”tab页中指明其目标。
如果你的消息驱动bean自己就是一个发送消息到一个目标的客户端,你必须在该bean属性页中的“References”tab页中指明下述信息:
接着会讨论这些属性的设定。
要指明该消息驱动bean是一个队列监听器还是一个主题监听器,执行以下步骤:
1.在IDE对象管理器中,单击该消息驱动bean的逻辑结点并选择“Properties” 。
该bean的属性页显示出来。
2. 在“Properties”tab页中, 单击“ Message-Driven Destination”域后单击省略号按钮(...)。
属性编辑器显示出来
3. 选择 “Queue”, “Topic”, 或者“(Not Set)”。
4. 单击“OK”关闭属性编辑器。
如果你想过滤传给你的bean的消息,执行以下步骤:
1.单击“Message Selector” 域后再单击省略号(...)按钮。
一个属性编辑器显示出来。
2.如果你想减少你的bean必须监听的消息数目,指明一个过滤器。
3. 单击“OK”关闭属性编辑器。
一个消息驱动bean属性页的“References”tab页包含“Resource Reference”和“Resource Environment Reference”域。这些域是代发送消息的客户端来设置的。例如,你的消息驱动bean可能是一个应用的一部分,该应用中的一个web模块发送消息到一个队列供你的bean用。在该例子中,“Resource Reference”和“Resource Environment Reference”就应该由该web模块的提供者来指明。
或者,如果你的消息驱动bean本来在它自己的模块中就被当作一个发送消息到一个队列或者主题的客户端,那么你可以在这里指明资源工厂和资源。
要把该消息驱动bean同一个创建目的对象的工厂对象关联,执行下述步骤:
1.在“References”tab页中,单击“Resource References”域后再单击省略号(...)按钮。
在属性编辑器中的域就是用来指明客户端(或作为客户端的消息驱动bean)用于访问消息资源的连接工厂的。
2. 单击“Add”按钮。
带有两个tab页的“Add Resource Reference”对话框显示出来。
如果你打算把你的消息驱动bean发布到RI上,完成以下步骤:
3. 完成后单击“OK”关闭对话框。
要把该消息驱动bean 同一特定目标对象关联,执行下述步骤:
1.在“References”tab页中,单击“Resource Environment References”域后再单击省略号(...)按钮。
在属性编辑器中的域就是用来指明客户端(或作为客户端的消息驱动bean)将要发送消息的实际资源。
2. 单击“Add”按钮
带有两个tab页的“Add Resource Environment Reference”对话框显示出来。
如果你打算把你的消息驱动bean发布到J2EE资源实现应用服务器(RI)上,完成以下步骤:
3. 完成后单击“OK”关闭对话框。
如果你的bean要发布到RI上,你不仅要说明它是监听一个队列还是监听一个主题。你还要指明该资源的JNDI名称以便RI可以找到它。执行下述步骤:
1.在“J2EE RI”tab页里单击“Destination JNDI Name”域再单击省略号(...)按钮.
2.在属性编辑器中为你的bean指明消息资源的JNDI名称。
用类型/资源的形式,例如,一个消息队列可以指明为jms/myQueue 。
请阅读第2章中关于消息驱动目标的更多内容以及第8章中关于设置属性的更多内容 。
附录A包含了处理已完成的企业bean的建议
如果你能理解下面可能的复杂情况,你的应用系统的消息层就很少会出问题:
要获得更详细的设计上的考虑,请参见企业级JavaBean规范版本2.0以及关于编写企业bean的教材。
企业bean可以是你的应用系统中一个非常强大和灵活的部分。创建一个企业bean的基本部分可以很简单,尤其通过利用像Sun Java System Studio IDE这样的工具。但是,完成能满足你应用需求的bean的工作可能会非常复杂。要获得详细信息,请参见企业级JavaBean规范,版本2.0,其位于:
http://java.sun.com/products/ejb/docs.html
|
创建EJB组件 |
816-7864-10 |
|
|||||||||||
|
|||||||||||
|
|||||||||||
|
|||||||||||