📄 lib0096.html
字号:
<html>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<head>
<title>Message-Driven Beans</title>
<link rel="STYLESHEET" type="text/css" href="images/xpolecat.css">
<link rel="STYLESHEET" type="text/css" href="images/ie.content.css">
</head>
<body>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle" alt="Team LiB"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="LiB0095.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0097.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr></table>
<br>
<div class="chapter">
<a name="ch14"></a>
<div class="section">
<h2 class="first-section-title"><a name="462"></a><a name="ch14lev1sec2"></a>Message-Driven Beans</h2><a name="463"></a><a name="IDX-191"></a>
<p class="para">Message-driven beans (MDBs) allow the container to handle the threading associated with listening to a JMS queue. When MDBs are deployed, the container administrator provides information about what queue it listens for. When a message is received from a queue, the container allocates an MDB and calls the onMessage() method on it, providing the content of the message. Processing within the MDB is similar to a stateless session bean in many ways. MDBs have the same set of responsibilities that session beans do, with a few differences. For the purchase order example, consider the onMessage() method in <a class="internaljump" href="#ch14list03">listing 14.3</a>.</p>
<div class="example">
<span class="example-title"><span class="example-titlelabel">Listing 14.3: </span>Using an MDB to Process Purchase Orders</span><a name="464"></a><a name="ch14list03"></a>
<div class="formalbody">
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="Start example" border="0"></b></font></td>
</tr>
</table>
<pre class="literallayout">
1:package book.sample.deploy.poxml;
2:
3:import book.sample.bo.PurchaseOrder;
4:// some code omitted
5:
6:public class PurchaseOrderMessageDrivenBean
7: extends DefaultMessageDrivenBean
8:{
9:
10: public PurchaseOrderMessageDrivenBean() {}
11:
12: public void onMessage(Message message)
13: {
14: String xmlText = null;
15: PurchaseOrderVO order = null;
16:
17: try
18: {
19: J2EETransactionContext context =
20: new J2EETransactionContext(
21: this._messageDrivenContext);
22: if ( message != null &&
23: message instanceof TextMessage)
24: {
25: TextMessage tm = (TextMessage) message;
26: xmlText = tm.getText();
27: }
28: else
29: {
30: LogManager.getLogger().logError
31: ("Null or invalid message received by "+
32: "PurchaseOrderMessageDrivenBean");
33: }<a name="465"></a><a name="IDX-192"></a>
34:
35: order = this.customerOrderListXlator(xmlText);
36:
37: PurchaseOrder po = new PurchaseOrder( context,
38: order);
39: po.record();
40: }
41: catch (InsufficientCreditException ice)
42: {
43: LogManager.getLogger().logInfo(ice.getMessage(),
44: ice);
45: }
46: catch (InternalApplicationException iae)
47: {
48: LogManager.getLogger().logError(iae.getMessage(),
49: iae);
50: }
51: catch (Throwable t)
52: {
53: StringBuffer errMessage = new StringBuffer();
54: errMessage.append("Error recording PO ==> ");
55: if (order != null)
56: {
57: errMessage.append(order.describe());
58: }
59: else errMessage.append("null");
60:
61: LogManager.getLogger().logError(
62: errMessage.toString(), t);
63: }
64: finally
65: {
66: JMSUtility.acknowledgeMessage(message);
67: }
68: }
69:}
</pre>
<table class="BlueLine" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td bgcolor="000080" class="bluecell"><font size="2" face="Arial" color="010100"><b><img src="_.gif" width="1" height="2" alt="End example" border="0"></b></font></td>
</tr>
</table>
<table class="BlankSpace" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td height="16"></td>
</tr>
</table>
</div>
</div>
<p class="para">
<i class="emphasis">Source:</i> /src/book/sample/poxml/PurchaseOrderMessageDrivenBean.java</p>
<p class="para">The MDB deployment for recording a purchase order has the additional burden of interpreting the message, but otherwise processing is very similar to a session bean. I typically use XML as a protocol for messages. However, this is a preference, not a technical requirement.</p>
<p class="para">
<b class="bold">MDBs should not throw exceptions.</b> There's no application "caller" to throw the exception to. The best you can do is log the error and possibly e-mail or page an application administrator. If you do throw an exception, it would <a name="466"></a><a name="IDX-193"></a>most likely be recorded in the containers' logs. My experience is that in most organizations, the probability that anyone will see it is extremely low.</p>
<p class="para">
<b class="bold">Acknowledge message receipt in a finally block.</b> If you receive a message but don't acknowledge it, it may be redelivered. This leads to a common messaging problem known as a "poison message." Essentially, if message processing continually errors out without acknowledgment, it creates an infinite loop when the message is redelivered. Generally, you should acknowledge the message even if processing the content of the message produced an error. Acknowledging the message means only that you successfully received it.</p>
<p class="para">An annoying consequence of message acknowledgment is a checked exception. To avoid this, I use a convenience class from CementJ that reduces the acknowledgment to one line of code as illustrated on line 66 of <a class="internaljump" href="#ch14list03">listing 14.3</a>.</p>
<p class="para">You can send multiple types of messages over one queue. For example, you might send customer information updates, product updates, and purchase orders over the same queue. In this case, the MDB would not directly contain logic to process the message but would forward it on to a handler. <a class="internaljump" href="#ch14fig02">Figure 14.2</a> is an object model illustrating this concept.</p>
<div class="figure">
<a name="467"></a><a name="ch14fig02"></a><span class="figuremediaobject"><a href="images/fig209%5F01%5F0%2Ejpg" NAME="IMG_40" target="_parent"><img src="images/fig209_01.jpg" height="243" width="350" alt="Click To expand" border="0"></a></span>
<br style="line-height: 1">
<span class="figure-title"><span class="figure-titlelabel">Figure 14.2: </span>Sample MDB Receiving Multiple Message Types</span>
</div>
</div>
</div><br>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td><div STYLE="MARGIN-LEFT: 0.15in;"><a href="toc.html"><img src="images/teamlib.gif" width="62" height="15" border="0" align="absmiddle" alt="Team LiB"></a></div></td>
<td align="right"><div STYLE="MARGIN-LEFT: 0.15in;">
<a href="LiB0095.html"><img src="images/previous.gif" width="62" height="15" border="0" align="absmiddle" alt="Previous Section"></a>
<a href="LiB0097.html"><img src="images/next.gif" width="41" height="15" border="0" align="absmiddle" alt="Next Section"></a>
</div></td></tr></table>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -