Skip Headers

Oracle9i Application Developer's Guide - Advanced Queuing
Release 2 (9.2)

Part Number A96587-01
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback

Go to previous page Go to next page

17
Internet Access to Advanced Queuing

You can access AQ over the Internet by using Simple Object Access Protocol (SOAP). Internet Data Access Presentation (IDAP) is the SOAP specification for AQ operations. IDAP defines XML message structure for the body of the SOAP request. An IDAP-structured message is transmitted over the Internet using transport protocols such as HTTP or SMTP.

This chapter discusses the following topics:

Overview of Advanced Queuing Operations Over the Internet

Figure 17-1 shows the architecture for performing AQ operations over HTTP. The major components are:

The AQ client program sends XML messages (conforming to IDAP) to the AQ servlet. Any HTTP client, for example Web browsers, can be used. The Web server/ServletRunner hosting the AQ servlet interprets the incoming XML messages. Examples include Apache/Jserv or Tomcat. The AQ servlet connects to the Oracle database server and performs operations on the users' queues.

Figure 17-1 Architecture for Performing AQ Operations Using HTTP

Text description of adque430.gif follows
Text description of the illustration adque430.gif


See "Using HTTP to Access the AQ XML Servlet" and "Using HTTP and HTTPS for Advanced Queuing Propagation" for details.

Figure 17-2 shows additional components in the architecture for sending AQ messages over SMTP:

The e-mail server verifies client signatures using certificates stored in LDAP and then routes the request to the AQ servlet.

Figure 17-2 Architecture for Performing AQ Operations Using SMTP

Text description of adque431.gif follows
Text description of the illustration adque431.gif


See "Using SMTP to Access the AQ Servlet" for more details.

The Internet Data Access Presentation (IDAP)

The Internet Data Access Presentation (IDAP) uses the Content-Type of text/xml to specify the body of the SOAP request. XML provides the presentation for IDAP request and response messages as follows:

SOAP Message Structure

SOAP structures a message request or response as follows:

The SOAP Envelope

The tag of this root element is SOAP:Envelope. SOAP defines a global attribute SOAP:encodingStyle that indicates serialization rules used instead of those described by the SOAP specification. This attribute may appear on any element and is scoped to that element and all child elements not themselves containing such an attribute. Omitting SOAP:encodingStyle means that type specification has been followed (unless overridden by a parent element).

The SOAP envelope also contains namespace declarations and additional attributes, provided they are namespace qualified. Additional namespace-qualified subelements can follow the body.

SOAP Headers

The tag of this first element under the root is SOAP:Header. A SOAP header passes necessary information, such as the transaction ID, with the request. The header is encoded as a child of the SOAP:Envelope XML element. Headers are identified by the name element and are namespace-qualified. A header entry is encoded as an embedded element.

The SOAP Body

The SOAP body, tagged SOAP:Body, contains a first subelement whose name is the method name. This method request element contains elements for each input and output parameter. The element names are the parameter names. The body also contains SOAP:Fault, indicating information about an error.

For performing AQ operations, the SOAP body must contain an AQ XML document. The AQ XML document has the namespace http://ns.oracle.com/AQ/schemas/access

SOAP Method Invocation

A method invocation is performed by creating the request header and body and processing the returned response header and body. The request and response headers can consist of standard transport protocol-specific and extended headers.

In the case of SMTP (e-mail), the method invocation can be done by the filter interface of the e-mail server, which invokes a Java method with the e-mail-message-body as argument. This results in remote invocation of the POST method on the AQ servlet. The response is e-mailed directly to the recipient specified in the reply of the message. The response header can contain SMTP-protocol-related headers also.

HTTP Headers

The POST method within the HTTP request header performs the SOAP method invocation. The request should include the header SOAPMethodName, whose value indicates the method to be invoked on the target. The value consists of a URI followed by a "#", followed by a method name (which must not include the "#" character), as follows:

SOAPMethodName: http://ns.oracle.com/AQ/schemas/access#AQXmlSend

The URI used for the interface must match the implied or specified namespace qualification of the method name element in the SOAP:Body part of the payload.

Method Invocation Body

SOAP method invocation consists of a method request and optionally a method response. The SOAP method request and method response are an HTTP request and response, respectively, whose content is an XML document that consists of the root and mandatory body elements. This XML document is referred to as the SOAP payload in the rest of this chapter.

The SOAP payload is defined as follows:

At the receiving site, a request can have one of the following outcomes:

  1. The HTTP infrastructure on the receiving site is able to receive and process the request.
  2. The HTTP infrastructure on the receiving site cannot receive and process the request.
  3. The SOAP infrastructure on the receiving site is able to decode the input parameters, dispatch to an appropriate server indicated by the server address, and invoke an application-level function corresponding semantically to the method indicated in the method request.
  4. The SOAP infrastructure on the receiving site cannot decode the input parameters, dispatch to an appropriate server indicated by the server address, and invoke an application-level function corresponding semantically to the interface or method indicated in the method request.

In (a), the HTTP infrastructure passes the headers and body to the SOAP infrastructure. In (b), the result is an HTTP response containing an HTTP error in the status field and no XML body. In (c), the result of the method request consists of a response or error. In (d), the result of the method is an error that prevented the dispatching infrastructure on the receiving side from successful completion. In (c) and (d), additional message headers may for extensibility again be present in the results of the request.

Results from a Method Request

The results of the request are to be provided in the form of a request-response. The HTTP response must be of Content-Type text/xml. A SOAP result indicates success and an error indicates failure. The method response will never contain both a result and an error.

IDAP Documents

The body of a SOAP message is an IDAP message. This XML document has the namespace http://ns.oracle.com/AQ/schemas/access. This body represents:

Client Requests for Enqueue

Client requests for enqueue--SEND and PUBLISH requests--use the following methods:

AQXmlSend and AQXmlPublish take the arguments and argument attributes shown in Table 17-1. Required arguments are shown in bold.

Table 17-1 Client Requests for Enqueue--Arguments and Attributes for AQXmlSend and AQXmlPublish
Argument Attribute

producer_options

destination--specify the queue/topic to which messages are to be sent. The destination element has an attribute lookup_type which determines how the destination element value is interpreted

  • DATABASE (default)--destination is interpreted as schema.queue_name
  • LDAP--the LDAP server is used to resolve the destination

-

visibility

  • ON_COMMIT--The enqueue is part of the current transaction. The operation is complete when the transaction commits. This is the default case.
  • IMMEDIATE--effects of the enqueue are visible immediately after the request is completed. The enqueue is not part of the current transaction. The operation constitutes a transaction on its own.

-

transformation--the PL/SQL transformation to be invoked before the message is enqueued

message_set--contains one or more messages.

Each message consists of a message_header and message_payload

  • message_header

message_id--unique identifier of the message, supplied during dequeue

-

correlation--correlation identifier of the message

-

expiration--duration in seconds that a message is available for dequeuing. This parameter is an offset from the delay. By default messages never expire.

If the message is not dequeued before it expires, then it is moved to the exception queue in the EXPIRED state

-

delay--duration in seconds after which a message is available for processing

-

priority--the priority of the message. A smaller number indicates higher priority. The priority can be any number, including negative numbers.

-

sender_id--the application-specified identifier

  • agent_name, address, protocol
  • agent_alias--if specified, resolves to a name, address, protocol using LDAP

-

recipient_list--list of recipients; overrides the default subscriber list. Each recipient consists of:

  • agent_name, address, protocol
  • agent_alias--if specified, resolves to a name, address, protocol using LDAP

-

message_state-- state of the message is filled in automatically during dequeue

0: The message is ready to be processed.

1: The message delay has not yet been reached.

2: The message has been processed and is retained.

3: The message has been moved to the exception queue.

-

exception_queue--in case of exceptions the name of the queue to which the message is moved if it cannot be processed successfully. Messages are moved in two cases: The number of unsuccessful dequeue attempts has exceeded max_retries or the message has expired. All messages in the exception queue are in the EXPIRED state.

The default is the exception queue associated with the queue table. If the exception queue specified does not exist at the time of the move, then the message is moved to the default exception queue associated with the queue table, and a warning is logged in the alert file. If the default exception queue is used, then the parameter returns a NULL value at dequeue time.

  • message_payload

this can have different sub-elements based on the payload type of the destination queue/topic. The different payload types are described in the next section

AQXmlCommit

this is an empty element--if specified, the user transaction is committed at the end of the request

Message Payloads

AQ supports messages of the following types:

All these types of queues can be accessed using SOAP. If the queue holds messages in RAW, Oracle object, or JMS format, XML payloads are transformed to the appropriate internal format during enqueue and stored in the queue. During dequeue, when messages are obtained from queues containing messages in any of the preceding formats, they are converted to XML before being sent to the client.

The message payload type depends on the type of the queue on which the operation is being performed. A discussion of the queue types follows:

RAW Queues

The contents of RAW queues are raw bytes. The user must supply the hex representation of the message payload in the XML message. For example, <raw>023f4523</raw>.

Oracle object (ADT) type queues

For ADT queues that are not JMS queues (that is, they are not type AQ$_JMS_*), the type of the payload depends on the type specified while creating the queue table that holds the queue. The XML specified here must map to the SQL type of the payload for the queue table.

See Also:

Oracle9i XML Database Developer's Guide - Oracle XML DB for details on mapping SQL types to XML

Example

Assume the queue is defined to be of type EMP_TYP, which has the following structure:

create or replace type emp_typ as object (
     empno NUMBER(4),
     ename VARCHAR2(10),
     job VARCHAR2(9),
     mgr NUMBER(4),
     hiredate DATE,
     sal   NUMBER(7,2),
     comm  NUMBER(7,2)
     deptno NUMBER(2));

The corresponding XML representation is:

              <EMP_TYP>
                 <EMPNO>1111</EMPNO>
                 <ENAME>Mary</ENAME>
                 <MGR>5000</MGR>
                 <HIREDATE>1996-01-01 0:0:0</HIREDATE>
                <SAL>10000</SAL>
                <COMM>100.12</COMM>
                 <DEPTNO>60</DEPTNO>
               </EMP_TYP>
JMS Type Queues/Topics

For queues with JMS types (that is, those with payloads of type AQ$_JMS_*), there are four different XML elements, depending on the JMS type. IDAP supports queues/topics with the following JMS types: TextMessage, MapMessage, BytesMessage and ObjectMessage. JMS queues with payload type StreamMessage are not supported through IDAP.

The JMS types and XML components are shown in Table 17-2. The distinct XML element for each JMS type is shown in its respective column.

Table 17-2 JMS Types and XML Components: Payload Types Used for Queues/Topics
AQ$_JMS_TEXT_MESSAGE AQ$_JMS_MAP_MESSAGE AQ$_JMS_BYTES_MESSAGE AQ$_JMS_OBJECT_MESSAGE
jms_text_message jms_map_message jms_bytes_message jms_object_message

oracle_jms_properties

oracle_jms_properties

oracle_jms_properties

oracle_jms_properties

user_properties

user_properties

user_properties

user_properties

text_data--string representing the text payload

map_data--set of name-value pairs called items, consisting of:

  • name
  • int_value or

    string_value or

    long_value or

    double_value or

    boolean_value or

    float_value or

    short_value or

    byte_value

bytes_data--hex representation of the payload bytes

ser_object_data--hex representation of the serialized object

Required elements are shown in bold in Table 17-2.

All JMS messages consist of the following common elements:

The following examples show enqueue requests using the different message and queue types.

