开发消息驱动Bean

779 篇文章 0 订阅
<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

  Sun Java System Studio IDE中的EJB构建器使你能开发消息驱动Bean(Message-Driven Beans),这类Bean能支持一个应用客户端的异步处理过程。本章将讨论创建和处理消息驱动Bean的过程。这些Bean的事务通常由EJB容器来管理,但如果你愿意,你可以自己提供事务管理代码。

  采用消息驱动Bean有以下几个原因:

  性能和对多任务的支持。客户端程序可以发出一个消息后继续其他的任务而不必等待该消息的响应。就是说,该客户端可以异步调用你的消息驱动Bean

  可靠性。如果应用系统使用了Java消息服务(Java Message Services,JMS),除非应用层突然瘫痪否则不会丢失任何客户端请求。

  但消息驱动Bean并不总是正确的选择。例如在下列情况中其他方式可能会工作的更好:

  当客户端需要确认请求已收到或需要返回一个结果时

  当该操作是一个时间敏感性事务(time-sensitive transaction)的一部分并且不能在非高峰期完成时

  当应用很小且并不复杂,同时添加其他层会减缓创建、调试和执行速度时

  该IDE提供了一个向导来让你创建一个消息驱动Bean所需要的一个单独的Bean类。因为一个消息驱动Bean只是从一个客户端提出消息并用它们开始其他的Bean处理,所以不需要其他的接口类。向导会自动执行创建一个消息驱动Bean所需的许多任务,而你需要用IDE的源码编辑器和属性页来完成创建任务。

  编写消息驱动Bean时你还有本章没有说明的一些选项。虽然Sun ONE Studio IDE被设计用来帮你做许多编码工作,但该IDE还灵活地支持那些选项并把决定权留给你。要获得更多信息,参见列在开始之前的相关资源,或者可以参考编写企业Bean方面的众多优秀教材中的一本。

  对消息驱动 Bean 使用 EJB 构建器

  创建一个Bean需要的类。执行过EJB构建器向导之后你就有了一个消息驱动Bean的框架,它由其Bean类和一个该Bean的其他部分的逻辑组构成。注意该类和逻辑组都会显示在对象管理器的“Filesystems”tab页中,还有它们的子结点。该向导会为Bean类生成两个必须的方法的声明: ejbCreate 和 onMessage。然后你可以提供方法的实现。

  逻辑结点是处理消息驱动Bean的最好地方。一个逻辑结点在对象管理器中显示这一图标:

  如果需要,完成Bean类结点。使用本章随后描述的IDE支持。

  在一个Bean的布署描述符中设定值。用来自逻辑结点的消息驱动Bean属性页编辑属性。

  从一个消息驱动Bean的逻辑结点你可以检查该Bean代码的有效性。

  决定事务管理

  在创建消息驱动Bean之前,你首先要考虑是让容器来管理你的Bean要执行的事务还是自己编写这些代码。你可以用IDE中EJB构建器的不同执行过程来创建这两种Bean。表7-1说明了设计时的考虑。

 

 

  表 7-1 在容器管理和Bean管理的事务间作出决定

 

 

 

  问题

 

 

  容器管理的事务(BMP)

 

 

  Bean管理的事务(BMP)

 

 

 

  事务的管理者

 

 

  容器自己是事务管理者。

 

 

  你利用JTA自己写代码管理事务。这可以包含用于其他资源如JDBC的事务。

 

 

 

  事务边界的设定

 

 

  EJB容器根据Java2平台企业版规范来决定何时开始和提交一个事务。

 

 

  程序员显示地编写事务边界来获得对事务更细化的控制。

 

 

 

  事务时效

 

 

  消息驱动Bean在同一个事务中接收一个消息并执行它的业务方法。

 

 

  事务直到该消息驱动Bean收到消息之后才开始。

 

 

 

  问题处理

 

 

  容器会回滚该事务并通知该Bean这一消息。

 

 

  该消息驱动Bean根据你生成该Bean后指明的通知模式来做出响应。

 

 

 

  关于这些选项的更多信息,参见书构建J2EE应用中关于事务的那一章。

  本章剩下的部分将介绍如何创建每种消息驱动Bean和开发中要考虑的问题。

  定义一个消息驱动 Bean

  EJB构建器向导会自动执行创建你的消息驱动Bean所需的一个Bean类的许多任务。要定义一个消息驱动Bean,按以下步骤执行:

  1. 选择或创建一个包含该Bean的包。

  2. 利用EJB构建器向导生成你的消息驱动Bean的基本结构。

  3. 完成onMessage方法体,并且如果需要,完成setMessageDrivenContext和ejbCreate方法。

  这些基本步骤随后会详细解释。

  完成本章讲述的步骤之后你必须给你完成的Bean的属性页中添加信息以便它可以同其他Bean交互、查找它的资源、以及监听相应的消息。这些关于准备把你完成的Bean用于一个应用中的步骤会在第8章讨论。

  创建一个包

  如果你需要创建一个包来保存你的消息驱动Bean,选择一个文件系统,单击鼠标右键并选择“New Java Package”

  启动EJB构建器向导

  当你准备要创建一个消息驱动Bean时,按以下步骤执行:

 

Bean

  在EJB构建器的“Message-Driven Bean Name”和“Properties”面板中命名你的消息驱动Bean并决定如何管理该Bean可能执行的事务。缺省值是容器管理的事务,但如果你愿意,你可以在该Bean类中提供所有事务管理代码。

  做出你的选择后你可以单击“Finish”。(或者你可以单击“Next”以打开你可以为你的消息驱动Bean指明一个既存的Bean类的面板。这之后你再单击“Finish”。)

  你新建的消息驱动Bean会显示在IDE对象管理器中的“Filesystems”面板中。该Bean的基本结构(它的基本Bean类和两个组件方法)已经被该EJB构建器自动生成了。

  在对象管理器中查看你的消息驱动 Bean

  图 7-1 展示了一个典型的消息驱动Bean是如何在对象管理器的“Filesystems”面板中显示的。

  图 7-1 一个典型的消息驱动Bean的缺省类和方法

  在显示的两个主要结点中,一个是逻辑结点(用一个Bean图标表示)一个表示其实际的类(用一个类图标表示)。在逻辑结点上进行你的所有编辑工作。该Bean的两个主要结点接下来会说明。

  在对象管理器中创建的逻辑结点是用来组织你的消息驱动Bean的所有元素的,而且使你对它们的处理更方便。

  该Bean类实现了 javax.ejb.MessageDrivenBean 和 javax.jms.MessageListener 接口,并且展现了消息驱动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,执行以下步骤:

  添加代码完成你的Bean的onMessage方法体。

  添加你的Bean的setMessageDrivenContext方法需要的任何代码。

  简单的消息驱动Bean不需要 ejbCreate 和 ejbRemove 方法。但如果确实需要,那么ejbCreate方法可以用来分配资源而ejbRemove可以释放那些资源。

  用属性页(发布你的Bean的应用服务器的tab接口)指明资源类型、资源工厂、以及该消息驱动Bean用到的服务器。 为客户消息驱动Bean指明资源和第8章提供了这方面的详细情况。

  单击对象管理器中逻辑Bean结点下的Bean组件来打开源码编辑器完成其他工作。

  在处理企业Bean时使用推荐的方法

  附录A 探讨了修改你的企业Bean的最佳方式,以及当你采用其他方式时可能会遇到的错误和异常。作为一条总的原则,你应该通过逻辑结点而不是单独的类结点来工作,利用Bean的属性页(property sheets)或定制对话框(Customizer dialog box)来编辑方法,以及使用IDE的源码编辑器(Source Editor)来完成或编辑所有通过这些对话框访问不到的Bean代码。

  完成 onMessage 方法

  你的消息驱动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 方法

  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的消息驱动目标,即,该Bean是从一个队列(queue)还是一个主题(topic)中取它的消息

  如果该Bean监听一个主题,它的订阅是持久的还是非持久的

  该Bean是否采用了一个选择器(过滤器)来缩小其获得消息的范围。

  如果你的消息驱动Bean将从一个客户端那里接收消息并且你打算把你的Bean发布到J2EE引用实现应用服务器(reference implementation application server,RI)上,你必须在该Bean的属性页中的“J2EE RI”tab页中指明其目标。

  如果你的消息驱动Bean自己就是一个发送消息到一个目标的客户端,你必须在该Bean属性页中的“References”tab页中指明下述信息:

  该Bean的资源引用(它用到的用于访问其消息驱动目标的连接工厂)

  该Bean的资源环境引用(实际的目标:队列或者主题)

  接着会讨论这些属性的设定。

  指明一个消息驱动目标

  要指明该消息驱动Bean是一个队列监听器还是一个主题监听器,执行以下步骤:

  1.在IDE对象管理器中,单击该消息驱动Bean的逻辑结点并选择“Properties” 。

  该Bean的属性页显示出来。

  2. 在“Properties”tab页中, 单击“ Message-Driven Destination”域后单击省略号按钮(...)。

  属性编辑器显示出来

  3. 选择 “Queue”, “Topic”, 或者“(Not Set)”。

  如果客户端只给这一特定Bean发送消息并且你需要使用点对点模式,选择“Queue”。

  如果你需要通过发布—订阅模式允许多个客户端给这个Bean发送消息,选择“Topic”。如果你选择了“Topic”,你还必须指明该Bean的订阅是持久(Durable)的还是非持久(non-durable)的。

  如果消息必须一直保存直到被该Bean处理,那么选择“Durable”。通过这种方式,即便该Bean的应用服务器崩溃,在下一次该Bean可用时依然可以获得该消息。

  如果该Bean只接收在其可用时发布的消息,那么选择“Non-durable”。所有其他消息都会被删除。

  如果你想以后再设置这一属性就保持该域为空(选择“Not Set”值)。

  4. 单击“OK”关闭属性编辑器。

  指明一个消息选择器

  如果你想过滤传给你的Bean的消息,执行以下步骤:

  1.单击“Message Selector” 域后再单击省略号(...)按钮。

  一个属性编辑器显示出来。

  2.如果你想减少你的Bean必须监听的消息数目,指明一个过滤器。

  3. 单击“OK”关闭属性编辑器。

  为客户消息驱动Bean指明资源

  一个消息驱动Bean属性页的“References”tab页包含“Resource Reference”和“Resource Environment Reference”域。这些域是代发送消息的客户端来设置的。例如,你的消息驱动Bean可能是一个应用的一部分,该应用中的一个web模块发送消息到一个队列供你的Bean用。在该例子中,“Resource Reference”和“Resource Environment Reference”就应该由该web模块的提供者来指明。

  或者,如果你的消息驱动Bean本来在它自己的模块中就被当作一个发送消息到一个队列或者主题的客户端,那么你可以在这里指明资源工厂和资源。

  明资源工厂(reference factories)

  要把该消息驱动Bean同一个创建目的对象的工厂对象关联,执行下述步骤:

  1.在“References”tab页中,单击“Resource References”域后再单击省略号(...)按钮。

  在属性编辑器中的域就是用来指明客户端(或作为客户端的消息驱动Bean)用于访问消息资源的连接工厂的。

  2. 单击“Add”按钮。

  带有两个tab页的“Add Resource Reference”对话框显示出来。

  在“Standard” tabb页中:

  键入创建你的Bean到它的队列或主题的连接的对象的名字。

  在“Type”组合框中选择你的Bean将要用的资源工厂的类型。这一类型应该和你在“Properties”tab页中的“Message-driven Destination”域中选择的相对应。参见指明资源环境引用查看对各种资源工厂类型的解释。

  在“Authorization”域中,指明是EJB容器还是应用客户端来给该Bean授权使用该资源。

  在“Sharing Scope”域中,指明到这一资源的连接是否可以被相同应用中的其他企业Bean来共享。如果两个或者多个Bean可以在同一个事务上下文中使用相同的资源,容器就可以在本地执行事务并节省时间。

  如果你打算把你的消息驱动Bean发布到RI上,完成以下步骤:

  在“J2EE RI”tab页中:

  在“JNDI Name”域中,键入定位该资源工厂所用到的名字。

  在“User Information”域中提供任何访问该资源时用到的信息。

  如果适合你的情况,在“Mail Configuration”域中提供使用一个JavaMail会话工厂将用到的信息。

  3. 完成后单击“OK”关闭对话框。

  指明资源

  要把该消息驱动Bean 同一特定目标对象关联,执行下述步骤:

  1.在“References”tab页中,单击“Resource Environment References”域后再单击省略号(...)按钮。

  在属性编辑器中的域就是用来指明客户端(或作为客户端的消息驱动Bean)将要发送消息的实际资源。

  2. 单击“Add”按钮

  带有两个tab页的“Add Resource Environment Reference”对话框显示出来。

  在“Standard”tab页中:

  键入你的客户端或Bean将要发送消息的队列或者主题的名字。

  在组合框中选择一个资源类型

  如果你打算把你的消息驱动Bean发布到J2EE资源实现应用服务器(RI)上,完成以下步骤:

  在“J2EE RI”tab页中键入该消息资源(队列或者主题)用到的JNDI名称。

  3. 完成后单击“OK”关闭对话框。

  为发布到RI上的消息驱动Bean监听器指明资源

  如果你的Bean要发布到RI上,你不仅要说明它是监听一个队列还是监听一个主题。你还要指明该资源的JNDI名称以便RI可以找到它。执行下述步骤:

  1.在“J2EE RI”tab页里单击“Destination JNDI Name”域再单击省略号(...)按钮.

  2.在属性编辑器中为你的Bean指明消息资源的JNDI名称。

  用类型/资源的形式,例如,一个消息队列可以指明为jms/myQueue 。

  请阅读第2章中关于消息驱动目标的更多内容以及第8章中关于设置属性的更多内容 。

  避免消息驱动 Bean 的缺陷

  如果你能理解下面可能的复杂情况,你的应用系统的消息层就很少会出问题:

  消息顺序。你的消息驱动Bean应该对没按顺序到达的消息有所准备。一个JMS服务器可能会以任一顺序给一个消息驱动Bean池发送消息。

  未调用的ejbRemove方法。一个简单的消息驱动Bean不需要使用ejbCreate或者ejbRemove方法,但是,如果你的Bean很复杂并确实需要这些方法,记住在某些情况下(比如系统或者容器崩溃)ejbRemove可能不会被调用。这种情况下,你应该准备让该Bean自己完成清理工作。这也依赖于你的应用服务器的行为。更多信息请参考你的服务器文档。

  有害消息。当你用EJB构建器向导来生成一个自己管理事务的消息驱动Bean的基本结构时,你可以设定Bean的“Acknowledge Mode”为“Auto”。这一设定会使该Bean在每次收到消息后自动发出通知。按这种方式,你可以避免事务失败而消息目标却不知道消息已收到并继续不断发消息的情况。

  要获得更详细的设计上的考虑,请参见企业级JavaBean规范版本2.0以及关于编写企业

<script type="text/javascript"> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值