Oracle8i Application Developer's Guide - Advanced Queuing
Release 2 (8.1.6)

Part Number A76938-01

Library

Product

Contents

Index

Go to previous page Go to beginning of chapter Go to next page

A Sample Application Using AQ, 4 of 6


ENQUEUE Features

Subscriptions and Recipient Lists

In a single-consumer queue a message can be processed once by only one consumer. What happens when there are multiple processes or operating system threads concurrently dequeuing from the same queue? Given that a locked message cannot be dequeued by a process other than the one which has created the lock, each process will dequeue the first unlocked message that is at the head of the queue. After processing, the message is removed if the retention_time of the queue is 0, or retained for the specified retention time. While the message is retained the message can be either queried using SQL on the queue table view or by dequeuing using the BROWSE mode and specifying the message ID of the processed message.

AQ allows a single message to be processed/consumed by more than one consumer. To use this feature, you must create multi-consumer queues and enqueue the messages into these multi-consumer queues. AQ allows two methods of identifying the list of consumers for a message: subscriptions and recipient lists.

Subscriptions

You can add a subscription to a queue by using the DBMS_AQADM.ADD_SUBSCRIBER PL/SQL procedure (see "Add a Subscriber" in Chapter 9, "Administrative Interface"). This lets you specify a consumer by means of the AQ$_AGENT parameter for enqueued messages. You can add more subscribers by repeatedly using the DBMS_AQADM.ADD_SUBSCRIBER procedure up to a maximum of 1024 subscribers for a multi-consumer queue. (Note that you are limited to 32 subscriber for multi-consumer queue created using Oracle 8.0.3.)

All consumers that are added as subscribers to a multi-consumer queue must have unique values for the AQ$_AGENT parameter. This means that two subscribers cannot have the same values for the NAME, ADDRESS and PROTOCOL attributes for the AQ$_AGENT type. At least one of the three attributes must be different for two subscribers (see "Agent" for formal description of this data structure).

You cannot add subscriptions to single-consumer queues or exception queues. A consumer that is added as a subscriber to a queue will only be able to dequeue messages that are enqueued after the DBMS_AQADM.ADD_SUBSCRIBER procedure is completed. In other words, messages that had been enqueued before this procedure is executed will not be available for dequeue by this consumer.

You can remove a subscription by using the DBMS_AQADM.REMOVE_SUBSCRIBER procedure (see "Remove a Subscriber" in Chapter 9, "Administrative Interface"). AQ will automatically remove from the queue all metadata corresponding to the consumer identified by the AQ$_AGENT parameter. In other words, it is not an error to execute the REMOVE_SUBSCRIBER procedure even when there are pending messages that are available for dequeue by the consumer. These messages will be automatically made unavailable for dequeue after the REMOVE_SUBSCRIBER procedure is executed. In a queue table that is created with the compatible parameter set to '8.1' or higher, such messages that were not dequeued by the consumer will be shown as "UNDELIVERABLE" in the AQ$<queue_table> view. Note that a multi-consumer queue table created without the compatible parameter, or with the compatible parameter set to '8.0', does not display the state of a message on a consumer basis, but only displays the global state of the message.

Recipient Lists

You do not need to specify subscriptions for a multi-consumer queue provided that producers of messages for enqueue supply a recipient list of consumers. In some situations it may be desirable to enqueue a message that is targeted to a specific set of consumers rather than the default list of subscribers. You accomplish this by specifying a recipient list at the time of enqueuing the message.

If a recipient list is specified during enqueue, it overrides the subscription list. In other words, messages that have a specified recipient list will not be available for dequeue by the subscribers of the queue. The consumers specified in the recipient list may or may not be subscribers for the queue. It is an error if the queue does not have any subscribers and the enqueue does not specify a recipient list (see "Enqueue a Message" in Chapter 11, "Operational Interface: Basic Operations").

Priority and Ordering of Messages

The message ordering dictates the order in which messages will be dequeued from a queue. The ordering method for a queue is specified when a queue table is created (see "Create a Queue Table" in Chapter 9, "Administrative Interface"). Currently, AQ supports two types of message ordering:

Example Scenario

In the BooksOnLine application, a customer can request