Enqueue Request Example--Sending an ADT Message to a Single-Consumer Queue

The queue QS.NEW_ORDER_QUE has a payload of type ORDER_TYP.

 <?xml version="1.0"?>
   <Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">
      <Body>
        <AQXmlSend xmlns = "http://ns.oracle.com/AQ/schemas/access">
          <producer_options>
            <destination>QS.NEW_ORDERS_QUE</destination>
          </producer_options>
          
          <message_set>
            <message_count>1</message_count>   
          
            <message>
              <message_number>1</message_number>
          
              <message_header>
                <correlation>ORDER1</correlation>
                   <sender_id>
                   <agent_name>scott</agent_name>
                 </sender_id> 
              </message_header>
          
              <message_payload>  

               <ORDER_TYP>
                     <ORDERNO>100</ORDERNO>
                     <STATUS>NEW</STATUS>
                     <ORDERTYPE>URGENT</ORDERTYPE>
                     <ORDERREGION>EAST</ORDERREGION>
                     <CUSTOMER>
                        <CUSTNO>1001233</CUSTNO>
                        <CUSTID>MA1234555623212</CUSTID>
                        <NAME>AMERICAN EXPRESS</NAME>
                        <STREET>EXPRESS STREET</STREET>
                        <CITY>REDWOOD CITY</CITY>
                        <STATE>CA</STATE>
                        <ZIP>94065</ZIP>
                        <COUNTRY>USA</COUNTRY>
                     </CUSTOMER>
                     <PAYMENTMETHOD>CREDIT</PAYMENTMETHOD>
                     <ITEMS>
                        <ITEMS_ITEM>
                           <QUANTITY>10</QUANTITY>
                           <ITEM>
                              <TITLE>Perl</TITLE>
                              <AUTHORS>Randal</AUTHORS>
                              <ISBN>ISBN20200</ISBN>
                              <PRICE>19</PRICE>
                           </ITEM>
                           <SUBTOTAL>190</SUBTOTAL>
                        </ITEMS_ITEM>
                        <ITEMS_ITEM>
                           <QUANTITY>20</QUANTITY>
                           <ITEM>
                              <TITLE>XML</TITLE>
                              <AUTHORS>Micheal</AUTHORS>
                              <ISBN>ISBN20212</ISBN>
                              <PRICE>59</PRICE>
                           </ITEM>
                           <SUBTOTAL>590</SUBTOTAL>
                        </ITEMS_ITEM>
                     </ITEMS>
                     <CCNUMBER>NUMBER01</CCNUMBER>
                     <ORDER_DATE>2000-08-23 0:0:0</ORDER_DATE>
               </ORDER_TYP>
             </message_payload>
            </message>
          </message_set>
        </AQXmlSend>  
      </Body>
</Envelope> 

Enqueue Request Example--Publishing an ADT Message to a Multiconsumer Queue

The multiconsumer queue AQUSER.EMP_TOPIC has a payload of type EMP_TYP. EMP_TYP has the following structure:

 create or replace type emp_typ as object (
     empno NUMBER(4),
     ename VARCHAR2(10),
     job VARCHAR2(9),
     mgr NUMBER(4),
     hiredate DATE,
     sal   NUMBER(7,2),
     comm  NUMBER(7,2)
     deptno NUMBER(2));


 

A PUBLISH request has the following format:

<?xml version="1.0"?>   
<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">

      <Body>
        <AQXmlPublish xmlns = "http://ns.oracle.com/AQ/schemas/access">
          <producer_options>
            <destination>AQUSER.EMP_TOPIC</destination>
          </producer_options>
          


          <message_set>
            <message_count>1</message_count>   
          
            <message>
              <message_number>1</message_number>
          
              <message_header>
                 <correlation>NEWEMP</correlation>
                  <sender_id>
                     <agent_name>scott</agent_name>
                  </sender_id> 
              </message_header>
          
              <message_payload>  
               <EMP_TYP>
                 <EMPNO>1111</EMPNO>
                 <ENAME>Mary</ENAME>
                 <MGR>5000</MGR>
                 <HIREDATE>1996-01-01 0:0:0</HIREDATE>
                <SAL>10000</SAL>
                <COMM>100.12</COMM>
                 <DEPTNO>60</DEPTNO>
               </EMP_TYP>
             </message_payload>
            </message>
          </message_set>
        </AQXmlPublish>  
      </Body>
</Envelope> 

Enqueue Request Example--Sending a Message to a JMS Queue

The JMS queue AQUSER.JMS_TEXTQ has payload type JMS Text message (SYS.AQ$_JMS_TEXT_MESSAGE). The send request has the following format:

<?xml version="1.0"?>
<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">
      <Body>
      
        <AQXmlSend xmlns = "http://ns.oracle.com/AQ/schemas/access">
          <producer_options>
            <destination>AQUSER.JMS_TEXTQ</destination>
          </producer_options>
          
          <message_set>
            <message_count>1</message_count>   
          
            <message>
              <message_number>1</message_number>
          
              <message_header>
                <correlation>text_msg</correlation>
                   <sender_id>
                       <agent_name>john</agent_name>
                   </sender_id>
              </message_header>
          
              <message_payload>  
          
               <jms_text_message>    
                   <oracle_jms_properties>
                    <appid>AQProduct</appid>
                  <groupid>AQ</groupid>
                 </oracle_jms_properties>
          
                 <user_properties>
                   <property>
                     <name>Country</name>
                     <string_value>USA</string_value>
                   </property>
                   <property>
                      <name>State</name>
                     <string_value>California</string_value>
                   </property>
                  </user_properties>

                  <text_data>All things bright and beautiful</text_data>
               </jms_text_message>
             </message_payload>
            </message>
          </message_set>          
           </AQXmlSend>  
      </Body>
</Envelope> 

Enqueue Request Example--Publishing a Message to a JMS Topic

The JMS topic AQUSER.JMS_MAP_TOPIC has payload type JMS Map message (SYS.AQ$_JMS_MAP_MESSAGE). The publish request has the following format:

<?xml version="1.0"?>

<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">
      <Body>
      
        <AQXmlPublish xmlns = "http://ns.oracle.com/AQ/schemas/access">

          <producer_options>
            <destination>AQUSER.JMS_MAP_TOPIC</destination>
          </producer_options>
          
          <message_set>
            <message_count>1</message_count>   
          
            <message>
              <message_number>1</message_number>
          
              <message_header>
                   <correlation>toyota</correlation>
                   <sender_id >
                            <agent_name>john</agent_name>
                         </sender_id>
                   <recipient_list>
                      <recipient>
                         <agent_name>scott</agent_name>
                      </recipient>
                      <recipient>
                         <agent_name>aquser</agent_name>
                      </recipient>
                      <recipient>
                         <agent_name>jmsuser</agent_name>
                      </recipient>
                   </recipient_list>     
              </message_header>
          
              <message_payload>  
          
                 <jms_map_message> 
                   <oracle_jms_properties>
                     <reply_to>
                              <agent_name>oracle</agent_name>
                           </reply_to>
                    <groupid>AQ</groupid>
                  </oracle_jms_properties>
          
                    <user_properties>
                    <property>
                      <name>Country</name>
                      <string_value>USA</string_value>
                    </property>
                    <property>
                      <name>State</name>
                      <string_value>California</string_value>
                    </property>
                   </user_properties>
          
                    <map_data>
                   <item>
                      <name>Car</name>
                    <string_value>Toyota</string_value>
                   </item>
                   <item>
                     <name>Color</name>
                     <string_value>Blue</string_value>
                     </item>
                   <item>
                     <name>Price</name>
                     <int_value>20000</int_value>
                   </item>
                 </map_data>
               </jms_map_message>
             </message_payload>
            </message>
          </message_set>
          </AQXmlPublish>  
      </Body>
</Envelope> 

Enqueue Request Example--Sending a Message to a Queue with a RAW Payload

The queue AQUSER.RAW_MSGQ has a payload of type RAW. The SEND request has the following format:

<?xml version="1.0"?>
   <Envelope  xmlns =  "http://schemas.xmlsoap.org/soap/envelope/">
   <Body>                     
      <AQXmlSend xmlns = "http://ns.oracle.com/AQ/schemas/access">
        <producer_options>
          <destination>AQUSER.RAW_MSGQ</destination>
        </producer_options>
        <message_set>
          <message_count>1</message_count> 

          <message>
             <message_number>1</message_number>

                 <message_header>
                   <correlation>TKAXAS11</correlation>
                   <sender_id>
                      <agent_name>scott</agent_name>
                   </sender_id>  
                 </message_header>
                 <message_payload>
                    
<RAW>426C6F622064617461202D20626C6F622064617461202D20626C6F62206461746120426C6F6
22064617461202D20626C6F622064617461202D20626C6F62206461746120426</RAW>
                 </message_payload>
               </message>
            </message_set>
          </AQXmlSend>
      </Body>
</Envelope>

Enqueue Request Example--Sending/Publishing and Committing the Transaction

<?xml version="1.0"?>   
<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">

      <Body>
        <AQXmlPublish xmlns = "http://ns.oracle.com/AQ/schemas/access">
          <producer_options>
            <destination>AQUSER.EMP_TOPIC</destination>
          </producer_options>
          
          <message_set>
            <message_count>1</message_count>   
          
            <message>
              <message_number>1</message_number>
          
              <message_header>
           <correlation>NEWEMP</correlation>
           <sender_id>
              <agent_name>scott</agent_name>
           </sender_id> 
              </message_header>
          
              <message_payload>  
                <EMP_TYP>
                  <EMPNO>1111</EMPNO>
                   <ENAME>Mary</ENAME>
                  <MGR>5000</MGR>
                   <HIREDATE>1996-01-01 0:0:0</HIREDATE>
                  <SAL>10000</SAL>
                  <COMM>100.12</COMM>
                   <DEPTNO>60</DEPTNO>
                </EMP_TYP>
             </message_payload>
            </message>
          </message_set>

        <AQXmlCommit/>

        </AQXmlPublish>  
      </Body>
</Envelope>

Client Requests for Dequeue

Client requests for dequeue use the AQXmlReceive method, which takes the arguments and argument attributes shown in Table 17-3. Required arguments are shown in bold.

Table 17-3 Client Requests for Dequeue--Arguments and Attributes for AQXmlReceive
Argument Attribute

consumer_options

destination--specify the queue/topic from which messages are to be received. The destination element has an attribute lookup_type which determines how the destination element value is interpreted

  • DATABASE (default)--destination is interpreted as schema.queue_name
  • LDAP--the LDAP server is used to resolve the destination

-

consumer_name--Name of the consumer. Only those messages matching the consumer name are accessed. If a queue is not set up for multiple consumers, then this field should not be specified

-

wait_time--the time (in seconds) to wait if there is currently no message available which matches the search criteria

-

selector--criteria used to select the message, specified as one of:

  • correlation--the correlation identifier of the message to be dequeued.
  • message_id-- the message identifier of the message to be dequeued
  • condition--dequeue message that satisfy this condition.

A condition is specified as a Boolean expression using syntax similar to the WHERE clause of a SQL query. This Boolean expression can include conditions on message properties, user data properties (object payloads only), and PL/SQL or SQL functions (as specified in the where clause of a SQL query). Message properties include priority, corrid and other columns in the queue table

To specify dequeue conditions on a message payload (object payload), use attributes of the object type in clauses. You must prefix each attribute with tab.user_data as a qualifier to indicate the specific column of the queue table that stores the payload. The deq_condition parameter cannot exceed 4000 characters.

