Thursday, December 16, 2010

JMS Question...............


General questions
Q: What is the Java Message Service? 
A: The Java Message Service (JMS) API is an API for accessing enterprise messaging systems. It is part of the Java 2 Platform, Enterprise Edition (J2EE).
The Java Message Service makes it easy to write business applications that asynchronously send and receive critical business data and events.
The Java Message Service defines a common enterprise messaging API that is designed to be easily and efficiently supported by a wide range of enterprise messaging products.
The Java Message Service supports both message queueing and publish-subscribe styles of messaging.
Q: Is the Java Message Service another mail API? 
A: No. The term messaging is broadly defined in computing. It is used for describing various operating system concepts; it is used to describe email and fax systems; and with the JMS API, it is used to describe asynchronous communication between enterprise applications.
JMS messages are asynchronous requests, reports, or events that are consumed by enterprise applications, not humans. They contain vital information needed to coordinate these systems. They contain precisely formatted data that describe specific business actions. Through the exchange of these messages, each application tracks the progress of the enterprise.
Q: Is the Java Message Service a product? 
A: No, the Java Message Service is the specification of a common API for enterprise messaging. A JMS provider supplied by an enterprise messaging vendor is required to use it.
Q: Where can I find the Java Message Service specification? 
A: The Java Message Service 1.0.2 specification is available at http://java.sun.com/products/jms/docs.html. A link to the online JMS API documentation is at the same location.
Q: Who was involved with Sun in the creation of the specification of Java Message Service 1.0.2? 
A: A number of important industry players initially collaborated with Sun to define the first draft of the Java Message Service specification. In addition, many comments were received from other companies, government and educational organizations, and others during the three-month public review period.
Q: What is compelling about the Java Message Service? 
A: The Java Message Service is compelling for these reasons:
  • It is the first enterprise messaging API that has achieved wide industry support.
  • It simplifies the development of enterprise applications by providing standard messaging concepts and conventions that apply across a wide range of enterprise messaging systems.
  • It leverages existing, enterprise-proven messaging systems.
Q: Why should developers use the Java Message Service? 
A: The Java Message Service makes it easy to do the following:
  • Write portable, message-based business applications
  • Extend existing message-based applications by adding new JMS clients that interoperate fully with their existing non-JMS clients