The Order Entry application uses a FIFO-priority queue to store booked orders. Booked orders are propagated to the regional booked orders queues. At each region, orders in these regional booked orders queues are processed in the order of the shipping priorities.

The following calls create the FIFO-priority queues for the Order Entry application.

PL/SQL (DBMS_AQ/ADM Package): Example Code

/* Create a priority queue table for OE: */ 
EXECUTE dbms_aqadm.create_queue_table( \                        
   queue_table         => 'OE_orders_pr_mqtab', \          
   sort_list           =>'priority,enq_time', \ 
   comment             => 'Order Entry Priority  \
                          MultiConsumer Orders queue table',\ 
   multiple_consumers  => TRUE, \                           
   queue_payload_type  => 'BOLADM.order_typ', \                      
   compatible          => '8.1', \                                  
   primary_instance    => 2, \                                       
   secondary_instance  => 1); 
 
EXECUTE dbms_aqadm.create_queue ( \                                
   queue_name          => 'OE_bookedorders_que', \       
   queue_table         => 'OE_orders_pr_mqtab'); 
 
/* When an order arrives, the order entry application can use the following 
   procedure to enqueue the order into its booked orders queue. A shipping 
   priority is specified for each order: */
CREATE OR REPLACE procedure order_enq(book_title        IN VARCHAR2, 
                                      book_qty          IN NUMBER, 
                                      order_num         IN NUMBER, 
                                      shipping_priority IN NUMBER, 
                                      cust_state        IN VARCHAR2, 
                                      cust_country      IN VARCHAR2, 
                                      cust_region       IN VARCHAR2, 
                                      cust_ord_typ      IN VARCHAR2) AS 
 
OE_enq_order_data        BOLADM.order_typ; 
OE_enq_cust_data         BOLADM.customer_typ; 
OE_enq_book_data         BOLADM.book_typ; 
OE_enq_item_data         BOLADM.orderitem_typ; 
OE_enq_item_list         BOLADM.orderitemlist_vartyp; 
enqopt                   dbms_aq.enqueue_options_t; 
msgprop                  dbms_aq.message_properties_t; 
enq_msgid                RAW(16); 
  
BEGIN 
   msgprop.correlation := cust_ord_typ; 
   OE_enq_cust_data    := BOLADM.customer_typ(NULL, NULL, NULL, NULL, 
                                cust_state, NULL, cust_country); 
   OE_enq_book_data    := BOLADM.book_typ(book_title, NULL, NULL, NULL); 
   OE_enq_item_data    := BOLADM.orderitem_typ(book_qty,  
                                OE_enq_book_data, NULL); 
   OE_enq_item_list    := BOLADM.orderitemlist_vartyp( 
                                BOLADM.orderitem_typ(book_qty,  
                                OE_enq_book_data, NULL)); 
   OE_enq_order_data   := BOLADM.order_typ(order_num, NULL,  
                                cust_ord_typ, cust_region, 
                                OE_enq_cust_data, NULL,  
                                OE_enq_item_list, NULL); 
 
   /*Put the shipping priority into message property before enqueueing 
     the message: */
   msgprop.priority    := shipping_priority; 
   dbms_aq.enqueue('OE.OE_bookedorders_que', enqopt, msgprop,  
                        OE_enq_order_data, enq_msgid); 
        COMMIT; 
  END; 
  / 
 
 
/* At each region, similar booked order queues are created. The orders are    
   propagated from the central Order Entry's booked order queues to the regional 
   booked order queues.For example, at the western region, the booked orders   
   queue is created. 
   Create a priority queue table for WS shipping: */
EXECUTE dbms_aqadm.create_queue_table( \                       
   queue_table        =>  'WS_orders_pr_mqtab',           
   sort_list          =>'  priority,enq_time',  \
   comment            =>  'West Shipping Priority  \
                           MultiConsumer Orders queue table',\ 
   multiple_consumers => TRUE, \                           
   queue_payload_type => 'BOLADM.order_typ', \                     
   compatible         => '8.1'); 
 
/* Booked orders are stored in the priority queue table: */ 
EXECUTE dbms_aqadm.create_queue ( \                                 
   queue_name         => 'WS_bookedorders_que', \        
   queue_table        => 'WS_orders_pr_mqtab'); 
 