-

visibility

  • ON_COMMIT (default)--The dequeue is part of the current transaction. The operation is complete when the transaction commits.
  • IMMEDIATE--effects of the dequeue are visible immediately after the request is completed. The dequeue is not part of the current transaction. The operation constitutes a transaction on its own.

-

dequeue_mode--Specifies the locking behavior associated with the dequeue. The dequeue_mode can be specified as one of:

  • REMOVE (default): Read the message and update or delete it. This is the default. The message can be retained in the queue table based on the retention properties.
  • BROWSE: Read the message without acquiring any lock on the message. This is equivalent to a select statement.
  • LOCKED: Read and obtain a write lock on the message. The lock lasts for the duration of the transaction. This is equivalent to a select for update statement.

-

navigation_mode--Specifies the position of the message that will be retrieved. First, the position is determined. Second, the search criterion is applied. Finally, the message is retrieved. The navigation_mode can be specified as one of:

  • FIRST_MESSAGE: Retrieves the first message which is available and matches the search criteria. This resets the position to the beginning of the queue.
  • NEXT_MESSAGE (default): Retrieve the next message which is available and matches the search criteria. If the previous message belongs to a message group, then AQ retrieves the next available message which matches the search criteria and belongs to the message group. This is the default.
  • NEXT_TRANSACTION: Skip the remainder of the current transaction group (if any) and retrieve the first message of the next transaction group. This option can only be used if message grouping is enabled for the current queue.

-

transformation--the PL/SQL transformation to be invoked after the message is dequeued

AQXmlCommit

this is an empty element--if specified, the user transaction is committed at the end of the request

The following examples show dequeue requests using different attributes of AQXmlReceive.

Dequeue Request Example--Receiving Messages from a Single-Consumer Queue

Using the single-consumer queue QS.NEW_ORDERS_QUE, the receive request has the following format:

<?xml version="1.0"?>

<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">
      <Body>
        <AQXmlReceive xmlns = "http://ns.oracle.com/AQ/schemas/access">
          <consumer_options>
            <destination>QS.NEW_ORDERS_QUE</destination>
            <wait_time>0</wait_time>
          </consumer_options>
           </AQXmlReceive>  
      </Body>
</Envelope> 

Dequeue Request Example--Receiving Messages from a Multiconsumer Queue

Using the multiconsumer queue AQUSER.EMP_TOPIC with subscriber APP1, the receive request has the following format:

<?xml version="1.0"?>
<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">
      <Body>
        <AQXmlReceive xmlns = "http://ns.oracle.com/AQ/schemas/access">
          <consumer_options>
            <destination>AQUSER.EMP_TOPIC</destination>
            <consumer_name>APP1</consumer_name>
            <wait_time>0</wait_time>
            <navigation_mode>FIRST_MESSAGE</navigation_mode> 
          </consumer_options>
           </AQXmlReceive>  
      </Body>
</Envelope> 

Dequeue Request Example--Receiving Messages from a Specific Correlation ID

Using the single consumer queue QS.NEW_ORDERS_QUE, to receive messages with correlation ID NEW, the receive request has the following format:

<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">
      <Body>
        <AQXmlReceive xmlns = "http://ns.oracle.com/AQ/schemas/access">
          <consumer_options>
            <destination>QS.NEW_ORDERS_QUE</destination>
            <wait_time>0</wait_time>
            <selector>
                 <correlation>NEW</correlation>
            </selector>
          </consumer_options>
           </AQXmlReceive>  
      </Body>
</Envelope> 

Dequeue Request Example--Receiving Messages that Satisfy a Specific Condition

Using the multiconsumer queue AQUSER.EMP_TOPIC with subscriber APP1 and condition deptno=60, the receive request has the following format:

<?xml version="1.0"?>
<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">
      <Body>
        <AQXmlReceive xmlns = "http://ns.oracle.com/AQ/schemas/access">
          <consumer_options>
            <destination>AQUSER.EMP_TOPIC</destination>
            <consumer_name>APP1</consumer_name>
            <wait_time>0</wait_time>
            <selector>
                 <condition>tab.user_data.deptno=60</condition>
            </selector>
          </consumer_options>
           </AQXmlReceive>  
      </Body>
</Envelope> 

Dequeue Request Example--Receiving Messages and Committing

In the dequeue request examples, if you include AQXmlCommit at the end of the RECEIVE request, the transaction is committed upon completion of the operation. In "Dequeue Request Example--Receiving Messages from a Multiconsumer Queue", the receive request can include the commit flag as follows:

 <?xml version="1.0"?>

<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">
      <Body>
        <AQXmlReceive xmlns = "http://ns.oracle.com/AQ/schemas/access">
          <consumer_options>
            <destination>QS.NEW_ORDERS_QUE</destination>
            <wait_time>0</wait_time>
          </consumer_options>

             <AQXmlCommit/>

           </AQXmlReceive>  
      </Body>
</Envelope>

Dequeue Request Example--Browsing Messages

Messages are dequeued in REMOVE mode by default. To receive messages from QS.NEW_ORDERS_QUE in BROWSE mode, modify the receive request as follows:

<?xml version="1.0"?>

<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">
      <Body>
        <AQXmlReceive xmlns = "http://ns.oracle.com/AQ/schemas/access">
          <consumer_options>
            <destination>QS.NEW_ORDERS_QUE</destination>
            <wait_time>0</wait_time>
            <dequeue_mode>BROWSE</dequeue_mode>
          </consumer_options>
          </AQXmlReceive>  
      </Body>
</Envelope> 

Client Requests for Registration

Client requests for registration use the AQXmlRegister method, which takes the arguments and argument attributes shown in Table 17-4. Required arguments are shown in bold.

.
Table 17-4 Client Registration--Arguments and Attributes for AQXmlRegister
Argument Attribute

register_options

destination--specify the queue or topic on which notifications are registered. The destination element has an attribute lookup_type which determines how the destination element value is interpreted

  • DATABASE (default)--destination is interpreted as schema.queue_name
  • LDAP--the LDAP server is used to resolve the destination

-

consumer_name--the consumer name for multiconsumer queues or topics. For single consumer queues, this parameter must not be specified

-

notify_url--where notification is sent when a message is enqueued. The form can be http://<url> or mailto://<email address> or plsql://<pl/sql procedure>.

Register Request Example--Registering for Notification at an E-mail Address

To notify an e-mail address of messages enqueued for consumer APP1 in queue AQUSER.EMP_TOPIC, the register request has the following format:

<?xml version="1.0"?>
<Envelope xmlns= "http://schemas.xmlsoap.org/soap/envelope/">
      <Body>
      
        <AQXmlRegister xmlns = "http://ns.oracle.com/AQ/schemas/access">

          <register_options>
            <destination>AQUSER.EMP_TOPIC</destination>
            <consumer_name>APP1</consumer_name>
            <notify_url>mailto:app1@hotmail.com</notify_url>
          </register_options>
          
          <AQXmlCommit/>
          
           </AQXmlRegister>  
      </Body>
</Envelope> 

Client Requests to Commit a Transaction

A request to commit all actions performed by the user in a session uses the AQXmlCommit method.

Commit Request Example

A commit request has the following format.

<?xml version="1.0"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <AQXmlCommit xmlns="http://ns.oracle.com/AQ/schemas/access"/>
   </Body>
</Envelope>
Client Requests to Rollback a Transaction

A request to roll back all actions performed by the user in a session uses the AQXmlRollback method. Actions performed with IMMEDIATE visibility are not rolled back.

Rollback Request Example

A rollback request has the following format:

<?xml version="1.0"?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <AQXmlRollback xmlns="http://ns.oracle.com/AQ/schemas/access"/>
   </Body>
</Envelope>

Server Response to Enqueue

The response to an enqueue request to a single-consumer queue uses the AQXmlSendResponse method. The components of the response are shown in Table 17-5.

.
Table 17-5 Server Response to an Enqueue to a Single-Consumer Queue (AQXmlSendResponse)
Response Attribute

status_response

status_code--indicates success (0) or failure (-1)

error_code--Oracle code for the error

error_message--description of the error

send_result

destination--where the message was sent

message_id--identifier for every message sent

Server Request Example--Enqueuing a Single Message to a Single-Consumer Queue

The result of a SEND request to the single consumer queue QS.NEW_ORDERS_QUE has the following format:

<?xml version = '1.0'?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <AQXmlSendResponse xmlns="http://ns.oracle.com/AQ/schemas/access">
         <status_response>
            <status_code>0</status_code>
         </status_response>
         <send_result>
            <destination>QS.NEW_ORDERS_QUE</destination>
            <message_id>12341234123412341234</message_id>
         </send_result>
      </AQXmlSendResponse>
   </Body>
</Envelope>

The response to an enqueue request to a multiconsumer queue or topic uses the AQXmlPublishResponse method. The components of the response are shown in Table 17-6.

.
Table 17-6 Server Response to an Enqueue to a Multiconsumer Queue or Topic (AQXmlPublishResponse)
Response Attribute

status_response

status_code--indicates success (0) or failure (-1)

error_code--Oracle code for the error

error_message--description of the error

publish_result

destination--where the message was sent

message_id--identifier for every message sent

Server Request Example--Enqueuing to a Multiconsumer Queue

The result of a SEND request to the multiconsumer queue AQUSER.EMP_TOPIC has the following format:

<?xml version = '1.0'?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <AQXmlPublishResponse xmlns="http://ns.oracle.com/AQ/schemas/access">
         <status_response>
            <status_code>0</status_code>
         </status_response>
         <publish_result>
            <destination>AQUSER.EMP_TOPIC</destination>
            <message_id>23434435435456546546546546</message_id>
         </publish_result>
      </AQXmlPublishResponse>
   </Body>
</Envelope>

Server Response to a Dequeue Request

The response to a dequeue request uses the AQXmlReceiveResponse method. The components of the response are shown in Table 17-7.

.
Table 17-7 Server Response to a Dequeue from a Queue or Topic (AQXmlReceiveResponse)
Response Attribute

status_response

status_code--indicates success (0) or failure (-1)

error_code--Oracle code for the error

error_message--description of the error

receive_result

destination--where the message was sent

message_set--the set of messages dequeued

Dequeue Response Example--Receiving Messages from an ADT Queue (AQXmlReceiveResponse)

The result of a RECEIVE request on the queue AQUSER.EMP_TOPIC with a payload of type EMP_TYP has the following format:

<?xml version = '1.0'?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <AQXmlReceiveResponse xmlns="http://ns.oracle.com/AQ/schemas/access">
         <status_response>
            <status_code>0</status_code>
         </status_response>
         <receive_result>
            <destination>AQUSER.EMP_TOPIC</destination>
            <message_set>
               <message_count>1</message_count>
               <message>
                  <message_number>1</message_number>
                  <message_header>
                     <message_id>1234344545565667</message_id>
                     <correlation>TKAXAP10</correlation>
                     <priority>1</priority>
                     <delivery_count>0</delivery_count>
                     <sender_id>
                        <agent_name>scott</agent_name>
                     </sender_id>
                     <message_state>0</message_state>
                  </message_header>
                  <message_payload>
                    <EMP_TYP>
                       <EMPNO>1111</EMPNO>
                       <ENAME>Mary</ENAME>
                       <MGR>5000</MGR>
                       <HIREDATE>1996-01-01 0:0:0</HIREDATE>
                      <SAL>10000</SAL>
                      <COMM>100.12</COMM>
                       <DEPTNO>60</DEPTNO>
                     </EMP_TYP>
                 </message_payload>
               </message>
            </message_set>
         </receive_result>
      </AQXmlReceiveResponse>
   </Body>