Q: What does a programmer need to learn to use the Java Message Service? 
A: Message-based applications are fundamentally different from remote procedure call based applications. Once a developer understands how best to employ both technologies, the JMS API makes writing message-based applications as easy as learning a few additional interfaces.
Q: What is the relationship between the Java Message Service and Enterprise JavaBeans components? 
A: Since J2EE version 1.2 was released, Enterprise JavaBeans components have been able to use the JMS API to send enterprise messages and receive them synchronously. The Java 2 SDK, Enterprise Edition, version 1.3, now available, provides a new kind of enterprise bean, the message-driven bean, that allows an enterprise application to receive messages asynchronously.
Q: What is the relationship between the Java Message Service and the Java Naming and Directory Interface (JNDI) API? 
A: The JMS API, like the other Java Enterprise APIs, uses the JNDI API for administration. The JMS API defines ConnectionFactories and Destinations as administered objects that are configured and placed in a JNDI naming context. JMS clients then look up and use these preconfigured objects. This insures that JMS applications are easy to deploy and administer.
Q: What is the relationship between the Java Message Service and the Java DataBase Connectivity (JDBC) API? 
A: JMS clients may also use the JDBC API. They may use both the JMS API and the JDBC API in the same transaction. In most cases, they will achieve this automatically by implementing these clients as enterprise beans. They may also use the Java Transaction API.
Q: What is the relationship between the Java Message Service, the Java Transaction API, and the Java Transaction Service? 
A: The Java Transaction API (JTA) provides a client API for delimiting distributed transactions and an API for accessing a resource's ability to participate in a distributed transaction. A JMS client may use JTA to delimit distributed transactions. A JMS provider can optionally support distributed transactions via JTA.
The Java Transaction Service (JTS) can be used with the JMS API to form distributed transactions that combine message sends and receives with database updates and other JTS aware services. These services should be handled automatically when a JMS client is run from within an application server such as a J2EE server; however, it is also possible for JMS clients to program them explicitly.
Q: Where can I find a JMS API discussion group? 
A: You can find a JMS API discussion forum at http://java.sun.com/j2ee/community/forums/index.html. You must be a member of the Java Developer Connection to join this forum.
Q: Why is the JMS API promoted as a technology for providing communication between components within an enterprise, but not for business-to-business (B2B) communication between enterprises over the Internet? What prevents its use over the Internet? 
A: The main issue in providing Internet-based JMS API messaging is that JMS API vendors would have to agree on a common (interoperable) wire format, and the JMS specification would have to specify a router-router API.
B2B messaging is an important area with its own unique requirements. This area is being addressed by emerging standards such as the Electronic Business XML initiative, ebXML (see http://www.ebxml.org/), where Sun is playing an active role. The ebXML initiative currently defines a Messaging Service (see the ebXML Specifications page), which supports XML messaging over the Internet. Current ebXML specifications focus on providing point-to-point asynchronous communication between parties over the Internet using multiple transport protocols such as HTTP, mail, and FTP. Work is also planned in ebXML to provide publish/subscribe XML messaging. Sun and its partners are currently defining a new Java API for XML Messaging, JAXM (see JSR #000067, Java APIs for XML Messaging 1.0), which supports the ebXML Messaging Service specification. An early-access version of JAXM is available via the Java Developer Connection at The M Project 1.0 Early Access.
In summary, the JMS API is intended for use within an enterprise, while XML messaging between independent enterprises over the Internet is being supported by the ebXML initiative and the new Java APIs (including JAXM) that support various ebXML specifications.
Technical questions
Q: What JDK release does the JMS API need? 
A: The JMS API requires JDK/JRE release 1.1.x or higher.
Q: Does the JMS API provide a version of a distributed Java event model? 
A: The JMS API can be used, in general, as a notification service; however, it does not define a distributed version of Java Events. One alternative for implementing distributed Java Events would be as JavaBeans components that transparently, to the event producer and listener beans, distribute the events via the JMS API.
Q: Why are there two separate JMS API domains, point-to-point and publish/subscribe, instead of just one? 
A: 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).
Q: Why doesn't the JMS API specify a set of JavaBeans components? 
A: The JMS API is a low-level API, and like other low-level Java APIs, it doesn't lend itself to direct representation as JavaBeans components.
Q: How is the JMS API aligned with the CORBA Notification Service? 
A: The Notification Service adds filtering, delivery guarantee semantics, durable connections, and the assembly of event networks to the CORBA Event Service. It gets its delivery guarantee semantics from the CORBA Messaging Service (which defines asynchronous CORBA method invocation).
Java technology is well integrated with CORBA. It provides Java IDL and COS Naming. In addition, OMG has recently defined RMI over IIOP.
It is expected that most use of IIOP from Java will be via RMI. It is expected that most use of COS Naming from Java will be via the JNDI API (Java Naming and Directory Service). The JMS API is a Java specific API designed to be layered over a wide range of existing and future Message Oriented Middleware (MOM) systems (just as the JNDI API is layered over existing name and directory services).
Q: Why doesn't the JMS API provide end-to-end synchronous message delivery and notification of delivery? 
A: 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 the JMS API.
JMS API 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.
The JMS API 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.
These issues are more clearly understood when they are examined in the context of publish/subscribe 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 do not want to be, responsible for end-to-end message delivery).
Q: Why doesn't the JMS API provide a send-to-list mechanism? 
A: Currently the JMS API provides a number of message send options; however, messages can only be sent to one Destination at a time.
The benefit of send-to-list is slightly less work for the programmer and the potential for the JMS provider to optimize the fact that several destinations are being sent the same message.
The down side of a send-to-list mechanism is that the list is, in effect, a group that is implemented and maintained by the client. This would complicate the administration of JMS clients.
Instead of the JMS API providing a send-to-list mechanism, it is recommended that providers support configuring destinations that represent a group. This allows a client to reach all consumers with a single send, while insuring that groups are properly administrable.
Q: Why doesn't the JMS API provide subscription notification? If it were possible for a publisher to detect when subscribers for a topic existed, it could inhibit publication on unsubscribed topics. 
A: Although there may be some benefit in providing publishers with a mechanism for inhibiting publication to unsubscribed topics, the complexity this would add to the JMS API and the additional provider overhead it would require are not justified by its potential benefits. Instead, JMS providers should insure that they minimize the overhead for handling messages published to an unsubscribed topic.
Q: Can a message be acknowledged after its message consumer is closed? 
A: Yes. Since message acknowledgment processing is performed at the session level, message acknowledgement is still relevant after a consumer is closed. All messages consumed by the session are acknowledged for the following two examples:
// CLIENT_ACKNOWLEDGE session
Message msg1 = topicSubscriber1.receive();
Message msg2 = topicSubscriber2.receive();
topicSubscriber1.close();
msg2.acknowledge();

// transacted session
Message msg1 = queueReceiver.receive();
queueReceiver.close();
session.commit();

After the session has been closed, however, a call to the Message.acknowledge or Session.commit method throws an IllegalStateException. If closeis called on a transacted session before the transaction in progress is committed, the transaction is rolled back.
Note that in order to prevent duplicate delivery of a message from a durable subscription or queue, a message that can still be acknowledged by a session cannot be redelivered to another message consumer. The message can only be redelivered to another message consumer when it can no longer be acknowledged by the session that initially received the message.
Q: What message distribution policy does the JMS API specify when there are two or more QueueReceivers for the same queue at the same time? 
A: The JMS API does not specify a message distribution policy when two or more QueueReceivers are registered with a destination at the same time. JMS API semantics account for only one QueueReceiver at any point in time. The JMS API does not prohibit multiple QueueReceivers for a queue; it just does not define the behavior for this case.
TopicSession allows the creation of multiple TopicSubscribers per destination, it will deliver each message for a destination to eachTopicSubscriber eligible to receive it. Each copy of the message is treated as a completely separate message. Work done on one copy has no affect on the other; acknowledging one does not acknowledge the other; one message may be delivered immediately while another waits for its consumer to process messages ahead of it.
The Message.acknowledge method is documented to acknowledge the receipt of all messages consumed by the session. Thus, if msgA is delivered to topic subscribers TS1 and TS2 of the same session, and TS1 synchronously receives its copy of msgA and acknowledges it, TS2 will still be able to synchronously receive its copy of the message. However, if TS1 receives its copy of msgA and then TS2 receives its copy of msgA, acknowledging receiving the message fromTS2 will acknowledge both the msgAs received by TS1 and TS2, based on the fact that TS1's copy of msgA was received by the session before TS2's copy ofmsgA was received by the session.
Q: What is the recoverability of messages for closed consumers? 
A: For messages consumed from a queue or durable subscription, a rollback ensures that the messages are not acknowledged and that they will be delivered to the next consumer of these persistent entities. The JMS specification states that messages delivered to non-durable subscribers may be dropped. This statement means that the JMS API does not define the recoverability of messages consumed from a non-durable subscriber.
Q: Why can't I run the JMS API sample programs using the J2EE 1.2.x SDK? 
A: The J2EE 1.2.x Reference Implementation did not include an implementation of the JMS API. It included only the interfaces. The JMS Reference Implementation is available as part of J2EE 1.3 and you can run the sample programs with the J2EE 1.3 server. See the JMS Tutorial for information on running simple JMS client programs with the J2EE 1.3 server.
Please see Java Message Service API Licensees for a list of vendors that provide implementations of the JMS API. Many of these vendors have demonstration copies of their JMS API implementations that you can use to run the JMS API samples that you downloaded from the website.
Q: According to the specification, "Getting a property value for a name which has not been set is handled as if the the property exists with a null value." In the case of getStringProperty, does this mean a null value or a null string? 
A: Either is permissible. The reason for this ambiguity is that some MOM systems do not have the native concept of a null string, so they convert all null-valued strings at send time to empty strings.
Q: I used the Connection.setExceptionListener(ExceptionListener) method to try to handle connection problems, but when I stop the server, noJMSException seems to be triggered; the onException method is not called. Is this a bug? 
A: The JMS specification does not specify exactly what exceptions are delivered to an ExceptionListener or when they are delivered, so providers vary in how they handle connection problems. Check with your JMS provider if you have questions.
Q: According to Section 3.4 of the JMS Specification, a client can effectively set only three of the message header fields. All the others are set either by the JMS provider or by the send or publish method. Why do all the fields have a setter method, when any client setting will be overridden when the message is sent or when the JMS provider delivers it? Wouldn't it make sense to allow only getter methods for most of the fields? 
A: The specification requires setter methods mainly for consistency, so that each message header field has both a getter and setter method. Another reason is to allow a receiving client to change a field after a message is received but before it is passed to some other part of an application for processing. Although most setter methods are used very rarely, they are provided to give programmers flexibility.
Q: Can two different JMS services talk to each other? For instance, if A and B are two different JMS providers, can Provider A send messages directly to Provider B? If not, then can a subscriber to Provider A act as a publisher to Provider B? [new!]
A: The answers are no to the first question and yes to the second. The JMS specification does not require that one JMS provider be able to send messages directly to another provider. However, the specification does require that a JMS client must be able to accept a message created by a different JMS provider, so a message received by a subscriber to Provider A can then be published to Provider B. One caveat is that the publisher to Provider B is not required to handle aJMSReplyTo header that refers to a destination that is specific to Provider A.

JMS : queues on glassfish

Setting up GlassFish for JMS and Working with Message Queues

https://www.packtpub.com/article/setting-glassfish-jms-working-with-message-queues


The Java Messaging API (JMS) provides a mechanism for Java EE applications to send messages to each other. JMS applications do not communicate directly, instead message producers send messages to a destination and message consumers receive the message from the destination.
The message destination is a message queue when the point-to-point (PTP) messaging domain is used, or a message topic when the publish/subscribe (pub/sub) messaging domain is used.
In this article by David Heffelfinger, author of the book Java EE 6 with GlassFish 3 Application Server, we will cover the following topics:
  • Setting up GlassFish for JMS
  • Working with message queues
(For more resources on Java, see here.)

Setting up GlassFish for JMS

Before we start writing code to take advantage of the JMS API, we need to configure some GlassFish resources. Specifically, we need to set up a JMS connection factory, a message queue, and a message topic.

Setting up a JMS connection factory

The easiest way to set up a JMS connection factory is via GlassFish's web console. The web console can be accessed by starting our domain, by entering the following command in the command line:
asadmin start-domain domain1
Then point the browser to http://localhost:4848 and log in:
Setting up GlassFish for JMS and Working with Message Queues
A connection factory can be added by expanding the Resources node in the tree at the left-hand side of the web console, expanding the JMS Resources node and clicking on the Connection Factories node, then clicking on the New... button in the main area of the web console.
Setting up GlassFish for JMS and Working with Message Queues
For our purposes, we can take most of the defaults. The only thing we need to do is enter a Pool Nameand pick a Resource Type for our connection factory.
It is always a good idea to use a Pool Name starting with "jms/" when picking a name for JMS resources. This way JMS resources can be easily identified when browsing a JNDI tree.
In the text field labeled Pool Name, enter jms/GlassFishBookConnectionFactory. Our code examples later in this article will use this JNDI name to obtain a reference to this connection factory.
The Resource Type drop-down menu has three options:
  • javax.jms.TopicConnectionFactory - used to create a connection factory that creates JMS topics for JMS clients using the pub/sub messaging domain
  • javax.jms.QueueConnectionFactory - used to create a connection factory that creates JMS queues for JMS clients using the PTP messaging domain
  • javax.jms.ConnectionFactory - used to create a connection factory that creates either JMS topics or JMS queues
