Oracle® Streams Advanced Queuing User's Guide and Reference Release 10.1 Part Number B10785-01 |
|
|
View PDF |
You can access Oracle Streams Advanced Queuing (AQ) over the Internet by using Simple Object Access Protocol (SOAP). Internet Data Access Presentation (IDAP) is the SOAP specification for Oracle Streams AQ operations. IDAP defines XML message structure for the body of the SOAP request. An IDAP-structured message is transmitted over the Internet using HTTP.
This chapter contains these topics:
Figure 17-1 shows the architecture for performing Oracle Streams AQ operations over HTTP. The major components are:
Oracle Streams AQ client program
Web server/Servlet Runner hosting the Oracle Streams AQ servlet
Oracle Database server
The Oracle Streams AQ client program sends XML messages (conforming to IDAP) to the Oracle Streams AQ servlet. Any HTTP client, for example Web browsers, can be used. The Web server/Servlet Runner hosting the Oracle Streams AQ servlet interprets the incoming XML messages. Examples include Apache/Jserv or Tomcat. The Oracle Streams AQ servlet connects to the Oracle Database server and performs operations on the users' queues.
Figure 17-1 Architecture for Performing Oracle Streams AQ Operations Using HTTP
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:
All request and response tags are scoped in the SOAP namespace.
Oracle Streams AQ operations are scoped in the IDAP namespace.
The sender includes namespaces in IDAP elements and attributes in the SOAP body.
The receiver processes SOAP messages that have correct namespaces; for the requests with incorrect namespaces, the receiver returns an invalid request error.
The SOAP namespace has the value http://schemas.xmlsoap.org/soap/envelope/
The IDAP namespace has the value http://ns.oracle.com/AQ/schemas/access
SOAP structures a message request or response as follows:
SOAP envelope (the root or top element in an XML tree))
SOAP header (first element under the root)
SOAP body (the Oracle Streams AQ XML document)
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 can 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.
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, 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 Oracle Streams AQ operations, the SOAP body must contain an Oracle Streams AQ XML document. The Oracle Streams AQ XML document has the namespace http://ns.oracle.com/AQ/schemas/access
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.
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.
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:
The SOAP root element is the top element in the XML tree.
The SOAP payload headers contain additional information that must travel with the request.
The method request is represented as an XML element with additional elements for parameters. It is the first child of the SOAP:Body
element. This request can be one of the Oracle Streams AQ XML client requests described in the next section.
The response is the return value or an error or exception that is passed back to the client.
At the receiving site, a request can have one of the following outcomes:
The HTTP infrastructure on the receiving site is able to receive and process the request. In this case, the HTTP infrastructure passes the headers and body to the SOAP infrastructure.
The HTTP infrastructure on the receiving site cannot receive and process the request. In this case, the result is an HTTP response containing an HTTP error in the status field and no XML body.
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. In this case, the result of the method request consists of a response or error.
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 this case, the result of the method is an error that prevented the dispatching infrastructure on the receiving side from successful completion.
In the last two cases, additional message headers can be present in the results of the request for extensibility.
The body of a SOAP message is an IDAP message. This XML document has the namespace http://ns.oracle.com/AQ/schemas/access
. The body represents:
Server responses to client requests for enqueue, dequeue, and registration
Notifications from the server to the client.
Note: Oracle Streams AQ Internet Access is supported only for 8.1or higher style queues. 8.0-compatible queues cannot be accessed using IDAP. |
Client send and publish requests use the following methods:
AQXmlSend
—to enqueue to a single-consumer queue
AQXmlPublish
—to enqueue to multiconsumer queues/topics
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.
|
- | visibility
|
- | 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 |
- | 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
|
- | recipient_list —list of recipients; overrides the default subscriber list. Each recipient consists of:
|
- | message_state — state of the message is filled in automatically during dequeue
|
- | 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 |
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 |
See Also: "Internet Integration and Internet Data Access Presentation" for an explanation of IDAP message payloads |
The following examples show enqueue requests using different message and queue types.
Example 17-1 IDAP Enqueue Request: 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>
Example 17-2 IDAP Enqueue Request: 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>
Example 17-3 IDAP Enqueue Request: Sending a Message to a JMS Queue
The Java Message Service (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>
Example 17-4 IDAP Enqueue Request: 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>
Example 17-5 IDAP Enqueue Request: 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>
Example 17-6 IDAP Enqueue Request: 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 use the AQXmlReceive
method, which takes the arguments and argument attributes shown in Table 17-2. Required arguments are shown in bold.
Table 17-2 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
|
- | 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:
A condition is specified as a Boolean expression using syntax similar to the To specify dequeue conditions on a message payload (object payload), use attributes of the object type in clauses. You must prefix each attribute with |
- | visibility
|
- | dequeue_mode —Specifies the locking action associated with the dequeue. The dequeue_mode can be specified as one of:
|
- | navigation_mode —Specifies the position of the message that is 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:
|
- | 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
.
Example 17-7 IDAP Dequeue Request: 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>
Example 17-8 IDAP Dequeue Request: 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>
Example 17-9 IDAP Dequeue Request: 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>
Example 17-10 IDAP Dequeue Request: 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>
Example 17-11 IDAP Dequeue Request: Receiving Messages and Committing
In the dequeue request examples, if you include AQXmlCommit
at the end of the RECEIVE
request, then the transaction is committed upon completion of the operation. In "IDAP Dequeue Request: 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>
Example 17-12 IDAP Dequeue Request: 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 use the AQXmlRegister method, which takes the arguments and argument attributes shown in Table 17-3. Required arguments are shown in bold.
Table 17-3 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
|
- | 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 . |
Example 17-13 IDAP Register Request: 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>
A request to commit all actions performed by the user in a session uses the AQXmlCommit
method.
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.
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-4.
Table 17-4 IDAP Server Response to an Enqueue to a Single-Consumer Queue (AQXmlSendResponse)
Response | Attribute |
---|---|
status_response |
status_code —indicates success (0) or failure (-1)
|
send_result |
destination —where the message was sent
|
Example 17-16 Server Request: 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-5.
Table 17-5 IDAP Server Response to an Enqueue to a Multiconsumer Queue or Topic (AQXmlPublishResponse)
Response | Attribute |
---|---|
status_response |
status_code —indicates success (0) or failure (-1)
|
publish_result |
destination —where the message was sent
|
Example 17-17 IDAP Server Request: 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>
The response to a dequeue request uses the AQXmlReceiveResponse
method. The components of the response are shown in Table 17-6.
Table 17-6 IDAP Server Response to a Dequeue from a Queue or Topic (AQXmlReceiveResponse)
Response | Attribute |
---|---|
status_response |
status_code —indicates success (0) or failure (-1)
|
receive_result |
destination —where the message was sent
|
Example 17-18 IDAP Dequeue Response: 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>
Example 17-19 IDAP Dequeue Response: 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>
The response to a register request uses the AQXmlRegisterResponse
method, which consists of status_response
. (See Table 17-6 for a description of status_response
.)
The response to a commit request uses the AQXmlCommitResponse method, which consists of status_response
. (See Table 17-6 for a description of status_response
.)
Example 17-20 IDAP Commit Response
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>
The response to a rollback request uses the AQXmlRollbackResponse
method, which consists of status_response
. (See Table 17-6 for a description of status_response
.)
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:
notification_options
, which has
destination
—the destination queue/topic on which the event occurred
consumer_name
—in case of multiconsumer queues/topics, this refers to the consumer name for which the event occurred
message_set
—the set of message properties.
In case of an error in any of the preceding requests, a FAULT
is generated. The FAULT
element consists of:
faultcode
- error code for fault
faultstring
- indicates a client error or a server error. A client error means that the request is not valid. Server error indicates that the Oracle Streams AQ servlet has not been set up correctly
detail
, which consists of
status_response
Example 17-21 IDAP Response in Case of Error
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>
IDAP exposes the SOAP schema and the Oracle Streams AQ XML schema to the client. All documents sent are validated against these schemas:
SOAP schema—http://schemas.xmlsoap.org/soap/envelope/
Oracle Streams AQ XML schema—http://ns.oracle.com/AQ/schemas/access
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 through 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>
The IDAP schema describes the contents of the IDAP body for Internet access to Oracle Streams AQ features.
<?xml version="1.0"?> <!-- ****************** Oracle Streams 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" /> <!-- ****************** Oracle Streams 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> <!-- ****************** Oracle Streams 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>
The Oracle Streams 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 Oracle Streams AQ XML servlet can be found in$ORACLE_HOME/rdbms/demo/ . Check the aqxmlREADME.txt file for details. |
The Oracle Streams 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 Oracle Streams AQ XML document.
The Oracle Streams AQ servlet creates a JDBC Oracle Call Interface (OCI) connection pool to connect to the Oracle Database 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 Oracle XML API Reference for information on the AQxmlDataSource
class.
The user specified in the AQxmlDataSource is the Oracle Streams AQ servlet super-user. This user must have CREATE SESSION
privilege and EXECUTE
privilege on the DBMS_AQIN
package.
Example 17-22 Creating Oracle Streams AQ XML Servlet Class
Create a user AQADM
as the Oracle Streams AQ servlet super-user 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 super-user as follows:
import javax.servlet.*; import javax.servlet.http.*; import oracle.AQ.xml.*; /** * This is a sample Oracle Streams 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 Oracle Streams AQ operations.
Note: The example assumes that the Oracle Streams 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 theoracle.AQ.xml.AQxmlServlet20 class instead of the AQxmlServlet class and override the appropriate write() method. |
The Oracle Streams 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).
Because the servlet uses JDBC OCI drivers to connect to the Oracle Database server, the Oracle Database client libraries must be installed on the computer hosting the servlet.
The LD_LIBRARY_PATH
must contain $ORACLE_HOME/lib
.
The servlet can be compiled using JDK 1.2.x, JDK 1.3.x or JDK 1.4.x libraries.
For JDK 1.4.x, the CLASSPATH
must contain:
$ORACLE_HOME/jdbc/lib/classes12.jar $ORACLE_HOME/jdbc/lib/ojdbc14.jar $ORACLE_HOME/jdbc/lib/orai18n.jar $ORACLE_HOME/jlib/jndi.jar $ORACLE_HOME/jlib/jta.jar $ORACLE_HOME/lib/servlet.jar $ORACLE_HOME/lib/xmlparserv2.jar $ORACLE_HOME/lib/xschema.jar $ORACLE_HOME/lib/xsu12.jar $ORACLE_HOME/rdbms/jlib/aqapi.jar $ORACLE_HOME/rdbms/jlib/aqxml.jar $ORACLE_HOME/rdbms/jlib/jmscommon.jar
For JDK 1.3.x, the CLASSPATH
must contain:
$ORACLE_HOME/jdbc/lib/classes12.jar $ORACLE_HOME/jdbc/lib/orai18n.jar $ORACLE_HOME/jlib/jndi.jar $ORACLE_HOME/jlib/jta.jar $ORACLE_HOME/lib/servlet.jar $ORACLE_HOME/lib/xmlparserv2.jar $ORACLE_HOME/lib/xschema.jar $ORACLE_HOME/lib/xsu12.jar $ORACLE_HOME/rdbms/jlib/aqapi.jar $ORACLE_HOME/rdbms/jlib/aqxml.jar $ORACLE_HOME/rdbms/jlib/jmscommon.jar
For JDK 1.2.x, the CLASSPATH
must contain:
$ORACLE_HOME/jdbc/lib/classes12.jar $ORACLE_HOME/jdbc/lib/orai18n.jar $ORACLE_HOME/jlib/jndi.jar $ORACLE_HOME/jlib/jta.jar $ORACLE_HOME/lib/xmlparserv2.jar $ORACLE_HOME/lib/servlet.jar $ORACLE_HOME/lib/xschema.jar $ORACLE_HOME/lib/xsu12.jar $ORACLE_HOME/rdbms/jlib/aqapi.jar $ORACLE_HOME/rdbms/jlib/aqxml.jar $ORACLE_HOME/rdbms/jlib/jmscommon.jar
After setting the CLASSPATH
, compile the servlet using javac
or any other Java compiler.
Note: If you are using the Oracle Streams AQ XML Servlet or the Oracle Streams AQ JMS API with JDK1.2, versions 1.2.2_05a or higher, then you must turn off the JIT compiler. SetJAVA_COMPILER = none to avoid problems in multithreaded applications. |
After the servlet is installed, the Web server must be configured to authenticate all users that send POST
requests to the Oracle Streams AQ servlet. The Oracle Streams AQ servlet allows only authenticated users to access the servlet. If the user is not authenticated, then 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.
In the context of the Oracle Streams AQ servlet, the username that is used to connect to the Web server is known as the Oracle Streams AQ HTTP agent or Oracle Streams AQ Internet user.
Example 17-23 Restricting Access To Servlets in Apache
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>
After authenticating the users who connect to the Oracle Streams AQ servlet, you establish which operations the users are authorized to perform by doing the following:
Register the Oracle Streams AQ agent for Internet access.
Map the Oracle Streams AQ agent to one or more database users.
To register the Oracle Streams AQ agent for Internet access, use DBMS_AQADM.CREATE_AQ_AGENT
. The CREATE_AQ_AGENT
procedure takes an agent_name.
Example 17-24 Creating and Registering an Oracle Streams AQ Agent
Create an Oracle Streams AQ agent JOHN
to access the Oracle Streams 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 Oracle Streams AQ agents function similarly to CREATE_AQ_AGENT
. These procedures are documented in the PL/SQL Packages and Types Reference.
To map an Oracle Streams AQ agent to one or more database users, use DBMS_AQADM.ENABLE_DB_ACCESS
. With the ENABLE_DB_ACCESS
procedure, you give an Oracle Streams 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 17-25 Mapping Oracle Streams AQ Agent to Database Users
Map the Oracle Streams 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');
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 Oracle Streams AQ servlet creates a database session as one of the database users (db_user
) t
hat maps to the Oracle Streams AQ agent. The db_user
selected has privileges to access the queue specified in the request. For example:
Oracle Streams 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
. Because OE.OE_NEW_ORDERS_QUE
is in the OE schema, it does a CREATE SESSION
as OE to perform the requested operation.
The Oracle Streams AQ servlet creates a connection pool to the Oracle Database server using the Oracle Streams AQ servlet super-user. This super-user creates sessions on behalf of db_users
that the Oracle Streams 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.
Example 17-26 Granting Connect to Oracle Streams AQ Servlet Super-User
The Oracle Streams AQ servlet super-user can be granted CONNECT
THROUGH
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 Oracle Streams 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 Oracle Streams AQ agents, the protocols they are enabled for, and the mapping between Oracle Streams AQ agents and database users. Example entries in this view are shown in Table 17-7.
An LDAP server is required if:
The lookup_type
destination attribute is specified as LDAP. In this case the destination name is resolved to a schema.queue_name
using the LDAP server.
You use agent_alias
instead of (agent_name, address, protocol)
. If an agent_alias
is specified in a client request, then it is resolved to agent_name, address, protocol
using the LDAP server.
Example 17-27 Specifying the LDAP Server Context for Oracle Streams AQ XML Servlet
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) ; } }
The procedures for an Oracle Streams AQ client to make a request to the Oracle Streams AQ servlet using HTTP and for the Oracle Streams AQ servlet to process the request are as follows:
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.
The client logs in to the server by either:
HTTP basic authentication (with or without SSL)
SSL certificate-based client authentication
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>
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.
The server accepts the client HTTP(S) connection.
The server authenticates the user (Oracle Streams AQ agent) specified by the client.
The server receives the POST
request.
The Oracle Streams AQ servlet is invoked.
If this is the first request being serviced by this servlet, then the servlet is initialized—its init() method
is invoked. The init () method
creates a connection pool to the Oracle Database server using the AQxmlDataSource parameters (SID, host, port, Oracle Streams AQ servlet super-username, password) provided by the client.
The servlet processes the message as follows:
If this is the first request from this client, then 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 "Oracle Streams AQ Client Request to the Oracle Streams 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 Oracle Streams 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, then the Oracle Streams 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 creates a session for the agent JOHN
with the privileges of database user OE
.
A new database transaction is started if no transaction is active in the HTTP session. Subsequent requests in the session are 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 can 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, then the transaction remains 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, then it is automatically terminated.
After a client is authenticated and connects to the Oracle Streams 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 terminated. 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, then it must include this HTTP header containing the session ID cookie in subsequent requests. This is automatically accomplished by most Web browsers. However, if you are using a Java or C client to post requests, then this must be accomplished 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 applied to end the transaction. The commit or rollback requests can also be included as part of other Oracle Streams 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, then the transaction is automatically terminated. This timeout can be modified in the init() method of the servlet by using setSessionMaxInactiveTime()
.
Using Oracle Streams AQ propagation in Oracle Database, you can propagate over HTTP and HTTPS (HTTP over SSL) instead of Oracle Net Services. HTTP, unlike Oracle Net Services, is easy to configure for firewalls.
HTTP Oracle Streams AQ propagation uses the infrastructure for Internet access to Oracle Streams AQ as its basis. The background process doing propagation pushes messages to an Oracle Streams AQ Servlet that enqueues them into the destination database, as shown in Figure 17-2.
Because 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.
The database link 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 Oracle Streams AQ servlet. The username and password of the database link are used for authentication with the Web server/servlet runner.
An Oracle Streams AQ servlet that connects to the destination database should be deployed.
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 Oracle Streams AQ HTTP propagation without any change to the existing code, by following steps 1-3. Similarly an application using Oracle Streams AQ HTTP propagation can easily switch back to Net Services propagation just by re-creating the database link with a Net Services connection string, without any other changes.
The source database must be created for running Java and XML.
Create the database link with protocol as HTTP and the host and port of the Web server running the Oracle Streams AQ servlet, with the username and password for authentication with the Web Server/Servlet Runner.
For example, if the Web Server is running on the computer 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 Oracle Streams AQ HTTP agent.
Note: You cannot usenet_service_name in tnsnames.ora with the database link. Doing so results in error ORA-12538. |
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 PL/SQL Packages and Types Reference.
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, then communication between the source database and the Oracle Streams 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.
Deploy the Oracle Streams AQ Servlet.
Create a class AQPropServlet that extends AQxmlServlet as described in [create the Oracle Streams 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 Oracle Database, the propagation servlet name and deployment path are fixed; that is, they must be AQPropServlet
and the servlet, respectively.
Make sure that the Oracle Streams AQ HTTP agent (John) is authorized to perform Oracle Streams AQ operations. This is accomplished at the destination database:
Register the Oracle Streams AQ agent as follows:
DBMS_AQADM.CREATE_AQ_AGENT(agent_name => 'John', enable_http => true);
Map the Oracle Streams AQ agent to a database user as follows:
DBMS_AQADM.ENABLE_DB_ACCESS(agent_name =>'John', db_username =>'CBADM')'
Start propagation at the source site by calling:
dbms_aqdm.schedule_propagation. DBMS_AQADM.SCHEDULE_PROPAGATION('src_queue', 'dba');
The oracle.AQ.xml.AQxmlServlet provides the API to set the connection pool size, session timeout, style sheet, and callbacks before and after Oracle Streams AQ operations.
The Oracle Streams AQ data source is used the specify the back-end database to which the servlet connects to perform Oracle Streams AQ operations. It contains the database SID, host name, listener port and the username/password of the Oracle Streams 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 Oracle XML API Reference for more information.
The Oracle Streams 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, then you must specify a cache size using the AQxmlDataSource.setCacheSize(size)
method.
After a client is authenticated and connects to the Oracle Streams 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 terminated.
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 for that session, then the transaction is automatically terminated. This timeout can be specified in the init()
method of the servlet by using setSessionMaxInactiveTime()
method.
Example 17-28 Initializing the Oracle Streams AQ Servlet for HTTP: Setting the HTTP Session Timeout
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); } }
Oracle Streams AQ servlet sends back XML responses. The servlet administrator can specify a style sheet that is to be set for all responses sent back from this servlet. This can be accomplished by invoking the setStyleSheet(type,href)
or the setStyleSheetProcessingInstr(proc_instr)
in the init()
method of the servlet.
Example 17-29 Specifying a Stylesheet for Use in AQ XML Servlet Responses
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); } }
Using the Oracle Streams AQ servlet, you can register callbacks that are invoked before and after Oracle Streams AQ operations are performed. This allows users to perform Oracle Streams AQ operations and other operations in the same transaction.
To receive callbacks, users register an object that implements the oracle.AQ.xml.AQxmlCallback
interface.
Example 17-30 Registering Callbacks Invoked Before and After Performing Oracle Streams AQ Operations
The AQxmlCallback
interface has the following methods:
public interface AQxmlCallback { /** Callback invoked before any Oracle Streams AQ operations are performed by the servlet */ public void beforeAQOperation(HttpServletRequest request, HttpServletResponse response, AQxmlCallbackContext ctx); /** Callback invoked after any Oracle Streams 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:
The java.sql.Connection getDBConnection()
method gives a handle to the database connection that is used by the servlet for performing Oracle Streams AQ operations. Users can perform other SQL operations in the callback functions using this connection object.
You cannot call close()
, commit()
, or rollback()
methods
on this connection object.
org.w3c.org.Document parseRequestStream()
gives a DOM document representing the parsed request stream.
The void setStyleSheet(String type,String href)
method allows the user to set the style sheet for a particular call. So instead of specifying a single style sheet for all responses from this servlet, users can set style sheets for specific responses.
The style sheet specified in the callback overrides the style sheet (if any) specified for the servlet in the init()
method
Example 17-31 Inserting a Row in the EMP Table by Creating a Callback Class and Associating it with a Servlet
Before any Oracle Streams 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 Oracle Streams AQ Servlet callback */ public class TestCallback implements oracle.AQ.xml.AQxmlCallback { /** Callback invoked before any Oracle Streams 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 Oracle Streams 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 Oracle Streams 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); } }
The following frequently asked questions cover using Oracle Streams AQ and the Internet and Oracle Internet Directory.
IDAP is Internet Data Access Presentation. IDAP defines the message structure for the body of a SOAP request. An IDAP message encapsulates the Oracle Streams AQ request and response in XML. IDAP is used to perform Oracle Streams AQ operations such as enqueue, dequeue, send notifications, register for notifications, and propagation over the Internet standard transports—HTTP(s) and e-mail. In addition, IDAP encapsulates transactions, security, transformation, and the character set ID for requests.
Internet access functionality for Oracle Streams AQ is supported on Apache. This feature is certified to work with Apache, along with the Tomcat or Jserv servlet execution engines. However, the code does not prevent the servlet from working with other Web server and servlet execution engines that support Java Servlet 2.0 or higher interfaces.
You can create an alias to an Oracle Streams AQ agent in Oracle Internet Directory. You can use these Oracle Streams AQ agent aliases in the IDAP document sent over the Internet to perform Oracle Streams AQ operations. Using aliases prevents exposing the internal name of the Oracle Streams AQ agent.
Yes, you can use your own authentication framework for authentication. HTTP POST
requests to the Oracle Streams AQ Servlet for Oracle Streams AQ operations must be authenticated by the Web server. For 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 "Restrict AQ Servlet Access" AuthType Basic AuthUserFile /apache/htdocs/userdb/users require valid-user
</Limit>
</Location>
All types of events—system events, user events, and notifications on queues—can be registered with Oracle Internet Directory. System events are database startup, database shutdown, and system error events. User events include user log on and user log off, DDL statements (create, drop, alter), and DML statement triggers. Notifications on queues include OCI notifications, PL/SQL notifications, and e-mail notifications.
You can create aliases for an Oracle Streams AQ agent in Oracle Internet Directory. These aliases can be specified while performing Oracle Streams AQ operations-enqueue, dequeue, and notifications. This is specifically useful while performing Oracle Streams AQ operations over the Internet when you do not want to expose an internal agent name. An alias can be used in an Oracle Streams AQ operation (IDAP request).