COMP 655: Distributed/Operating Systems - Summer 2011
2024-05-07 11:40:45 UTC
Home
Lectures
Assignments
Books, web, tools
 
Turnitin.com
Guidelines
Writing help
Plagiarism
 
DiNo
Glassfish
RESTful client
Menu service
JAX-RS
JAXB
EJB
Java
 
Bulletin board
Contact
 JMS

JMS (Java Message Service) is the Java EE technology for non-blocking, persistent communication. It supports both message queuing (via JMS Queues) and publish-subscribe (via JMS Topics).


JMS for DiNo

We won't use all of JMS in DiNo, of course. Furthermore, we will use our subset of JMS in an unusual way. Normally, JMS connection factories and destinations are created with administrative tools and last a long time - days or weeks in test environments, months or years in production. Clients look them up with JNDI, and JNDI naming hides differences among the various JMS providers. In DiNo, by contrast, we will create JMS resources dynamically, in a GlassFish-specific way. This non-portability is undesirable, but given our time constraints, the simplification that results from cutting out administrative tools and JNDI indirection will be worth it.

Creating connection factories

We will create JMS connection factories and topics in a GlassFish-dependent way. Specifically, to create a connection factory that talks to the local JMS provider, do

javax.jms.ConnectionFactory cf = new com.sun.messaging.ConnectionFactory();

To create a connection factory that talks to the JMS provider on a remote machine,

com.sun.messaging.ConnectionFactory sunCf = new com.sun.messaging.ConnectionFactory();
if( host != null ) {
   
sunCf.setProperty(ConnectionConfiguration.imqAddressList, host);
}
javax.jms.ConnectionFactory cf = sunCf;

Non-portability across JMS providers is clear here; another provider cannot be expected to implement com.sun.messaging.ConnectionFactory. (of course, all providers will implement javax.jms.ConnectionFactory)

com.sun.messaging.ConnectionFactory is probably not in the jars that make up the normal GlassFish runtime environment. When working with the sample source code now, and your DiNo implementation later, you will need to include glassfish/lib/install/applications/jmsra/imqjmsra.jar in your project's build path. You do NOT need to include it in WAR or JAR files you deploy to GlassFish, because it is already on the container's classpath.

When using the code above to connect to a remote provider, host should be a string of the form hostname or hostname:port. If the port number is not provided, it defaults to GlassFish's default JMS port, which is 7676.

Creating topics

Given a connection factory cf and a destination name dn, you can create a topic like this

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.Session;

Connection connection = cf.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination d = session.createTopic(dn);

The non-portability is somewhat hidden here: the destination name dn must be a String that conforms to rules defined by GlassFish's JMS provider IMQ. Specifically, dn can contain letters, digits, and underscores. I'm not certain what other characters may be legal, but slash (/) is not. Such names may or may not work with a different JMS provider.

A nice characteristic of IMQ is that you do NOT have to create the named destination with an administrative tool or JMX. It will create physical destinations as needed. Those destinations are officially temporary, but from what I've seen so far, their lifetimes will be plenty for our purposes.


JMS sample code

jms-sample.war contains a RESTful web service that supports experimenting with a subset of JMS. Unless I have overlooked something, that subset is what we will need for DiNo. The sample can be downloaded into a GlassFish autodeploy directory and used via the RESTful client. Here's what it can do. 

PUT /destination/Example

Creates a JMS MessageListener on the destination named "Example" on the local machine

PUT /destination/Example?host=otherhost

Creates a JMS MessageListener on the destination named "Example" on the machine "otherhost". If you're using the RESTful client, use a parameter named "host" with a value of "otherhost", as shown below

PUT /destination/Example?host=thirdhost:43210

Creates a JMS MessageListener on the destination named "Example" on the machine "thirdhost," assuming the GlassFish on thirdhost is configured to use 43210 as its JMS port.

DELETE /destination/Example

Removes the MessageListener, if any, on the destination named "Example"

POST /destination/Example

Sends a text message to the destination named "Example" on the local machine. The request content is the message text. If you are using the RESTful client, put the message text in the box below the parameters

GET /destination/Example

Returns the text messages received by the listener on the destination named "Example". An example is below.

NOTES

  • URI shown above are relative the to service's context root. So if you keep the WAR file's name and deploy it in a GlassFish on your local machine using the default port, the URI /destination/Example refers to the service URL http://localhost:8080/jms-sample/destination/Example
  • This sample can only listen to one destination with a given name at a given time. Calling PUT on a destination name that already has a listener does nothing. If you want to change the host for a destination with a listener, call DELETE on the destination first, then PUT.
  • This sample can receive messages from topics on other machines, but it can only send messages to topics on the local machine.
  • Source code is included in the WAR file. As always, you are free to re-use that source if you wish.
  • The JMS sample has been deployed on einstein. However, given einstein's weird network configuration, it will only be able to receive from local destinations (that is, destinations on einstein), and JMS samples deployed on other machines will be unable to receive from destinations on einstein.
  • The RESTful client has been updated to include the JMS sample in the base URL drop-down menu. You will need to download and deploy the latest version to get the updated menu.
  • If you want to print this page, I think you'll get reasonable results in IE by setting View > Text size > Smaller, printing in landscape mode, and setting the left and right margins to 0.15 inches