/* At each region, the shipping application dequeues orders from the regional 
   booked order queue according to the orders' shipping priorities, processes 
   the orders, and enqueues the processed orders into the shipped orders queues 
   or the back orders queues. */

Visual Basic (OO4O): Example Code

Dim OraSession as object
Dim OraDatabase as object
Dim OraAq as object
Dim OraMsg as Object
Dim OraOrder,OraCust,OraBook,OraItem,OraItemList as Object
Dim Msgid as String

   Set OraSession = CreateObject("OracleInProcServer.XOraSession")
   Set OraDatabase = OraSession.DbOpenDatabase("dbname", "user/pwd", 0&)
   set oraaq = OraDatabase.CreateAQ("OE.OE_bookedorders_que")
   Set OraMsg = OraAq.AQMsg(ORATYPE_OBJECT, "BOLADM.order_typ")
   Set OraOrder = OraDatabase.CreateOraObject("BOLADM.order_typ")
   Set OraCust = OraDatabase.CreateOraObject("BOLADM.Customer_typ")
   Set OraBook = OraDatabase.CreateOraObject("BOLADM.book_typ")
   Set OraItem = OraDatabase.CreateOraObject("BOLADM.orderitem_typ")
   Set OraItemList = OraDatabase.CreateOraObject("BOLADM.orderitemlist_vartyp")

   ' Get the values of cust_state,cust_country etc from user(form_based
   ' input) and then a cmd_click event for Enqueue  
   ' will execute the subroutine order_enq.
   Private Sub Order_enq()
   
   OraMsg.correlation = txt_correlation
   'Initialize the customer details 
        OraCust("state") = txt_cust_state
   OraCust("country") = txt_cust_country
        OraBook("title") = txt_book_title
   OraItem("quantity") = txt_book_qty
   OraItem("item") = OraBook
   OraItemList(1) = OraItem
   OraOrder("orderno") = txt_order_num
   OraOrder("ordertype") = txt_cust_order_typ
   OraOrder("orderregion") = cust_region
   OraOrder("customer") = OraCust
   OraOrder("items") = OraItemList
        
   'Put the shipping priority into message property before enqueueing 
   '  the message: 
   OraMsg.priority = priority
   OraMsg = OraOrder
   Msgid = OraAq.enqueue

   'Release all allocations 
   End Sub

Java (JDBC): Example Code

public static void createPriorityQueueTable(Connection db_conn)
{
    AQSession            aq_sess;
    AQQueueTableProperty mqt_prop;
    AQQueueTable         pr_mq_table;   
    AQQueueProperty      q_prop;
    AQQueue              bookedorders_q;        

    try
    {

        /* Create an AQ Session: */
        aq_sess = AQDriverManager.createAQSession(db_conn);


        /* Create a priority queue table for OE */
        mqt_prop = new AQQueueTableProperty("BOLADM.order_typ");
        mqt_prop.setComment("Order Entry Priority " + 
                            "MultiConsumer Orders queue table");
        mqt_prop.setCompatible("8.1");
        mqt_prop.setMultiConsumer(true);

        mqt_prop.setSortOrder("priority,enq_time");

        pr_mq_table = aq_sess.createQueueTable("OE", "OE_orders_pr_mqtab", 
                                            mqt_prop);
     
        /* Create a Queue in this queue table */
        q_prop = new AQQueueProperty();
        
        bookedorders_q = aq_sess.createQueue(pr_mq_table, 
                                             "OE_bookedorders_que", q_prop);
        
        /* Enable enqueue and dequeue on the queue */
        bookedorders_q.start(true, true);
  
    }
    catch (AQException ex)
    {
        System.out.println("AQ Exception: " + ex); 
    }
}

 
/* When an order arrives, the order entry application can use the following 
   procedure to enqueue the order into its booked orders queue. A shipping 
   priority is specified for each order 
 */
public static void order_enqueue(Connection db_conn, String book_title,
                                 double book_qty, double order_num, 
                                 int ship_priority, String cust_state,
                                 String cust_country, String cust_region,
                                 String cust_order_type)
{
    AQSession         aq_sess;
    AQQueue           bookedorders_q;   
    Order             enq_order;
    Customer          cust_data;
    Book              book_data;
    OrderItem         item_data;
    OrderItem[]       items;
    OrderItemList     item_list;
    AQEnqueueOption   enq_option;
    AQMessageProperty m_property;
    AQMessage         message;
    AQObjectPayload   obj_payload;
    byte[]            enq_msg_id;

    try
    {

        /* Create an AQ Session: */
        aq_sess = AQDriverManager.createAQSession(db_conn);

        cust_data = new Customer();
        cust_data.setCountry(cust_country);
        cust_data.setState(cust_state);
  
        book_data = new Book();
        book_data.setTitle(book_title);

        item_data = new OrderItem();
        item_data.setQuantity(new BigDecimal(book_qty));
        item_data.setItem(book_data);

        items = new OrderItem[1];
        items[0] = item_data;

        item_list = new OrderItemList(items);

        enq_order = new Order();
        enq_order.setCustomer(cust_data);
        enq_order.setItems(item_list);
        enq_order.setOrderno(new BigDecimal(order_num));
        enq_order.setOrdertype(cust_order_type);

        bookedorders_q = aq_sess.getQueue("OE", "OE_bookedorders_que");
  
        message = bookedorders_q.createMessage();

        /* Put the shipping priority into message property before enqueuing */ 
        m_property = message.getMessageProperty();

        m_property.setPriority(ship_priority);

        obj_payload = message.getObjectPayload();

        obj_payload.setPayloadData(enq_order);

        enq_option = new AQEnqueueOption();

        /* Enqueue the message */
        enq_msg_id = bookedorders_q.enqueue(enq_option, message);

        db_conn.commit();

    }
    catch (AQException aq_ex)
    {
        System.out.println("AQ Exception: " + aq_ex); 
    }
    catch (SQLException sql_ex)
    {
        System.out.println("SQL Exception: " + sql_ex); 
    }

}


 
/* At each region, similar booked order queues are created. The orders are    
   propagated from the central Order Entry's booked order queues to the 
   regional booked order queues.
   For example, at the western region, the booked orders queue is created. 
   Create a priority queue table for WS shipping
 */
public static void createWesternShippingQueueTable(Connection db_conn)
{
    AQSession            aq_sess;
    AQQueueTableProperty mqt_prop;
    AQQueueTable         mq_table;      
    AQQueueProperty      q_prop;
    AQQueue              bookedorders_q;        

    try
    {

        /* Create an AQ Session: */
        aq_sess = AQDriverManager.createAQSession(db_conn);


        /* Create a priority queue table for WS */
        mqt_prop = new AQQueueTableProperty("BOLADM.order_typ");
        mqt_prop.setComment("Western Shipping Priority " + 
                            "MultiConsumer Orders queue table");
        mqt_prop.setCompatible("8.1");
        mqt_prop.setMultiConsumer(true);
        mqt_prop.setSortOrder("priority,enq_time");

        mq_table = aq_sess.createQueueTable("WS", "WS_orders_pr_mqtab", 
                                            mqt_prop);

        /* Booked orders are stored in the priority queue table: */      
        q_prop = new AQQueueProperty();

        bookedorders_q = aq_sess.createQueue(mq_table, "WS_bookedorders_que", 
                                             q_prop);

        /* Start the queue */
        bookedorders_q.start(true, true);
  
    }
    catch (AQException ex)
    {
        System.out.println("AQ Exception: " + ex); 
    }

  /* At each region, the shipping application dequeues orders from the 
     regional booked order queue according to the orders' shipping priorities,
     processes the orders, and enqueues the processed orders into the shipped 
     orders queues or the back orders queues. 
   */
}


Time Specification: Delay

AQ supports delay delivery of messages by letting the enqueuer specify a delay interval on a message when enqueueing the message, that is, the time before which a message cannot be retrieved by a dequeue call. (see "Enqueue a Message [Specify Message Properties]" in Chapter 11, "Operational Interface: Basic Operations"). The delay interval determines when an enqueued message is marked as available to the dequeuers after message is enqueued. The producer can also specify the time when a message expires, at which time the message is moved to an exception queue.

When a message is enqueued with a delay time set, the message is marked as in WAIT state. Messages in WAIT state are masked from the default dequeue calls.

A background time-manager daemon wakes up periodically, scans an internal index for all WAIT state messages, and marks messages as READY if their delay time has passed. The time-manager will then post to all foreground processes that are waiting on queues in which messages have just been made available.

