Jms 1 - 1 FR Spec PDF
Jms 1 - 1 FR Spec PDF
Jms 1 - 1 FR Spec PDF
The JMS API is an API for accessing enterprise messaging systems from Java programs . Version 1.1 April 12, 2002 Please send technical comments on this specification to:
[email protected]
JavaTM Message Service Specification ("Specification") Version: 1.1 Status: FCS Release: April 12, 2002 Copyright 2002 Sun Microsystems, Inc. 901 San Antonio Road, Palo Alto, California 94303, U.S.A. All rights reserved. NOTICE The Specification is protected by copyright and the information described therein may be protected by one or more U.S. patents, foreign patents, or pending applications. Except as provided under the following license, no part of the Specification may be reproduce d in any form by any means without the prior written authorization of Sun Microsystems, Inc. ("Sun") and its licensors, if any. Any use of the Specification and the information described therein will be governed by the terms and conditions of this license and the Export Control Guidelines as set forth in the Terms of Use on Sun's website. By viewing, downloading or otherwise copying the Specification, you agree that you have read, understood, and will comply with all of the terms and conditions set forth herein. Subject to the terms and conditions of this license, Sun hereby grants you a fully-paid, non-exclusive, non-transferable, worldwide, limited license (without the right to sublicense) under Sun's intellectual property rights to review the Specification internally solely for the purpose of designing and developing your Java applets and applications intended to run on the Java platform. Other than this limited license, you acquire no right, title or interest in or to the Specification or any other Sun intellectual property. The Specification contains the proprietary information of Sun and may only be used in accordance with the license terms set forth herein. This license will terminate immed iately without notice from Sun if you fail to comply with any provision of this license. Upon termination or expiration of this licen se, you must cease use of or destroy the Specification. TRADEMARKS No right, title, or interest in or to any trademarks, service marks, or trade names of Sun or Sun's licensors is granted hereund er. Sun,Sun Microsystems, the Sun logo, Java, Jini, J2EE, JavaServerPages, Enterprise JavaBeans, JavaCompatible, JDK, JDBC, JavaBeans, JavaM ail, Write Once, Run Anywhere, and Java Naming and Directory Interface are trademarks or registered trademarks of Sun Microsystems, I nc. in the U.S. and other countries. DISCLAIMER OF WARRANTIES THE SPECIFICATION IS PROVIDED "AS IS". SUN MAKES NO REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT THAT THE CONTENTS OF THE SPECIFICATION ARE SUITABLE FOR ANY PURPOSE OR THAT ANY PRACTICE OR IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADE SECRETS OR OTHER RIGHTS. This document does not represent any commitment to release or implement any portion of the Specification in any product . THE SPECIFICATION COULD INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS. CHANGES ARE PERIODICALLY ADDED TO THE INFORMATION THEREIN; THESE CHANGES WILL BE INCORPORATED INTO NEW VERSIONS OF THE SPECIFICATION, IF ANY. SUN MAY MAKE IMPROVEMENTS AND/OR CHANGES TO THE PRODUCT(S) AND/OR THE PROGRAM(S) DESCRIBED IN THE SPECIFICATION AT ANY TIME. Any use of such changes in the Specification will be governed by the then-current license for the applicable version of the Specification. LIMITATION OF LIABILITY TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES, INCLUDING WITHOUT LIMITATION, LOST REVENUE, PROFITS OR DATA, OR FOR SPECIAL, INDIRECT, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF OR RELATED TO ANY FURNISHING, PRACTICING, MODIFYING OR ANY USE OF THE SPECIFICATION, EVEN IF SUN AND/OR ITS LICENSORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. You will indemnify, hold harmless, and defend Sun and its licensors from any claims arising or resulting from: (i) your use of the Specification; (ii) the use or distribution of your Java applications or applets; and/or (iii) any claims that later versions or releases of any Specification furnished to you are incompatible with the Specification provided to you under this license. RESTRICTED RIGHTS LEGEND U.S. Government: If this Specification is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in the Software and accompanying documentation shall be only as set forth in this license; this is in accordance with 48 C.F.R. 227.7201 through 227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48 C.F.R. 2.101 and 12.212 (for non-DoD acquisitions). REPORT You may wish to report any ambiguities, inconsistencies or inaccuracies you may find in connection with your use of the Specification ("Feedback"). To the extent that you provide Sun with any Feedback, you hereby: (i) agree that such Feedback is provided on a no n-
proprietary and non-confidential basis, and (ii) grant Sun a perpetual, non-exclusive, worldwide, fully paid-up, irrevocable license, with the right to sublicense through multiple levels of sublicensees, to incorporate, disclose, and use without limitation the Feedba ck for any purpose related to the Specification and future versions, implementations, and test suites thereof.
(LFI#111700/Form ID#011801)
Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 1.2 1.2.1 1.2.2 1.2.3 1.2.3.1 1.2.3.2 1.2.3.3 1.2.3.4 1.2.4 1.3 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.5 2. Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Is This a Mail API? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Existing Messaging Systems . . . . . . . . . . . . . . . . . . . . . JMS Objectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS Provider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS Domains . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Portability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What JMS Does Not Include . . . . . . . . . . . . . . . . . . . . . What Is Required by JMS . . . . . . . . . . . . . . . . . . . . . . . Relationship to Other Java APIs . . . . . . . . . . . . . . . . . Java DataBase Connectivity (JDBCTM) Software . . . . JavaBeansTM Components . . . . . . . . . . . . . . . . . . . . . . Enterprise JavaBeansTM Component Model . . . . . . . Java Transaction API (JTA) . . . . . . . . . . . . . . . . . . . . . . Java Transaction Service (JTS). . . . . . . . . . . . . . . . . . . . Java Naming and Directory InterfaceTM (JNDI) API Java 2, Enterprise Edition (J2EE) Platform . . . . . . . . . Integration of JMS with the EJB Components . . . . . . What is New in JMS 1.1? . . . . . . . . . . . . . . . . . . . . . . . 13 13 13 14 14 15 15 15 15 16 16 17 17 17 18 18 18 18 19 19 19 19 21
Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1 2.2 2.3 2.4 2.5 2.6 2.6.1 2.7 2.8 2.9 2.10 3.
Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . What is a JMS Application? . . . . . . . . . . . . . . . . . . . . . Administration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Two Messaging Styles . . . . . . . . . . . . . . . . . . . . . . . . . . JMS Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Developing a JMS Application . . . . . . . . . . . . . . . . . . Developing a JMS Client . . . . . . . . . . . . . . . . . . . . . . . . Security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Multithreading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Triggering Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Request/Reply . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21 21 22 23 23 25 25 26 26 27 27 29 29 29 30 30 30 31 31 31 32 33 33 33 34 34 35 35 35 36 36 36 36 37 37 38 38
JMS Message Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 3.2 3.3 3.4 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.4.10 3.4.11 3.4.12 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Goals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Message Header Fields . . . . . . . . . . . . . . . . . . . . . . . . . JMSDestination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMSDeliveryMode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMSMessageID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMSTimestamp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMSCorrelationID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMSReplyTo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMSRedelivered . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMSType. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMSExpiration. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMSPriority . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How Message Header Values Are Set . . . . . . . . . . . . . Overriding Message Header Fields . . . . . . . . . . . . . . . Message Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . Property Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Property Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Using Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Property Value Conversion . . . . . . . . . . . . . . . . . . . . . . Property Values as Objects . . . . . . . . . . . . . . . . . . . . . . Property Iteration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Clearing a Messages Property Values. . . . . . . . . . . . . Nonexistent Properties . . . . . . . . . . . . . . . . . . . . . . . . .
3.5.9 3.5.10 3.6 3.7 3.8 3.8.1 3.8.1.1 3.8.1.2 3.8.1.3 3.9 3.10 3.11 3.11.1 3.11.2 3.11.3 3.11.4 3.12 4.
JMS Defined Properties . . . . . . . . . . . . . . . . . . . . . . . . . Provider-Specific Properties . . . . . . . . . . . . . . . . . . . . . Message Acknowledgment . . . . . . . . . . . . . . . . . . . . . The Message Interface . . . . . . . . . . . . . . . . . . . . . . . . . Message Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Message Selector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Message Selector Syntax . . . . . . . . . . . . . . . . . . . . . . . . Null Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Special Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Access to Sent Messages . . . . . . . . . . . . . . . . . . . . . . . . Changing the Value of a Received Message . . . . . . . . JMS Message Body . . . . . . . . . . . . . . . . . . . . . . . . . . . . Clearing a Message Body . . . . . . . . . . . . . . . . . . . . . . . Read-Only Message Body . . . . . . . . . . . . . . . . . . . . . . . Conversions Provided by StreamMessage and MapMessage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Messages for Non-JMS Clients . . . . . . . . . . . . . . . . . . . Provider Implementations of JMS Message Interfaces
38 40 40 40 41 41 42 45 46 47 47 48 48 48 49 50 51 53 53 53 54 54 55 55 55 56 57 57 58 59 59 60 60 61 61 62
JMS Common Facilities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 4.2 4.2.1 4.2.2 4.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.4 4.4.1 4.4.2 4.4.3 4.4.4 Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Administered Objects . . . . . . . . . . . . . . . . . . . . . . . . . . Destination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ConnectionFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Connection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Client Identifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Connection Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pausing Delivery of Incoming Messages . . . . . . . . . . Closing a Connection. . . . . . . . . . . . . . . . . . . . . . . . . . . Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ConnectionMetaData . . . . . . . . . . . . . . . . . . . . . . . . . . . ExceptionListener. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Closing a Session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MessageProducer and MessageConsumer Creation . Creating Temporary Destinations . . . . . . . . . . . . . . . . Creating Destination Objects . . . . . . . . . . . . . . . . . . . .
Contents
4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.4.10 4.4.10.1 4.4.10.2 4.4.11 4.4.12 4.4.13 4.4.14 4.4.15 4.5 4.5.1 4.5.2 4.6 4.7 4.8 4.9 4.10 4.11 5.
Optimized Message Implementations. . . . . . . . . . . . . Conventions for Using a Session . . . . . . . . . . . . . . . . . Transactions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Distributed Transactions . . . . . . . . . . . . . . . . . . . . . . . . Multiple Sessions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Message Order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Order of Message Receipt . . . . . . . . . . . . . . . . . . . . . . Order of Message Sends . . . . . . . . . . . . . . . . . . . . . . . . Message Acknowledgment . . . . . . . . . . . . . . . . . . . . . . Duplicate Delivery of Messages . . . . . . . . . . . . . . . . . . Duplicate Production of Messages. . . . . . . . . . . . . . . . Serial Execution of Client Code . . . . . . . . . . . . . . . . . . Concurrent Message Delivery . . . . . . . . . . . . . . . . . . . MessageConsumer . . . . . . . . . . . . . . . . . . . . . . . . . . . . Synchronous Delivery . . . . . . . . . . . . . . . . . . . . . . . . . . Asynchronous Delivery. . . . . . . . . . . . . . . . . . . . . . . . . MessageProducer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Message Delivery Mode . . . . . . . . . . . . . . . . . . . . . . . . Message Time-To-Live . . . . . . . . . . . . . . . . . . . . . . . . . Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reliability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Method Inheritance across Messaging Domains . . . .
62 62 64 64 65 65 65 65 66 67 67 68 68 68 69 69 70 70 71 71 71 73 75 75 76 76 76 77 77 77 77 78 78 78 79 79
JMS Point-to-Point Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 5.11 Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Queue Management . . . . . . . . . . . . . . . . . . . . . . . . . . . Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . TemporaryQueue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . QueueConnectionFactory . . . . . . . . . . . . . . . . . . . . . . QueueConnection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . QueueSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . QueueReceiver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . QueueBrowser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . QueueRequestor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reliability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.
6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 6.11 6.11.1 6.12 6.13 6.14 6.15 7.
Pub/Sub Latency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Durable Subscription . . . . . . . . . . . . . . . . . . . . . . . . . . Topic Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . Topic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . TemporaryTopic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . TopicConnectionFactory . . . . . . . . . . . . . . . . . . . . . . . . TopicConnection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . TopicSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . TopicPublisher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . TopicSubscriber . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Durable TopicSubscriber . . . . . . . . . . . . . . . . . . . . . . . . Recovery and Redelivery . . . . . . . . . . . . . . . . . . . . . . . Administering Subscriptions . . . . . . . . . . . . . . . . . . . . TopicRequestor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Reliability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
80 80 81 81 82 82 82 82 83 83 83 84 84 85 85 87 87 87 88 91 91 91 92 92 92 93 93 94 94 97 97 97 98
JMS Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.1 7.2 7.3 Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The JMSException . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Standard Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.
JMS Application Server Facilities . . . . . . . . . . . . . . . . . . . . . . . 8.1 8.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.2.7 8.3 8.4 8.5 8.6 Overview. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Concurrent Processing of a Subscriptions Messages Session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ServerSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ServerSessionPool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ConnectionConsumer . . . . . . . . . . . . . . . . . . . . . . . . . . How a ConnectionConsumer Uses a ServerSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . How an Application Server Implements a ServerSession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Result . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XAConnectionFactory . . . . . . . . . . . . . . . . . . . . . . . . . XAConnection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XASession . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS Application Server Interfaces . . . . . . . . . . . . . . .
Contents
9.
JMS Example Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.1.7 9.1.8 9.2 9.2.1 9.2.2 9.2.3 9.3 9.3.1 9.3.2 9.3.3 9.3.3.1 9.3.3.2 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.4.6 9.4.7 9.4.8 9.4.9 9.4.10 Preparing to Send and Receive Messages . . . . . . . . . Getting a ConnectionFactory . . . . . . . . . . . . . . . . . . . . Getting a Destination . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a Connection . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a Session . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a MessageProducer . . . . . . . . . . . . . . . . . . . . Creating a MessageConsumer . . . . . . . . . . . . . . . . . . . Starting Message Delivery . . . . . . . . . . . . . . . . . . . . . . Using a TextMessage . . . . . . . . . . . . . . . . . . . . . . . . . . . Sending and Receiving Messages . . . . . . . . . . . . . . . . Sending a Message . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Receiving a Message Synchronously . . . . . . . . . . . . . . Unpacking a TextMessage. . . . . . . . . . . . . . . . . . . . . . . Other Messaging Features . . . . . . . . . . . . . . . . . . . . . . Receiving Messages Asynchronously . . . . . . . . . . . . . Using Message Selection . . . . . . . . . . . . . . . . . . . . . . . . Using Durable Subscriptions . . . . . . . . . . . . . . . . . . . . Creating a Durable Subscription . . . . . . . . . . . . . . . . . Reconnecting to a Topic using a Durable Subscription . . . . . . . . . . . . . . . . . . . . . . . . . . JMS Message Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating a TextMessage . . . . . . . . . . . . . . . . . . . . . . . . . Unpacking a TextMessage. . . . . . . . . . . . . . . . . . . . . . . Creating a BytesMessage. . . . . . . . . . . . . . . . . . . . . . . . Unpacking a BytesMessage. . . . . . . . . . . . . . . . . . . . . . Creating a MapMessage . . . . . . . . . . . . . . . . . . . . . . . . Unpacking a MapMessage . . . . . . . . . . . . . . . . . . . . . . Creating a StreamMessage . . . . . . . . . . . . . . . . . . . . . . Unpacking a StreamMessage . . . . . . . . . . . . . . . . . . . . Creating an ObjectMessage. . . . . . . . . . . . . . . . . . . . . . Unpacking an ObjectMessage. . . . . . . . . . . . . . . . . . . .
99 99 100 100 100 101 101 101 102 102 102 103 103 103 103 104 105 106 106 107 107 108 108 108 108 109 110 110 111 112 112 115 115 115 115
10.
Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.1 10.1.1 10.1.2 10.1.3 Resolved Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JDK 1.1.x Compatibility. . . . . . . . . . . . . . . . . . . . . . . . . Distributed Java Event Model . . . . . . . . . . . . . . . . . . . Should the Two JMS Domains, PTP and Pub/Sub,
10
be merged? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Should JMS Specify a Set of JMS JavaBeans? . . . . . . . Alignment with the CORBA Notification Service . . . Should JMS Provide End-to-end Synchronous Message Delivery and Notification of Delivery? . . . . . . . . . . . . . . . . . . . . . . . . Should JMS Provide a Send-to-List Mechanism? . . . . Should JMS Provide Subscription Notification? . . . .
116 117 117 119 119 119 119 119 120 120 120 120 120 121 121 121 121 121 121 121 122 122 122 122 122 122 123
Change History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.1 11.1.1 11.2 11.2.1 11.2.2 11.2.3 11.2.4 11.2.5 11.2.6 11.2.7 11.2.8 11.2.9 11.2.10 11.2.11 11.2.12 11.2.13 11.2.14 11.2.15 11.2.16 11.2.17 11.2.18 11.2.19 11.2.20 Version 1.0.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Version 1.0.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Multiple Topic Subscriber Special Case . . . . . . . . Message Selector Comparison of Exact and Inexact Numeric Values. . . . . . . . . . . . . . . . . . . . . . . . . Connection and Session Close . . . . . . . . . . . . . . . . . . . Creating a Session on an Active Connection . . . . . . . Delivery Mode and Message Retention . . . . . . . . . . . The single thread Use of Sessions . . . . . . . . . . . . . . . Clearing a Messages Properties and Body . . . . . . . . . Message Selector Numeric Literal Syntax . . . . . . . . . . Comparison of Boolean Values in Message Selectors . . . . . . . . . . . . . . . . . . . . . . . . . . . Order of Messages Read from a Queue . . . . . . . . . . . . Null Values in Messages . . . . . . . . . . . . . . . . . . . . . . . . Closing Constituents of Closed Connections and Sessions . . . . . . . . . . . . . . . . . . . . . . . The Termination of a Pending Receive on Close . . . . Incorrect Entry in Stream and Map Message Conversion Table . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inactive Durable Subscription . . . . . . . . . . . . . . . . . . . Read-Only Message Body . . . . . . . . . . . . . . . . . . . . . . . Changing Header Fields of a Received Message . . . . Null/Missing Message Properties and Message Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS Source Errata. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS Source Java API documentation Errata . . . . . . . .
Contents
11
11.2.21 11.3 11.3.1 11.3.2 11.3.2.1 11.3.2.2 11.3.3 11.4 11.4.1 11.4.2 11.4.3 11.4.3.1 11.4.3.2 11.4.4 11.4.5 11.4.5.1 11.4.5.2
JMS Source Java API documentation Clarifications . Version 1.0.2b . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS API Specification, version 1.0.2: Errata and Clarifications . . . . . . . . . . . . . . . . . . . . . . . . JMS API Java API documentation, version 1.0.2a: Major Errata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Corrections of Mistakes . . . . . . . . . . . . . . . . . . . . . . . . Reconciliations between the Specification and the Java API documentation . . . . . . . . . . . . . . . . JMS API Java API documentation, version 1.0.2a: Lesser Errata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Version 1.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Unification of messaging domains. . . . . . . . . . . . . . . . JMS API Specification, version 1.1: Domain Unification . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS API Specification, version 1.1: Updates and Clarifications . . . . . . . . . . . . . . . . . . . . . . Updates to Introduction, Added Figures . . . . . . . . . . Clarifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS API Java API documentation, version 1.1: Domain Unification . . . . . . . . . . . . . . . . . . . . . . . . . . . . JMS API documentation, version 1.1: Changes . . . . . New Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Clarifications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
123 124 125 126 126 127 127 128 129 129 131 131 131 132 135 135 136
12
Introduction
1.1 Abstract
This specification describes the objectives and functionality of the Java TM Message Service (JMS). JMS provides a common way for Java programs to create, send, receive and read an enterprise messaging systems messages.
1.2 Overview
Enterprise messaging products (or as they are sometimes called, Message Oriented Middleware products) are becoming an essential component for integrating intra-company operations. They allow separate business components to be combined into a reliable, yet flexible, system. In addition to the traditional MOM vendors, enterprise messaging products are also provided by several database vendors and a number of internet related companies. Java language clients and Java language middle tier services must be capable of using these messaging systems. JMS provides a common way for Java language programs to access these systems. JMS is a set of interfaces and associated semantics that define how a JMS client accesses the facilities of an enterprise messaging product.
13
1
Since messaging is peer-to-peer, all users of JMS are referred to generically as clients. A JMS application is made up of a set of application defined messages and a set of clients that exchange them. Products that implement JMS do this by supplying a provider that implements the JMS interfaces.
14
1
1.2.3 JMS Objectives
If JMS provided a union of all the existing features of messaging systems it would be much too complicated for its intended users. On the other hand, JMS is more than an intersection of the messaging features common to all products. It is crucial that JMS include the functionality needed to implement sophisticated enterprise applications. JMS defines a common set of enterprise messaging concepts and facilities. It attempts to minimize the set of concepts a Java language programmer must learn to use enterprise messaging products. It strives to maximize the portability of messaging applications.
15
1
Publish and subscribe (Pub/Sub) clients address messages to some node in a content hierarchy. Publishers and subscribers are generally anonymous and may dynamically publish or subscribe to the content hierarchy. The system takes care of distributing the messages arriving from a nodes multiple publishers to its multiple subscribers. JMS provides a set of interfaces that allow the client to send and receive messages in both domains, while supporting the semantics of each domain. JMS also provides client interfaces tailored for each domain. Prior to version 1.1 of the JMS specification, only the client interfaces that were tailored to each domain were available. These interfaces continue to be supported to provide backward compatibility for those who have already implemented JMS clients using them. The preferred approach for implementing clients is to use the domain-independent interfaces. These interfaces, referred to as the common interfaces, are parents of the domain-specific interfaces.
1.2.3.4 Portability
The primary portability objective is that new, JMS only, applications are portable across products within the same messaging domain. This is in addition to the expected portability of a JMS client across machine architectures and operating systems (when using the same JMS provider). Although JMS is designed to allow clients to work with existing message formats used in a mixed language application, portability of such clients is not generally achievable (porting a mixed language application from one product to another is beyond the scope of JMS).
Load Balancing/Fault Tolerance - Many products provide support for multiple, cooperating clients implementing a critical service. The JMS API does not specify how such clients cooperate to appear to be a single, unified service. Error/Advisory Notification - Most messaging products define system messages that provide asynchronous notification of problems or system events to clients. JMS does not attempt to standardize these messages. By following the guidelines defined by JMS, clients can avoid using these messages and thus prevent the portability problems their use introduces.
16
1
Administration - JMS does not define an API for administering messaging products. Security - JMS does not specify an API for controlling the privacy and integrity of messages. It also does not specify how digital signatures or keys are distributed to clients. Security is considered to be a JMS providerspecific feature that is configured by an administrator rather than controlled via the JMS API by clients. Wire Protocol - JMS does not define a wire protocol for messaging. Message Type Repository - JMS does not define a repository for storing message type definitions and it does not define a language for creating message type definitions.
17
1
1.4.2 JavaBeansTM Components
JavaBeans components can use a JMS session to send/receive messages. JMS itself is an API and the interfaces it defines are not designed to be used directly as JavaBeans components.
18
1
1.4.6 Java Naming and Directory InterfaceTM (JNDI) API
JMS clients look up configured JMS objects using the JNDI API. JMS administrators use provider-specific facilities for creating and configuring these objects. This division of work maximizes the portability of clients by delegating provider-specific work to the administrator. It also leads to more administrable applications because clients do not need to embed administrative values in their code.
19
1
JMS 1.1, there is now a domain-independent approach to programming the client application. This provides several benefits:
For the client programmer, a simpler programming model The ability to engage queues and topics in the same transaction, now that they can be created in the same session For the JMS provider, increased opportunity to optimize implementations by pooling thread management
To take advantage of these features, the developer of JMS clients needs to use the domain-independent or common APIs. In the future, some of the domain-specific APIs may be deprecated. In JMS 1.1, all of the classes and methods from JMS 1.0.2b are retained to provide backward compatibility. The semantics of the two messaging domains are retained; the expected behavior of a Point-to-Point domain and a Pub/Sub domain remain the same, as described in Chapter 5, JMS Point-to-Point Model, and Chapter 6, JMS Publish/Subscribe Model. To see details of the changes made to this specification, see Chapter 11, Change History.
20
Architecture
2.1 Overview
This chapter describes the environment of message-based applications and the role JMS plays in this environment.
JMS Clients - These are the Java language programs that send and receive messages. Non-JMS Clients - These are clients that use a message systems native client API instead of JMS. If the application predated the availability of JMS it is likely that it will include both JMS and non-JMS clients. Messages - Each application defines a set of messages that are used to communicate information between its clients. JMS Provider - This is a messaging system that implements JMS in addition to the other administrative and control functionality required of a fullfeatured messaging product. Administered Objects - Administered objects are preconfigured JMS objects created by an administrator for the use of clients.
21
2
2.3 Administration
It is expected that JMS providers will differ significantly in their underlying messaging technology. It is also expected there will be major differences in how a provider s system is installed and administered. If JMS clients are to be portable, they must be isolated from these proprietary aspects of a provider. This is done by defining JMS administered objects that are created and customized by a provider s administrator and later used by clients. The client uses them through JMS interfaces that are portable. The administrator creates them using provider-specific facilities. There are two types of JMS administered objects:
ConnectionFactory - This is the object a client uses to create a connection with a provider. Destination - This is the object a client uses to specify the destination of messages it is sending and the source of messages it receives.
Administered objects are placed in a JNDI namespace by an administrator. A JMS client typically notes in its documentation the JMS administered objects it requires and how the JNDI names of these objects should be provided to it. Figure 2-1 illustrates how JMS administration ordinarily works.
22
2
2.4 Two Messaging Styles
A JMS application can use either the point-to-point (PTP) and the publish-andsubscribe (Pub/Sub) style of messaging, which are described in more detail later in this specification. An application can also combine both styles of messaging in one application. These two styles of messaging are often referred to as messaging domains. JMS provides these two messaging domains because they represent two common models for messaging. When using the JMS API, a developer can use interfaces and methods that support both models of messaging. When using these interfaces, the behavior of the messaging system may be somewhat different, because the two messaging domains have different semantics. These semantic differences are described in Chapter 5, JMS Point-to-Point Model, and Chapter 6, JMS Publish/Subscribe Model.
The JMS common interfaces provide a domain-independent view of the PTP and Pub/Sub messaging domains. JMS client programmers are encouraged to use these interfaces to create their client programs. The following list provides a brief definition of these JMS concepts. See Chapter 4, JMS Common Facilities, for more details about these concepts.
23
2
For the details about the differences in the two messaging domains, see Chapter 5, JMS Point-to-Point Model, and Chapter 6, JMS Publish/Subscribe Model.
ConnectionFactory - an administered object used by a client to create a Connection Connection - an active connection to a JMS provider Destination - an administered object that encapsulates the identity of a message destination Session - a single-threaded context for sending and receiving messages MessageProducer - an object created by a Session that is used for sending messages to a destination MessageConsumer - an object created by a Session that is used for receiving messages sent to a destination
The term consume is used in this document to mean the receipt of a message by a JMS client; that is, a JMS provider has received a message and has given it to its client. Since JMS supports both synchronous and asynchronous receipt of messages, the term consume is used when there is no need to make a distinction between them. The term produce is used as the most general term for sending a message. It means giving a message to a JMS provider for delivery to a destination.
24
Use JNDI to find a ConnectionFactory object Use JNDI to find one or more Destination objects Use the ConnectionFactory to create a JMS Connection with message delivery inhibited
25
2
Use the Connection to create one or more JMS Sessions Use a Session and the Destinations to create the MessageProducers and MessageConsumers needed Tell the Connection to start delivery of messages
At this point a client has the basic JMS setup needed to produce and consume messages.
2.7 Security
JMS does not provide features for controlling or configuring message integrity or message privacy. It is expected that many JMS providers will provide such features. It is also expected that configuration of these services will be handled by providerspecific administration tools. Clients will get the proper security configuration as part of the administered objects they use.
2.8 Multithreading
JMS could have required that all its objects support concurrent use. Since support for concurrent access typically adds some overhead and complexity, the JMS design restricts its requirement for concurrent access to those objects that would naturally be shared by a multithreaded client. The remainder are designed to be accessed by one logical thread of control at a time.
Table 2-2 JMS Objects that Support Concurrent Use Supports Concurrent Use YES YES YES NO NO NO
JMS defines some specific rules that restrict the concurrent use of Sessions. Since they require more knowledge of JMS specifics than we have presented at
26
2
this point, they will be described later. Here we will describe the rationale for imposing them. There are two reasons for restricting concurrent access to Sessions. First, Sessions are the JMS entity that supports transactions. It is very difficult to implement transactions that are multithreaded. Second, Sessions support asynchronous message consumption. It is important that JMS not require that client code used for asynchronous message consumption be capable of handling multiple, concurrent messages. In addition, if a Session has been set up with multiple, asynchronous consumers, it is important that the client is not forced to handle the case where these separate consumers are concurrently executing. These restrictions make JMS easier to use for typical clients. More sophisticated clients can get the concurrency they desire by using multiple sessions.
2.10 Request/Reply
JMS provides the JMSReplyTo message header field for specifying the Destination where a reply to a message should be sent. The JMSCorrelationID header field of the reply can be used to reference the original request. See Section 3.4, Message Header Fields, for more information. In addition, JMS provides a facility for creating temporary queues and topics that can be used as a unique destination for replies. Enterprise messaging products support many styles of request/reply, from the simple one message request yields a one message reply to one message request yields streams of messages from multiple respondents. Rather than architect a specific JMS request/reply abstraction, JMS provides the basic facilities on which many can be built.
27
2
For convenience, JMS defines request/reply helper classes (classes written using JMS) for both the PTP and Pub/Sub domains that implement a basic form of request/reply. JMS providers and clients may provide more specialized implementations.
28
Enterprise messaging products treat messages as lightweight entities that consist of a header and a body. The header contains fields used for message routing and identification; the body contains the application data being sent. Within this general form, the definition of a message varies significantly across products. There are major differences in the content and semantics of headers. Some products use a self-describing, canonical encoding of message data; others treat data as completely opaque. Some products provide a repository for storing message descriptions that can be used to identify and interpret message content; others dont. It would be quite difficult for JMS to capture the breadth of this sometimes conflicting union of message models.
3.2 Goals
The JMS message model has the following goals:
Provide a single, unified message API Provide an API suitable for creating messages that match the format used by existing, non-JMS applications Support the development of heterogeneous applications that span operating systems, machine architectures, and computer languages Support messages containing Java objects
29
Header - All messages support the same set of header fields. Header fields contain values used by both clients and providers to identify and route messages. Properties - In addition to the standard header fields, messages provide a built-in facility for adding optional header fields to a message.
Application-specific properties - This provides a mechanism for adding application-specific header fields to a message. Standard properties - JMS defines some standard properties that are, in effect, optional header fields. Provider-specific properties - Integrating a JMS client with a JMS provider native client may require the use of provider-specific properties. JMS defines a naming convention for these.
Body - JMS defines several types of message body which cover the majority of messaging styles currently in use.
3.4.1 JMSDestination
The JMSDestination header field contains the destination to which the message is being sent. When a message is sent, this field is ignored. After completion of the send, it holds the destination object specified by the sending method. When a message is received, its destination value must be equivalent to the value assigned when it was sent.
30
3
3.4.2 JMSDeliveryMode
The JMSDeliveryMode header field contains the delivery mode specified when the message was sent. When a message is sent, this field is ignored. After completion of the send, it holds the delivery mode specified by the sending method. See Section 4.7, Message Delivery Mode, for more information.
3.4.3 JMSMessageID
The JMSMessageID header field contains a value that uniquely identifies each message sent by a provider. When a message is sent, JMSMessageID is ignored. When the send method returns, the field contains a provider-assigned value. A JMSMessageID is a String value which should function as a unique key for identifying messages in a historical repository. The exact scope of uniqueness is provider defined. It should at least cover all messages for a specific installation of a provider where an installation is some connected set of message routers. All JMSMessageID values must start with the prefix ID:. Uniqueness of message ID values across different providers is not required. Since message IDs take some effort to create and increase a messages size, some JMS providers may be able to optimize message overhead if they are given a hint that message ID is not used by an application. JMS MessageProducer provides a hint to disable message ID. When a client sets a producer to disable message ID, it is saying that it does not depend on the value of message ID for the messages it produces. If the JMS provider accepts this hint, these messages must have the message ID set to null; if the provider ignores the hint, the message ID must be set to its normal unique value.
3.4.4 JMSTimestamp
The JMSTimestamp header field contains the time a message was handed off to a provider to be sent. It is not the time the message was actually transmitted because the actual send may occur later due to transactions or other client side queueing of messages.
31
3
When a message is sent, JMSTimestamp is ignored. When the send method returns, the field contains a a time value somewhere in the interval between the call and the return. It is in the format of a normal Java millis time value. Since timestamps take some effort to create and increase a messages size, some JMS providers may be able to optimize message overhead if they are given a hint that timestamp is not used by an application. JMS MessageProducer provides a hint to disable timestamps. When a client sets a producer to disable timestamps it is saying that it does not depend on the value of timestamp for the messages it produces. If the JMS provider accepts this hint, these messages must have the timestamp set to zero; if the provider ignores the hint, the timestamp must be set to its normal value.
3.4.5 JMSCorrelationID
A client can use the JMSCorrelationID header field to link one message with another. A typical use is to link a response message with its request message. JMSCorrelationID can hold one of the following:
Since each message sent by a JMS provider is assigned a message ID value, it is convenient to link messages via message ID. All message ID values must start with the ID: prefix. In some cases, an application (made up of several clients) needs to use an application-specific value for linking messages. For instance, an application may use JMSCorrelationID to hold a value referencing some external information. Application-specified values must not start with the ID: prefix; this is reserved for provider-generated message ID values. If a provider supports the native concept of correlation ID, a JMS client may need to assign specific JMSCorrelationID values to match those expected by non-JMS clients. A byte[] value is used for this purpose. JMS providers without native correlation ID values are not required to support byte[] values*. The use of a byte[] value for JMSCorrelationID is non-portable.
* Their implementation of setJMSCorrelationIDAsBytes() and getJMSCorrelationIDAsBytes() may throw java.lang.UnsupportedOperationException.
32
3
3.4.6 JMSReplyTo
The JMSReplyTo header field contains a Destination supplied by a client when a message is sent. It is the destination where a reply to the message should be sent. Messages sent with a null JMSReplyTo value may be a notification of some event or they may just be some data the sender thinks is of interest. Messages sent with a JMSReplyTo value are typically expecting a response. A response may be optional; it is up to the client to decide.
3.4.7 JMSRedelivered
If a client receives a message with the JMSRedelivered indicator set, it is likely, but not guaranteed, that this message was delivered but not acknowledged in the past. In general, a provider must set the JMSRedelivered message header field of a message whenever it is redelivering a message. If the field is set to true, it is an indication to the consuming application that the message may have been delivered in the past and that the application should take extra precautions to prevent duplicate processing. See Section 4.4.11, Message Acknowledgment, for more information. This header field has no meaning on send and is left unassigned by the sending method.
3.4.8 JMSType
The JMSType header field contains a message type identifier supplied by a client when a message is sent. Some JMS providers use a message repository that contains the definitions of messages sent by applications. The type header field may reference a messages definition in the providers repository. JMS does not define a standard message definition repository, nor does it define a naming policy for the definitions it contains. Some messaging systems require that a message type definition for each application message be created and that each message specify its type. In order to work with such JMS providers, JMS clients should assign a value to JMSType whether the application makes use of it or not. This insures that the field is properly set for those providers that require it.
33
3
To insure portability, JMS clients should use symbolic values for JMSType that can be configured at installation time to the values defined in the current provider s message repository. If string literals are used, they may not be valid type names for some JMS providers.
3.4.9 JMSExpiration
When a message is sent, its expiration time is calculated as the sum of the timeto-live value specified on the send method and the current GMT value. On return from the send method, the messages JMSExpiration header field contains this value. When a message is received its JMSExpiration header field contains this same value. If the time-to-live is specified as zero, expiration is set to zero to indicate that the message does not expire. When GMT is later than an undelivered messages expiration time, the message should be destroyed. JMS does not define a notification of message expiration. Clients should not receive messages that have expired; however, JMS does not guarantee that this will not happen.
3.4.10 JMSPriority
The JMSPriority header field contains the messages priority. When a message is sent, this field is ignored. After completion of the send, it holds the value specified by the method sending the message. JMS defines a ten-level priority value, with 0 as the lowest priority and 9 as the highest. In addition, clients should consider priorities 0-4 as gradations of normal priority and priorities 5-9 as gradations of expedited priority. JMS does not require that a provider strictly implement priority ordering of messages; however, it should do its best to deliver expedited messages ahead of normal messages.
34
3
3.4.11 How Message Header Values Are Set
Table 3-1 Message Header Field Value Sent Set By Send Method Send Method Send Method Send Method Send Method Send Method Client Client Client Provider Header Fields JMSDestination JMSDeliveryMode JMSExpiration JMSPriority JMSMessageID JMSTimestamp JMSCorrelationID JMSReplyTo JMSType JMSRedelivered
35
3
3.5.1 Property Names
Property names must obey the rules for a message selector identifier. See Section 3.8.1.1, Message Selector Syntax, for more information.
36
3
A value set as the row type can be read as the column type.
Table 3-2 Property Value Conversion boolean boolean byte short int long float double String X X X X X X X X X X X X X X X X X X X X X byte short int long float double String X X X X X X X X
37
3
3.5.7 Clearing a Messages Property Values
A messages properties are deleted by the clearProperties method. This leaves the message with an empty set of properties. New property entries can then be both created and read. Clearing a messages property entries does not clear the value of its body. JMS does not provide a way to remove an individual property entry once it has been added to a message.
38
3
property. It may choose to include them in some messages and omit them in others depending on administrative or other criteria.
Table 3-3 Name JMSXUserID JMSXAppID JMSXDeliveryCount JMSXGroupID JMSXGroupSeq JMS Defined Properties Type String String int String int Set By Provider on Send Provider on Send Provider on Receive Client Client Use The identity of the user sending the message The identity of the application sending the message The number of message delivery attempts; the first is 1, the second 2,... The identity of the message group this message is part of The sequence number of this message within the group; the first message is 1, the second 2,... The transaction identifier of the transaction within which this message was produced The transaction identifier of the transaction within which this message was consumed The time JMS delivered the message to the consumer Assume there exists a message warehouse that contains a separate copy of each message sent to each consumer and that these copies exist from the time the original message was sent. Each copys state is one of: 1(waiting), 2(ready), 3(expired) or 4(retained). Since state is of no interest to producers and consumers, it is not provided to either. It is only relevant to messages looked up in a warehouse, and JMS provides no API for this.
JMSXProducerTXID
String
JMSXConsumerTXID
String
JMSXRcvTimestamp JMSXState
long int
39
3
JMSX properties set by the provider on send are available to both the producer and the consumers of the message. JSMX properties set by the provider on receive are available only to the consumers. JMSXGroupID and JMSXGroupSeq are standard properties clients should use if they want to group messages. All providers must support them. The case of these JMSX property names must be as defined in the table above. Unless specifically noted, the values and semantics of the JMSX properties are undefined.
40
3
3.8 Message Selection
Many messaging applications need to filter and categorize the messages they produce. In the case where a message is sent to a single receiver, this can be done with reasonable efficiency by putting the criteria in the message and having the receiving client discard the ones its not interested in. When a message is broadcast to many clients, it becomes useful to place the criteria into the message header so that it is visible to the JMS provider. This allows the provider to handle much of the filtering and routing work that would otherwise need to be done by the application. JMS provides a facility that allows clients to delegate message selection to their JMS provider. This simplifies the work of the client and allows JMS providers to eliminate the time and bandwidth they would otherwise waste sending messages to clients that dont need them. Clients attach application-specific selection criteria to messages using message properties. Clients specify message selection criteria using JMS message selector expressions.
41
3
3.8.1.1 Message Selector Syntax
A message selector is a String whose syntax is based on a subset of the SQL92 * conditional expression syntax. If the value of a message selector is an empty string, the value is treated as a null and indicates that there is no message selector for the message consumer. The order of evaluation of a message selector is from left to right within precedence level. Parentheses can be used to change this order. Predefined selector literals and operator names are written here in upper case; however, they are case insensitive. A selector can contain:
Literals:
A string literal is enclosed in single quotes, with an included single quote represented by doubled single quote; for example, literal and literals. Like Java String literals, these use the Unicode character encoding. An exact numeric literal is a numeric value without a decimal point, such as 57, -957, +62; numbers in the range of Java long are supported. Exact numeric literals use the Java integer literal syntax. An approximate numeric literal is a numeric value in scientific notation, such as 7E3 and -57.9E2, or a numeric value with a decimal, such as 7., 95.7, and +6.2; numbers in the range of Java double are supported. Approximate literals use the Java floating-point literal syntax. The boolean literals TRUE and FALSE.
Identifiers: An identifier is an unlimited-length character sequence that must begin with a Java identifier start character; all following characters must be Java identifier part characters. An identifier start character is any character for which the method Character.isJavaIdentifierStart returns true. This includes _ and $. An identifier part character is any character for which the method Character.isJavaIdentifierPart returns true. Identifiers cannot be the names NULL, TRUE, or FALSE.
* See X/Open CAE Specification Data Management: Structured Query Language (SQL), Version 2, ISBN: 185912-151-9 March 1996.
42
3
Identifiers cannot be NOT, AND, OR , BETWEEN, LIKE, IN, IS, or ESCAPE. Identifiers are either header field references or property references. The type of a property value in a message selector corresponds to the type used to set the property. If a property that does not exist in a message is referenced, its value is NULL. The semantics of evaluating NULL values in a selector are described in Section 3.8.1.2, Null Values. The conversions that apply to the get methods for properties do not apply when a property is used in a message selector expression. For example, suppose you set a property as a string value, as in the following:
myMessage.setStringProperty("NumberOfOrders", "2");
The following expression in a message selector would evaluate to false, because a string cannot be used in an arithmetic expression:
"NumberOfOrders > 1"
Identifiers are case sensitive. Message header field references are restricted to JMSDeliveryMode, JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be null and if so are treated as a NULL value. Any name beginning with JMSX is a JMS defined property name. Any name beginning with JMS_ is a provider-specific property name. Any name that does not begin with JMS is an application-specific property name.
Whitespace is the same as that defined for Java: space, horizontal tab, form feed and line terminator. Expressions:
A selector is a conditional expression; a selector that evaluates to true matches; a selector that evaluates to false or unknown does not match. Arithmetic expressions are composed of themselves, arithmetic operations, identifiers with numeric values, and numeric literals. Conditional expressions are composed of themselves, comparison operations, logical operations, identifiers with boolean values, and boolean literals.
43
3
Standard bracketing () for ordering expression evaluation is supported. Logical operators in precedence order: NOT, AND, OR Comparison operators: =, >, >=, <, <=, <> (not equal)
Only like type values can be compared. One exception is that it is valid to compare exact numeric values and approximate numeric values (the type conversion required is defined by the rules of Java numeric promotion). If the comparison of non-like type values is attempted, the value of the operation is false. If either of the type values evaluates to NULL, the value of the expression is unknown. String and Boolean comparison is restricted to = and <>. Two strings are equal if and only if they contain the same sequence of characters.
+, - (unary) *, / (multiplication and division) +, - (addition and subtraction) Arithmetic operations must use Java numeric promotion.
age BETWEEN 15 AND 19 is equivalent to age >= 15 AND age <= 19 age NOT BETWEEN 15 AND 19 is equivalent to age < 15 OR age > 19
identifier [NOT] IN ( string-literal1, string-literal2,...) (comparison operator where identifier has a String or NULL value)
Country IN ( UK, US, France) is true for UK and false for Peru; it is equivalent to the expression (Country = UK) OR (Country = US) OR (Country = France) Country NOT IN ( UK, US, France) is false for UK and true for Peru; it is equivalent to the expression NOT ((Country = UK) OR (Country = US) OR (Country = France)) If identifier of an IN or NOT IN operation is NULL, the value of the operation is unknown.
identifier [NOT] LIKE pattern-value [ESCAPE escape-character] (comparison operator, where identifier has a String value; pattern-value is a string literal
44
3
where _ stands for any single character; % stands for any sequence of characters, including the empty sequence, and all other characters stand for themselves. The optional escape-character is a single-character string literal whose character is used to escape the special meaning of the _ and % in pattern-value.)
phone LIKE 12%3 is true for 123 or 12993 and false for 1234 word LIKE l_se is true for lose and false for loose underscored LIKE \_% ESCAPE \ is true for _foo and false for bar phone NOT LIKE 12%3 is false for 123 and 12993 and true for 1234 If identifier of a LIKE or NOT LIKE operation is NULL, the value of the operation is unknown.
identifier IS NULL (comparison operator that tests for a null header field value or a missing property value)
prop_name IS NULL
identifier IS NOT NULL (comparison operator that tests for the existence of a non-null header field value or property value)
JMS providers are required to verify the syntactic correctness of a message selector at the time it is presented. A method providing a syntactically incorrect selector must result in a JMS InvalidSelectorException. JMS providers may also optionally provide some semantic checking at the time the selector is presented. Not all semantic checking can be performed at the time a message selector is presented, because property types are not known. The following message selector selects messages with a message type of car and color of blue and weight greater than 2500 lbs:
"JMSType = car AND color = blue AND weight > 2500 "
45
3
SQL treats a NULL value as unknown. Comparison or arithmetic with an unknown value always yields an unknown value. The IS NULL and IS NOT NULL operators convert an unknown header or property value into the respective TRUE and FALSE values. The boolean operators use three-valued logic as defined by the following tables:
Table 3-4 AND T F U The Definition of the AND Operator T T F U F F F F U U F U
Table 3-5 OR T F U
46
3
Date and time values should use the standard Java long millis value. When a date or time literal is included in a message selector, it should be an integer literal for a millis value. The standard way to produce millis values is to use java.util.Calendar. Although SQL supports fixed decimal comparison and arithmetic, JMS message selectors do not. This is the reason for restricting exact numeric literals to those without a decimal (and the addition of numerics with a decimal as an alternate representation for an approximate numeric values). SQL comments are not supported.
47
3
3.11 JMS Message Body
JMS provides five forms of message body. Each form is defined by a message interface:
StreamMessage - a message whose body contains a stream of Java primitive values. It is filled and read sequentially. MapMessage - a message whose body contains a set of name-value pairs where names are Strings and values are Java primitive types. The entries can be accessed sequentially by enumerator or randomly by name. The order of the entries is undefined. TextMessage - a message whose body contains a java.lang.String. The inclusion of this message type is based on our presumption that String messages will be used extensively. One reason for this is that XML will likely become a popular mechanism for representing the content of JMS messages. ObjectMessage - a message that contains a Serializable Java object. If a collection of Java objects is needed, one of the collection classes provided in JDK 1.2 can be used. BytesMessage - a message that contains a stream of uninterpreted bytes. This message type is for literally encoding a body to match an existing message format. In many cases, it will be possible to use one of the other, self-defining, message types instead. Although JMS allows the use of message properties with byte messages, they are typically not used, since the inclusion of properties may affect the format.
48
3
3.11.3 Conversions Provided by StreamMessage and MapMessage
Both StreamMessage and MapMessage support the same set of primitive data types. The types can be read or written explicitly using methods for each type. They may also be read or written generically as objects. For instance, a call to MapMessage.setInt(foo, 6) is equivalent to MapMessage.setObject(foo, new Integer(6)). Both forms are provided because the explicit form is convenient for static programming and the object form is needed when types are not known at compile time. Both StreamMessage and MapMessage support the following conversion table. The marked cases must be supported. The unmarked cases must throw a JMS MessageFormatException. The String to numeric conversions must throw a java.lang.NumberFormatException if the numerics valueOf() method does not accept the String value as a valid representation. StreamMessage and MapMessage must implement the String to boolean conversion as specified by the valueOf(String) method of Boolean as defined by the Java language. Attempting to read a null value as a Java primitive type must be treated as calling the primitives corresponding valueOf(String) conversion method with a null value. Since char does not support a String conversion, attempting to read a null value as a char must throw NullPointerException . Getting a MapMessage field for a field name that has not been set is handled as if the field exists with a null value. If a read method of StreamMessage or BytesMessage throws a MessageFormatException or NumberFormatException, the current position of the read pointer must not be incremented. A subsequent read must be capable of recovering from the exception by rereading the data as a different type.
49
3
A value written as the row type can be read as the column type.
Table 3-7 Conversions for StreamMessage and MapMessage boolean byte boolean X byte short char int long float double String byte[] X X X X X X X X X X X X X X X X X X X X X short char int long float double String X X X X X X X X X X byte[]
50
3
If a JMS provider receives a message created by a native client, the provider should do its best to transform it into the best JMS message type. For instance, if it is a native stream message it should be transformed into a StreamMessage. If this is not possible, the provider is always able to transform it into a BytesMessage.
51
52
This chapter describes the JMS facilities that are shared by both the PTP and Pub/Sub domains.
It hides provider-specific configuration details from JMS clients. It abstracts JMS administrative information into Java objects that are easily organized and administered from a common management console. Since there will be JNDI providers for all popular naming services, this means JMS providers can deliver one implementation of administered objects that will run everywhere.
53
4
An administered object should not hold on to any remote resources. Its lookup should not use remote resources other than those used by JNDI itself. Clients should think of administered objects as local Java objects. Looking them up should not have any hidden side effects or use surprising amounts of local resources. JMS defines two administered objects, Destination and ConnectionFactory. It is expected that JMS providers will provide the tools an administrator needs to create and configure administered objects in a JNDI namespace. JMS provider implementations of administered objects should be both javax.naming.Referenceable and java.io.Serializable so that they can be stored in all JNDI naming contexts. In addition, it is recommended that these implementations follow the JavaBeans TM design patterns.
4.2.1 Destination
JMS does not define a standard address syntax. Although this was considered, it was decided that the differences in address semantics between existing enterprise messaging products was too wide to bridge with a single syntax. Instead, JMS defines the Destination object which encapsulates providerspecific addresses. Since Destination is an administered object, it may contain provider-specific configuration information in addition to its address. JMS also supports a clients use of provider-specific address names. See Section 4.4.4 Creating Destination Objects, for more information. Destination objects support concurrent use.
4.2.2 ConnectionFactory
A ConnectionFactory encapsulates a set of connection configuration parameters that has been defined by an administrator. A client uses it to create a Connection with a JMS provider. ConnectionFactory objects support concurrent use.
54
4
4.3 Connection
A JMS Connection is a clients active connection to its JMS provider. It will typically allocate provider resources outside the Java virtual machine. Connection objects support concurrent use. A Connection serves several purposes:
It encapsulates an open connection with a JMS provider. It typically represents an open TCP/IP socket between a client and a provider s service daemon. Its creation is where client authentication takes place. It can specify a unique client identifier. It creates Session objects. It provides ConnectionMetaData. It supports an optional ExceptionListener.
Due to the authentication and communication setup done when a Connection is created, a Connection is a relatively heavyweight JMS object. Most clients will do all their messaging with a single Connection. Other more advanced applications may use several Connections. JMS does not architect a reason for using multiple connections (other than when a client acts as a gateway between two different providers); however, there may be operational reasons for doing so.
4.3.1 Authentication
When creating a connection, a client may specify its credentials as name/password. If no credentials are specified, the current threads credentials are used. At this point, the JDK does not define the concept of a threads default credentials; however, it is likely this will be defined in the near future. For now, the identity of the user under which the JMS client is running should be used.
55
4
connection it creates. Alternatively, a client can set a connections client identifier using a provider-specific value. The facility to explicitly set a connections client identifier is not a mechanism for overriding the identifier that has been administratively configured. It is provided for the case where no administratively specified identifier exists. If one does exist, an attempt to change it by setting it must throw a IllegalStateException. If a client explicitly does the set it must do this immediately after creating the connection and before any other action on the connection is taken. After this point, setting the client identifier is a programming error that should throw an IllegalStateException . The purpose of the client identifier is to associate a connection and its objects with a state maintained on behalf of the client by a provider. By definition, the client state identified by a client identifier can be in use by only one client at a time. A JMS provider must prevent concurrently executing clients from using it. This prevention may take the form of JMSExceptions thrown when such use is attempted; it may result in the offending client being blocked; or some other solution. A JMS provider must insure that such attempted sharing of an individual client state does not result in messages being lost or doubly processed. The only individual client state identified by JMS is that required to support durable subscriptions.
56
4
It is important to note that clients rely on the fact that no messages are delivered by a connection until it has been started. JMS providers must insure that this is the case.
57
4
when writing a message consumer. It bears repeating that the message consumer cannot rely on a null return value to indicate this last message case. If one or more of the connections sessions message listeners is processing a message at the point when connection close is invoked, all the facilities of the connection and its sessions must remain available to those listeners until they return control to the JMS provider. When connection close is invoked it should not return until message processing has been shut down in an orderly fashion. This means that all message listeners that may have been running have returned, and that all pending receives have returned. If a connection is closed, there is no need to close its constituent objects. The connection close is sufficient to signal the JMS provider that all resources for the connection should be released. Closing a connection must roll back the transactions in progress on its transacted sessions*. Closing a connection does NOT force an acknowledgement of client-acknowledged sessions. Invoking the acknowledge method of a received message from a closed connections sessions must throw an IllegalStateException . These semantics insure that closing a connection does not cause messages to be lost for queues and durable subscriptions that require reliable processing by a subsequent execution of their JMS client. Once a connection has been closed, an attempt to use it or its sessions or their message consumers and producers must throw an IllegalStateException (calls to the close method of these objects must be ignored). It is valid to continue to use message objects created or received via the connection, with the exception of a received messages acknowledge method. Closing a closed connection must NOT throw an exception.
4.3.6 Sessions
A Connection is a factory for Sessions that use its underlying connection to a JMS provider for producing and consuming messages.
* The term transacted session refers to the case where a sessions commit and rollback methods are used to demarcate a transaction local to the session. In the case where a sessions work is coordinated by an external transaction manager, a sessions commit and rollback methods are not used and the result of a closed sessions work is determined later by the transaction manager.
58
4
4.3.7 ConnectionMetaData
A Connection provides a ConnectionMetaData object. This object provides the latest version of JMS supported by the provider as well as the providers product name and version. It also provides a list of the JMS defined property names supported by the connection.
4.3.8 ExceptionListener
If a JMS provider detects a problem with a connection, it will inform the connections ExceptionListener, if one has been registered. To retrieve an ExceptionListener, the JMS provider calls the connections getExceptionListerer() method. This method returns the ExceptionListener for the connection. If no ExceptionListener is registered, the value null is returned. The connection can then use the listener by calling the listener s onException() method, passing it a JMSException describing the problem. This allows a client to be asynchronously notified of a problem. Some connections only consume messages, so they would have no other way to learn their connection has failed. A Connection serializes execution of its ExceptionListener. A JMS provider should attempt to resolve connection problems itself prior to notifying the client of them. The exceptions delivered to ExceptionListener are those that have no other place to be reported. If an exception is thrown on a JMS call it, by definition, must not be delivered to an ExceptionListener (in other words, ExceptionListener is not for the purpose of monitoring all exceptions thrown by a connection).
59
4
4.4 Session
A JMS Session is a single-threaded context* for producing and consuming messages. Although it may allocate provider resources outside the Java virtual machine, it is considered a lightweight JMS object. A Session serves several purposes:
It is a factory for its MessageProducers and MessageConsumers. It is a factory for TemporaryTopics and TemporaryQueues. It provides a way to create Queue or Topic objects for those clients that need to dynamically manipulate provider-specific destination names. It supplies provider-optimized message factories. It supports a single series of transactions that combine work spanning this sessions producers and consumers into atomic units. It defines a serial order for the messages it consumes and the messages it produces. It retains messages it consumes until they have been acknowledged. It serializes execution of MessageListeners registered with it. It is a factory for QueueBrowsers.
* There are no restrictions on the number of threads that can use a Session object or those it creates. The restriction is that the resources of a Session should not be used concurrently by multiple threads. It is up to the user to insure that this concurrency restriction is met. The simplest way to do this is to use one thread. In the case of asynchronous delivery, use one thread for setup in stopped mode and then start asynchronous delivery. In more complex cases the user must provide explicit synchronization.
60
4
Session close is the only session method that may be invoked from a thread of control separate from the one that is currently controlling the session. When session close is invoked, it should not return until its message processing has been shut down in an orderly fashion. This means that none of its message listeners are running, and that if there is a pending receive, it has returned with either null or a message. When a session is closed, there is no need to close its constituent message producers and consumers. The session close is sufficient to signal the JMS provider that all resources for the session should be released. Closing a transacted session must roll back its transaction in progress. Closing a client-acknowledged session does NOT force an acknowledge. Once a session has been closed, an attempt to use it or its message consumers and producers must throw an IllegalStateException (calls to the close method of these objects must be ignored). It is valid to continue to use message objects created or received via the session, with the exception of a received messages acknowledge method. Closing a closed session must NOT throw an exception.
61
4
One typical use for a temporary destination is as the JMSReplyTo destination for service requests. Each TemporaryQueue or TemporaryTopic object is unique. It cannot be copied. Since temporary destinations may allocate resources outside the JVM, they should be deleted if they are no longer needed. They will be automatically deleted when they are garbage collected or when their connection is closed.
62
4
Another typical use is to have one thread set up a session by creating its producers and one or more asynchronous consumers. In this case, the message producers are exclusively for the use of the consumer s message listeners. Since the session serializes execution of its consumers MessageListeners, they can safely share the resources of their session. If a connection is left in stopped mode while its sessions are being set up, a client does not have to deal with messages arriving before the client is fully prepared to handle them. This is the preferred strategy because it eliminates the possibility of unanticipated conflicts between setup and message processing. It is possible to create and set up a session while a connection is receiving messages. In this case, more care is required to insure that a sessions MessageProducers, MessageConsumers, and MessageListeners are created in the right order. For instance, a bad order may cause a MessageListener to use a MessageProducer that has yet to be created; or messages may arrive in the wrong order due to the order in which MessageListeners are registered. If a client desires to have one thread producing messages while others consume them, the client should use a separate session for its producing thread. Once a connection has been started, all its sessions with a registered message listener are dedicated to the thread of control that delivers messages to them. It is erroneous for client code to use such a session from another thread of control. The only exception to this is the use of the session or connection close method. One consequence of the sessions single-thread-of-control restriction is that a session with message listeners cannot also be used to synchronously receive messages. Either the session is dedicated to the thread of control used for delivery to message listeners, or it is dedicated to a thread of control initiated by client code. It is erroneous to attempt to combine both in the same session. Another consequence is that a connection must be in stopped mode to set up a session with more than one message listener. The reason is that when a connection is actively delivering messages, once the first message listener for a session has been registered, the session is now controlled by the thread of control that delivers messages to it. At this point a client thread of control cannot be used to further configure the session. It should be natural for most clients to partition their work into sessions. This model allows clients to start simply and incrementally add message processing complexity as their need for concurrency grows.
63
4
4.4.7 Transactions
A Session may optionally be specified as transacted. Each transacted session supports a single series of transactions. Each transaction groups a set of produced messages and a set of consumed messages into an atomic unit of work. In effect, transactions organize a sessions input message stream and output message stream into series of atomic units. When a transaction commits, its atomic unit of input is acknowledged and its associated atomic unit of output is sent. If a transaction rollback is done, its produced messages are destroyed and its consumed messages are automatically recovered. For more information on session recovery, see Section 4.4.11 Message Acknowledgment. A transaction is completed using its sessions commit() or rollback() method. The completion of a sessions current transaction automatically begins the next. The result is that a transacted session always has a current transaction within which its work is done. JTS or some other transaction monitor facility may be used to combine a sessions transaction with transactions on other resources (databases, other JMS sessions, etc.). Since Java distributed transactions are controlled via the JTA transaction demarcation API, use of the sessions commit and rollback methods in this context throws a JMS TransactionInProgressException.
64
4
4.4.9 Multiple Sessions
A client may create multiple sessions. Each session is an independent producer and consumer of messages. For Pub/Sub, if two sessions each have a TopicSubscriber that subscribes to the same Topic , each subscriber is given each message. Delivery to one subscriber does not block if the other gets behind. For PTP, JMS does not specify the semantics of concurrent QueueReceivers for the same Queue; however, JMS does not prohibit a provider from supporting this. Therefore, message delivery to multiple QueueReceivers will depend on the JMS provider s implementation. Applications that depend on delivery to multiple QueueReceivers are not portable
65
4
messages a session sends to a particular destination. Several things can affect this order:
Messages of higher priority may jump ahead of previous lower-priority messages. A client may not receive a NON_PERSISTENT message due to a JMS provider failure. If both PERSISTENT and NON_PERSISTENT messages are sent to a destination, order is only guaranteed within delivery mode. That is, a later NON_PERSISTENT message may arrive ahead of an earlier PERSISTENT message; however, it will never arrive ahead of an earlier NON_PERSISTENT message with the same priority. A client may use a transacted session to group its sent messages into atomic units (the producer component of a JMS transaction). A transactions order of messages to a particular destination is significant. The order of sent messages across destinations is not significant. See Section 4.4.7 Transactions, for more information.
DUPS_OK_ACKNOWLEDGE - This option instructs the session to lazily acknowledge the delivery of messages. This is likely to result in the delivery of some duplicate messages if JMS fails, so it should be used only by consumers that are tolerant of duplicate messages. Its benefit is the reduction of session overhead achieved by minimizing the work the session does to prevent duplicates. AUTO_ACKNOWLEDGE - With this option, the session automatically acknowledges a clients receipt of a message when it has either successfully returned from a call to receive or the MessageListener it has called to process the message successfully returns. CLIENT_ACKNOWLEDGE - With this option, a client acknowledges a message by calling the messages acknowledge method. Acknowledging a consumed message automatically acknowledges the receipt of all messages that have been delivered by its session.
66
4
When CLIENT_ACKNOWLEDGE mode is used, a client may build up a large number of unacknowledged messages while attempting to process them. A JMS provider should provide administrators with a way to limit client over-run so that clients are not driven to resource exhaustion and ensuing failure when some resource they are using is temporarily blocked. A sessions recover method is used to stop a session and restart it with its first unacknowledged message. In effect, the sessions series of delivered messages is reset to the point after its last acknowledged message. The messages it now delivers may be different from those that were originally delivered due to message expiration and the arrival of higher-priority messages. A session must set the redelivered flag of messages it redelivers due to a recovery.
67
4
It is up to a JMS application to deal with this ambiguity. In some cases, this may cause a client to produce functionally duplicate messages. A message that is redelivered due to session recovery is not considered a duplicate message.
4.5 MessageConsumer
A client uses a MessageConsumer to receive messages from a destination. A MessageConsumer is created by passing a Queue or Topic to a Sessions createConsumer method.
68
4
A consumer can be created with a message selector. This allows the client to restrict the messages delivered to the consumer to those that match the selector. See Section 3.8.1 Message Selector, for more information. A client may either synchronously receive a consumer s messages or have the provider asynchronously deliver them as they arrive.
AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE - the message will be immediately redelivered. The number of times a JMS provider will redeliver the same message before giving up is provider-dependent. The JMSRedelivered message header field will be set for a message redelivered under these circumstances. CLIENT_ACKNOWLEDGE - the next message for the listener is delivered. If a client wishes to have the previous unacknowledged message redelivered, it must manually recover the session. Transacted Session - the next message for the listener is delivered. The client can either commit or roll back the session (in other words, a RuntimeException does not automatically rollback the session).
JMS providers should flag clients with message listeners that are throwing RuntimeExceptions as possibly malfunctioning.
69
4
See Section 4.4.14 Serial Execution of Client Code, for information about how onMessage calls are serialized by a session.
4.6 MessageProducer
A client uses a MessageProducer to send messages to a Destination. A MessageProducer is created by passing a Queue or Topic to a sessions createProducer method. A client also has the option of creating a producer without supplying a destination. In this case, a destination must be input on every send operation. A typical use for this style of producer is to send replies to requests using the requests JMSReplyTo destination. A client can specify a default delivery mode, priority, and time-to-live for messages sent by a producer. It can also specify delivery mode, priority, and time-to-live per message. Each time a client creates a MessageProducer, it defines a new sequence of messages that have no ordering relationship with the messages it has previously sent. See Section 3.4.9 JMSExpiration, for more information on time-to-live. See Section 3.4.10 JMSPriority, for more information on priority.
The NON_PERSISTENT mode is the lowest-overhead delivery mode because it does not require that the message be logged to stable storage. A JMS provider failure can cause a NON_PERSISTENT message to be lost. The PERSISTENT mode instructs the JMS provider to take extra care to insure the message is not lost in transit due to a JMS provider failure.
A JMS provider must deliver a NON_PERSISTENT message at-most-once. This means that it may lose the message, but it must not deliver it twice. A JMS provider must deliver a PERSISTENT message once-and-only-once. This means a JMS provider failure must not cause it to be lost, and it must not deliver it twice.
70
4
PERSISTENT (once-and-only-once) and NON_PERSISTENT (at-most-once) message delivery are a way for a JMS client to select between delivery techniques that may lose a messages if a JMS provider dies and those which take extra effort to insure that messages can survive such a failure. There is typically a performance/reliability trade-off implied by this choice. When a client selects the NON_PERSISTENT delivery mode, it is indicating that it values performance over reliability; a selection of PERSISTENT reverses the requested trade-off. The use of PERSISTENT messages does not guarantee that all messages are always delivered to every eligible consumer. See Section 4.10 Reliability, for further discussion on this topic.
4.9 Exceptions
JMSException is the base class for all JMS exceptions. See Chapter 7, JMS Exceptions, for more information.
4.10 Reliability
Most clients should use producers that produce PERSISTENT messages. This insures once-and-only-once message delivery for messages delivered from a queue or a durable subscription. In some cases, an application may only require at-most-once message delivery for some of its messages. This is accomplished by publishing NON_PERSISTENT messages. These messages typically have lower overhead;
71
4
however, they may be lost if a JMS provider fails. Both PERSISTENT and NON_PERSISTENT messages can be published to the same destination. Normally, a consumer fully processes each message before acknowledging its receipt to JMS. This insures that JMS does not discard a partially processed message due to machine failure, etc. A consumer accomplishes this by using either a transacted or CLIENT_ACKNOWLEDGE session. Unacknowledged messages redelivered due to system failure must have the JMSRedelivered message header field set by the JMS provider. If a NON_PERSISTENT message is delivered to a durable subscription or a queue, delivery is not guaranteed if the durable subscription becomes inactive (that is, if it has no current subscriber) or if the JMS provider is shut down and later restarted. It is expected that important messages will be produced with a PERSISTENT delivery mode within a transaction and will be consumed within a transaction from a nontemporary queue or a durable subscription. When this is done, applications have the highest level of assurance that a message has been properly produced, reliably delivered, and accurately consumed. Non-transactional production and consumption can also achieve the same level of assurance; however, this requires careful programming. A JMS provider may have resource restrictions that limit the number of messages that can be held for high-volume destinations or non-responsive clients. If messages are dropped due to resource limits, this is usually a serious administrative issue that needs attention. Correct functioning of JMS requires that clients are responsive and that adequate resources to service them are available. Once-and-only-once message delivery, as described in this specification, has the important caveat that it does not cover message destruction due to message expiration or other administrative destruction criteria. It also does not cover loss due to resource restrictions. Configuration of adequate resources and processing power for JMS applications is the job of administrators, who must be aware of their JMS providers reliability features. NON_PERSISTENT messages, nondurable subscriptions, and temporary destinations are by definition unreliable. A JMS provider shutdown or failure will likely cause the loss of NON_PERSISTENT messages and the loss of messages held by temporary destinations and nondurable subscriptions. The termination of an application will likely cause the loss of messages held by nondurable subscriptions and temporary destinations of the application
72
4
4.11 Method Inheritance across Messaging Domains
As a result of unifying the domains, some methods that are not appropriate to a domain may be inherited in the domain-specific classes. For example, the Session interface has the method createQueueBrowser. Since TopicSession inherits from the Session interface, TopicSession inherits the createQueueBrowser method, though that method must not be used by a topic, as topics do not support QueueBrowsers. Table 4-1 outlines these instances. If a application attempts to call any of the methods listed, the JMS provider must throw an IllegalStateException.
Methods That Must Throw an IllegalStateException Method createDurableConnectionConsumer createDurableSubscriber createTemporaryTopic createTopic unsubscribe
QueueConnection QueueSession
TopicSession
73
74
Point-to-point systems are about working with queues of messages. They are point-to-point in that a client sends a message to a specific queue. Some PTP systems blur the distinction between PTP and Pub/Sub by providing system clients that automatically distribute messages. It is common for a client to have all its messages delivered to a single queue. Like any generic mailbox, a queue can contain a mixture of messages. And, like real mailboxes, creating and maintaining each queue is somewhat costly. Most queues are created administratively and are treated as static resources by their clients. The JMS PTP model defines how a client works with queues: how it finds them, how it sends messages to them, and how it receives messages from them. This chapter describes the semantics of the Point-to-Point model. A JMS provider that supports the Point-to-Point model must deliver the semantics described here. Whether a JMS client program uses the PTP domain-specific interfaces, or the common interfaces that are described in Chapter 4, JMS Common Facilities, the client program must be guaranteed the same behavior. Table 5-1 shows the interfaces that are specific to the PTP domain and the JMS common interfaces. The common interfaces are preferred for creating JMS application programs, because they are domain-independent.
75
5
Table 5-1 PTP Domain Interfaces and JMS Common Interfaces JMS Common Interfaces Preferred ConnectionFactory Connection Destination Session MessageProducer MessageConsumer
5.3 Queue
A Queue object encapsulates a provider-specific queue name. It is the way a client specifies the identity of a queue to JMS methods. The actual length of time messages are held by a queue and the consequences of resource overflow are not defined by JMS. See Section 4.2, Administered Objects, for more information about JMS Destination objects.
5.4 TemporaryQueue
A TemporaryQueue is a unique Queue object created for the duration of a Connection or QueueConnection. It is a system-defined queue that can be consumed only by the Connection or QueueConnection that created it. See Section 4.4.3, Creating Temporary Destinations, for more information.
76
5
5.5 QueueConnectionFactory
A client uses a QueueConnectionFactory to create QueueConnections with a JMS PTP provider. See Section 4.2, Administered Objects, for more information about JMS ConnectionFactory objects.
5.6 QueueConnection
A QueueConnection is an active connection to a JMS PTP provider. A client uses a QueueConnection to create one or more QueueSession s for producing and consuming messages. See Section 4.3, Connection, for more information.
5.7 QueueSession
A QueueSession provides methods for creating QueueReceivers, QueueSenders, QueueBrowsers, and TemporaryQueues. If there are messages that have been received but not acknowledged when a QueueSession terminates, these messages must be retained and redelivered when a consumer next accesses the queue. See Section 4.4, Session, for more information.
5.8 QueueReceiver
A client uses a QueueReceiver for receiving messages that have been delivered to a queue. Although it is possible to have two sessions with a QueueReceiver for the same queue, JMS does not define how messages are distributed between the QueueReceivers. If a QueueReceiver specifies a message selector, the messages that are not selected remain on the queue. By definition, a message selector allows a QueueReceiver to skip messages. This means that when the skipped messages are eventually read, the total ordering of the reads does not retain the partial order defined by each message producer. Only QueueReceivers without a message selector will read messages in message producer order.
77
5
For more information, see Section 4.5, MessageConsumer. If MessageConsumer is consuming messages from a Queue, then it must behave as described here in Section 5.8, QueueReceiver. A client uses a MessageProducer or QueueSender to send messages to a Queue. For more information, see Section 4.6, MessageProducer.
5.9 QueueBrowser
A client uses a QueueBrowser to look at messages on a queue without removing them. A QueueBrowser can be created from a Session or a QueueSession . The browse methods return a java.util.Enumeration that is used to scan the queues messages. It may be an enumeration of the entire content of a queue, or it may contain only the messages matching a message selector. Messages may be arriving and expiring while the scan is done. JMS does not require the content of an enumeration to be a static snapshot of queue content. Whether these changes are visible or not depends on the JMS provider.
5.10 QueueRequestor
JMS provides a QueueRequestor helper class to simplify making service requests. The QueueRequestor constructor is given a QueueSession and a destination queue. It creates a TemporaryQueue for the responses and provides a request method that sends the request message and waits for its reply. This is a basic request/reply abstraction that should be sufficient for most uses. JMS providers and clients can create more sophisticated versions.
5.11 Reliability
A queue is typically created by an administrator and exists for a long time. It is always available to hold messages sent to it, whether or not the client that consumes its messages is active. For this reason, a client does not have to take any special precautions to insure that it does not miss messages.
78
The JMS Pub/Sub model defines how JMS clients publish messages to, and subscribe to messages from, a well-known node in a content-based hierarchy. JMS calls these nodes topics. In this section, the terms publish and subscribe are used in place of the more generic terms produce and consume used previously. A topic can be thought of as a mini message broker that gathers and distributes messages addressed to it. By relying on the topic as an intermediary, message publishers are kept independent of subscribers and vice versa. The topic automatically adapts as both publishers and subscribers come and go. Publishers and subscribers are active when the Java objects that represent them exist. JMS also supports the optional durability of subscribers that remembers the existence of them while they are inactive. This chapter describes the semantics of the Publish/Subscribe model. A JMS provider that supports the Publish/Subscribe model must deliver the semantics described here. Whether a JMS client program uses the Pub/Sub domain-specific interfaces, or the common interfaces that are described in Chapter 4, JMS Common Facilities, the clien program must be guaranteed the same behavior.
79
6
Table 6-1 shows the interfaces that are specific to the PTP domain and the JMS common interfaces. The common interfaces are preferred for creating JMS application programs, because they are domain-independent.
Table 6-1 Pub/Sub Domain Interfaces and JMS Common Interfaces JMS Common interfaces Preferred ConnectionFactory Connection Destination Session MessageProducer MessageConsumer
80
6
subscriber is active. If the subscriber is not active, it is missing messages published on its topic. At the cost of higher overhead, a subscriber can be made durable. A durable subscriber registers a durable subscription with a unique identity that is retained by JMS. Subsequent subscriber objects with the same identity resume the subscription in the state it was left in by the prior subscriber. If there is no active subscriber for a durable subscription, JMS retains the subscriptions messages until they are received by the subscription or until they expire. All JMS providers must be able to run JMS applications that dynamically create and delete durable subscriptions. Some JMS providers may, in addition, provide facilities to administratively configure durable subscriptions. If a durable subscription has been administratively configured, it is valid for it to silently override the subscription specified by the client. An inactive durable subscription is one that exists but does not currently have a message consumer subscribed to it.
6.5 Topic
A Topic object encapsulates a provider-specific topic name. It is the way a client specifies the identity of a topic to JMS methods. Many Pub/Sub providers group topics into hierarchies and provide various options for subscribing to parts of the hierarchy. JMS places no restrictions on what a Topic object represents. It might be a leaf in a topic hierarchy, or it might be a larger part of the hierarchy (for subscribing to a general class of information).
81
6
The organization of topics and the granularity of subscriptions to them is an important part of a Pub/Sub applications architecture. JMS does not specify a policy for how this should be done. If an application takes advantage of a provider-specific topic grouping mechanism, it should document this. If the application is installed using a different provider, it is the job of the administrator to construct an equivalent topic architecture and create equivalent Topic objects.
6.6 TemporaryTopic
A TemporaryTopic is a unique Topic object created for the duration of a Connection or TopicConnection. It is a system-defined Topic that can be consumed only by the Connection or TopicConnection that created it. By definition, it does not make sense to create a durable subscription to a temporary topic. To do this is a programming error that may or may not be detected by a JMS provider. See Section 4.4.3, Creating Temporary Destinations, for more information.
6.7 TopicConnectionFactory
A client uses a TopicConnectionFactory to create TopicConnections with a JMS Pub/Sub provider. See Section 4.2, Administered Objects, for more information about JMS ConnectionFactory objects.
6.8 TopicConnection
A TopicConnection is an active connection to a JMS Pub/Sub provider. A client uses a TopicConnection to create one or more TopicSessions for producing and consuming messages. See Section 4.3, Connection, for more information.
6.9 TopicSession
A TopicSession provides methods for creating TopicPublishers, TopicSubscribers, and TemporaryTopics. It also provides the unsubscribe method for deleting its clients durable subscriptions.
82
6
If there are messages that have been received but not acknowledged when a TopicSession terminates, a durable TopicSubscriber must retain and redeliver them; a nondurable subscriber need not do so. See Section 4.4, Session, for more information.
6.10 TopicPublisher
A client uses a TopicPublisher for publishing messages on a topic. TopicPublisher is the Pub/Sub variant of a JMS MessageProducer. Messages can also be sent to a Topic using a MessageProducer. See Section 4.6, MessageProducer, for a description of its common features.
6.11 TopicSubscriber
A client uses a TopicSubscriber for receiving messages that have been published to a topic. TopicSubscriber is the Pub/Sub variant of a JMS MessageConsumer. For more information, see Section 4.5, MessageConsumer. Ordinary TopicSubscribers are not durable. They only receive messages that are published while they are active. Messages filtered out by a subscriber s message selector will never be delivered to the subscriber. From the subscriber s perspective, they simply dont exist. In some cases, a connection may both publish and subscribe to a topic. The subscriber NoLocal attribute allows a subscriber to inhibit the delivery of messages published by its own connection. A TopicSession allows the creation of multiple TopicSubscribers per destination, it will deliver each message for a destination to each TopicSubscriber eligible to receive it. Each copy of the message is treated as a completely separate message. Work done on one copy has no effect on any other; acknowledging one does not acknowledge any other; one message may be delivered immediately, while another waits for its consumer to process messages ahead of it.
83
6
TopicSubscriber. A durable TopicSubscriber can be created by a Session or by a TopicSession. JMS retains a record of this durable subscription and insures that all messages from the Topic s publishers are retained until either they are acknowledged by this durable subscriber or they have expired. Sessions with durable subscribers must always provide the same client identifier. In addition, each client must specify a name that uniquely identifies (within client identifier) each durable subscription it creates. Only one session at a time can have a TopicSubscriber for a particular durable subscription. See Section 4.3.2, Client Identifier, for more information. A client can change an existing durable subscription by creating a durable TopicSubscriber with the same name and a new topic and/or message selector, or NoLocal attribute. Changing a durable subscription is equivalent to deleting and recreating it. Sessions and TopicSessions provide the unsubscribe method for deleting a durable subscription created by their client. This deletes the state being maintained on behalf of the subscriber by its provider. It is erroneous for a client to delete a durable subscription while it has an active TopicSubscriber for it or while a message received by it is part of a current transaction or has not been acknowledged in the session.
84
6
the administrator s viewpoint, other tasks may be needed to support the creation of publishers and subscribers. The amount of resources allocated for message storage and the consequences of resource overflow are not defined by JMS.
6.14 TopicRequestor
JMS provides a TopicRequestor helper class to simplify making service requests. The TopicRequestor constructor is given a TopicSession and a destination topic. It creates a TemporaryTopic for the responses and provides a request() method that sends the request message and waits for its reply. This is a basic request/reply abstraction that should be sufficient for most uses. JMS providers and clients are free to create more sophisticated versions.
6.15 Reliability
When all messages for a topic must be received, a durable subscriber should be used. JMS insures that messages published while a durable subscriber is inactive are retained by JMS and delivered when the subscriber subsequently becomes active. Nondurable subscribers should be used only when missed messages are tolerable.
Table 6-2 Pub/Sub Reliability Nondurable Subscriber at-most-once (missed if inactive) once-and-only-once (missed if inactive) Durable Subscriber at-most-once once-and-only-once
85
86
JMS Exceptions
7.1 Overview
This chapter provides an overview of JMS exception handling and defines the standard JMS exceptions.
A provider-specific string describing the error - This string is the standard Java exception message, and is available via getMessage(). A provider-specific string error code A reference to another exception - Often a JMS exception will be the result of a lower level problem. If appropriate, this lower level exception can be linked to the JMS exception.
JMS methods include only JMSException in their signatures. JMS methods can throw any JMS standard exception as well as any JMS provider-specific exception. The javadoc for JMS methods documents only the mandatory
exception cases.
87
7
7.3 Standard Exceptions
In addition to JMSException, JMS defines several additional exceptions that standardize the reporting of basic error conditions. There are only a few cases where JMS mandates that a specific JMS exception must be thrown. These cases are indicated by the words must be in the exception description. These cases are the only ones on which client logic
should depend on a specific problem resulting in a specific JMS exception being thrown.
In the remainder of cases, it is strongly suggested that JMS providers use one of the standard exceptions where possible. JMS providers may also derive provider-specific exceptions from these if needed. JMS defines the following standard exceptions:
IllegalStateException : This exception is thrown when a method is invoked at an illegal or inappropriate time or if the provider is not in an appropriate state for the requested operation. For example, this exception must be thrown if Session.commit() is called on a non-transacted session. This exception is also must be called when domain inappropriate method is called, such as calling TopicSession.CreateQueueBrowser() . JMSSecurityException: This exception must be thrown when a provider rejects a user name/password submitted by a client. It may also be thrown for any case where a security restriction prevents a method from completing. InvalidClientIDException : This exception must be thrown when a client attempts to set a connections client identifier to a value that is rejected by a provider. InvalidDestinationException: This exception must be thrown when a destination is either not understood by a provider or is no longer valid. InvalidSelectorException : This exception must be thrown when a JMS client attempts to give a provider a message selector with invalid syntax. MessageEOFException: This exception must be thrown when an unexpected end of stream has been reached when a StreamMessage or BytesMessage is being read. MessageFormatException: This exception must be thrown when a JMS client attempts to use a data type not supported by a message or attempts to read data in a message as the wrong type. It must also be thrown when
88
7
equivalent type errors are made with message property values. For example, this exception must be thrown if StreamMessage.writeObject() is given an unsupported class or if StreamMessage.readShort() is used to read a boolean value. This exception also must be thrown if a provider is given a type of message it cannot accept. Note that the special case of a failure caused by attempting to read improperly formatted String data as numeric values must throw the java.lang.NumberFormatException.
MessageNotReadableException: This exception must be thrown when a JMS client attempts to read a write-only message. MessageNotWriteableException: This exception must be thrown when a JMS client attempts to write to a read-only message. ResourceAllocationException: This exception is thrown when a provider is unable to allocate the resources required by a method. For example, this exception should be thrown when a call to createTopicConnection fails due to lack of JMS provider resources. TransactionInProgressException: This exception is thrown when an operation is invalid because a transaction is in progress. For instance, attempting to call Session.commit() when a session is part of a distributed transaction should throw a TransactionInProgressException. TransactionRolledBackException : This exception must be thrown when a call to Session.commit results in a rollback of the current transaction.
89
90
This chapter describes JMS facilities for concurrent processing of a subscriptions messages. It also defines how a JMS provider supplies JTS aware sessions. These facilities are primarily intended for the use of the JMS provider. If JMS clients use the JTS aware facilitiest client program may be non-portable code, because JMS providers are not required to support these interfaces. The facilities described in this chapter are a special category of JMS. They are optional and might only be supported by some JMS providers.
JMS provider - its role is to deliver the messages. Application Server - its role is to create the consumer and manage the threads used by the concurrent MessageListener objects. Application - its role is to define a subscription with a destination and optionally a message selector and provide a single-threaded MessageListener class to consume its messages. An application server will construct multiple objects of this class to concurrently consume messages.
91
8
8.2.1 Session
Sessions provide three methods for use by application servers:
setMessageListener() and getMessageListener() - a sessions MessageListener consumes messages that have been assigned to the session by a ConnectionConsumer, as described in the next few paragraphs. run() - causes the messages assigned to its session by a ConnectionConsumer to be serially processed by the sessions MessageListener. When the listener returns from processing the last message, run( ) returns.
An application server would typically be given a MessageListener class that contained the single-threaded code written by an application programmer to process messages. It would also be given the destination and message selector that specified the messages the listener was to consume. An application server would take care of creating the JMS Connection, ConnectionConsumer, and Sessions it needs to handle message processing. It would create as many MessageListener instances as it needed and register each with its own session. Since many listeners will need to use the services of its session, the listener is likely to require that its session be passed to it as a constructor parameter.
8.2.2 ServerSession
A ServerSession is an object implemented by an application server. It is used by an application server to associate a thread with a JMS session. A ServerSession implements two methods:
getSession() - returns the ServerSession s JMS Session. start() - starts the execution of the ServerSession thread and results in the execution of the associated JMS Sessions run method.
8.2.3 ServerSessionPool
A ServerSessionPool is an object implemented by an application server to provide a pool of ServerSessions for processing the messages of a ConnectionConsumer.
92
8
Its only method is getServerSession() . This removes a ServerSession from the pool and gives it to the caller (which is assumed to be a ConnectionConsumer) to use for consuming one or more messages. JMS does not architect how the pool is implemented. It could be a static pool of ServerSessions or it could use a sophisticated algorithm to dynamically create ServerSessions as needed. If the ServerSessionPool is out of ServerSessions, the getServerSession() method may block. If a ConnectionConsumer is blocked, it cannot deliver new messages until a ServerSession is eventually returned.
8.2.4 ConnectionConsumer
For application servers, connections provide a special facility for creating a ConnectionConsumer. The messages it is to consume are specified by a destination and a message selector. In addition, a ConnectionConsumer must be given a ServerSessionPool to use for processing its messages. A maxMessages value is specified to limit the number of messages a ConnectionConsumer may load at one time into a ServerSession s Session. Normally, when traffic is light, a ConnectionConsumer gets a ServerSession from its pool, loads its Session with a single message, and starts it. As traffic picks up, messages can back up. If this happens, a ConnectionConsumer can load each Session with more than one message. This reduces the thread context switches and minimizes resource use at the expense of some serialization of message processing.
93
8
A ConnectionConsumer for a QueueConnection will expect to load its messages into a QueueSession, as one for a TopicConnection would expect to load a TopicSession. Note that JMS does not architect how the ConnectionConsumer loads the Session with messages. Since both the ConnectionConsumer and Session are implemented by the same JMS provider, they can accomplish the load using a private mechanism.
94
8
The following diagram illustrates the relationship between the three roles and the objects they implement.
JMS Provider ServerSession App Server
implements
implements
Manages a pool of
implements
ServerSessionPool
delivers messages to
implements
App
95
8
The following diagram illustrates the process a ConnectionConsumer uses to deliver a message to a MessageListener.
ServerSessionPool
getSession
ServerSession
ConnectionConsumer
ServerSession
run
Session
onMessage
Message Listener
96
8
8.3 XAConnectionFactory
Some application servers provide support for grouping resource use into a distributed transaction. To include JMS transactions in a distributed transaction, an application server requires a Java Transaction API (JTA) capable JMS provider. A JMS provider exposes its JTA support using a JMS XAConnectionFactory, which an application server uses to create XAConnections. XAConnectionFactory provides the same authentication options as ConnectionFactory. XAConnectionFactory objects are JMS administered objects, just like ConnectionFactory objects. It is expected that application servers will find them by using JNDI.
8.4 XAConnection
XAConnection extends the capability of Connection by providing the ability to create XASessions.
8.5 XASession
XASession provides access to what looks like a normal Session object and a javax.transaction.xa.XAResource object which controls the sessions transaction context. The functionality of XAResource closely resembles that defined by the standard X/Open XA Resource interface. An application server controls the transactional assignment of an XASession by obtaining its XAResource. It uses the XAResource to assign the session to a distributed transaction, prepare and commit work on the transaction, and so on. An XAResource provides some fairly sophisticated facilities for interleaving work on multiple transactions, recovering a list of transactions in progress, and so on. A JTA aware JMS provider must fully implement this functionality. This could be done by using the services of a database that supports XA, or a JMS provider may choose to implement this functionality from scratch. A client of the application server is given the XASessions Session. Behind the scenes, the application server controls the transaction management of the underlying XASession.
97
8
It is important to note that a distributed transaction context does not flow with a message; that is, the receipt of the message cannot be part of the same transaction that produced the message. This is the fundamental difference between messaging and synchronized processing. Message producers and consumers use an alternative approach to reliability that is built upon a JMS provider s ability to supply a once-and-only-once message delivery guarantee. To reiterate, the act of producing and/or consuming messages in a Session can be transactional. The act of producing and consuming a specific message across different sessions cannot.
JMS Common Interfaces ServerSessionPool ServerSession Connection Consumer XAConnection Factory XAConnection XASession
98
This chapter gives some code examples that show how a JMS client could use the JMS API. It also demonstrates how to use several message types. The examples use methods that support a unified messaging model: these examples work with either Point-to-Point or Publish/Subscribe messaging. This is the recommended approach to working with the JMS API. In earlier versions of the JMS Specification, only the separate interfaces for each messaging domain (Point-to-Point or Pub/Sub) were supported, and the client was programmed to use one messaging domain or the other. Now, the JMS client can be programmed using the JMS common interfaces. In the example program, a client application sends and receives stock quote information. The messages the client application receives are from a stock quote service that sends out stock quote messages. The stock quote service is not described in the example. To simplify the example, no exception-handling code is included. This chapter describes the steps for creating the correct environment for sending and receiving a message. After describing these basic functions, this chapter describes how to perform some other common functions, such as using message selectors.
99
9
Get a ConnectionFactory and Destination Create a Connection and Session Create a MessageConsumer Create a MessageProducer
100
9
9.1.4 Creating a Session
Having obtained the Connection, the client program uses it to create a Session. The Session is used to create a MessageProducer (to send messages) or a MessageConsumer (to receive messages). The Connection.createSession method takes two parameters:
A boolean indicating whether this session is transacted or not The mode of acknowledging message receipt
Session session; /* Session is not transacted, * uses AUTO_ACKNOWLEDGE for message * acknowledgement */ session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
/* Value in stockQueue previously looked up in the JNDI * createProducer takes a Destination */ sender = session.createProducer(stockQueue);
101
9
A MessageConsumer is used to receive messages from the destination, which in this example is the Queue StockQuote. A MessageConsumer is created using the Session.createConsumer method, supplying one parameter, the destination from which messages are received.
MessageConsumer receiver; /* Value in stockQueue previously looked up in the JNDI * createConsumer takes a Destination */ receiver = session.createConsumer(stockQueue);
/* Set the messages text to be the stockData string */ message = session.createTextMessage(); message.setText(stockData);
102
To limit the amount of time that the client blocks, use a timeout parameter with the receive method. If no messages arrive by the end of the timeout, then the receive method returns. The timeout parameter is expressed in milliseconds.
TextMessage stockMessage; /* Wait 4 seconds for a message */ TextMessage = (TextMessage)receiver.receive(4000);
newStockData = message.getText();
103
9
Create an asynchronous MessageListener Use a message selector to filter message delivery Create a durable subscription to a Topic Re-connect to a Topic using a durable subscription
The client program registers the MessageListener object with the MessageConsumer object in the following way:
StockListener myListener = new StockListener(); /* Receiver is MessageConsumer object */ receiver.setMessageListener(myListener);
The Connection must be started for the message delivery to begin. The MessageListener is asynchronously notified whenever a message has been published to the Queue. This is done via the onMessage method in the MessageListener interface. It is up to the client to process the message there.
104
9
public void onMessage(Message message) { String newStockData; /* Unpack and handle the messages received */ newStockData = message.getText(); if(...) { /* Logic related to the data */ } }
When the client program that receives the stock quote messages creates MessageConsumer is created, the client program can create a message selector string to determine which messages it will receive.
105
9
String selector; selector = new String("(StockSector = Technology)");
The client program receives only messages related to the Technology sector.
106
9
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Having performed the normal setup, the client program can now create a durable subscriber to the destination. To do this, the client program creates a durable TopicSubscriber, using session.CreateDurableSubscriber. The name mySubscription is used as an identifier of the durable subscription.
session.createDurableSubscriber(newsFeedTopic,"mySubscription");
At this point, the client program can start the connection and start to receive messages.
This reconnects the client program to the Topic , and any messages that arrived while the client was disconnected are delivered. However, there are some important restrictions to be aware of:
The client must be attached to the same Connection. The Destination and subscription name must be the same. If a message selector was specified, it must also be the same.
If these conditions are not met, then the durable subscription is deleted, and a new subscription is created.
107
9
9.4.1 Creating a TextMessage
In this example, the stock quote information is sent as a TextMessage. A TextMessage carries the message as a text string that can be read by the client. The following code demonstrates how to create such a message:
String TextMessage stockData; message; /* Stock information as a string */
message = session.createTextMessage(); /* Set the stockData string to the message body */ message.setText(stockData);
stockInfo = message.getText();
108
9
byte[] int stockInfo; /* Byte array to hold stock information */ length;
length = message.readBytes(stockData);
The message body is copied to the byte array. The client program can then begin reading and interpreting the data.
Stock quote name - represented as a String Current value - represented as a double Time of quote - represented as a long Last change - represented as a double Stock information - represented as a String
To construct the MapMessage, the client program uses the various set method (setString, setLong , and so forth) that are associated with MapMessage, and sets each named value in the MapMessage.
String stockName; double stockValue; long stockTime; double stockDiff; String stockInfo; MapMessage message; /* Name of the stock */ /* Current value of the stock */ /* Time the stock quote was updated */ /* the +/- change in the stock quote*/ /* Other information on this stock */
message = session.createMapMessage();
109
9
message.setString("Info", "Recent server announcement causes market interest");
The data is retrieved from the message by using a get method and providing the name of the value desired. The elements from the MapMessage can be obtained in any order.
stockName stockDiff stockValue stockTime = = = = message.getString("Name"); message.getDouble("Diff"); message.getDouble("Value"); message.getLong("Time");
If a client program needs to get a list of the elements in a MapMessage, it can use the method MapMessage.getMapNames.
Stock quote name - String Current value - double Time of quote - long Last change - double Stock information - String
110
9
The client program might be interested in only some of the message fields, but in the case of a StreamMessage, the client has to read and potentially discard each field in turn. In the following example, the values for each of the following has already been set.:
String stockName; double stockValue; long stockTime; double stockDiff; String stockInfo; StreamMessage message; /* /* /* /* /* Name of the stock */ Current value of the stock */ Time of the stock update */ +/- change in the stock quote */ Information on this stock*/
The following elements have to be written to the StreamMessage in the order they will be read. Notice that they are not separately named properties, as in MapMessage.
/* Set data for message */ message.writeString(stockName); message.writeDouble(stockValue); message.writeLong(stockTime); message.writeDouble(stockDiff); message.writeString(stockInfo);
111
9
9.4.9 Creating an ObjectMessage
The stock information could be sent in the form of a special StockObject Java object. This object can then be sent as the body of a ObjectMessage. The ObjectMessage can be used to sent Java objects. These values are set using methods that are unique to the StockObject implementation. For example, the StockObject may have methods that set the various data values. An application using StockObject might look like this:
String double long double String stockName; stockValue; stockTime; stockDiff; stockInfo; /* /* /* /* /* Name of the stock quote */ Current value of the stock */ Time of the stock update */ +/- change in the stock quote */ Information on this stock */
/* Establish the values for the StockObject */ stockObject.setName(stockName); stockObject.setValue(stockValue); stockObject.setTime(stockTime); stockObject.setDiff(stockDiff); stockObject.setInfo(stockInfo);
To create an ObjectMessage, to pass the StockObject in the message, you would do the following:
/* Create an ObjectMessage */ ObjectMessage message; message = session.createObjectMessage(); /* Set the body of the message to the StockObject */ message.setObject(stockObject);
112
9
StockObject stockObject; /* Retrieve the StockObject from the message */ stockObject = (StockObject)message.getObject(); /* Extract data from the StockObject by using StockObject methods */ String double long double String stockName; stockValue; stockTime; stockDiff; stockInfo; /* /* /* /* /* Name of the stock quote */ Current value of the stock */ Time of the stock update */ +/- change in the stock quote */ Information on this stock */
113
114
Issues
10.1 Resolved Issues
10.1.1 JDK 1.1.x Compatibility
JMS is compatible with JDK 1.1.x.
10
10.1.3 Should the Two JMS Domains, PTP and Pub/Sub, be merged?
Even though there are many similarities, providing separate domains still seems to be important. It means that vendors aren't forced to support facilities out of their domain, and that client code can be a bit more portable because products more fully support a domain (as opposed to supporting less defined subsets of a merged domain).
115
10
10.1.4 Should JMS Specify a Set of JMS JavaBeans?
JMS is a low-level API, and like other Java low-level APIs, it doesn't lend itself to direct representation as JavaBeans.
10.1.6 Should JMS Provide End-to-end Synchronous Message Delivery and Notification of Delivery?
Some messaging systems provide synchronous delivery to destinations as a mechanism for implementing reliable applications. Some systems provide clients with various forms of delivery notification so that the clients can detect dropped or ignored messages. This is not the model defined by JMS. JMS messaging provides guaranteed delivery via the once-and-only-once delivery semantics of PERSISTENT messages. In addition, message consumers can insure reliable processing of messages by using either CLIENT_ACKNOWLEDGE mode or transacted sessions. This achieves reliable delivery with minimum synchronization and is the enterprise messaging model most vendors and developers prefer. JMS does not define a schema of systems messages (such as delivery notifications). If an application requires acknowledgment of message receipt, it can define an application-level acknowledgment message.
116
10
These issues are more clearly understood when they are examined in the context of Pub/Sub applications. In this context, synchronous delivery and/or system acknowledgment of receipt are not an effective mechanism for implementing reliable applications (because producers by definition are not, and dont want to be, responsible for end-to-end message delivery).
117
10
118
Change History
11.1 Version 1.0.1
11.1.1 JMS Exceptions
11
A new JMS Exception chapter was added and it contains the following new information:
Two fields were added to JMSException - a vendor error code and an Exception reference. In version 1.0, JMSException was the only JMS exception specified. Version 1.0.1 adds a list of standard exceptions derived from JMSException and describes when each should be thrown by JMS providers.
119
11
was better handled in the same way that overlapping subscriptions from different sessions are treated, so this special case has been removed.
120
11
11.2.7 Clearing a Messages Properties and Body
A clarification has been added that notes that clearing a messages properties and clearing its body are independent.
121
11
11.2.14 Incorrect Entry in Stream and Map Message Conversion Table
This table erroneously included a required conversion between char and String. This has been removed.
122
11
The type of the parameter of the createTextMessage method that takes an input value was changed from StringBuffer to String. The subscription name parameter was missing from the createDurableSubscription method of TopicConnection. It has been added.
123
11
Note the createTopic method of TopicSession and the createQueue method of QueueSession are used for converting a JMS provider specific name into a Topic or Queue object that represents an existing topic or queue by that name. These methods are not for creating the physical topic or queue. The physical creation of topics and queues are administrative tasks and are not done by JMS. The one exception is the creation of temporary topics and queues which is done using the createTemporaryTopic and createTemporaryQueue methods. Note that the setObject method of ObjectMessage places a copy of the input object in a message. Note that a connection is created in stopped mode and, for incoming messages to be delivered to the message listeners of its sessions, its start method must be called. Documentation of Message default constants has been added. Note the result of readBytes method of StreamMessage when the callers byte[] buffer is smaller than the byte[] field value being read. The documentation of QueueRequestor and TopicRequestor has been improved. The IllegalStateException has been noted as a required exception for several more error conditions. they are acknowledging a message received from a closed session; attempting to call the recover method of a transacted session; attempting to call any method of a closed connection, session, consumer or producer (with the exception of the close method itself); attempting to set a connections client identifier at the wrong time or when it has been administratively configured.
Major errata and clarifications approved by a Java Community Process SM program Maintenance Review that closed June 25, 2001. Minor errata formerly listed on the JMS documentation web page.
124
11
11.3.1 JMS API Specification, version 1.0.2: Errata and Clarifications
The following errata and clarifications have been incorporated into the Specification. They are listed in the order in which they occur in the Specification.
Section 3.4.7, JMSRedelivered: Change first paragraph to clarify when a provider must set this header field. Section 3.5.9, JMS Defined Properties: Correct return value of ConnectionMetaData.getJMSXPropertyNames method. Section 3.8.1.1, Message Selector Syntax: After the first sentence, add sentence about the interpretation of a message selector whose value is an empty string. In the third sub-bullet item under Identifiers, add ESCAPE to the list of prohibited identifiers. In the fourth sub-bullet item, add sentence about data types of property values, and move description of the value of nonexistent properties referenced in a selector from last bullet item to here. Add sub-bullet item clarifying that data type conversions do not apply to properties used in message selectors. In the first sub-bullet item under Comparison Operators, clarify the result of comparing non-like type values. At end of section, correct quotation marks in example. Section 3.10, Changing the Value of a Received Message: Add paragraph clarifying the semantics of redelivering a message that was modified after being received. Section 3.12, Provider Implementations of JMS Message Interfaces: Insert paragraph clarifying the handling of destinations for foreign message implementations. Section 4.4.12, Duplicate Delivery of Messages (formerly misnumbered 4.4.14): Add sentence about JMSRedelivered message header field. Section 4.5.2, Asynchronous Delivery: Clarify explanation of redelivery for AUTO_ACKNOWLEDGE and DUPS_OK_ACKNOWLEDGE acknowledgment modes. Section 4.10, Reliability: Clarify meaning of PERSISTENT and NON_PERSISTENT delivery modes throughout section. Section 6.9, TopicSession: Clarify redelivery of messages for durable and nondurable subscriptions. Rationale for this change: The scope of redelivery is the lifetime of a destination, not of the session that is consuming it. Each nondurable subscription is a different destination, and its lifetime is the session that
125
11
creates it. Each temporary queue or topic is a different destination whose lifetime is the connection that creates it.
Section 6.12, Recovery and Redelivery: Clarify recoverability of messages for nondurable subscriptions. Rationale for this change: Update the Specification to meet the expectation that a nondurable subscriber performs the same as a durable subscriber as long as the nondurable subscriber is in existence. The original statement in the specification could be interpreted to mean that message recovery was optional for a nondurable subscriber. It would be valuable to have a lower quality of service that did not require acknowledgement overhead, but a new mechanism should be provided to specify the lower quality of service option; the minimum quality of service required by the current specification should not be lowered.
Section 7.3, Standard Exceptions: In description of IllegalStateException, change should to must. In description of MessageFormatException, correct method names, and change should to must in last sentence.
11.3.2 JMS API Java API documentation, version 1.0.2a: Major Errata
The following items represent significant clarifications of the JMS API Java API documentation, version 1.0.2a. They are categorized as follows:
Corrections of mistakes Reconciliations between the Specification and the Java API documentation
Less important clarifications to the Java API documentation are listed in Section 11.3.3, JMS API Java API documentation, version 1.0.2a: Lesser Errata.
BytesMessage and StreamMessage interfaces: Correct discussion of modification of sent messages. TemporaryQueue.delete and TemporaryTopic.delete methods: Remove references to senders and publishers.
126
11
11.3.2.2 Reconciliations between the Specification and the Java API documentation
The following items update the Java API documentation to match the correct language in the Specification:
Message interface: Correct description of getting values for unset property names to match Section 3.5.4, Property Value Conversion. Remove incorrect bullet items about NULL values in arithmetic operations and BETWEEN operations. Message.acknowledge method: Clarify that the method applies to all consumed messages of the session. Rationale for this change: A possible misinterpretation of the existing Java API documentation for Message.acknowledge assumed that only messages received prior to this message should be acknowledged. The updated Java API documentation statement emphasizes that message acknowledgement is really a session-level activity and that this message is only being used to identify the session in order to acknowledge all messages consumed by the session. The acknowledge method was placed in the message object only to enable easy access to acknowledgement capability within a message listeners onMessage method. This change aligns the specification and Java API documentation to define Message.acknowledge in the same manner.
Message.getJMSTimestamp and MessageProducer.setDisableMessageTimestamp methods: Correct descriptions of effect of disabling timestamps. TopicSession.createSubscriber and TopicSession.createDurableSubscriber methods: Correct Throws: lists.
11.3.3 JMS API Java API documentation, version 1.0.2a: Lesser Errata
The Java API documentation corrections listed in this section concern the application of logic from the Specification or elsewhere in the Java API documentation:
Corrections to the Specification listed in Section 11.3.1, JMS API Specification, version 1.0.2: Errata and Clarifications Information in the Specification not previously reflected in the Java API documentation Information provided in some parts of the Java API documentation, but not in others where it also belongs
127
11
1. Message interface: Add the corrections to Section 3.8.1.1, Message Selector Syntax, to the section on message selectors. Also change the Java API documentation for the following methods to reflect these changes:
QueueConnection.createConnectionConsumer QueueSession.createReceiver QueueSession.createBrowser TopicConnection.createConnectionConsumer TopicConnection.createDurableConnectionConsumer TopicSession.createSubscriber TopicSession.createDurableSubscriber QueueBrowser.getMessageSelector MessageConsumer.getMessageSelector
2. Correct the Java API documentation for the following methods to add InvalidDestinationException to the Throws: list, in accordance with Section 7.3, Standard Exceptions:
QueueConnection.createConnectionConsumer QueueRequestor.QueueRequestor TopicConnection.createConnectionConsumer TopicConnection.createDurableConnectionConsumer TopicRequestor.TopicRequestor
3. TopicSession.createDurableSubscriber method: Change the description of the twoargument form to accord with the description of the one-argument form of the TopicSession.createSubscriber method. 4. QueueSender and TopicPublisher interfaces: Add clarifications from Section 3.9, Access to Sent Messages, and Section 3.4.11, How Message Header Values Are Set. Add UnsupportedOperationException to send and publish method Throws: lists where relevant. 5. QueueReceiver interface: Add language from Section 5.8, QueueReceiver. 6. IllegalStateException and MessageFormatException classes: Add corrections from Section 7.3, Standard Exceptions.
128
11
11.4.1 Unification of messaging domains
This maintenance release addresses the unification of the programming interfaces for the Point-to-Point and Pub/Sub messaging domains in the Java Message Service (JMS) API. In the 1.0.2b version of the JMS specification, the client programming model made a strong distinction between these two domains. One consequence of domain separation is that actions from the Pointto-Point domain and the Pub/Sub domain could not be used in the same transaction. In this version of the interfaces, methods have been added to support the ability to include PTP and Pub/Sub messaging in the same transaction. In addition, domain unification simplifies the client programming model, so that the client programmer can use a simplified set of APIs to create an application. The scope of a transaction in JMS is on a per Session basis. To add the ability to work across both domains, a number of methods have been added the javax.jms.Session interface. Adding these methods supports the creation of javax.jms.MessageConsumers and javax.jms.MessageProducers for either domain at the Session level, and supports sending and receiving message using either domain within the same Session. For example, using these proposed methods, a JMS client can create a transacted Session, and then receive messages from a Queue and send messages to a Topic within the same transaction. In JMS 1.0.2b, this was not possible. At the same time, the semantic differences between the two domains are retained. While it is possible to support actions on PTP and Pub/Sub destinations within the same session, the semantic differences that cause different behaviors within those domains are retained.
Section 1.2.3.3, JMS Domains, describes the backward compatibility relationship between earlier versions of the JMS specification and version 1.1 of the JMS specification. Section 2.4, Two Messaging Styles, and Section 2.5, JMS Interfaces, add information about the two message domains, and a table that describes the
129
11
relationship between the JMS common interfaces and the domain-specific interfaces that are derived from the JMS common interfaces.
Section 4.4, Session, updates the list of the activities that can be performed in a Session to include that it a Session is a factory for MessageProducers and MessageConsumers, and is a factory for TemporaryTopics and TemporaryQueues. Section 4.5, MessageConsumer, adds that a MessageConsumer can be created from a Session. Section 4.11, Method Inheritance across Messaging Domains, is a new section that describes how to handle methods that are not appropriate to a specific messaging domain. Section 5.1, Overview,adds a table that describes the relationship between the JMS common interfaces and the domain-specific interfaces that are derived from the JMS common interfaces. Section 5.4, TemporaryQueue, adds that the lifespan of the TemporaryQueue is the life of the Connection or QueueConnection that creates it. Previously, only QueueConnection was mentioned, but TemporaryQueues can now be created from Connections. Section 5.9, QueueBrowser, adds that a QueueBrowser can be created from Session, as well as from the QueueSession . Section 6.1, Overview, adds a table that describes the relationship between the JMS common interfaces and the domain-specific interfaces that are derived from the JMS common interfaces. Section 6.6, TemporaryTopic, adds that the lifespan of the TemporaryTopic is the life of the Connection or TopicConnection that creates it. Previously, only TopicConnection was mentioned, but a TemporaryTopic can now be created from Connection. Section 6.10, TopicPublisher, adds a comment that messages can be sent to a Topic either using a TopicPublisher or a MessageProducer. Section 6.11.1, Durable TopicSubscriber, adds that durable TopicSubscribers can be created either relative to a TopicConnection or a Connection. The unsubscribe method for the durable Topic subscription can also be used either at the TopicConnection or Connection level. Section 8.6, JMS Application Server Interfaces, adds a table that shows the relationships between the JMS common interfaces and the domain-specific interfaces that are derived from the JMS common interfaces.
130
11
Chapter 9, JMS Example Code has been rewritten to reflect the use of the JMS common interfaces. It now usese the new methods associated with domain unification.
Section 1.4, Relationship to Other Java APIs, is updated with the current status of the relationship of the JMS specification to the JDBC API, the EJB API, and the JTA API. Section 1.4, Relationship to Other Java APIs has two new sections: Section 1.4.7, Java 2, Enterprise Edition (J2EE) Platform, and, Sectio n1.4.8, Integration of JMS with the EJB Components. These new sections describe how JMS relates to the J2EE platform. Section 1.5, What is New in JMS 1.1? is a new section that summarizes the changes in this maintenance release. Section 2.3, Administration, contains a new figure which illustrates the relationship between the Administered objects and other elements of the JMS system. Section 2.5, JMS Interfaces, adds a figure which illustrates the relationships among the basic JMS elements.
11.4.3.2 Clarifications
Section 3.8.1.1, Message Selector Syntax, clarifies when semantic checking may occur. At the end of that section, there is a requirement that JMS providers must check syntactic correctness at the time that a message selector is presented. This statement has been updated to note that JMS providers are also permitted to check semantic correctness at that time, although not all semantic correctness can be verified at that time.
131
11
Section 4.3.8, ExceptionListener,adds a clarification that if no ExceptionListener is registered, the getExceptionListener method should return null. Section 4.4.6, Conventions for Using a Session, adds a clarification that use of the JTS aware interfaces described in Chapter 8 are not intended for use in the client JMS program. Use of these interfaces may create nonportable software, as the JTS aware interfaces described in Chapter 8 are optional. Section 4.4.9, Multiple Sessions, adds a further clarification that the JMS specification does not assign a semantic meaning to multiple QueueReceivers consuming from one Queue. Section 6.12, Recovery and Redelivery adds an additional clarification that setting the delivery mode to PERSISTENT will not change the delivery model for messages sent to a non durable subscriber. This is already described in Section 6.15, Reliability. Section 8.1, Overview, adds a clarification that JMS client program use of the JTS aware interfaces described in Chapter 8 may create non-portable code.
11.4.4 JMS API Java API documentation, version 1.1: Domain Unification
In order to support domain unification a number of existing interfaces were updated with additional methods.Table 11-1 lists the interfaces that were changed, and the new methods for those interfaces.
132
11
Table 11-1 New JMS API Methods for Domain Unification Interface Connection New Methods ConnectionConsumer createConnectionConsumer (Destination destination, String messageSelector, ServerSessionPool sessionPool, int maxMessages) throws JMSException; ConnectionConsumer createDurableConnectionConsumer(Topic topic,String subscriptionName, String messageSelector, ServerSessionPool sessionPool, int maxMessages) throws JMSException; ConnectionFactory Connection createConnection() throws JMSException; Connection createConnection(String userName, String password) throws JMSException; MessageProducer Destination getDestination() throws JMSException; void send(Message message) throws JMSException; void send(Message message, int deliveryMode, int priority, long timeToLive) throws JMSException; void send(Destination destination, Message message) throws JMSException;
133
11
Table 11-1 New JMS API Methods for Domain Unification Interface Session New Methods MessageProducer createProducer (Destination destination) throws JMSException; MessageConsumer createConsumer (Destination destination) throws JMSException; MessageConsumer createConsumer (Destination destination, java.lang.String messageSelector) throws JMSException; MessageConsumer createConsumer (Destination destination, java.lang.String messageSelector, boolean NoLocal) throws JMSException; TopicSubscriber createDurableSubscriber (Topic topic, java.lang.String name) throws JMSException; Session TopicSubscriber createDurableSubscriber( Topic topic, java.lang.String name, java.lang.String messageSelector, boolean noLocal) throws JMSException; QueueBrowser createBrowser(Queue queue) throws JMSException; QueueBrowser createBrowser(Queue queue, String messageSelector)
throws JMSException;
Queue createQueue (String name) throws JMSException; Topic createTopic (String name) throws JMSException; TemporaryTopic createTemporaryTopic() throws JMSException; TemporaryQueue createTemporaryQueue() throws JMSException; void unsubscribe(String string name); XAConnection XASession createXASession() throws JMSException;
134
11
Table 11-1 New JMS API Methods for Domain Unification Interface New Methods
XAConnectionFactory XAConnection createXAConnection() throws JMSException; XAConnection createXAConnection( String userName, String password) throws JMSException; XASession Session getSession() throws JMSException;
In addition, explanatory material was added to describe the relationship between the new methods and existing interfaces and methods. The interfaces that have been changed to describe these relationships are:
Queue QueueBrowser QueueConnection QueueConnectionFactory QueueReceiver QueueSender QueueSession Session TemporaryQueue TemporaryTopic Topic TopicConnection TopicConnectionFactory TopicPublisher TopicSubscriber TopicSession
135
11
This method permits the programmer to determine he size of the BytesMessage body and, if necessary, allocate a bytes array to copy the body. 2. Session.getAckowledgeMode
int getAcknowledgeMode() throws JMSException
This method returns the currently set value of how a Session acknowledges messages. This method is added for completeness, because in previous versions of the specification there was no way to get this value.
11.4.5.2 Clarifications
1. Connection.getExceptionListener If Connection.getExceptionListeneris called, and no ExceptionListener is registered, the JMS provider must return null. A client program may optionally associate an ExceptionListener with a Connection. If no ExceptionListener is associated with the ConnectionListener, a null should be returned. Previously, the Java API documentation did not specify what the return value should be. 2. MapMessage A clarification to the set methods of MapMessage, stating if the name parameter is null or an empty string, the method must throw the error InvalidArgumentException . The rationale is that each of the named elements in the MapMessage should have names that are not null or blank. Methods affected:
MapMessage.setBoolean MapMessage.setByte MapMessage.setBytes MapMessage.setChar MapMessage.setDouble MapMessage.setFloat MapMessage.setInt MapMessage.setLong MapMessage.setObject MapMessage.setShort MapMessage.setString
Message A clarification to the set property methods of Message states if the property
136
11
name parameter is null or empty string, the method must throw the error InvalidArgumentException . The rationale is that each of the properties in the Message should have names that are not null or blank. Methods affected:
Message.setBooleanProperty Message.setByteProperty Message.setDoubleProperty Message.setFloatProperty Message.setIntProperty Message.setLongProperty Message.setObjectProperty Message.setShortProperty Message.setStringProperty
3. TextMessage A comment in the description for TextMessage that indicated that XML might become popular has been changed to state that TextMessage can be used to send XML messages. 6. XA interfaces The descriptions of the XA interfaces now state that those interfaces are primarily used by JMS providers, and are optional; that is, the JMS provider is not required to support them. Use of the XA interfaces by a client program may lead to non-portable code. Interfaces affected:
XAConnection XAConnectionFactory XAQueueConnection XAQueueConnectionFactory XAQueueSession XASession XATopicConnection XATopicConnectionFactory XATopicSession
4. The descriptions of QueueSession, TopicSession, and QueueConnection now list methods that must not be called through these interfaces. These methods are a result of inheritance, but are not appropriate to be called from domain-specific interfaces. These are also described in Section 4.11, Method Inheritance across
137
11
Messaging Domains. If they are invoked, an IllegalStateException must be thrown.
Table 11-2 Domain Dependent Interfaces Interface QueueConnection QueueSession Method createDurableConnectionConsumer createDurableSubscriber createTemporaryTopic createTopic unsubscribe TopicSession createQueueBrowser createQueue createTemporaryQueue
138
Sun Microsystems, Inc. 901 San Antonio Road Palo Alto, CA 94303 650 960-1300 For U.S. Sales Office locations, call: 800 821-4643 In California: 800 821-4642 Australia: (02) 844 5000 Belgium: 32 2 716 7911 Canada: 416 477-6745 Finland: +358-0-525561 France: (1) 30 67 50 00 Germany: (0) 89-46 00 8-0 Hong Kong: 852 802 4188 Italy: 039 60551 Japan: (03) 5717-5000 Korea: 822-563-8700 Latin America: 650 688-9464 The Netherlands: 033 501234 New Zealand: (04) 499 2344 Nordic Countries: +46 (0) 8 623 90 00 PRC: 861-849 2828 Singapore: 224 3388 Spain: (91) 5551648 Switzerland: (1) 825 71 11 Taiwan: 2-514-0567 UK: 0276 20444 Elsewhere in the world, call Corporate Headquarters: 650 960-1300 Intercontinental Sales: 650 688-9000