For our example, we will select javax.jms.ConnectionFactory. This way we can use the same connection factory for all our examples, those using the PTP messaging domain and those using the pub/sub messaging domain.
After entering the Pool Name for our connection factory, selecting a connection factory type, and optionally entering a description for our connection factory, we must click on the OK button for the changes to take effect.
Setting up GlassFish for JMS and Working with Message Queues
We should then see our newly created connection factory listed in the main area of the GlassFish web console.

Setting up a JMS message queue

A JMS message queue can be added by expanding the Resources node in the tree at the left-hand side of the web console, expanding the JMS Resources node and clicking on the Destination Resourcesnode, then clicking on the New... button in the main area of the web console.
Setting up GlassFish for JMS and Working with Message Queues
In our example, the JNDI name of the message queue is jms/GlassFishBookQueue. The resource type for message queues must be javax.jms.Queue. Additionally, a Physical Destination Name must be entered. In this example, we use GlassFishBookQueue as the value for this field.
After clicking on the New... button, entering the appropriate information for our message queue, and clicking on the OK button, we should see the newly created queue:
Setting up GlassFish for JMS and Working with Message Queues

Setting up a JMS message topic

Setting up a JMS message topic in GlassFish is very similar to setting up a message queue.
In the GlassFish web console, expand the Resources node in the tree at the left hand side, then expand the JMS Resouces node and click on the Destination Resources node, then click on the New... button in the main area of the web console.
Setting up GlassFish for JMS and Working with Message Queues
Our examples will use a JNDI Name of jms/GlassFishBookTopic. As this is a message topic, Resource Type must be javax.jms.Topic. The Description field is optional. The Physical Destination Name property is required. For our example, we will use GlassFishBookTopic as the value for this property.
After clicking on the OK button, we can see our newly created message topic:
Setting up GlassFish for JMS and Working with Message Queues
Now that we have set up a connection factory, a message queue, and a message topic, we are ready to start writing code using the JMS API.

Message queues

Like we mentioned earlier, message queues are used when our JMS code uses the point-to-point (PTP) messaging domain. For the PTP messaging domain, there is usually one message producer and one message consumer. The message producer and the message consumer don't need to run concurrently in order to communicate. The messages placed in the message queue by the message producer will stay in the message queue until the message consumer executes and requests the messages from the queue.

Sending messages to a message queue

The following example illustrates how to add messages to a message queue:
package net.ensode.glassfishbook;

import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

public class MessageSender
{
@Resource(mappedName = "jms/GlassFishBookConnectionFactory")
private static ConnectionFactory connectionFactory;
@Resource(mappedName = "jms/GlassFishBookQueue")
private static Queue queue;

public void produceMessages()
{
MessageProducer messageProducer;
TextMessage textMessage;
try
{
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
messageProducer = session.createProducer(queue);
textMessage = session.createTextMessage();

textMessage.setText("Testing, 1, 2, 3. Can you hear me?");
System.out.println("Sending the following message: "
+ textMessage.getText());
messageProducer.send(textMessage);

textMessage.setText("Do you copy?");
System.out.println("Sending the following message: "
+ textMessage.getText());
messageProducer.send(textMessage);
textMessage.setText("Good bye!");
System.out.println("Sending the following message: "
+ textMessage.getText());
messageProducer.send(textMessage);

messageProducer.close();
session.close();
connection.close();
}
catch (JMSException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new MessageSender().produceMessages();
}
}
Before delving into the details of this code, alert readers might have noticed that this class is a standalone Java application as it contains a main method. As this class is standalone, it executes outside the application server. In spite of this, we can see that some resources are injected into it, specifically the connection factory and queue. The reason we can inject resources into this code, even though it runs outside the application server, is because GlassFish includes a utility called appclient.
This utility allows us to "wrap" an executable JAR file and allows it to have access to the application server resources. To execute the previous code, assuming it is packaged in an executable JAR file calledjmsptpproducer.jar, we would type the following command in the command line:
appclient -client jmsptpproducer.jar
We would then see, after some GlassFish log entries, the following output on the console:

Sending the following message: Testing, 1, 2, 3. Can you hear me?
Sending the following message: Do you copy?
Sending the following message: Good bye!

The appclient executable can be found under [GlassFish installation directory]/glassfish/bin. The previous example assumes this directory is in your PATH variable. If it isn't the complete path to the appclientexecutable, it must be typed in the command line.
With that out of the way, we can now explain the code.
The produceMessages() method performs all the necessary steps to send messages to a message queue.
The first thing this method does is obtain a JMS connection by invoking the createConnection() method on the injected instance of javax.jms. ConnectionFactory. Notice that the mappedName attribute of the@Resource annotation decorating the connection factory object matches the JNDI name of the connection factory we set up in the GlassFish web console. Behind the scenes, a JNDI lookup is made using this name to obtain the connection factory object.
After obtaining a connection, the next step is to obtain a JMS session from said connection. This can be accomplished by calling the createSession() method on the Connection object. As can be seen in the previous code, the createSession() method takes two parameters.
The first parameter of the createSession() method is a Boolean indicating if the session is transacted. If this value is true, several messages can be sent as part of a transaction by invoking the commit() method in the session object. Similarly, they can be rolled back by invoking its rollback() method .
The second parameter of the createSession() method indicates how messages are acknowledged by the message receiver. Valid values for this parameter are defined as constants in the javax.jms.Sessioninterface.
  • Session.AUTO_ACKNOWLEDGE: indicates that the session will automatically acknowledge the receipt of a message.
  • Session.CLIENT_ACKNOWLEDGE: indicates that the message receiver must explicitly call the acknowledge() method on the message.
  • Session.DUPS_OK_ACKNOWLEDGE: indicates that the session will lazily acknowledge the receipt of messages. Using this value might result in some messages being delivered more than once.
After obtaining a JMS session, an instance of javax.jms.MessageProducer is obtained by invoking thecreateProducer() method on the session object. The MessageProducer object is the one that will actually send messages to the message queue. The injected Queue instance is passed as a parameter to thecreateProducer() method . Again, the value of the mappedName attribute for the @Resource annotation decorating this object must match the JNDI name we gave our message queue when setting it up in the GlassFish web console.
After obtaining an instance of MessageProducer, the code creates a series of text messages by invoking the createTextMessage() method on the session object. This method returns an instance of a class implementing the javax.jms.TextMessage interface. This interface defines a method called setText() , which is used to set the actual text in the message. After creating each text message and setting its text, they are sent to the queue by invoking the send() method on the MessageProducer object.
After sending the messages, the code disconnects from the JMS queue by invoking the close() method on the MessageProducer object , on the Session object , and on the Connection object.
Although the previous example sends only text messages to the queue, we are not limited to this type of message. The JMS API provides several types of messages that can be sent and received by JMS applications. All message types are defined as interfaces in the javax.jms package.
The following table lists all the available message types:
Message type
Description
BytesMessage
Allows sending an array of bytes as a message.
MapMessage
Allows sending an implementation of java.util.Map as a
message.
ObjectMessage
Allows sending any Java object implementing
java.io.Serializable as a message.
StreamMessage
Allows sending an array of bytes as a message. Differs from BytesMessage in that it stores the type of each primitive type added to the stream.
TextMessage
Allows sending a java.lang.String as a message.
For more information on all of these message types, consult their JavaDoc documentation athttp://java.sun.com/javaee/6/docs/api/.

Retrieving messages from a message queue

There is no point in sending messages from a queue if nothing is going to receive them. The following example illustrates how to retrieve messages from a JMS message queue:

package net.ensode.glassfishbook; import javax.annotation.Resource; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.jms.MessageConsumer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage; public class MessageReceiver { @Resource(mappedName = "jms/GlassFishBookConnectionFactory") private static ConnectionFactory connectionFactory; @Resource(mappedName = "jms/GlassFishBookQueue") private static Queue queue; public void getMessages() { Connection connection; MessageConsumer messageConsumer; TextMessage textMessage; boolean goodByeReceived = false; try { connection = connectionFactory.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); messageConsumer = session.createConsumer(queue); connection.start(); while (!goodByeReceived) { System.out.println("Waiting for messages..."); textMessage = (TextMessage) messageConsumer.receive(); if (textMessage != null) { System.out.print("Received the following message: "); System.out.println(textMessage.getText()); System.out.println(); } if (textMessage.getText() != null && textMessage.getText().equals("Good bye!")) { goodByeReceived = true; } } messageConsumer.close(); session.close(); connection.close(); } catch (JMSException e) { e.printStackTrace(); } } public static void main(String[] args) { new MessageReceiver().getMessages(); } }
Just like in the previous example, an instance of javax.jms.ConnectionFactory and an instance ofjavax.jms.Queue are injected by using the @Resource annotation. Getting a connection and a JMS session is exactly the same as in the previous example.
In this example, we obtain an instance of javax.jms.MessageConsumer by calling the createConsumer()method on the JMS session object. When we are ready to start receiving messages from the message queue, we need to invoke the start() method on the JMS connection object.
Code not receiving messages?
A common mistake when writing JMS messages is to fail to call the start() method on the JMS connection object. If our code is not receiving messages it should be receiving, we need to make sure we didn't forget to call this method.
Messages are received by invoking the receive() method on the instance of MessageConsumer obtained from the JMS session. This method returns an instance of a class implementing the javax.jms.Messageinterface. It must be casted to the appropriate type in order to obtain the actual message.
In this particular example, we placed this method call in a while loop, as we are expecting a message that will let us know that no more messages are coming. Specifically, we are looking for a message containing the text "Good bye!". Once we receive said message, we break out of the loop and continue processing. In this particular case, there is no more processing to do. Therefore, all we do is call theclose() method on the message consumer object, on the session object, and on the connection object.
Just like in the previous example, using the appclient utility allows us to inject resources into the code and prevents us from having to add any libraries to the CLASSPATH. After executing the code through theappclient utility, we should see the following output in the command line:
appclient -client target/jmsptpconsumer.jar
Waiting for messages...
Received the following message: Testing, 1, 2, 3. Can you hear me?
Waiting for messages...
Received the following message: Do you copy?
Waiting for messages...
Received the following message: Good bye!
This of course assumes that the previous example was already executed and it placed the messages in the message queue.

Asynchronously receiving messages from a message queue