</Envelope>

Dequeue Response Example--Receiving Messages from a JMS Queue

The result of a RECEIVE request on a queue with a payload of type JMS Text message has the following format:

<?xml version = '1.0'?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
      <AQXmlReceiveResponse xmlns="http://ns.oracle.com/AQ/schemas/access">
         <status_response>
            <status_code>0</status_code>
         </status_response>
         <receive_result>
            <destination>AQUSER.JMS_TEXTQ</destination>
            <message_set>
               <message_count>1</message_count>
               <message>
                  <message_number>1</message_number>
                  <message_header>
                     <message_id>12233435454656567</message_id>
                     <correlation>TKAXAP01</correlation>
                     <delay>0</delay>
                     <priority>1</priority>
                     <message_state>0</message_state>
                     <sender_id>
                        <agent_name>scott</agent_name>
                     </sender_id>
                  </message_header>
                  <message_payload>
                     <jms_text_message>
                        <oracle_jms_properties>
                           <reply_to>
                              <agent_name>oracle</agent_name>
                              <address>redwoodshores</address>
                              <protocol>100</protocol>
                           </reply_to>
                           <userid>AQUSER</userid>
                           <appid>AQProduct</appid>
                           <groupid>AQ</groupid>
                           <timestamp>01-12-2000</timestamp>
                           <recv_timestamp>12-12-2000</recv_timestamp>
                        </oracle_jms_properties>
                        <user_properties>
                           <property>
                              <name>Country</name>
                              <string_value>USA</string_value>
                           </property>
                           <property>
                              <name>State</name>
                              <string_value>California</string_value>
                           </property>
                        </user_properties>
                        <text_data>All things bright and beautiful</text_data>
                     </jms_text_message>
                  </message_payload>
               </message>
            </message_set>
         </receive_result>
      </AQXmlReceiveResponse>
   </Body>
</Envelope>

Server Response to a Register Request

The response to a register request uses the AQXmlRegisterResponse method, which consists of status_response. (See Table 17-7 for a description of status_response.)

Commit Response

The response to a commit request uses the AQXmlCommitResponse method, which consists of status_response. (See Table 17-7 for a description of status_response.)

Example

The response to a commit request has the following format:

<?xml version = '1.0'?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <AQXmlCommitResponse xmlns="http://ns.oracle.com/AQ/schemas/access">
         <status_response>
            <status_code>0</status_code>
         </status_response>
      </AQXmlCommitResponse>
   </Body>
</Envelope>

Rollback Response

The response to a rollback request uses the AQXmlRollbackResponse method, which consists of status_response. (See Table 17-7 for a description of status_response.)

Notification

When an event for which a client has registered occurs, a notification is sent to the client at the URL specified in the REGISTER request. AQXmlNotification consists of:

Response in Case of Error

In case of an error in any of the preceding requests, a FAULT is generated. The FAULT element consists of:

Example

A FAULT message has the following format:

<?xml version = '1.0'?>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
   <Body>
      <Fault xmlns="http://schemas.xmlsoap.org/soap/envelope/">
         <faultcode>100</faultcode>
         <faultstring>Server Fault</faultstring>
         <detail>
            <status_response>
               <status_code>-1</status_code>
               <error_code>410</error_code>
               <error_message>JMS-410: XML SQL Excetpion 
ORA-24031: invalid value, OWNER_NAME should be non-NULL
ORA-06512: at "SYS.DBMS_AQJMS", line 177
ORA-06512: at line 1
</error_message>
            </status_response>
         </detail>
      </Fault>
   </Body>
</Envelope>

SOAP and AQ XML Schemas

IDAP exposes the SOAP schema and the AQ XML schema to the client. All documents sent are validated against these schemas:

The SOAP Schema

The SOAP schema describes the structure of a document: envelope, header, and body.

<?xml version='1.0'?>
<!-- XML Schema for SOAP v 1.1 Envelope -->
<schema xmlns='http://www.w3.org/2001/XMLSchema'
        xmlns:tns='http://schemas.xmlsoap.org/soap/envelope/'
        targetNamespace='http://schemas.xmlsoap.org/soap/envelope/'>
     
  <!-- SOAP envelope, header and body -->
  
  <element name="Envelope" type="tns:Envelope"/>
  <complexType name='Envelope'>
   <sequence>
    <element ref='tns:Header' minOccurs='0'/>
    <element ref='tns:Body' minOccurs='1'/>
    <any minOccurs='0' maxOccurs='*'/>
   </sequence>
    <anyAttribute/>
  </complexType>
          
  <element name="Header" type="tns:Header"/>
  <complexType name='Header'>
   <sequence>
    <any minOccurs='0' maxOccurs='*'/>
   </sequence>
    <anyAttribute/>
  </complexType>
  
  <element name="Body" type="tns:Body"/>
  <complexType name='Body'>
   <sequence>
    <any minOccurs='0' maxOccurs='*'/>
   </sequence>
    <anyAttribute/>
  </complexType>
       
  <!-- Global Attributes.  The following attributes are intended 
       to be usable via qualified attribute names on any complex type
       referencing them.  -->
 
  <attribute name="mustUnderstand" type="tns:mutype" use="optional" value="0"/>
  </attribute>

  <simpleType  name="mutype">
     <restriction base="string">
     <enumeration value="0"/>
        <enumeration value="1"/>
     </restriction>
  </simpleType>
      
  <attribute name='actor' type='anyURI'/>
 
  <!-- 'encodingStyle' indicates any canonicalization conventions followed
       in the contents of the containing element.  For example, the value
       'http://schemas.xmlsoap.org/soap/encoding/' indicates 
       the pattern described in SOAP specification. -->  
         
  <simpleType name='encodingStyle'>
    <list itemType='anyURI'/>
  </simpleType>
  <attributeGroup name='encodingStyle'>
    <attribute name='encodingStyle' type='tns:encodingStyle'/>
  </attributeGroup>

  <!-- SOAP fault reporting structure -->
  <complexType name='Fault' final='extension'>
   <sequence>
    <element name='faultcode' type='QName'/>
    <element name='faultstring' type='string'/>
    <element name='faultactor' type='anyURI' minOccurs='0'/>
    <element name='detail' type='tns:detail' minOccurs='0'/>
   </sequence>
  </complexType>

  <complexType name='detail'>
   <sequence>
    <any minOccurs='0' maxOccurs='*'/>
   </sequence>
    <anyAttribute/> 
  </complexType>

</schema>

IDAP Schema

The IDAP schema describes the contents of the IDAP body for Internet access to AQ features.

<?xml version="1.0"?>

<!-- ****************** AQ xml schema  ****************** -->

<schema xmlns = "http://www.w3.org/2001/XMLSchema"
        targetNamespace = "http://ns.oracle.com/AQ/schemas/access"
        xmlns:aq = "http://ns.oracle.com/AQ/schemas/access"
        xmlns:xsd = "http://www.w3.org/2001/XMLSchema">

<import namespace = "http://schemas.xmlsoap.org/soap/envelope/"
        schemaLocation = "soap_env.xsd" />



