Examining a Queue

A QueueBrowser is a specialized object that allows you to peek ahead at pending messages on a Queue without actually consuming them. This feature is unique to point-to-point messaging. Queue browsing can be useful for monitoring the contents of a queue from an administration tool, or for browsing through multiple messages to locate a message that is more important than the one that is at the head of the queue. The latter scenario is what we chose to explore in our new version the wholesaler application, the QWBrowser .

QWBrowser sends out price quotes to multiple instances of QRetailer, which respond with "Buy" orders. To make this more interesting, we'll modify the retailer so that each order requests a random number of items. The QWBrowser may not be able to fulfill all of the orders from its on-hand inventory.

In order to sell as many items from inventory as possible without going into backorder, QWBrowser examines all of the responses that are pending in the queue, then finds the one order with a quantity that most closely fits the amount it has in inventory. It then synchronously consumes all of the messages using QueueReceiver.receive(long timeout), fulfills the desired order, and places the rest of them in a back-order status.

If you would like to see this in action, shut down all the other wholesalers and retailers you may have running. Start one instance of QWBrowser and four or more instances of QRetailer, each in a separate command window:

java chap5.B2B.QWBrowser localhost WHOLESALER1 password

java chap5.B2B.QRetailer localhost RETAILER1 password
java chap5.B2B.QRetailer localhost RETAILER2 password
java chap5.B2B.QRetailer localhost RETAILER3 password
java chap5.B2B.QRetailer localhost RETAILER3 password

In the command window for the QWBrowser, type the following command:

Surfboards, 999.99, 499.99

When you press Enter, each instance of QRetailer will get the price quote, and respond with a "Buy Order." Each order will request a different quantity. You should see output in the QWBrowser window indicating that it is browsing the queue, placing the order for one of the messages, and placing the rest on back-order status.

The QWBrowser Source Code

The QueueBrowser object is simple to use. We will examine this listing from QWBrowser.examineQueue( ) in detail:

private int examineQueue(int inStockQty)
{
    int cnt = 0;
    int bestQty = 0;
    try  {
        System.out.println("In Stock QTY: " + inStockQty);
        System.out.print ( "Creating QueueBrowser..." );
        javax.jms.QueueBrowser browser 
            = qSession.createBrowser(receiveQueue);
        System.out.println ("[done]");

        java.util.Enumeration e = browser.getEnumeration( );
        while(e.hasMoreElements( )){
            System.out.print(" --> getting message " 
            	+ String.valueOf(++cnt) + "...");
            javax.jms.TextMessage message = 
                (javax.jms.TextMessage) e.nextElement( );
            System.out.println("[" + message.getText( ) + "]");
            if (message != null){
                int orderQty = message.getIntProperty("QTY");
                if ( orderQty > bestQty && orderQty <= inStockQty)
                    bestQty = orderQty;
            }
        }
        // Free any resources in the browser
        browser.close( );
    } catch ( javax.jms.JMSException jmse ){
        jmse.printStackTrace( );
    }
    System.out.println("
BestQty: " + bestQty);
    return bestQty;
}

First, note the call to create the QueueBrowser:

System.out.print ( "Creating QueueBrowser..." );
        javax.jms.QueueBrowser browser
            = qSession.createBrowser(receiveQueue);
        System.out.println ("[done]");

The method createQueueBrowser( ) is a session method. It takes a Queue object as a parameter and returns a QueueBrowser object. The createQueueBrowser( ) method, in additon, allows you to set a message selector using an overloaded method signature.

The QueueBrowser object contains a java.util.Enumeration that holds the messages in the queue. Here's how to use it:

...
java.util.Enumeration e = browser.getEnumeration( );
while(e.hasMoreElements( )){
    javax.jms.TextMessage message = 
        (javax.jms.TextMessage) e.nextElement( );
    System.out.println("[" + message.getText( ) + "]");
...

When the browser has served its purpose, it must be closed. This informs the JMS provider that it is no longer needed, thus allowing the provider to clean up any resources it may have allocated on the browser's behalf:

// Free any resources in the browser
        browser.close( );

Now let's look at the main input loop, which publishes the prices quotes, browses the queue, then uses a synchronous QueueReceiver to consume the messages after it has browsed them:

public void processInput( ){
    try  {
	   ...
        System.out.println ("Enter: Item, Old Price, New Price");
        System.out.println("
e.g. Bowling Shoes, 100.00, 55.00");
        String dealDesc = stdin.readLine( );
	    ...
        publishPriceQuotes(dealDesc,uname,
                    itemDesc, oldPrice,newPrice);

        int inStockQty = 
               (int)(java.lang.Math.random( ) * (double)1000);
        int bestQty = examineQueue(inStockQty);
        qConnect.start( ); // Start the connection
        javax.jms.TextMessage textMessage = null;
        while( true ){
            textMessage = 
                (javax.jms.TextMessage)qReceiver.receive(1000);
            if ( textMessage == null ){
                qConnect.stop( );
                break;  // No more messages to get
            }
            String text = textMessage.getText( );
            int qty = textMessage.getIntProperty("QTY");
            System.out.println("
Order received - "+text+
                " from " + textMessage.getJMSCorrelationID( ));

            if (qty == bestQty){
                System.out.println("Fulfilling order");
                // Do some processing to fulfill order
            } else {
                System.out.println("Placing in BACK-ORDER status");
                // Do some processing to create BACK-ORDER status
            }
        }
	...
}

Messages obtained from a QueueBrowser are copies of messages contained in the queue and are not considered to be consumed—they are merely for browsing.

It is important to note that the QueueBrowser is not guaranteed to have a definitive list of messages in the queue. The JMS specification allows the QueueBrowser to contain a snapshot, or a copy of, the queue as it appears at the time the QueueBrowser is created. The behavior may vary depending on vendor implementation, since the contents of the queue may change between the time the browser is created and the time you examine its contents. No matter how small that window of time is, new messages may arrive and other messages may be consumed by other JMS clients. Some JMS providers will update QueueBrowsers as the status of the queue changes while others will not.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset