2. Using the Tutorial Examples 3. Getting Started with Web Applications 5. JavaServer Pages Technology 7. JavaServer Pages Standard Tag Library 10. JavaServer Faces Technology 11. Using JavaServer Faces Technology in JSP Pages 12. Developing with JavaServer Faces Technology 13. Creating Custom UI Components 14. Configuring JavaServer Faces Applications 15. Internationalizing and Localizing Web Applications 16. Building Web Services with JAX-WS 17. Binding between XML Schema and Java Classes 19. SOAP with Attachments API for Java 21. Getting Started with Enterprise Beans 23. A Message-Driven Bean Example 24. Introduction to the Java Persistence API 25. Persistence in the Web Tier 26. Persistence in the EJB Tier 27. The Java Persistence Query Language 28. Introduction to Security in the Java EE Platform 29. Securing Java EE Applications 31. The Java Message Service API How Does the JMS API Work with the Java EE Platform? Point-to-Point Messaging Domain Publish/Subscribe Messaging Domain Programming with the Common Interfaces Writing Simple JMS Client Applications A Simple Example of Synchronous Message Receives Writing the Client Programs for the Synchronous Receive Example Creating JMS Administered Objects for the Synchronous Receive Example Compiling and Packaging the Clients for the Synchronous Receive Example Running the Clients for the Synchronous Receive Example A Simple Example of Asynchronous Message Consumption Writing the Client Programs for the Asynchronous Receive Example Compiling and Packaging theAsynchConsumer Client Running the Clients for the Asynchronous Receive Example A Simple Example of Browsing Messages in a Queue Writing the Client Program for the Queue Browser Example Compiling and Packaging theMessageBrowser Client Running the Clients for the Queue Browser Example Running JMS Client Programs on Multiple Systems Creating Administered Objects for Multiple Systems Editing, Recompiling, Repackaging, and Running the Programs Deleting the Connection Factory and Stopping the Server Creating Robust JMS Applications Using Basic Reliability Mechanisms Controlling Message Acknowledgment Specifying Message Persistence Setting Message Priority Levels Creating Temporary Destinations Using Advanced Reliability Mechanisms Using the JMS API in a Java EE Application Using@Resource Annotations in Java EE Components Using Session Beans to Produce and to Synchronously Receive Messages Using Message-Driven Beans to Receive Messages Asynchronously Managing Distributed Transactions Using the JMS API with Application Clients and Web Components 32. Java EE Examples Using the JMS API 36. The Coffee Break Application | Creating Robust JMS ApplicationsThis section explains how to use features of the JMS API toachieve the level of reliability and performance your application requires. Many people choose toimplement JMS applications because they cannot tolerate dropped or duplicate messages and requirethat every message be received once and only once. The JMS API providesthis functionality. The most reliable way to produce a message is to send aPERSISTENT message within a transaction. JMS messages arePERSISTENT by default. Atransactionis a unit of work into which you can group a series ofoperations, such as message sends and receives, so that the operations either allsucceed or all fail. For details, seeSpecifying Message Persistence andUsing JMS API Local Transactions. The most reliable way to consume a message is to do sowithin a transaction, either from a queue or from a durable subscription toa topic. For details, seeCreating Temporary Destinations,Creating Durable Subscriptions, andUsing JMS API Local Transactions. For other applications, a lower level of reliability can reduce overhead and improveperformance. You can send messages with varying priority levels (seeSetting Message Priority Levels) and you canset them to expire after a certain length of time (seeAllowing Messages to Expire). The JMS API provides several ways to achieve various kinds and degrees ofreliability. This section divides them into two categories: The following sections describe these features as they apply to JMS clients. Someof the features work differently in Java EE applications; in these cases, thedifferences are noted here and are explained in detail inUsing the JMS API in a Java EE Application. This section includes three sample programs, which you can find in the directorytut-install/javaeetutorial5/examples/jms/advanced/. Each sample uses a utility class calledSampleUtilities.java. Using Basic Reliability MechanismsThe basic mechanisms for achieving or affecting reliable message delivery are as follows:
Controlling Message AcknowledgmentUntil a JMS message has been acknowledged, it is not considered tobe successfully consumed. The successful consumption of a message ordinarily takes place in threestages.
In transacted sessions (seeUsing JMS API Local Transactions), acknowledgment happens automatically when a transaction is committed.If a transaction is rolled back, all consumed messages areredelivered. In nontransacted sessions, when and how a message is acknowledged depend on thevalue specified as the second argument of thecreateSession method. The three possibleargument values are as follows:
If messages have been received from a queue but not acknowledged when asession terminates, the JMS provider retains them and redelivers them when a consumernext accesses the queue. The provider also retains unacknowledged messages for a terminatedsession that has a durableTopicSubscriber. (SeeCreating Durable Subscriptions.) Unacknowledged messages for a nondurableTopicSubscriberare dropped when the session is closed. If you use a queue or a durable subscription, you can usetheSession.recover method to stop a nontransacted session and restart it with itsfirst unacknowledged message. In effect, the session’s series of delivered messages is resetto the point after its last acknowledged message. The messages it now deliversmay be different from those that were originally delivered, if messages have expiredor if higher-priority messages have arrived. For a nondurableTopicSubscriber, the provider maydrop unacknowledged messages when its session is recovered. The sample program in the next section demonstrates two ways to ensure thata message will not be acknowledged until processing of the message is complete. A Message Acknowledgment ExampleTheAckEquivExample.java program shows how both of the following two scenarios ensure thata message will not be acknowledged until processing of it is complete:
With a message listener, the automatic acknowledgment happens when theonMessage methodreturns (that is, after message processing has finished). With a synchronous receiver, theclient acknowledges the message after processing is complete. If you useAUTO_ACKNOWLEDGE with asynchronous receive, the acknowledgment happens immediately after thereceive call; if anysubsequent processing steps fail, the message cannot be redelivered. The program is in the following directory: tut-install/javaeetutorial5/examples/jms/advanced/ackequivexample/src/java/ The program contains aSynchSender class, aSynchReceiver class, anAsynchSubscriber classwith aTextListener class, aMultiplePublisher class, amain method, and a methodthat runs the other classes’ threads. The program uses the following objects:
To create the new queue and connection factory, you can use Anttargets defined in the filetut-install/javaeetutorial5/examples/jms/advanced/ackequivexample/build.xml. To run this example, follow these steps:
The program output looks something like this: Queue name is jms/ControlQueueQueue name is jms/QueueTopic name is jms/TopicConnection factory name is jms/DurableConnectionFactory SENDER: Created client-acknowledge session SENDER: Sending message: Here is a client-acknowledge message RECEIVER: Created client-acknowledge session RECEIVER: Processing message: Here is a client-acknowledge message RECEIVER: Now I’ll acknowledge the messageSUBSCRIBER: Created auto-acknowledge sessionSUBSCRIBER: Sending synchronize message to control queuePUBLISHER: Created auto-acknowledge sessionPUBLISHER: Receiving synchronize messages from control queue; count = 1PUBLISHER: Received synchronize message; expect 0 morePUBLISHER: Publishing message: Here is an auto-acknowledge message 1PUBLISHER: Publishing message: Here is an auto-acknowledge message 2SUBSCRIBER: Processing message: Here is an auto-acknowledge message 1PUBLISHER: Publishing message: Here is an auto-acknowledge message 3SUBSCRIBER: Processing message: Here is an auto-acknowledge message 2SUBSCRIBER: Processing message: Here is an auto-acknowledge message 3 After you run the program, you can delete the destination resourcejms/ControlQueue.Go to the directorytut-install/javaeetutorial5/examples/jms/advanced/ackequivexample/ and type the following command: ant delete-control-queue You will need the other resources for other examples. To delete the class and JAR files for the program using NetBeansIDE, right-click the project and choose Clean. To delete the class and JAR files for the program using Ant,type the following: ant clean Specifying Message PersistenceThe JMS API supports two delivery modes for messages to specify whether messagesare lost if the JMS provider fails. These delivery modes are fields oftheDeliveryMode interface.
You can specify the delivery mode in either of two ways.
If you do not specify a delivery mode, the default isPERSISTENT. UsingtheNON_PERSISTENT delivery mode may improve performance and reduce storage overhead, but youshould use it only if your application can afford to miss messages. Setting Message Priority LevelsYou can use message priority levels to instruct the JMS provider to deliverurgent messages first. You can set the priority level in either of twoways.
The ten levels of priority range from 0 (lowest) to 9 (highest).If you do not specify a priority level, the default level is 4.A JMS provider tries to deliver higher-priority messages before lower-priority ones but does nothave to deliver messages in exact order of priority. Allowing Messages to ExpireBy default, a message never expires. If a message will become obsolete aftera certain period, however, you may want to set an expiration time.You can do this in either of two ways.
If the specifiedtimeToLive value is0, the message never expires. When the message is sent, the specifiedtimeToLive is added to the currenttime to give the expiration time. Any message not delivered before the specifiedexpiration time is destroyed. The destruction of obsolete messages conserves storage and computingresources. Creating Temporary DestinationsNormally, you create JMS destinations (queues and topics) administratively rather than programmatically. YourJMS provider includes a tool that you use to create and remove destinations,and it is common for destinations to be long-lasting. The JMS API also enables you to create destinations (TemporaryQueue andTemporaryTopicobjects) that last only for the duration of the connection in which theyare created. You create these destinations dynamically using theSession.createTemporaryQueue and theSession.createTemporaryTopic methods. The only message consumers that can consume from a temporary destination are thosecreated by the same connection that created the destination. Any message producer cansend to the temporary destination. If you close the connection that a temporarydestination belongs to, the destination is closed and its contents are lost. You can use temporary destinations to implement a simple request/reply mechanism. If youcreate a temporary destination and specify it as the value of theJMSReplyTomessage header field when you send a message, then the consumer of themessage can use the value of theJMSReplyTo field as the destination towhich it sends a reply. The consumer can also reference the original requestby setting theJMSCorrelationID header field of the reply message to the value oftheJMSMessageID header field of the request. For example, anonMessage method cancreate a session so that it can send a reply to the messageit receives. It can use code such as the following: producer = session.createProducer(msg.getJMSReplyTo());replyMsg = session.createTextMessage("Consumer " + "processed message: " + msg.getText());replyMsg.setJMSCorrelationID(msg.getJMSMessageID());producer.send(replyMsg);For more examples, seeChapter 32, Java EE Examples Using the JMS API. Using Advanced Reliability MechanismsThe more advanced mechanisms for achieving reliable message delivery are the following:
Creating Durable SubscriptionsTo ensure that a pub/sub application receives all published messages, usePERSISTENT deliverymode for the publishers. In addition, use durable subscriptions for the subscribers. TheSession.createConsumer method creates a nondurable subscriber if a topic is specified asthe destination. A nondurable subscriber can receive only messages that are published whileit is active. At the cost of higher overhead, you can use theSession.createDurableSubscriber methodto create a durable subscriber. A durable subscription can have only one activesubscriber at a time. A durable subscriber registers a durable subscription by specifying a unique identity thatis retained by the JMS provider. Subsequent subscriber objects that have the sameidentity resume the subscription in the state in which it was left bythe preceding subscriber. If a durable subscription has no active subscriber, the JMSprovider retains the subscription’s messages until they are received by the subscription oruntil they expire. You establish the unique identity of a durable subscriber by setting the following:
You set the client ID administratively for a client-specific connection factory using theAdmin Console. After using this connection factory to create the connection and the session, youcall thecreateDurableSubscriber method with two arguments: the topic and a string thatspecifies the name of the subscription: String subName = "MySub";MessageConsumer topicSubscriber = session.createDurableSubscriber(myTopic, subName); The subscriber becomes active after you start theConnection orTopicConnection. Later,you might close the subscriber: topicSubscriber.close(); The JMS provider stores the messages sent or published to the topic, asit would store messages sent to a queue. If the program oranother application callscreateDurableSubscriber using the same connection factory and its client ID, thesame topic, and the same subscription name, the subscription is reactivated, and theJMS provider delivers the messages that were published while the subscriber was inactive. To delete a durable subscription, first close the subscriber, and then use theunsubscribe method, with the subscription name as the argument: topicSubscriber.close();session.unsubscribe("MySub");Theunsubscribe method deletes the state that the provider maintains for the subscriber. Figure 31-7 andFigure 31-8 show the difference between a nondurable and a durable subscriber.With an ordinary, nondurable subscriber, the subscriber and the subscription begin and endat the same point and are, in effect, identical. When a subscriber isclosed, the subscription also ends. Here,create stands for a call toSession.createConsumerwith aTopic argument, andclose stands for a call toMessageConsumer.close. Anymessages published to the topic between the time of the firstclose andthe time of the secondcreate are not consumed by the subscriber. InFigure 31-7,the subscriber consumes messages M1, M2, M5, and M6, but messages M3 andM4 are lost. Figure 31-7 Nondurable Subscribers and Subscriptions ![]() With a durable subscriber, the subscriber can be closed and re-created, but thesubscription continues to exist and to hold messages until the application calls theunsubscribe method. InFigure 31-8,create stands for a call toSession.createDurableSubscriber,closestands for a call toMessageConsumer.close, andunsubscribe stands for a calltoSession.unsubscribe. Messages published while the subscriber is closed are received when thesubscriber is created again. So even though messages M2, M4, and M5 arrivewhile the subscriber is closed, they are not lost. Figure 31-8 A Durable Subscriber and Subscription ![]() SeeA Java EE Application That Uses the JMS API with a Session Bean for an example of a Java EE application that uses durablesubscriptions. SeeA Message Acknowledgment Example and the next section for examples of client applicationsthat use durable subscriptions. A Durable Subscription ExampleTheDurableSubscriberExample.java program shows how durable subscriptions work. It demonstrates that a durablesubscription is active even when the subscriber is not active. The program containsaDurableSubscriber class, aMultiplePublisher class, amain method, and a method thatinstantiates the classes and calls their methods in sequence. The program is in the following directory: tut-install/javaeetutorial5/examples/jms/advanced/durablesubscriberexample/src/java/ The program begins in the same way as any publish/subscribe program: The subscriberstarts, the publisher publishes some messages, and the subscriber receives them. At thispoint, the subscriber closes itself. The publisher then publishes some messages while thesubscriber is not active. The subscriber then restarts and receives the messages. Before you run this program, compile and package the source file and createa connection factory that has a client ID. Perform the following steps:
To run the program using NetBeans IDE, right-click thedurablesubscriberexample project andchoose Run. To run the program from the command line, follow these steps:
The output looks something like this: Connection factory without client ID is jms/ConnectionFactoryConnection factory with client ID is jms/DurableConnectionFactoryTopic name is jms/TopicStarting subscriberPUBLISHER: Publishing message: Here is a message 1SUBSCRIBER: Reading message: Here is a message 1PUBLISHER: Publishing message: Here is a message 2SUBSCRIBER: Reading message: Here is a message 2PUBLISHER: Publishing message: Here is a message 3SUBSCRIBER: Reading message: Here is a message 3Closing subscriberPUBLISHER: Publishing message: Here is a message 4PUBLISHER: Publishing message: Here is a message 5PUBLISHER: Publishing message: Here is a message 6Starting subscriberSUBSCRIBER: Reading message: Here is a message 4SUBSCRIBER: Reading message: Here is a message 5SUBSCRIBER: Reading message: Here is a message 6Closing subscriberUnsubscribing from durable subscription After you run the program, you can delete the connection factoryjms/DurableConnectionFactory.Go to the directorytut-install/javaeetutorial5/examples/jms/advanced/durablesubscriberexample/ and type the following command: ant delete-durable-cf To delete the class and JAR files for the program using NetBeansIDE, right-click the project and choose Clean. To delete the class and JAR files for the program using Ant,type the following: ant clean Using JMS API Local TransactionsYou can group a series of operations into an atomic unit ofwork called a transaction. If any one of the operations fails, the transactioncan be rolled back, and the operations can be attempted again from thebeginning. If all the operations succeed, the transaction can be committed. In a JMS client, you can use local transactions to group messagesends and receives. The JMS APISession interface providescommit androllback methodsthat you can use in a JMS client. A transaction commit means thatall produced messages are sent and all consumed messages are acknowledged. A transactionrollback means that all produced messages are destroyed and all consumed messages arerecovered and redelivered unless they have expired (seeAllowing Messages to Expire). A transacted session is always involved in a transaction. As soon as thecommit or therollback method is called, one transaction ends and another transactionbegins. Closing a transacted session rolls back its transaction in progress, including anypending sends and receives. In an Enterprise JavaBeans component, you cannot use theSession.commit andSession.rollbackmethods. Instead, you use distributed transactions, which are described inUsing the JMS API in a Java EE Application. You can combine several sends and receives in a single JMS APIlocal transaction. If you do so, you need to be careful about theorder of the operations. You will have no problems if the transaction consistsof all sends or all receives or if the receives come before thesends. But if you try to use a request/reply mechanism, whereby you senda message and then try to receive a reply to the sent messagein the same transaction, the program will hang, because the send cannot takeplace until the transaction is committed. The following code fragment illustrates the problem: // Don’t do this!outMsg.setJMSReplyTo(replyQueue);producer.send(outQueue, outMsg);consumer = session.createConsumer(replyQueue);inMsg = consumer.receive();session.commit(); Because a message sent during a transaction is not actually sent until thetransaction is committed, the transaction cannot contain any receives that depend on thatmessage’s having been sent. In addition, the production and the consumption of a message cannot both bepart of the same transaction. The reason is that the transactions take placebetween the clients and the JMS provider, which intervenes between the production andthe consumption of the message.Figure 31-9 illustrates this interaction. Figure 31-9 Using JMS API Local Transactions ![]() The sending of one or more messages to one or more destinationsby client 1 can form a single transaction, because it forms a singleset of interactions with the JMS provider using a single session. Similarly, thereceiving of one or more messages from one or more destinations by client2 also forms a single transaction using a single session. But because thetwo clients have no direct interaction and are using two different sessions, notransactions can take place between them. Another way of putting this is that the act of producing and/orconsuming messages in a session can be transactional, but the act of producingand consuming a specific message across different sessions cannot be transactional. This is the fundamental difference between messaging and synchronized processing. Instead of tightlycoupling the sending and receiving of data, message producers and consumers use analternative approach to reliability, one that is built on a JMS provider’s abilityto supply a once-and-only-once message delivery guarantee. When you create a session, you specify whether it is transacted. The firstargument to thecreateSession method is aboolean value. A value oftrue means that the session is transacted; a value offalse means thatit is not transacted. The second argument to this method is the acknowledgmentmode, which is relevant only to nontransacted sessions (seeControlling Message Acknowledgment). If the sessionis transacted, the second argument is ignored, so it is a good ideato specify0 to make the meaning of your code clear. For example: session = connection.createSession(true, 0); Thecommit and therollback methods for local transactions are associated with thesession. You can combine queue and topic operations in a single transaction ifyou use the same session to perform the operations. For example, you canuse the same session to receive a message from a queue and senda message to a topic in the same transaction. You can pass a client program’s session to a message listener’s constructor functionand use it to create a message producer. In this way, you canuse the same session for receives and sends in asynchronous message consumers. The next section provides an example of the use of JMS APIlocal transactions. A Local Transaction ExampleTheTransactedExample.java program demonstrates the use of transactions in a JMS client application.The program is in the following directory: tut-install/javaeetutorial5/examples/jms/advanced/transactedexample/src/java/ This example shows how to use a queue and a topic ina single transaction as well as how to pass a session to amessage listener’s constructor function. The program represents a highly simplified e-commerce application in whichthe following things happen.
Figure 31-10 illustrates these steps. Figure 31-10 Transactions: JMS Client Example ![]() The program contains five classes:Retailer,Vendor,GenericSupplier,VendorMessageListener, andOrder. The programalso contains amain method and a method that runs the threads oftheRetailer,Vendor, and two supplier classes. All the messages use theMapMessage message type. Synchronous receives are used forall message reception except for the case of the vendor processing the repliesof the suppliers. These replies are processed asynchronously and demonstrate how to usetransactions within a message listener. At random intervals, theVendor class throws an exception to simulate a databaseproblem and cause a rollback. All classes exceptRetailer use transacted sessions. The program uses three queues namedjms/AQueue,jms/BQueue, andjms/CQueue, and onetopic namedjms/OTopic. Before you run the program, do the following:
To run the program using NetBeans IDE, follow these steps:
To run the program from the command line, follow these steps:
The output looks something like this: Quantity to be ordered is 3Retailer: ordered 3 computer(s)Vendor: Retailer ordered 3 Computer(s)Vendor: ordered 3 monitor(s) and hard drive(s)Monitor Supplier: Vendor ordered 3 Monitor(s)Monitor Supplier: sent 3 Monitor(s) Monitor Supplier: committed transaction Vendor: committed transaction 1Hard Drive Supplier: Vendor ordered 3 Hard Drive(s)Hard Drive Supplier: sent 1 Hard Drive(s)Vendor: Completed processing for order 1 Hard Drive Supplier: committed transactionVendor: unable to send 3 computer(s) Vendor: committed transaction 2Retailer: Order not filledRetailer: placing another orderRetailer: ordered 6 computer(s)Vendor: JMSException occurred: javax.jms.JMSException: Simulated database concurrent access exceptionjavax.jms.JMSException: Simulated database concurrent access exception at TransactedExample$Vendor.run(Unknown Source) Vendor: rolled back transaction 1Vendor: Retailer ordered 6 Computer(s)Vendor: ordered 6 monitor(s) and hard drive(s)Monitor Supplier: Vendor ordered 6 Monitor(s)Hard Drive Supplier: Vendor ordered 6 Hard Drive(s)Monitor Supplier: sent 6 Monitor(s) Monitor Supplier: committed transactionHard Drive Supplier: sent 6 Hard Drive(s) Hard Drive Supplier: committed transaction Vendor: committed transaction 1Vendor: Completed processing for order 2Vendor: sent 6 computer(s)Retailer: Order filled Vendor: committed transaction 2 After you run the program, you can delete the physical destinations and thedestination resources. Go to the directorytut-install/javaeetutorial5/examples/jms/advanced/transactedexample/ and type the following command: ant delete-resources Use the following command to remove the class and JAR files: ant clean Copyright © 2010, Oracle and/or its affiliates. All rights reserved.Legal Notices |