<!-- ****************** AQ xml client operations  ****************** -->

   <element name="AQXmlSend">
      <complexType mixed="true">
        <sequence>
           <element ref="aq:producer_options" minOccurs="1" maxOccurs="1" />
           <element ref="aq:message_set" minOccurs="1" maxOccurs="1"/>
           <element ref="aq:AQXmlCommit" minOccurs="0" maxOccurs="1"/>
        </sequence>
      </complexType>
    </element>   

   <element name="AQXmlPublish">
      <complexType mixed="true">
        <sequence>
           <element ref="aq:producer_options" minOccurs="1" maxOccurs="1" />
           <element ref="aq:message_set" minOccurs="1" maxOccurs="1"/>
           <element ref="aq:AQXmlCommit" minOccurs="0" maxOccurs="1"/>
        </sequence>
      </complexType>
    </element>   


   <element name="AQXmlReceive">
      <complexType mixed="true">
        <sequence>
           <element ref="aq:consumer_options" minOccurs="1" maxOccurs="1" />
           <element ref="aq:AQXmlCommit" minOccurs="0" maxOccurs="1"/>
        </sequence>
      </complexType>
   </element>   


   <element name="AQXmlRegister">
      <complexType mixed="true">
        <sequence>
           <element ref="aq:register_options" minOccurs="1" maxOccurs="1" />
           <element ref="aq:AQXmlCommit" minOccurs="0" maxOccurs="1"/>
        </sequence>
      </complexType>
   </element>   

   <element name="AQXmlCommit">
      <complexType>
      </complexType>
   </element>   

   <element name="AQXmlRollback">
      <complexType>
      </complexType>
   </element>   

 

   <!-- ****************** AQ xml server responses  ****************** -->

   <element name="AQXmlSendResponse">
      <complexType mixed="true">
        <sequence>
           <element ref="aq:status_response" minOccurs="1" maxOccurs="1"/> 
           <element ref="aq:send_result" minOccurs="0" maxOccurs="1"/>
        </sequence>
      </complexType>
    </element>   

   <element name="AQXmlPublishResponse">
      <complexType mixed="true">
        <sequence>
           <element ref="aq:status_response" minOccurs="1" maxOccurs="1"/> 
           <element ref="aq:publish_result" minOccurs="0" maxOccurs="1"/>
        </sequence>
      </complexType>
    </element>   


   <element name="AQXmlReceiveResponse">
      <complexType mixed="true">
        <sequence>
           <element ref="aq:status_response" minOccurs="1" maxOccurs="1"/> 
           <element ref="aq:receive_result" minOccurs="0" maxOccurs="1"/>
        </sequence>
      </complexType>
    </element>   


   <element name="AQXmlRegisterResponse">
      <complexType mixed="true">
        <sequence>
           <element ref="aq:status_response" minOccurs="1" maxOccurs="1"/> 
        </sequence>
      </complexType>
    </element>   

   <element name="AQXmlCommitResponse">
      <complexType mixed="true">
        <sequence>
           <element ref="aq:status_response" minOccurs="1" maxOccurs="1"/> 
        </sequence>
      </complexType>
    </element>   

   <element name="AQXmlRollbackResponse">
      <complexType mixed="true">
        <sequence>
           <element ref="aq:status_response" minOccurs="1" maxOccurs="1"/> 
        </sequence>
      </complexType>
    </element>   

 
   <element name="destination">
     <complexType>
      <simpleContent>
        <extension base='string'>
          <attribute name="lookup_type" type="aq:dest_lookup_type" 
              default="DATABASE"/>
        </extension>
     </simpleContent>  
   </complexType>
   </element>        

   <!-- **** destination lookup type ******* -->
   <!-- lookup_type can be specified to either lookup LDAP or use  -->
   <simpleType name="dest_lookup_type">
    <restriction base="string">
      <enumeration value="DATABASE"/>
      <enumeration value="LDAP"/>
     </restriction>
    </simpleType>

   <!-- ****************** Producer Options ****************** -->
   <element name="producer_options">
      <complexType mixed="true">
        <sequence>
        <element ref="aq:destination" minOccurs="1" maxOccurs="1"/>      
        <element ref="aq:visibility" minOccurs="0" maxOccurs="1"/>
        <element ref="aq:transformation" minOccurs="0" maxOccurs="1"/>
        </sequence>
      </complexType>
    </element>   

   <!-- ****************** Consumer Options ****************** -->
   <element name="consumer_options">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:destination" minOccurs="1" maxOccurs="1"/> 
        <element ref="aq:consumer_name" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:wait_time" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:selector" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:batch_size" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:visibility" minOccurs="0" maxOccurs="1"/>
        <element ref="aq:dequeue_mode" minOccurs="0" maxOccurs="1"/>
        <element ref="aq:navigation_mode" minOccurs="0" maxOccurs="1"/>
        <element ref="aq:transformation" minOccurs="0" maxOccurs="1"/>
        </sequence>
       </complexType>
    </element>   


   <!-- ****************** Register Options ****************** -->
   <element name="register_options">
      <complexType mixed="true">
        <sequence>
        <element ref="aq:destination" minOccurs="1" maxOccurs="1"/> 
        <element ref="aq:consumer_name" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:notify_url" minOccurs="1" maxOccurs="1"/> 
        </sequence>
      </complexType>
    </element>   

   <element name="recipient_list">
     <complexType mixed="true">
      <sequence>
   <element ref="aq:recipient" minOccurs="1" maxOccurs="*"/>
      </sequence>
     </complexType>
   </element>   


   <!-- ****************** Message Set ************************* -->
   <element name="message_set">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:message_count" minOccurs="0" maxOccurs="1"/>
        <element ref="aq:message" minOccurs="0" maxOccurs="*"/>  
       </sequence>
      </complexType>
   </element>   


   <!-- ****************** Message ************************* -->
   <element name="message">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:message_number" minOccurs="0" maxOccurs="1"/>   
        <element ref="aq:message_header" minOccurs="1" maxOccurs="1"/>  
        <element ref="aq:message_payload" minOccurs="0" maxOccurs="1"/>  
       </sequence>
      </complexType>
   </element>   


   <!-- ****************** Message header ****************** -->
   <element name="message_header">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:message_id" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:correlation" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:delay" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:expiration" minOccurs="0" maxOccurs="1"/>
        <element ref="aq:priority" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:delivery_count" minOccurs="0" maxOccurs="1"/>
        <element ref="aq:sender_id" minOccurs="1" maxOccurs="1"/>  
        <element ref="aq:recipient_list" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:message_state" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:exception_queue" minOccurs="0" maxOccurs="1"/> 
      </sequence> 
     </complexType>
    </element>   


   <!-- ****************** Oracle JMS properties ****************** -->
   <element name="oracle_jms_properties">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:type" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:reply_to" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:userid" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:appid" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:groupid" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:group_sequence" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:timestamp" minOccurs="0" maxOccurs="1"/> 
        <element ref="aq:recv_timestamp" minOccurs="0" maxOccurs="1"/> 
       </sequence>
      </complexType>
    </element>   


   <!-- ****************** Message payload ****************** -->
   <element name="message_payload">
     <complexType>
        <choice>
          <element ref="aq:raw" minOccurs="0" maxOccurs="1"/> 
          <element ref="aq:jms_text_message" minOccurs="0" maxOccurs="1"/> 
          <element ref="aq:jms_map_message" minOccurs="0" maxOccurs="1"/> 
          <element ref="aq:jms_bytes_message" minOccurs="0" maxOccurs="1"/> 
          <element ref="aq:jms_object_message" minOccurs="0" maxOccurs="1"/> 
         <any minOccurs="0" maxOccurs="*" processContents="skip"/>
        </choice>
     </complexType>
   </element>        


   <!-- ****************** User-defined properties ****************** -->
   <element name="user_properties">
      <complexType mixed="true">
        <sequence>
        <element ref="aq:property" minOccurs="0" maxOccurs="*"/> 
        </sequence>
      </complexType>
   </element>   

   <!-- ****************** Property  ****************** -->
   <element name="property">
      <complexType mixed="true">
        <sequence>
     <element ref="aq:name" minOccurs="1" maxOccurs="1"/> 
     <choice>
       <element ref="aq:int_value" minOccurs="1" maxOccurs="1"/> 
       <element ref="aq:string_value" minOccurs="1" maxOccurs="1"/> 
       <element ref="aq:long_value" minOccurs="1" maxOccurs="1"/> 
       <element ref="aq:double_value" minOccurs="1" maxOccurs="1"/> 
       <element ref="aq:boolean_value" minOccurs="1" maxOccurs="1"/> 
       <element ref="aq:float_value" minOccurs="1" maxOccurs="1"/> 
       <element ref="aq:short_value" minOccurs="1" maxOccurs="1"/> 
       <element ref="aq:byte_value" minOccurs="1" maxOccurs="1"/> 
     </choice>
        </sequence>
      </complexType>
    </element>   


   <!-- ****************** Status response ****************** -->
   <element name="status_response">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:acknowledge" minOccurs="0" maxOccurs="1"/>      
        <element ref="aq:status_code" minOccurs="0" maxOccurs="1"/>      
        <element ref="aq:error_code" minOccurs="0" maxOccurs="1"/>       
        <element ref="aq:error_message" minOccurs="0" maxOccurs="1"/>  
       </sequence>
      </complexType>
   </element>   


   <!-- ****************** Send result ****************** -->
   <element name="send_result">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:destination" minOccurs="1" maxOccurs="1"/>      
        <element ref="aq:message_id" minOccurs="0" maxOccurs="*"/>       
      </sequence>
      </complexType>
   </element>   

   <!-- ****************** Publish result ****************** -->
   <element name="publish_result">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:destination" minOccurs="1" maxOccurs="1"/>      
        <element ref="aq:message_id" minOccurs="0" maxOccurs="*"/>       
       </sequence>
      </complexType>
   </element>   


   <!-- ****************** Receive result ****************** -->
   <element name="receive_result">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:destination" minOccurs="1" maxOccurs="1"/>      
        <element ref="aq:message_set" minOccurs="0" maxOccurs="*"/>   
       </sequence>   
      </complexType>
   </element>   


   <!-- ****************** Notification *************************** -->
   <element name="notification_options">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:destination" minOccurs="1" maxOccurs="1"/>      
        <element ref="aq:consumer_name" minOccurs="1" maxOccurs="1"/> 
       </sequence>
      </complexType>
   </element>   


   <element name="priority" type="integer"/>         
   <element name="expiration" type="integer"/>           
   <element name="consumer_name" type="string"/> 
   <element name="wait_time" type="integer"/>  
   <element name="batch_size" type="integer"/>  

   <element name="notify_url" type="string"/> 
   <element name="message_id" type="string"/> 
   <element name="message_state" type="string"/>


   <element name="message_number" type="integer"/>  
   <element name="message_count" type="integer"/>  

   <element name="correlation" type="string"/> 
   <element name="delay" type="integer"/> 
   <element name="delivery_count" type="integer"/> 
   <element name="exception_queue" type="string"/> 
   <element name="agent_alias" type="string"/>

   <element name="type" type="string"/> 
   <element name="userid" type="string"/> 
   <element name="appid" type="string"/> 
   <element name="groupid" type="string"/> 
   <element name="group_sequence" type="integer"/> 
   <element name="timestamp" type="date"/> 
   <element name="recv_timestamp" type="date"/> 

   <element name="recipient">
     <complexType>
       <choice>
         <sequence>
           <element ref="aq:agent_name" minOccurs="0" maxOccurs="1"/>
          <element ref="aq:address" minOccurs="0" maxOccurs="1"/>    
           <element ref="aq:protocol" minOccurs="0" maxOccurs="1"/> 
         </sequence>
         <element ref="aq:agent_alias" minOccurs="1" maxOccurs="1"/>
       </choice>
     </complexType>
   </element>        


   <element name="sender_id">
     <complexType>
       <choice>
         <sequence>
           <element ref="aq:agent_name" minOccurs="0" maxOccurs="1"/>
          <element ref="aq:address" minOccurs="0" maxOccurs="1"/>    
           <element ref="aq:protocol" minOccurs="0" maxOccurs="1"/> 
         </sequence>
         <element ref="aq:agent_alias" minOccurs="1" maxOccurs="1"/>
       </choice>
     </complexType>
   </element>        


   <element name="reply_to">
     <complexType>
       <choice>
         <sequence>
           <element ref="aq:agent_name" minOccurs="1" maxOccurs="1"/>
          <element ref="aq:address" minOccurs="0" maxOccurs="1"/>    
           <element ref="aq:protocol" minOccurs="0" maxOccurs="1"/> 
         </sequence>
         <element ref="aq:agent_alias" minOccurs="1" maxOccurs="1"/>
       </choice>
     </complexType>
   </element>        


   <element name="selector"> 
     <complexType>
   <choice>
          <element ref="aq:correlation" minOccurs="0" maxOccurs="1"/> 
          <element ref="aq:message_id" minOccurs="0" maxOccurs="1"/> 
          <element ref="aq:condition" minOccurs="0" maxOccurs="1"/> 
        </choice>
     </complexType>
   </element>


   <element name="condition" type="string"/>  

   <element name="visibility">
    <simpleType>
     <restriction base="string">
      <enumeration value="ON_COMMIT"/>
      <enumeration value="IMMEDIATE"/>
     </restriction>
    </simpleType>
    </element>   

   <simpleType name="del_mode_type">
     <restriction base="string">
      <enumeration value="PERSISTENT"/>
      <enumeration value="NONPERSISTENT"/>
     </restriction>
    </simpleType>

   <element name="dequeue_mode"> 
   <simpleType>   
    <restriction base="string">
      <enumeration value="BROWSE"/>
      <enumeration value="LOCKED"/>
      <enumeration value="REMOVE"/>
      <enumeration value="REMOVE_NODATA"/>
    </restriction>
    </simpleType>
   </element>    

   <element name="navigation_mode"> 
   <simpleType>
    <restriction base="string">
      <enumeration value="FIRST_MESSAGE"/>
      <enumeration value="NEXT_MESSAGE"/>
      <enumeration value="NEXT_TRANSACTION"/>
    </restriction>
    </simpleType>
   </element>
 
   <element name="transformation" type="string"/> 

   <element name="acknowledge">
     <complexType>
     </complexType>
   </element>        
   <element name="status_code" type="string"/> 
   <element name="error_code" type="string"/> 
   <element name="error_message" type="string"/> 

   <element name="name" type="string"/> 
   <element name="int_value" type="integer"/> 
   <element name="string_value" type="string"/> 
   <element name="long_value" type="long"/> 
   <element name="double_value" type="double"/> 
   <element name="boolean_value" type="boolean"/> 
   <element name="float_value" type="float"/> 
   <element name="short_value" type="short"/> 
   <element name="byte_value" type="byte"/> 

   <element name="agent_name" type="string"/> 
   <element name="address" type="string"/> 
   <element name="protocol" type="integer"/> 


   <!-- ****************** RAW message *********************** -->
   <element name="raw" type="string"/> 


   <!-- ****************** JMS text message ****************** -->
   <element name="jms_text_message">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:oracle_jms_properties" minOccurs="0" maxOccurs="1"/>  
        <element ref="aq:user_properties" minOccurs="0" maxOccurs="1"/>  
        <element ref="aq:text_data" minOccurs="1" maxOccurs="1"/>  
      </sequence>
      </complexType>
   </element>   
   
   <element name="text_data" type="string"/> 


   <!-- ****************** JMS map message ****************** -->
   <element name="jms_map_message">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:oracle_jms_properties" minOccurs="0" maxOccurs="1"/>  
        <element ref="aq:user_properties" minOccurs="0" maxOccurs="1"/>  
        <element ref="aq:map_data" minOccurs="1" maxOccurs="1"/>  
       </sequence>
      </complexType>
   </element>   

   <!-- ****************** Map data ****************** -->
   <element name="map_data">
      <complexType mixed="true">
        <sequence>
        <element ref="aq:item" minOccurs="0" maxOccurs="*"/> 
        </sequence>
      </complexType>
   </element>   

   <!-- ****************** Map Item  ****************** -->
   <element name="item">
      <complexType mixed="true">
        <sequence>
     <element ref="aq:name" minOccurs="1" maxOccurs="1"/> 
     <choice>
       <element ref="aq:int_value" minOccurs="1" maxOccurs="1"/> 
       <element ref="aq:string_value" minOccurs="1" maxOccurs="1"/>
       <element ref="aq:long_value" minOccurs="1" maxOccurs="1"/>  
       <element ref="aq:double_value" minOccurs="1" maxOccurs="1"/>  
       <element ref="aq:boolean_value" minOccurs="1" maxOccurs="1"/>  
       <element ref="aq:float_value" minOccurs="1" maxOccurs="1"/>  
       <element ref="aq:short_value" minOccurs="1" maxOccurs="1"/>  
       <element ref="aq:byte_value" minOccurs="1" maxOccurs="1"/>  
     </choice>
        </sequence>
      </complexType>
    </element>   
   

   <!-- ****************** JMS bytes message ****************** -->
   <element name="jms_bytes_message">
      <complexType mixed="true">
       <sequence>
        <element ref="aq:oracle_jms_properties" minOccurs="0" maxOccurs="1"/>  
        <element ref="aq:user_properties" minOccurs="0" maxOccurs="1"/>  
        <element ref="aq:bytes_data" minOccurs="1" maxOccurs="1"/>  
       </sequence>
      </complexType>
   </element>   
   
   <element name="bytes_data" type="string"/> 


   <!-- ****************** JMS object message ****************** -->
   <element name="jms_object_message">
      <complexType mixed="true">
        <sequence>
        <element ref="aq:oracle_jms_properties" minOccurs="0" maxOccurs="1"/>  
        <element ref="aq:user_properties" minOccurs="0" maxOccurs="1"/>  
        <element ref="aq:ser_object_data" minOccurs="1" maxOccurs="1"/>  
        </sequence>
      </complexType>
   </element>   
   
   <element name="ser_object_data" type="string"/> 

</schema>

Deploying the AQ XML Servlet

The AQ XML servlet is a Java class that extends the oracle.AQ.xml.AQxmlServlet class. The AQxmlServlet class extends the javax.servlet.http.HttpServlet class.


Note:

Demos for the AQ XML servlet can be found in $ORACLE_HOME/rdbms/demo/. Check the aqxmlREADME.txt file for details.


The AQ XML Servlet accepts requests with Content-Type "text/xml" or application/x-www-form-urlencoded. When the Content-Type request is set to application/x-www-form-urlencoded, you must set the parameter name to aqxmldoc and the value must be the URL-encoded AQ XML document.

Creating the AQ XML Servlet Class

The AQ servlet creates a JDBC OCI connection pool to connect to the Oracle9i server. The init() method of the servlet must specify an AQxmlDataSource object that encapsulates the database connection parameters and the username and password. See the Oracle9i Supplied Java Packages Reference for information on the AQxmlDataSource class.

The user specified in the AQxmlDataSource is the AQ servlet super-user. This user must have CREATE SESSION privilege and EXECUTE privilege on the DBMS_AQIN package.

Example:

Create a user AQADM as the AQ servlet superuser as follows:

connect sys/change_on_install as sysdba;
grant connect, resource to aqadm identified by aqadm;
grant create session to aqadm;
grant execute on dbms_aqjms to aqadm;

A sample servlet can be created using this superuser as follows:

import javax.servlet.*;
import javax.servlet.http.*;
import oracle.AQ.xml.*;

/**
 * This is a sample AQ Servlet.  
 */
public class AQTestServlet extends oracle.AQ.xml.AQxmlServlet
{ 
  
  /* The init method must be overloaded to specify the AQxmlDataSource */
  public void init()
  {
      AQxmlDataSource  db_drv = null;

      try
      {
        /* Create data source with username, password, sid, host, port */
        db_drv = new AQxmlDataSource("AQADM", "AQADM", "test_db", "sun-248", 
"5521");

        this.setAQDataSource(db_drv);
      }
      catch (Exception ex)
      {
          System.out.println("Exception in init: " + ex);
      }
}

The superclass oracle.AQ.xml.AQxmlServlet implements the doPost() and doGet() methods in javax.servlet.http.HttpServlet. The doPost() method handles incoming SOAP requests and performs the requested AQ operations.


Note:

The example assumes that the AQ servlet is installed in a Web server that implements Javasoft's Servlet2.2 specification (such as Tomcat 3.1). For a Web server that implements the Servlet 2.0 specification (such as Apache Jserv), you should extend the oracle.AQ.xml.AQxmlServlet20 class instead of the AQxmlServlet class and override the appropriate write() method.


Compiling the AQ XML Servlet

The AQ servlet can be deployed with any Web server or servlet-runner that implements Javasoft's Servlet2.0 or Servlet2.2 interfaces (for example, Apache Jserv or Tomcat). Note the following considerations:

User Authentication

After the servlet is installed, the Web server must be configured to authenticate all users that send POST requests to the AQ servlet. The AQ servlet allows only authenticated users to access the servlet. If the user is not authenticated, an error is returned by the servlet.

The Web server can be configured in multiple ways to restrict access. Some of the common techniques are basic authentication (username/password) over SSL and client certificates. Consult your Web server documentation to see how you can restrict access to servlets.

Using HTTP

In the context of the AQ servlet, the user name that is used to connect to the Web server is known as the AQ HTTP agent or AQ Internet user.

Example:

In Apache, the following can be used to restrict access (using basic authentication) to servlets installed under aqserv/servlet. In this example, all users sending POST requests to the servlet are authenticated using the users file in /apache/htdocs/userdb.

<Location /aqserv/servlet>
  <Limit POST>   
    AuthName "AQ restricted stuff"
    AuthType Basic 
    AuthUserFile /apache/htdocs/userdb/users
    require valid-user 
  </Limit>
</Location> 

User Authorization

After authenticating the users who connect to the AQ servlet, you establish which operations the users are authorized to perform by doing the following:

  1. Register the AQ agent for Internet access.
  2. Map the AQ agent to one or more database users.

Registering the AQ Agent

To register the AQ agent for Internet access, use DBMS_AQADM.CREATE_AQ_AGENT. The CREATE_AQ_AGENT procedure takes an agent_name. You specify which protocols the user can use to access the servlet--HTTP, SMTP, or both. For agents accessing the AQ servlet using SMTP, an LDAP certificate_location must also be specified. See "Setup for Receiving AQ XML Requests Using SMTP (E-mail)" for more information.

Example

Create an AQ agent JOHN to access the AQ servlet using HTTP.

DBMS_AQADM.CREATE_AQ_AGENT(agent_name => 'JOHN', enable_http => true);

The procedures ALTER_AQ_AGENT and DROP_AQ_AGENT for altering and dropping AQ agents function similarly to CREATE_AQ_AGENT. These procedures are documented in the Oracle9i Supplied PL/SQL Packages and Types Reference.

Mapping the AQ Agent to Database Users

To map an AQ agent to one or more database users, use DBMS_AQADM.ENABLE_DB_ACCESS. With the ENABLE_DB_ACCESS procedure, you give an AQ agent the privileges of a particular database user. This allows the agent to access all queues that are visible to the database users to which the agent is mapped.

Example

Map the AQ Internet agent JOHN to database users OE (overseas shipping) and CBADM (customer billing administrator).

DBMS_AQADM.ENABLE_DB_ACCESS(agent_name =>'JOHN', db_username => 'OE');
DBMS_AQADM.ENABLE_DB_ACCESS(agent_name =>'JOHN', db_username => 'CBADM');

Database Sessions

When the user sends a POST request to the servlet, the servlet parses the request to determine which queue/topic the user is trying to access. Accordingly, the AQ servlet creates a database session as one of the database users (db_user) that maps to the AQ agent. The db_user selected has privileges to access the queue specified in the request.

Example

AQ agent JOHN sends an enqueue request to OE.OE_NEW_ORDERS_QUE. The servlet sees that JOHN can map to db_users OE and CBADM. Since OE.OE_NEW_ORDERS_QUE is in the OE schema, it does a CREATE SESSION as OE to perform the requested operation.

The AQ servlet creates a connection pool to the Oracle server using the AQ servlet super-user. This super-user creates sessions on behalf of db_users that the AQ Internet agent maps to. Hence the super-user must have privileges to create proxy sessions for all the users specified in the ENABLE_DB_ACCESS call. See "Creating the AQ XML Servlet Class" for how to create the AQ servlet super-user.

The AQ servlet super-user can be granted CREATE PROXY session privileges as follows:

connect sys/change_on_install as sysdba
rem grant super-user AQADM privileges to create proxy sessions as OE
alter user OE grant CONNECT THROUGH AQADM;

rem grant super-user AQADM privileges to create proxy sessions as CBADM
alter user CBADM grant CONNECT THROUGH AQADM;

If an AQ Internet agent is mapped to more than one db_user, then all the db_users must have the FORCE ANY TRANSACTION privilege:

grant FORCE ANY TRANSACTION to OE; 
grant FORCE ANY TRANSACTION to CBADM; 

To disable the mapping between an agent and a database user, use DBMS_AQADM.DISABLE_DB_ACCESS.

The SYSTEM.AQ$INTERNET_USERS view lists AQ agents, the protocols they are enabled for, and the mapping between AQ agents and database users. Example entries in this view are shown in Table 17-8.

Table 17-8
agent_name db_username http_enabled smtp_enabled

scott

cbadmin

YES

NO

scott

buyer

YES

NO

aqadmin

OE

YES

YES

aqadmin

seller

YES

YES

bookstore

-

NO

YES

The SYSTEM.AQ$INTERNET_USERS View

Using an LDAP Server with an AQ XML Servlet

An LDAP server is required if:

The LDAP context must be specified by the setLDAPContext(DirContext) call, as follows:

public void init()
{
             Hashtable env = new Hashtable(5, 0.75f);
             AQxmlDataSource  db_drv = null;

      try
      {
           /* Create data source with username, password, sid, host, port */
           db_drv = new AQxmlDataSource("AQADM", "AQADM", "test_db",
                                        "sun-248", "5521");
           this.setAQDataSource(db_drv);

           env.put(Context.INITIAL_CONTEXT_FACTORY, 
                   "com.sun.jndi.ldap.LdapCtxFactory");
           env.put(Context.PROVIDER_URL, "ldap://yow:389");
           env.put(SEARCHBASE, "cn=server1,cn=dbservers,cn=wei");
           env.put(Context.SECURITY_AUTHENTICATION, "simple");
           env.put(Context.SECURITY_PRINCIPAL, "cn=orcladmin");
           env.put(Context.SECURITY_CREDENTIALS, "welcome");

              DirContext inictx = new InitialDirContext(env);
              String searchbase = (String)env.get("server_dn");
              lctx = (DirContext)inictx.lookup(searchbase);

              // Set up LDAP context
              setLdapContext(lctx);

              // Set the EMAIL server address (if any)
              setEmailServerAddr("144.25.186.236");
      }
      catch (Exception ex)
      {
            System.err.println("Servlet init exception: " +ex) ;
      }
 }

Setup for Receiving AQ XML Requests Using SMTP (E-mail)

You must set up the database, Web server, LDAP server, and e-mail server to receive AQ XML requests using SMTP.

Database and LDAP Server Setup

To store AQ agents in the LDAP server, the database must be registered to the LDAP server using the Database Configuration Assistant (DBCA), and the value of GLOBAL_TOPIC_ENABLED must be set to TRUE (default is FALSE; reset using alter system set global_topic_enabled=TRUE).

To create AQ agents that can access the servlet using SMTP, use the DBMS_AQADM.CREATE_AQ_AGENT procedure.

Example

Create an AQ agent for the appl application to access the AQ servlet using SMTP and the digital certificate of the application owner, Kurt:

DBMS_AQADM.CREATE_AQ_AGENT(
   agent_name => 'appl',  
   enable_http => true, 
   enable_smtp => true, 
   certificate_location => 'cn=kurt,cn=acme,cn=com');

The certificate_location parameter is required to authenticate the appl application when a message is received.

Web Server Setup

  1. Establish a user called ORACLE_SMTP_AGENT on the Web server that is allowed to access the AQ servlet.

    The Oracle e-mail server will connect to the servlet using user ORACLE_SMTP_AGENT.

  2. Specify the e-mail server host name or the IP address in the servlet's init( ) method.

    Use setEmailServerHost(hostname) or setEmailServerAddr(ip_address)in the AQxmlServlet to do this.

    Example: Specify the e-mail server host as follows:

    setEmailServerAddr("144.25.186.236");  or 
    setEmailServerHost("email-srv.us.oracle.com");
    
    
  3. Set up an LDAP context in the servlet, as described in "Using an LDAP Server with an AQ XML Servlet".

    The LDAP server is used to retrieve certificates for the AQ agent and verify the signature in the incoming message.

E-mail Server Setup

Internet access to AQ using SMTP requires Oracle Email Server 5.5. Do the following:

  1. Check that DBMS_AQST is installed on the e-mail server.
  2. Create an e-mail account for the destination database, that is, the database against which AQ operations are to be performed using the AQ servlet.

    See Also:

    Oracle eMail Server 5.5 Administration Guide for how to create an e-mail account on the e-mail server.

  3. Set up an e-mail rule for the destination database e-mail account so that it can handle AQ XML client requests by sending them to the AQ servlet.

    The following information is required:

    • The e-mail account of the destination database, for example, 'aqdb1';
    • The password of the e-mail account, for example, 'welcome'
    • The domain in which this e-mail account resides, for example, 'acme.com'
    • The complete e-mail address of the destination e-mail address, for example, 'aqdb1@acme.com'
    • The name of the destination database, for example, 'aqdb1'
    • The URL of the destination database servlet, for example,
       http://aq-sun.us.oracle.com:8000/aqserv/servlet/AQTestServlet
      
      
    • The user name and password to access the destination database servlet (user name is ORACLE_SMTP_AGENT; password is established in "Web Server Setup").
    • The host and port for LDAP lookup. For example, host=ldaphost, port=389.
    • The base distinguished name (DN) for LDAP lookup, that is, the DN of the destination database in the LDAP server, for example, 'cn=aqdb1, cn=oraclecontext,cn=acme,cn=com'.
    • The login DN and password for LDAP lookup, for example NULL for anonymous binds.
  4. Register the rule using dbms_aqst:
    declare
       status binary_integer;
    begin
       status := dbms_aqst.register_db(
          'aqdb1', -- email user account for aqdb1
          'welcome', -- email user password
          'acme.com', -- email user domain
          'aqdb1@acme.com', -- complete email address
          'aqdb1', -- name of destination database
          'http://aq-sun:8000/aqserv/servlet/AQTestServlet', -- URL to access 
    the destination database servlet
          'welcome', -- password of ORACLE_SMTP_AGENT
          'ldaphost', -- LDAP host for lookup client certificates
          '389', -- LDAP port for LDAP lookup
          'cn=aqdb1,cn=oraclecontext,cn=acme,cn=com', -- base DN of LDAP lookup
          NULL, NULL -- anonymous bind
          );
       dbms_output.put_line('register DB status: ' || status);
    end;
    
  5. Make sure the operation returns status 0.

After the setup is complete, an AQ agent can send e-mail messages to the database e-mail address to perform AQ operations. The AQ operations should be constructed according to IDAP, signed using the Oracle e-mail S/MIME toolkit, and sent as a binary attachment with the name including IDAP_MESSAGE.

Using HTTP to Access the AQ XML Servlet

The procedures for an AQ client to make a request to the AQ servlet using HTTP and for the AQ servlet to process the request are as follows:

AQ Client Request to the AQ Servlet Using HTTP

  1. The client opens an HTTP(S) connection to the server.

    For example, https://aq.us.oracle.com:8000/aqserv/servlet/AQTestServlet

    This opens a connection to port 8000 on aq.us.oracle.com.

  2. The client logs in to the server by either:
    • HTTP basic authentication (with or without SSL)
    • SSL certificate-based client authentication
  3. The client constructs the XML message representing the Send, Publish, Receive or Register request.

    Example:

    <?xml version="1.0"?>
    <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
          <Body>
    
            <AQXmlSend  xmlns = "http://ns.oracle.com/AQ/schemas/access">
              <producer_options>
                <destination>OE.OE_NEW_ORDERS_QUE</destination>
              </producer_options>
           
              <message_set>
                <message_count>1</message_count>             
                <message>
                  <message_number>1</message_number>   
                  <message_header>
                               <correlation>XML_ADT_SINGLE_ENQ</correlation>
                       <sender_id>
                          <agent_name>john</agent_name>
                      </sender_id>
                  </message_header>
                  <message_payload>  
                  <ORDER_TYP>
                         <ORDERNO>100</ORDERNO>
                         <STATUS>NEW</STATUS>
                         <ORDERTYPE>NORMAL</ORDERTYPE>
                         <ORDERREGION>EAST</ORDERREGION>
                         <CUSTOMER>
                            <CUSTNO>1001233</CUSTNO>
                            <CUSTID>JOHN</CUSTID>
                            <NAME>AMERICAN EXPRESS</NAME>
                            <STREET>EXPRESS STREET</STREET>
                            <CITY>REDWOOD CITY</CITY>
                            <STATE>CA</STATE>
                            <ZIP>94065</ZIP>
                            <COUNTRY>USA</COUNTRY>
                         </CUSTOMER>
                         <PAYMENTMETHOD>CREDIT</PAYMENTMETHOD>
                         <ITEMS>
                            <ITEMS_ITEM>
                               <QUANTITY>10</QUANTITY>
                               <ITEM>
                                  <TITLE>Perl</TITLE>
                                  <AUTHORS>Randal</AUTHORS>
                                  <ISBN>ISBN20200</ISBN>
                                  <PRICE>19</PRICE>
                               </ITEM>
                               <SUBTOTAL>190</SUBTOTAL>
                            </ITEMS_ITEM>
                          </ITEMS>
                         <CCNUMBER>NUMBER01</CCNUMBER>
                         <ORDER_DATE>2000-08-23 0:0:0</ORDER_DATE>
                   </ORDER_TYP>
                 </message_payload>
                </message>
              </message_set>
              </AQXmlSend>
          </Body>
    </Envelope> 
    
    
    
  4. The client sends an HTTP POST to the servlet at the remote server.

    See the $ORACLE_HOME/demo directory for sample code of POST requests using HTTP.

AQ Servlet Processes a Request Using HTTP

  1. The server accepts the client HTTP(S) connection.
  2. The server authenticates the user (AQ agent) specified by the client.
  3. The server receives the POST request.
  4. The AQ servlet is invoked.

    If this is the first request being serviced by this servlet, the servlet is initialized--its init() method is invoked. The init () method creates a connection pool to the Oracle server using the AQxmlDataSource parameters (SID, host, port, AQ servlet super-user name, password) provided by the client.

  5. The servlet processes the message as follows:
    • If this is the first request from this client, a new HTTP session is created. The XML message is parsed and its contents are validated. If a session ID is passed by the client in the HTTP headers, then this operation is performed in the context of that session. This is described in detail in the next section.
    • The servlet determines which object (queue and topic) the agent is trying to perform operations on:

      For example, in the client request (step 3 in "AQ Client Request to the AQ Servlet Using HTTP"), the agent JOHN is trying to access OE.OE_NEW_ORDERS_QUE.

    • The servlet looks through the list of database users that map to this AQ agent (using the AQ$INTERNET_USERS view). If any one of these db_users has privileges to access the queue/topic specified in the request, the AQ servlet super-user creates a session on behalf of this db_user.

      For example, where the agent JOHN is mapped to the database user OE using the DBMS_AQADM.ENABLE_DB_ACCESS call, the servlet will create a session for the agent JOHN with the privileges of database user OE. (See "Mapping the AQ Agent to Database Users" for information on ENABLE_DB_ACCESS.)

    • A new database transaction is started if no transaction is active in the HTTP session. Subsequent requests in the session will be part of the same transaction until an explicit COMMIT or ROLLBACK request is made.
    • The requested operation (SEND/PUBLISH/RECEIVE/REGISTER/COMMIT/ROLLBACK) is performed.
    • The response is formatted as an XML message and sent back the client.

      For example, the response for the preceding request may be as follows:

       <Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
         <Body>
            <AQXmlSendResponse xmlns="http://ns.oracle.com/AQ/schemas/access">
               <status_response>
                  <status_code>0</status_code>
               </status_response>
               <send_result>
                  <destination>OE.OE_NEW_ORDERS_QUE</destination>
                  <message_id>12341234123412341234123412341234</message_id>
               </send_result>
            </AQXmlSendResponse>
         </Body>
      </Envelope>
      
      
    • The response also includes the session id in the HTTP headers as a cookie. For example, Tomcat sends back session IDs as JSESSIONID=239454ds2343. If the operation does not commit the transaction, the transaction will remain active until an explicit commit/rollback call is received. The effects of the transaction are visible only after it is committed. If the transaction remains inactive for 120 seconds, it is automatically aborted.

User Sessions and Transactions

After a client is authenticated and connects to the AQ servlet, an HTTP session is created on behalf of the user. The first request in the session also implicitly starts a new database transaction. This transaction remains open until it is explicitly committed or aborted. The responses from the servlet includes the session ID in the HTTP headers as cookies.

If the client wishes to continue work in the same transaction, it must include this HTTP header containing the session ID cookie in subsequent requests. This is automatically done by most Web browsers. However, if you are using a Java or C client to post requests, this has to be done programmatically. An example of a Java program used to post requests as part of the same session is given in $ORACLE_HOME/demo directory.

An explicit commit or rollback must be issued to end the transaction. The commit or rollback requests can also be included as part of other AQ operations (Send, Publish, Receive, Register).

Each HTTP session has a default timeout of 120 seconds. If the user does not commit or rollback the transaction in 120 seconds after the last request that session, the transaction is automatically aborted. This timeout can be modified in the init() method of the servlet by using setSessionMaxInactiveTime(). See "Customizing the AQ Servlet" for more information.

Using HTTP and HTTPS for Advanced Queuing Propagation

Using Advanced Queuing propagation in Oracle9i, you can propagate over HTTP and HTTPS (HTTP over SSL) instead of Oracle Net Services (formerly Net8). HTTP, unlike Oracle Net Services, is easy to configure for firewalls.

High-Level Architecture

HTTP AQ propagation uses the infrastructure for Internet access to AQ as its basis. The background process doing propagation pushes messages to an AQ Servlet that enqueues them into the destination database, as shown in Figure 17-3.

Figure 17-3 HTTP Advanced Queuing Propagation

Text description of adque445.gif follows
Text description of the illustration adque445.gif


Since HTTP propagation is different from Net Services in only the transport, most of the setup is the same as for Net Services propagation. The additional steps and differences are outlined in the following section.

Setting Up for HTTP Propagation (and the Differences from Net Services Propagation)