Example Scenario

In the BooksOnLine application, delay can be used to implement deferred billing. A billing application can define a queue in which shipped orders that are not billed immediately can be placed in a deferred billing queue with a delay. For example, a certain class of customer accounts, such as those of corporate customers, may not be billed for 15 days. The billing application dequeues incoming shipped order messages (from the shippedorders queue) and if the order is for a corporate customer, this order is enqueued into a deferred billing queue with a delay.

PL/SQL (DBMS_AQ/ADM Package): Example Code

/* Enqueue an order to implement deferred billing so that the order is not made 
   visible again until delay has expired: */
CREATE OR REPLACE PROCEDURE defer_billing(deferred_billing_order order_typ) 
AS 
  defer_bill_queue_name    VARCHAR2(62); 
  enqopt                   dbms_aq.enqueue_options_t; 
  msgprop                  dbms_aq.message_properties_t; 
  enq_msgid                RAW(16); 
BEGIN 
 
/* Enqueue the order into the deferred billing queue with a delay of 15 days: */ 
  defer_bill_queue_name := 'CBADM.deferbilling_que'; 
  msgprop.delay := 15*60*60*24; 
  dbms_aq.enqueue(defer_bill_queue_name, enqopt, msgprop,  
                  deferred_billing_order, enq_msgid); 
END; 
/ 

Visual Basic (OO4O): Example Code

   set oraaq = OraDatabase.CreateAQ("CBADM.deferbilling_que")
   Set OraMsg = OraAq.AQMsg(ORATYPE_OBJECT, "BOLADM.order_typ")
   Set OraOrder = OraDatabase.CreateOraObject("BOLADM.order_typ")
   
   Private Sub defer_billing
   
   OraMsg = OraOrder
   OraMsg.delay = 15*60*60*24
   OraMsg = OraOrder 'OraOrder contains the order details
   Msgid = OraAq.enqueue

   End Sub

Java (JDBC): Example Code

public static void defer_billing(Connection db_conn, Order deferred_order)
{
    AQSession         aq_sess;
    AQQueue           def_bill_q;       
    AQEnqueueOption   enq_option;
    AQMessageProperty m_property;
    AQMessage         message;
    AQObjectPayload   obj_payload;
    byte[]            enq_msg_id;

    try
    {
        /* Create an AQ Session: */
        aq_sess = AQDriverManager.createAQSession(db_conn);

        def_bill_q = aq_sess.getQueue("CBADM", "deferbilling_que");

        message = def_bill_q.createMessage();

        /* Enqueue the order into the deferred billing queue with a delay 
           of 15 days */ 
        m_property = message.getMessageProperty();
        m_property.setDelay(15*60*60*24);

        obj_payload = message.getObjectPayload();
        obj_payload.setPayloadData(deferred_order);

        enq_option = new AQEnqueueOption();

        /* Enqueue the message */
        enq_msg_id = def_bill_q.enqueue(enq_option, message);
        
        db_conn.commit();
    }
    catch (Exception ex)
    {
        System.out.println("Exception " + ex);
    }
    
}

Time Specification: Expiration

Messages can be enqueued with an expiration which specifies the interval of time the message is available for dequeuing. Note that expiration processing requires that the queue monitor be running.

Example Scenario

In the BooksOnLine application, expiration can be used to control the amount of time that is allowed to process a back order. The shipping application places orders for books that are not available on a back order queue. If the shipping policy is that all back orders must be shipped within a week, then messages can be enqueued into the back order queue with an expiration of 1 week. In this case, any back orders that are not processed within one week are moved to the exception queue with the message state set to EXPIRED. This can be used to flag any orders that have not been shipped according to the back order shipping policy.

PL/SQL (DBMS_AQ/ADM Package): Example Code

CONNECT BOLADM/BOLADM 
/* Req-enqueue a back order into a back order queue and set a delay of 7 days; 
   all back orders must be processed in 7 days or they are moved to the 
   exception queue: */ 
CREATE OR REPLACE PROCEDURE requeue_back_order(sale_region varchar2,  
                                               backorder order_typ) 