The MessageConsumer.receive() method has a disadvantage—it blocks execution until a message is received from the queue. We can avoid this disadvantage by receiving messages asynchronously via an implementation of the javax.jms.MessageListener interface.
The javax.jms.MessageListener interface contains a single method called onMessage. It takes an instance of a class implementing the javax.jms.Message interface as its sole parameter. The following example illustrates a typical implementation of this interface:
package net.ensode.glassfishbook; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.TextMessage; public class ExampleMessageListener implements MessageListener { @Override public void onMessage(Message message) { TextMessage textMessage = (TextMessage) message; try { System.out.print("Received the following message: "); System.out.println(textMessage.getText()); System.out.println(); } catch (JMSException e) { e.printStackTrace(); } } }
In this case, the onMessage() method simply outputs the message text to the console.
Our main code can now delegate message retrieval to our custom MessageListener implementation:
package net.ensode.glassfishbook; import javax.annotation.Resource; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.jms.MessageConsumer; import javax.jms.Queue; import javax.jms.Session; public class AsynchMessReceiver { @Resource(mappedName = "jms/GlassFishBookConnectionFactory") private static ConnectionFactory connectionFactory; @Resource(mappedName = "jms/GlassFishBookQueue") private static Queue queue; public void getMessages() { Connection connection; MessageConsumer messageConsumer; try { connection = connectionFactory.createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); messageConsumer = session.createConsumer(queue); messageConsumer.setMessageListener(new ExampleMessageListener()); connection.start(); System.out.println("The above line wil l allow the " + "MessageListener implementation to " + "receiving and processing messages from the queue."); Thread.sleep(1000); System.out.println("Our code does not have to block " + "while messages are received."); Thread.sleep(1000); System.out.println("It can do other stuff " + "(hopefully something more useful than sending " + "silly output to the console. :)"); Thread.sleep(1000); messageConsumer.close(); session.close(); connection.close(); } catch (JMSException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { new AsynchMessReceiver().getMessages(); } }
The only relevant difference between this example and the one in the previous section is that in this case, we are calling the setMessageListener() method on the instance of javax.jms.MessageConsumerobtained from the JMS session. We pass an instance of our custom implementation ofjavax.jms.MessageListener to this method. Its onMessage() method is automatically called whenever there is a message waiting in the queue. By using this approach, the main code does not block while waiting to receive messages.
Executing the previous example (using of course GlassFish's appclient utility) results in the following output:
appclient -client target/jmsptpasynchconsumer.jar The above line will allow the MessageListener implementation to receiving and processing messages from the queue. Received the following message: Testing, 1, 2, 3. Can you hear me? Received the following message: Do you copy? Received the following message: Good bye! Our code does not have to block while messages are received. It can do other stuff (hopefully something more useful than sending silly output to the console. :)
Notice how the messages were received and processed while the main thread was executing. We can tell this is the case because the output of the onMessage() method of our MessageListener can be seen between calls to System.out.println() in the primary class.

Browsing message queues

JMS provides a way to browse message queues without actually removing the messages from the queue. The following example illustrates how to do this:

package net.ensode.glassfishbook;

import java.util.Enumeration;

import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.Session;
import javax.jms.TextMessage;

public class MessageQueueBrowser
{
@Resource(mappedName = "jms/GlassFishBookConnectionFactory")
private static ConnectionFactory connectionFactory;
@Resource(mappedName = "jms/GlassFishBookQueue")
private static Queue queue;

public void browseMessages()
{
try
{
Enumeration messageEnumeration;
TextMessage textMessage;
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
QueueBrowser browser = session.createBrowser(queue);
messageEnumeration = browser.getEnumeration();
if (messageEnumeration != null)
{
if (!messageEnumeration.hasMoreElements())
{
System.out.println("There are no messages " + "in the
queue.");
}
else
{
System.out.println("The following messages are in the
queue:");
while (messageEnumeration.hasMoreElements())
{
textMessage =
(TextMessage) messageEnumeration.nextElement();
System.out.println(textMessage.getText());
}
}
}
session.close();
connection.close();
}
catch (JMSException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new MessageQueueBrowser().browseMessages();
}
}

As we can see, the procedure to browse messages in a message queue is straightforward. We obtain a JMS connection and a JMS session the usual way, then invoke the createBrowser() method on the JMS session object. This method returns an implementation of the javax.jms.QueueBrowser interface. This interface contains a getEnumeration() method that we can invoke to obtain an enumeration containing all messages in the queue. To examine the messages in the queue, we simply traverse this enumeration and obtain the messages one by one. In the previous example, we simply invoke the getText() method of each message in the queue.

Summary

In this article, we saw how to set up JMS connection factories, JMS message queues, and JMS message topics in GlassFish using the GlassFish web console. We also saw how to send and receive messages to and from a message queue.






Thursday, June 24, 2010

Java theory and practice: Garbage collection in the HotSpot JVM

Summary:  In last month's Java theory and practice, columnist Brian Goetz reviewed the basic algorithms for garbage collection. This month, he goes a step further and examines how the 1.4.1 JVM actually handles garbage collection, including some of the new garbage collection options for multiprocessor systems.





Last month, we looked at the classic garbage collection techniques of reference counting, copying, mark-sweep, and mark-compact. Each of these approaches has advantages and disadvantages in certain situations. For example, copying does well when a large proportion of objects are garbage, but does poorly with many long-lived objects (copying them repeatedly). Conversely, mark-compact does quite well with long-lived objects (copying them only once), but not so well with many short-lived objects. The technique used by the 1.2 and later JVMs, called generational garbage collection, combines these two techniques to get the best of both worlds, and as a bonus provides very low object allocation overhead.
In any application heap, some objects become garbage shortly after their creation, some survive for a long time and then become garbage, and others can remain live for the entirety of the program's run. Empirical studies have shown that for most object-oriented languages, the Java language included, the vast majority of objects -- as much as 98 percent, depending on your metric for object youth -- die young. One can measure an object's age in wall-clock seconds, in total bytes allocated by the memory management subsystem since the object was allocated, or the number of garbage collections since the object was allocated. But no matter how you measure, the studies show the same thing -- most objects die young. The fact that most objects die young has significance for the choice of collector. In particular, copying collectors perform quite well when the majority of objects die young, since copying collectors do not visit dead objects at all; they simply copy the live objects to another heap region, then reclaim the whole of the remaining space in one fell swoop.
Of the objects that survive past their first collection, a significant portion of those will become long-lived or permanent. The various garbage collection strategies perform very differently depending on the mix of short-lived and long-lived objects. Copying collectors work very well when most objects die young, because objects that die young never need to be copied at all. However, the copying collector deals poorly with long-lived objects, repeatedly copying them back and forth from one semi-space to another. Conversely, mark-compact collectors do very well with long-lived objects, because long-lived objects tend to accumulate at the bottom of the heap and then do not need to be copied again. Mark-sweep and mark-compact collectors, however, expend considerably more effort examining dead objects, because they must examine every object in the heap during the sweep phase.
A generational collector divides the heap into multiple generations. Objects are created in the young generation, and objects that meet some promotion criteria, such as having survived a certain number of collections, are then promoted to the next older generation. A generational collector is free to use a different collection strategy for different generations and perform garbage collection on the generations separately.
One of the advantages of generational collection is that it can make garbage collection pauses shorter by not collecting all generations at once. When the allocator is unable to fulfill an allocation request, it first triggers a minor collection, which only collects the youngest generation. Since many of the objects in the young generation will already be dead and the copying collector does not need to examine dead objects at all, minor collection pauses can be quite short and can often reclaim significant heap space. If the minor collection frees enough heap space, the user program can resume immediately. If it does not free enough heap space, it proceeds to collect higher generations until enough memory has been reclaimed. (In the event the garbage collector cannot reclaim enough memory after a full collection, it will either expand the heap or it will throw anOutOfMemoryError.)
Tracing garbage collectors, such as copying, mark-sweep, and mark-compact, all start scanning from the root set, traversing references between objects, until all live objects have been visited.
A generational tracing collector starts from the root set, but does not traverse references that lead to objects in the older generation, which reduces the size of the object graph to be traced. But this creates a problem -- what if an object in the older generation references a younger object, which is not reachable through any other chain of references from a root?
To address this problem, generational collectors must explicitly track references from older objects to younger objects and add these old-to-young references into the root set of the minor collection. There are two ways to create a reference from an old object to a young object. Either one of the references contained in an old object is modified to refer to a young object, or a young object that refers to other young objects is promoted into the older generation.
Whether an old-to-young reference is created by promotion or a pointer modification, the garbage collector needs to have a comprehensive set of old-to-young references when it wants to perform a minor collection. One way to do this would be to trace the old generation, but this clearly has significant overhead. Somewhat better would be to linearly scan the old generation looking for references to young objects. This approach is faster than tracing and has better locality, but is still considerable work.
The mutator and garbage collector can work together to maintain a comprehensive list of old-to-young references as they are created. When objects are promoted into the older generation, the garbage collector can note any old-to-young references that are created as a result of the promotion, which leaves only the tracking of intergenerational references created by pointer modifications.
The garbage collector can track old-to-young references that arise through modifying references held within existing objects in several ways. It could track them in the same manner as maintaining reference counts in reference-counting collectors (the compiler could generate additional instructions surrounding pointer assignments) or could use virtual memory protection on the old generation heap to trap writes to older objects. Another potentially more efficient virtual memory approach would be to use the page modification dirty bits in the old generation heap to identify blocks to scan for objects containing old-to-young pointers.
With a little cleverness, it is possible to avoid the overhead of tracking every pointer modification and inspecting it to see if it crosses generational boundaries. For example, it is not necessary to track stores to local or static variables, because they will already be part of the root set. It may also be possible to avoid tracking pointer stores within constructors that simply initialize fields of newly created objects (so-called initializing stores), as (almost) all objects are allocated in the young generation. In any case, the runtime must maintain an explicit set of references from old objects to young ones and add these references to the root set when collecting the young generation.
In Figure 1, the arrows represent references between objects in the heap. The red arrows represent old-to-young references that must be added to the root set for a minor collection. The blue arrows represent references to old objects, either from the root set or from the young generation, which don't need to be traced when collecting only the young generation.

Figure 1. Intergenerational references
Intergenerational references
The Sun JDKs use an optimized variant of an algorithm called card marking to identify modifications to pointers held in fields of old-generation objects. In this approach, the heap is divided into a set of cards, each of which is usually smaller than a memory page. The JVM maintains a card map, with one bit (or byte, in some implementations) corresponding to each card in the heap. Each time a pointer field in an object in the heap is modified, the corresponding bit in the card map for that card is set. At garbage collection time, the mark bits associated with cards in the old generation are examined, and dirty cards are scanned for objects containing references into the younger generation. Then the mark bits are cleared. There are several costs to card marking – additional space for the card map, additional work to be done on each pointer store, and additional work to be done at garbage collection time. Card marking algorithms can add as little as two or three machine instructions per non-initializing heap pointer store, and entails scanning any objects on dirty cards at minor collection time.
By default, the 1.4.1 JDK divides the heap into two sections, a young generation and an old generation. (Actually, there is also a third section, the permanent space, which is used for storing loaded class and method objects.) The young generation is divided into a creation space, often called Eden, and two survivor semi-spaces, using a copying collector.
The old generation uses a mark-compact collector. Objects are promoted from the young generation to the old generation after they have survived copying a certain number of times. A minor collection will copy live objects from Eden and one of the survivor semi-spaces into the other survivor space, potentially promoting some objects to the older generation. A major collection will collect both the young and old generation. The System.gc() method always triggers a major collection, which is one of the reasons you should use System.gc() sparingly, if at all, because major collections can take much longer than a minor collection. There is no way to programmatically trigger a minor collection.
In addition to the copying and mark-compact collectors used by default, the 1.4.1 JDK also contains four other garbage collection algorithms, each of which is suited to a different purpose. JDK 1.4.1 includes an incremental collector (which has been around since JDK 1.2) and three new collectors for more efficient collection on multiprocessor systems -- the parallel copying collector, the parallel scavenging collector, and the concurrent mark-sweep collector. These new collectors address the problem of the garbage collector being a scalability bottleneck on multiprocessor systems. Figure 2 shows some guidelines on when to choose alternate collection options.

Figure 2. 1.4.1 garbage collection options (courtesy of Folgmann IT-Consulting)
Garbage collection options
The incremental collection option has been part of the JDK since 1.2. Incremental collection reduces garbage collection pauses at the expense of throughput, making it desirable only in cases where shorter collection pauses are very important, such as near-realtime systems.
The algorithm used by the JDK for incremental collection, the Train algorithm, creates a new section of the heap between the old and young generations. These heap sections are divided into "trains," each of which is divided into a sequence of "cars." Each car can be collected separately. Effectively, each train car constitutes a separate generation, which means that not only must old-to-young references be tracked, but also references from older trains to younger trains and older cars to younger cars. This creates significant extra work for the mutator and garbage collector, but permits much shorter collection pauses.
The new collectors in JDK 1.4.1 are all designed to address the issue of garbage collection on multiprocessor systems. Because most garbage collection algorithms stop the world for some period of time, a single-threaded garbage collector can quickly become a scalability bottleneck, because all but one processor are idle while the garbage collector has suspended the user program threads. Two of the new collectors are designed to reduce collection pause time -- the parallel copying collector and the concurrent mark-sweep collector. The other, the parallel scavenge collector, is designed for higher throughput on large heaps.
The parallel copying collector, enabled by the -XX:+UseParNewGC JVM option, is a young-generation copying collector that divides the work of garbage collection among as many threads as there are CPUs. The concurrent mark-sweep collector, enabled by the -XX:+UseConcMarkSweepGC option, is an old-generation mark-sweep collector that stops the world briefly for an initial mark phase (and again later for a brief re-mark phase) and then allows the user program to resume while the garbage collector threads execute concurrently with the user program. The parallel copying collector and concurrent mark-sweep collector are basically concurrent versions of the default copying and mark-compact collectors. The parallel scavenging collector, enabled by -XX:+UseParallelGC, is a young-generation collector optimized for very large (gigabyte and larger) heaps on multiprocessor systems.
With six algorithms to choose from, you're probably wondering which one to use. Figure 2 offers some guidance, dividing collectors into single-threaded and concurrent, and into low-pause and high-throughput. Given what you know about your application and deployment environment, this may be enough to select the appropriate algorithm. For many applications, the default collectors work just fine -- so if you don't have a performance problem, there's no point in inviting more complexity. However, if your application is deployed on a multiprocessor system or uses a very large heap, you may get some performance boost from changing collector options.
JDK 1.4.1 also includes numerous options for tuning garbage collection. You can spend considerable time tweaking these options and measuring their effect, so before you try and tune the garbage collector, you'll probably get a better return on your tuning investment by making sure your application has been thoroughly profiled and optimized first.
The first place to start with tuning garbage collection is to examine the verbose GC output. This will give you information on the frequency, timing, and duration of garbage collection operations. The simplest form of garbage collection tuning is simply expanding the maximum heap size (-Xmx). Copying collection becomes more efficient as the heap grows, so by expanding the heap, you reduce the cost of collection on a per-object basis. In addition to increasing the maximum heap size, you can also use the -XX:NewRatio option to increase the proportion of space assigned to the young generation. You also can specify the size of the young generation explicitly with the -Xmn option. See Resources for a number of articles offering more detailed garbage collection tuning advice.
As the JVM has evolved, the default garbage collector has gotten better and better. The generational collector employed by JDK 1.2 and later offers far better allocation and collection performance than the mark-sweep-compact collector used by earlier JDKs. The 1.4.1 JDK further improves the effectiveness of garbage collection by adding new multithreaded collection options for multiprocessor systems and very large heaps.
Next month, we'll wrap up our exploration of garbage collection by looking at some performance hints and myths about garbage collection, including the true cost of object allocation, the costs and benefits of explicit nulling, and the cost of finalization.