  1. The dblink at the source database must be created differently. The connect string should specify the protocol as HTTP and specify the host and port of the Web server running the AQ servlet. The username and password of the dblink will be used for authentication with the Web server/servlet runner.
  2. An AQ servlet that connects to the destination database should be deployed.
  3. The source database must be enabled for running Java and XML.

The rest of the steps for propagation remain the same. The administrator must use dbms_aqadm.schedule_propagation to start propagation. Propagation can be disabled with the dbms_aqadm.disable_propagation_schedule and re-enabled using dbms_aqadm.enable_propagation_schedule. The background processes, the job queue processes propagate the messages to the destination database.The job_queue_processes parameters must be at least 2 for propagation to take place.

Any application can be easily set up to use AQ HTTP propagation without any change to the existing code, by following steps 1-3. Similarly an application using AQ http propagation can easily switch back to Net Services propagation just by re-creating the dblink with a Net Services connection string, without any other changes.

Setting Up for AQ propagation over HTTP

  1. The source database must be created for running Java and XML.
  2. Create the dblink with protocol as HTTP and the host and port of the Web server running the AQ servlet, with the username and password for authentication with the webserver/servlet runner.

    For example, if the webserver is running on the machine webdest.oracle.com and listening for requests on port 8081, then the connect string of the database is as follows:

    (DESCRIPTION=(ADDRESS=(PROTOCOL=http)(HOST=webdest.oracle.com)(PORT=8081))
    
    

    If SSL is used, then specify HTTPS as the protocol in the connect string.

    The database link is created as follows:

    create public database link dba connect to john identified by welcome using 
    '(DESCRIPTION=(ADDRESS=(PROTOCOL=http)(HOST=webdest.oracle.com)(PORT=8081))'
    ;
    
    

    Where user john with password welcome is used to authenticate with the Web server and is also known by the term AQ HTTP agent.

  3. You can optionally set a proxy to use for all HTTP requests from the database. Use the UTL_HTTP.SET_PROXY procedure, as described in Oracle9i Supplied PL/SQL Packages and Types Reference.
  4. If HTTP over SSL is used, then a database wallet must be created for the source database. The wallet must be open for the duration of propagation. If HTTPS is used for propagation, communication between the source database and the AQ servlet is encrypted and the HTTPS server is authenticated with the source database. The database uses the database link username-password to authenticate itself with the HTTPS server.
  5. Deploy the AQ Servlet.

    Create a class AQPropServlet that extends AQxmlServlet as described in [create the AQ XML Servlet Class]. This servlet must connect to the destination database. The servlet must be deployed on the Web server in the path aqserv/servlet.

    In Oracle9i, the propagation servlet name and deployment path are fixed; that is, they must be AQPropServlet and the servlet, respectively.

  6. Make sure that the AQ HTTP agent (John) is authorized to perform AQ operations. This is done at the destination database:
    1. Register the AQ agent as follows:
      dbms_aqadm.create_aq_agent(agent_name => 'John', enable_http => true);
      
      
    2. Map the AQ agent to a database user as follows:
      dbms_aqadm.enable_db_access(agent_name =>'John', db_username =>'CBADM')'
          
      
  7. Start propagation at the source site by calling:
    dbms_aqdm.schedule_propagation.
    dbms_aqadm.schedule_propagation('src_queue', 'dba');
    

Using SMTP to Access the AQ Servlet

The general procedure for an AQ client to make a request to the AQ servlet using SMTP is as follows:

  1. The client creates a message with the AQ XML client request. The client signs the message with its private key using the Oracle S/MIME toolkit.
  2. The client names the message with a substring, IDAP_MESSAGE, and sends it as a binary attachment to the database e-mail address.
  3. The e-mail server receives the message.
  4. The e-mail server triggers the rule registered for the database e-mail address, which does the following:
    1. Connects to the LDAP server and retrieves the certificate of the sending AQ agent
    2. Verifies the signature of the message
    3. Connects to the Web server as user ORACLE_SMTP_AGENT if authentication succeeds, and sends an HTTP POST message containing the client request

The procedure for the AQ servlet to process a request is described in "AQ Servlet Processes a Request Using HTTP". When the servlet sends a response, the e-mail server sends an e-mail message containing the XML response to the address specified in the reply-to field of the original e-mail message.

Customizing the AQ Servlet

The oracle.AQ.xml.AQxmlServlet provides the API to set the connection pool size, session timeout, style sheet, and callbacks before and after AQ operations.

Setting the Connection Pool Size

The AQ data source is used the specify the backend database to which the servlet connects to perform AQ operations. It contains the database SID, host name, listener port and the username/password of the AQ servlet super-user.

The data source is represented by the AQxmlDataSource class, which can be set using the setAQDataSource method in the servlet. See the Oracle9i Supplied Java Packages Reference for more information.

The AQ data source creates a pool of connections to the database server. By default the maximum size of the pool is set to 50 and the minimum is set to 1. The number of connections in the pool grows and shrinks dynamically based on the number of incoming requests. If you want to change the maximum limit on the number of connections, you must specify a cache size using the AQxmlDataSource.setCacheSize(size) method.

Setting the Session Timeout

After a client is authenticated and connects to the AQ servlet, an HTTP session is created on behalf of the user. The first request in the session also implicitly starts a new database transaction. This transaction remains open until it is explicitly committed or aborted.

Each HTTP session has a default timeout of 120 seconds. If the user does not commit or rollback the transaction in 120 seconds after the last request that session, the transaction is automatically aborted. This timeout can be specified in the init() method of the servlet by using setSessionMaxInactiveTime() method.

The servlet is initialized as follows:

public class AQTestServlet extends oracle.AQ.xml.AQxmlServlet
{ 
  /* The init method must be overloaded to specify the AQxmlDataSource */
  public void init()
  {
      AQxmlDataSource  db_drv = null;

      try
      {
        /* Create data source with username, password, sid, host, port */
        db_drv = new AQxmlDataSource("AQADM", "AQADM", 
                                     "test_db", "sun-248", "5521");

           /* Set the minimum cache size to 10 connections */
                   db_drv.getCacheSize(10);

        this.setAQDataSource(db_drv);

           /* Set the transaction timeout to 180 seconds */    
           this.setSessionMaxInactiveTime(180);
      }
      catch (Exception ex)
      {
          System.out.println("Exception in init: " + ex);
      }
}

Setting the Style Sheet for All Responses from the Servlet

The AQ servlet sends back responses in XML. The servlet administrator can specify a style sheet that is to be set for all responses sent back from this servlet. This can be done by invoking the setStyleSheet(type,href)or the setStyleSheetProcessingInstr(proc_instr) in init() method of the servlet.

For example, to include the following style sheet instruction for all responses, do the following:

<?xml-stylesheet type="text/xsl" 
href="http://sun-248/stylesheets/bookOrder.xsl"?>

The servlet is initialized as follows:

public class AQTestServlet extends oracle.AQ.xml.AQxmlServlet
{ 
  /* The init method must be overloaded to specify the AQxmlDataSource */
  public void init()
  {
      AQxmlDataSource  db_drv = null;

      try
      {
        /* Create data source with username, password, sid, host, port */
        db_drv = new AQxmlDataSource("AQADM", "AQADM", 
                                     "test_db", "sun-248", "5521");

        this.setAQDataSource(db_drv);

           /* Set the bookOrder.xsl style sheet for all responses */
        setStyleSheet("text/xsl", 
"http://sun-248:8000/stylesheets/bookOrder.xsl");
      }
      catch (Exception ex)
      {
          System.out.println("Exception in init: " + ex);
      }
}

Callbacks Before and After AQ Operations

Using the AQ servlet, you can register callbacks that will be invoked before and after AQ operations are performed. This allows users to perform AQ and non-AQ operations in the same transaction.

To receive callbacks, users register an object that implements the oracle.AQ.xml.AQxmlCallback interface. The AQxmlCallback interface has the following methods:

public interface AQxmlCallback
{

  /** Callback invoked before any AQ operations are performed by the servlet */
  public void beforeAQOperation(HttpServletRequest request,                HttpServletResponse 
response, 
                                               AQxmlCallbackContext ctx);
  
  /** Callback invoked after any AQ operations are performed by the servlet */
  public void afterAQOperation(HttpServletRequest request, HttpServletResponse 
response, 
                                          AQxmlCallbackContext ctx);
}

The callbacks are passed in the HTTP request and response streams and an AQxmlCallbackContext object. The object has the following methods:

Example

Before any AQ operation in the servlet, you want to insert a row in the EMP table. Do this by creating a callback class and associating it with a particular servlet as follows:

import javax.servlet.*;
import javax.servlet.http.*;
import oracle.AQ.xml.*;
import java.sql.*;
import javax.jms.*;

/**
 * This is a sample AQ Servlet callback 
 */
public class TestCallback implements oracle.AQ.xml.AQxmlCallback
{ 

   /** Callback invoked before any AQ operations are performed by the servlet */
  public void beforeAQOperation(HttpServletRequest request,                HttpServletResponse 
response, 
                   AQxmlCallbackContext ctx)
  {
         Connection conn = null;
      System.out.println("Entering BeforeAQ Callback ...");

         try
      {
            // Get the connection object from the callback context
              conn = ctx.getDBConnection();

            // Insert value in the EMP table
            PreparedStatement pstmt = 
            conn.prepareStatement ("insert into EMP (EMPNO, ENAME) values (100, 
'HARRY')");
            pstmt.execute ();
            pstmt.close();
      }
      catch (Exception ex)
      {
          System.out.println("Exception ex: " + ex);
      } 
  }
  
  /** Callback invoked after any AQ operations are performed by the servlet */
  public void afterAQOperation(HttpServletRequest request,          HttpServletResponse 
response, 
                  AQxmlCallbackContext ctx)      
  {
      System.out.println("Entering afterAQ Callback ...");
      
      try
      {
            // Set style sheet for response
         ctx.setStyleSheetProcessingInstr(
                    "type='text/xsl href='http://sun-248/AQ/xslt23.html'");

      }
      catch (Exception aq_ex)
      {
            System.out.println("Exception: " + ex);
   
      }
  }
}
 
/* Sample AQ servlet - using user-defined callbacks */ 
public class AQTestServlet extends oracle.AQ.xml.AQxmlServlet
{ 
  
  /* The init method must be overloaded to specify the AQxmlDataSource */
  public void init()
  {
      AQxmlDataSource  db_drv = null;
         AQxmlCallback    serv_cbk  = new TestCallback();

      try
      {
        /* Create data source with username, password, sid, host, port */
        db_drv = new AQxmlDataSource("AQADM", "AQADM", "test_db", "sun-248", 
"5521");

        this.setAQDataSource(db_drv);

           /* Set Callback */
           setUserCallback(serv_cbk);

      }
      catch (Exception ex)
      {
          System.out.println("Exception in init: " + ex);
      }
}

Go to previous page Go to next page
Oracle
Copyright © 1996, 2002 Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Home
Go To Product List
Book List
Go To Table Of Contents
Contents
Go To Index
Index

Master Index

Feedback