AS 
  back_order_queue_name    VARCHAR2(62); 
  enqopt                   dbms_aq.enqueue_options_t; 
  msgprop                  dbms_aq.message_properties_t; 
  enq_msgid                RAW(16); 
BEGIN 
  /* Look up a back order queue based the the region by means of a directory 
     service: */
  IF sale_region = 'WEST' THEN 
    back_order_queue_name := 'WS.WS_backorders_que';  
  ELSIF sale_region = 'EAST' THEN 
    back_order_queue_name := 'ES.ES_backorders_que';  
  ELSE 
    back_order_queue_name := 'OS.OS_backorders_que';  
  END IF; 
 
  /* Enqueue the order with expiration set to 7 days: */ 
  msgprop.expiration := 7*60*60*24; 
  dbms_aq.enqueue(back_order_queue_name, enqopt, msgprop,  
                  backorder, enq_msgid); 
END; 
/ 
 

Visual Basic (OO4O): Example Code

   set oraaq1 = OraDatabase.CreateAQ("WS.WS_backorders_que")
   set oraaq2 = OraDatabase.CreateAQ("ES.ES_backorders_que")
   set oraaq3 = OraDatabase.CreateAQ("CBADM.deferbilling_que")
   Set OraMsg = OraAq.AQMsg(ORATYPE_OBJECT, "BOLADM.order_typ")
   Set OraBackOrder = OraDatabase.CreateOraObject("BOLADM.order_typ")

Private Sub Requeue_backorder
   Dim q as oraobject
   If sale_region = WEST then
      q = oraaq1
   else if sale_region = EAST then
      q = oraaq2
   else 
      q = oraaq3
   end if

   OraMsg.delay = 7*60*60*24
   OraMsg = OraBackOrder 'OraOrder contains the order details
   Msgid = q.enqueue

End Sub

Java (JDBC): Example Code

/* Re-enqueue a back order into a back order queue and set a delay of 7 days; 
   all back orders must be processed in 7 days or they are moved to the 
   exception queue */ 
public static void requeue_back_order(Connection db_conn, 
                                      String sale_region, Order back_order)
{
    AQSession         aq_sess;
    AQQueue           back_order_q;     
    AQEnqueueOption   enq_option;
    AQMessageProperty m_property;
    AQMessage         message;
    AQObjectPayload   obj_payload;
    byte[]            enq_msg_id;

    try
    {
        /* Create an AQ Session: */
        aq_sess = AQDriverManager.createAQSession(db_conn);

        /* Look up a back order queue based on the region */
        if(sale_region.equals("WEST"))
        {
            back_order_q = aq_sess.getQueue("WS", "WS_backorders_que");
        }
        else if(sale_region.equals("EAST"))
        {
            back_order_q = aq_sess.getQueue("ES", "ES_backorders_que");
        }
        else
        {
            back_order_q = aq_sess.getQueue("OS", "OS_backorders_que");
        }

        message = back_order_q.createMessage();

        m_property = message.getMessageProperty();

        /* Enqueue the order with expiration set to 7 days: */ 
        m_property.setExpiration(7*60*60*24);

        obj_payload = message.getObjectPayload();
        obj_payload.setPayloadData(back_order);

        enq_option = new AQEnqueueOption();

        /* Enqueue the message */
        enq_msg_id = back_order_q.enqueue(enq_option, message);

        db_conn.commit();
    }
    catch (Exception ex)
    {
        System.out.println("Exception :" + ex); 
    }
}

Message Grouping

Messages belonging to one queue can be grouped to form a set that can only be consumed by one user at a time. This requires the queue be created in a queue table that is enabled for transactional message grouping (see "Create a Queue Table" in Chapter 9, "Administrative Interface"). All messages belonging to a group have to be created in the same transaction and all messages created in one transaction belong to the same group. This feature allows you to segment complex messages into simple messages.

For example, messages directed to a queue containing invoices could be constructed as a group of messages starting with the header message, followed by messages representing details, followed by the trailer message. Message grouping is also very useful if the message payload contains complex large objects such as images and video that can be segmented into smaller objects.

The general message properties (priority, delay, expiration) for the messages in a group are determined solely by the message properties specified for the first message (head) of the group irrespective of which properties are specified for subsequent messages in the group.

The message grouping property is preserved across propagation. However, it is important to note that the destination queue to which messages have to be propagated must also be enabled for transactional grouping. There are also some restrictions you need to keep in mind if the message grouping property is to be preserved while dequeuing messages from a queue enabled for transactional grouping (see "Dequeue Methods" and "Modes of Dequeuing" for additional information).

Example Scenario

In the BooksOnLine application, message grouping can be used to handle new orders. Each order contains a number of books ordered one by one in succession. Items ordered over the Web exhibit similar behavior.

In the example given below, each enqueue corresponds to an individual book that is part of an order and the group/transaction represents a complete order. Only the first enqueue contains customer information. Note that the OE_neworders_que is stored in the table OE_orders_sqtab which has been enabled for transactional grouping. Refer to the example code for descriptions of procedures new_order_enq() and same_order_enq().

PL/SQL (DBMS_AQ/ADM Package): Example Code

connect OE/OE; 
 
/* Create queue table for OE:  */
EXECUTE dbms_aqadm.create_queue_table( \
        queue_table        => 'OE_orders_sqtab',\
        comment            => 'Order Entry Single-Consumer Orders queue table',\
        queue_payload_type => 'BOLADM.order_typ',\
        message_grouping   => DBMS_AQADM.TRANSACTIONAL, \
        compatible         => '8.1',  \
        primary_instance   => 1,\
        secondary_instance => 2); 
 
/* Create neworders queue for OE: */ 
EXECUTE dbms_aqadm.create_queue ( \
        queue_name         => 'OE_neworders_que', 
        queue_table        => 'OE_orders_sqtab'); 
 
/* Login into OE account :*/
CONNECT OE/OE; 
SET serveroutput on; 
/* Enqueue some orders using message grouping into OE_neworders_que,
   First Order Group: */
EXECUTE BOLADM.new_order_enq('My First   Book', 1, 1001, 'CA'); 
EXECUTE BOLADM.same_order_enq('My Second  Book', 2); 
COMMIT; 
/ 
/* Second Order Group: */ 
EXECUTE BOLADM.new_order_enq('My Third   Book', 1, 1002, 'WA'); 
COMMIT; 
/ 
/* Third Order Group: */ 
EXECUTE BOLADM.new_order_enq('My Fourth  Book', 1, 1003, 'NV'); 
EXECUTE BOLADM.same_order_enq('My Fifth   Book', 3); 
EXECUTE BOLADM.same_order_enq('My Sixth   Book', 2); 
COMMIT; 
/ 
/* Fourth Order Group: */
EXECUTE BOLADM.new_order_enq('My Seventh Book', 1, 1004, 'MA'); 
EXECUTE BOLADM.same_order_enq('My Eighth  Book', 3); 
EXECUTE BOLADM.same_order_enq('My Ninth   Book', 2); 
COMMIT; 
/

Visual Basic (OO4O): Example Code

This functionality is currently not available.

Java (JDBC): Example Code

public static void createMsgGroupQueueTable(Connection db_conn)
{
    AQSession            aq_sess;
    AQQueueTableProperty sqt_prop;
    AQQueueTable         sq_table;      
    AQQueueProperty      q_prop;
    AQQueue              neworders_q;   

    try
    {

        /* Create an AQ Session: */
        aq_sess = AQDriverManager.createAQSession(db_conn);

        /* Create a single-consumer orders queue table */
        sqt_prop = new AQQueueTableProperty("BOLADM.order_typ");
        sqt_prop.setComment("Order Entry Single-Consumer Orders queue table");
        sqt_prop.setCompatible("8.1");
        sqt_prop.setMessageGrouping(AQQueueTableProperty.TRANSACTIONAL);

        sq_table = aq_sess.createQueueTable("OE", "OE_orders_sqtab", sqt_prop);

    
        /* Create new orders queue for OE */
        q_prop = new AQQueueProperty();

        neworders_q = aq_sess.createQueue(sq_table, "OE_neworders_que", 
                                          q_prop);
          
    }
    catch (AQException ex)
    {
        System.out.println("AQ Exception: " + ex); 
    }
}


Go to previous page Go to beginning of chapter Go to next page
Oracle
Copyright © 1996-2000, Oracle Corporation.

All Rights Reserved.

Library

Product

Contents

Index