PK -Aoa,mimetypeapplication/epub+zipPK-AiTunesMetadata.plistR artistName Oracle Corporation book-info cover-image-hash 263678087 cover-image-path OEBPS/dcommon/oracle-logo.jpg package-file-hash 845676741 publisher-unique-id E11013-04 unique-id 212594491 genre Oracle Documentation itemName Oracle® Streams Advanced Queuing User's Guide, 11g Release 2 (11.2) releaseDate 2011-07-22T07:06:56Z year 2011 PKO$nWRPK-AMETA-INF/container.xml PKYuPK-AOEBPS/qwnew.htm)x What's New in Oracle Streams Advanced Queuing?

What's New in Oracle Streams Advanced Queuing?

This chapter describes new features of the Oracle Database 11g Release 1 (11.1) and provides pointers to additional information. There are no new features for 11g Release 2 (11.2).

Notification Enhancements

The following notification enhancements are introduced:

Scalability for Streams Notifications

AQ Event Notification Infrastructure provides asynchronous communication of database events from the suppliers/publishers of their events to the consumers/registrations. The event monitor sends these notifications. In order to meet the demands of increased notification use, the notification server in 11g is enhanced to a parallel notification server consisting of a coordinator and a set of subordinate processes. The parallel notification server offers a capability to process a greater volume of notifications, faster notification processing and lower shared memory use for staging notification events.

Notification Grouping By Time

Sometimes a very large number of events occur in the database and it is important that applications not be overwhelmed with notifications. The preferred strategy is for notifications to be grouped and delivered at application-specified intervals and in application-specified formats. Oracle Streams AQ provides the infrastructure for notification grouping by time for AQ and DBCHANGE namespaces. Users have the option of specifying the grouping time interval and the predefined format in which to be notified at the end of those grouping intervals. Users can also specify when to start sending grouping notifications and how many times to send grouping notifications.

Better Diagnosability and Manageability

The following sections describe diagnosability:

New performance views and AWR support

This release adds new performance views for persistent messaging statistics and notification statistics. The Automatic Workload Repository (AWR) has also been enhanced for displaying queues with the most persistent messaging operations, allowing for easier diagnosability of AQ performance problems.

Dictionary View on Subscription Registrations

New dictionary views are provided to simplify subscription management for Oracle Streams Advanced Queuing. DBA_SUBSCR_REGISTRATIONS and USER_SUBSCR_REGISTRATIONS identify registered subscriptions, as well as detail information on the subscriptions. Runtime statistics for notifications are available with the V$SUBSCR_REGISTRATION_STATS view.

Queue Table Level Export and Import

Export import of queues is now fully supported at queue table level granularity. The user only needs to export the queue table. All the queues in the queue table, primary object grants, related objects like views, IOTs, rules are automatically exported.

Transition from Job Queue Processes to Database Scheduler

EMON PL/SQL notifications are executed by background jobs. In this release these jobs are DBMS_SCHEDULER jobs and are no longer conducted by DBMS_JOBS.

The init.ora parameter job_queue_processes does not need to be set for PL/SQL notifications or AQ propagations.

AQ propagation is now likewise handled by DBMS_SCHEDULER jobs rather than DBMS_JOBS. Additionally, propagation takes advantage of the event based scheduling features of DBMS_SCHEDULER for better scalability.

Messaging Gateway Enhancements

The following Messaging Gateway enhancements are introduced:

Enhanced Messaging Gateway Agent in an Oracle Real Application Clusters (Oracle RAC) Environment

The Oracle Scheduler will be used to start Messaging Gateway agents. Messaging Gateway will leverage the Oracle Scheduler RAC service feature so that a Messaging Gateway agent is associated with a database service. If the instance on which a Messaging Gateway agent is running fails or is shutdown, the Oracle Scheduler will automatically restart the agent on another instance supporting that service.

Multiple Messaging Gateway Agents

Messaging Gateway is enhanced to enable multiple agents per instance and database. With this enhancement, you can now statically partition propagation jobs based on functionality, organizations, or workload and assign them to different MGW agents hosted by different database instances on different machines. This not only enables MGW to scale, but also enables propagation job grouping and isolation, which is important when MGW is used in a complicated application integration environment.

Simplified Messaging Gateway Propagation Job Configuration

An enhanced PL/SQL API consolidates the propagation subscriber and the propagation schedule into a new propagation job. It is now easier to create and schedule a propagation job for the messaging gateway.

PKÿ))PK-AOEBPS/cover.htmO Cover

Oracle Corporation

PK[pTOPK-AOEBPS/aperrors.htm JMS and AQ XML Servlet Error Messages

B JMS and AQ XML Servlet Error Messages

A list of error messages is provided to aid you in troubleshooting problems.

JMS Error Messages

JMS-101 Invalid delivery mode (string)
Cause: The delivery mode is not supported
Action: The valid delivery mode is AQjmsConstants.PERSISTENT
JMS-102 Feature not supported (string)
Cause: This feature is not supported in the current release
Action: Self-explanatory
JMS-104 Message Payload must be specified
Cause: The message payload was null
Action: Specify a non-null payload for the message
JMS-105 Agent must be specified
Cause: AQjmsAgent object was null
Action: Specify a valid AQjmsAgent representing the remote subscriber
JMS-106 Cannot have more than one open Session on a JMSConnection
Cause: There is already one open JMS session on the connection. Cannot have more than one open session on a connection
Action: Close the open session and then open a new one
JMS-107 Operation not allowed on (string)
Cause: The specified operation is not allowed on this object
Action: Self-explanatory
JMS-108 Messages of type (string) not allowed with Destinations containing payload of type (string)
Cause: There was a mismatch between the message type being used and the payload type specified for the destination
Action: Use the message type that maps to the payload specified for the queue table that contains this destination
JMS-109 Class not found: (string)
Cause: The specified class was not found
Action: Make sure your CLASSPATH contains the class
JMS-110 Property (string) not writeable
Cause: An attempt was made to update a read-only message header field or property
Action: Self-explanatory
JMS-111 Connection must be specified
Cause: The connection object was null
Action: Specify a non-null JDBC connection
JMS-112 Connection is invalid
Cause: The JDBC connection is invalid
Action: Specify a non-null oracle JDBC connection
JMS-113 Connection is in stopped state
Cause: An attempt was made to receive messages on a connection that is in stopped state
Action: Start the connection
JMS-114 Connection is closed
Cause: An attempt was made to use a Connection that has been closed
Action: Create a new connection
JMS-115 Consumer is closed
Cause: An attempt was mode to use a Consumer that has been closed
Action: Create a new Message Consumer
JMS-116 Subscriber name must be specified
Cause: Subscriber name was null
Action: Specify a non-null subscription name
JMS-117 Conversion failed - invalid property type
Cause: An error occurred while converting the property to the requested type
Action: Use the method corresponding to the property data type to retrieve it
JMS-119 Invalid Property value
Cause: The property value specified is invalid
Action: Use the appropriate type of value for the property being set
JMS-120 Dequeue failed
Cause: An error occurred while receiving the message
Action: See message inside the JMSException and linked SQLException for more information
JMS-121 DestinationProperty must be specified
Cause: A null AQjmsDestinationProperty was specified while creating a queue/topic
Action: Specify a non-null AQjmsDestinationProperty for the destination
JMS-122 Internal error (string)
Cause: Internal error occurred
Action: Call Support
JMS-123 Interval must be at least (integer) seconds
Cause: An invalid interval was specified
Action: The interval must be greater than 30 seconds
JMS-124 Invalid Dequeue mode
Cause: Invalid dequeue mode was specified
Action: Valid Dequeue modes are AQConstants.DEQUEUE_BROWSE, AQConstants.DEQUEUE_REMOVE, AQConstants.DEQUEUE_LOCKED, AQConstants.DEQUEUE_REMOVE_NODATA
JMS-125 Invalid Queue specified
Cause: An invalid Queue object was specified
Action: Specify a valid Queue handle
JMS-126 Invalid Topic specified
Cause: An invalid Topic object was specified
Action: Specify a valid Topic handle
JMS-127 Invalid Destination
Cause: An invalid destination object was specified
Action: Specify a valid destination (Queue/Topic) object
JMS-128 Invalid Navigation mode
Cause: An invalid navigation mode was specified
Action: The valid navigation modes are AQjmsConstants.NAVIGATION_FIRST_MESSAGE, AQjmsConstants.NAVIGATION_NEXT_MESSAGE, AQjmsConstants.NAVIGATION_NEXT_TRANSACTION
JMS-129 Invalid Payload type
Cause: There was a mismatch between the message type being used and the payload type specified for the destination
Action: Use the message type that maps to the payload specified for the queue table that contains this destination. For ADT messages, use the appropriate CustomDatum factory to create the message consumer
JMS-130 JMS queue cannot be multi-consumer enabled
Cause: An attempt was made to get a AQ multi-consumer queue as a JMS queue
Action: JMS queues cannot be multi-consumer enabled
JMS-131 Session is closed
Cause: An attempt was made to use a session that has been closed
Action: Open a new session
JMS-132 Maximum number of properties (integer) exceeded
Cause: Maximum number of user defined properties for the message has been exceeded
Action: Self-explanatory
JMS-133 Message must be specified
Cause: Message specified was null
Action: Specify a non-null message
JMS-134 Name must be specified
Cause: Queue or Queue table Name specified was null
Action: Specify a non-null name
JMS-135 Driver (string) not supported
Cause: The specified driver is not supported
Action: Valid drivers are oci8 and thin. To use the kprb driver get the kprb connection using getDefaultConnection() and use the static createTopicConnection and createQueueConnection methods
JMS-136 Payload factory can only be specified for destinations with ADT payloads
Cause: A CustomDatumFactory was specified for consumers on destinations not containing ADT payloads
Action: This field must be set to null for destinations containing payloads of type SYS.AQ$_JMS_TEXT_MESSAGE, SYS.AQ$_JMS_BYTES_MESSAGE, SYS.AQ$_JMS_MAP_MESSAGE, SYS.AQ$_JMS_OBJECT_MESSAGE, SYS.AQ$_JMS_STREAM_MESSAGE
JMS-137 Payload factory must be specified for destinations with ADT payloads
Cause: CustomDatumFactory was not specified for destinations containing ADT payloads
Action: For destinations containing ADT messages, a CustomDatumFactory for a java class that maps to the SQL ADT type of the destination must be specified
JMS-138 Producer is closed
Cause: An attempt was made to use a producer that has been closed
Action: Create a new Message Producer
JMS-139 Property name must be specified
Cause: Property name was null
Action: Specify a non-null property name
JMS-140 Invalid System property
Cause: Invalid system property name specified.
Action: Specify one of the valid JMS system properties
JMS-142 JMS topic must be created in multi-consumer enabled queue tables
Cause: An attempt was made to create a JMS topic in a single-consumer queue table
Action: JMS topics can only be created in queue tables that are multi-consumer enabled
JMS-143 Queue must be specified
Cause: Null queue was specified
Action: Specify a non-null queue
JMS-144 JMS queue cannot be created in multiconsumer enabled queue tables
Cause: An attempt was made to create a JMS queue in a multi-consumer queue table
Action: JMS queues can only be created in queue tables that are not multi-consumer enabled
JMS-145 Invalid recipient list
Cause: The recipient list specified was empty
Action: Specify a recipient list with at least one recipient
JMS-146 Registration failed
Cause: An error occurred while registering the type in the type map
Action: Self-explanatory
JMS-147 Invalid ReplyTo destination type
Cause: The ReplyTo destination object type is invalid
Action: The ReplyTo destination must be of type AQjmsAgent
JMS-148 Property name size exceeded
Cause: The property name is greater than the maximum size
Action: Specify a property name that is less than 100 characters
JMS-149 Subscriber must be specified
Cause: Subscriber specified was null
Action: Specify a non-null subscriber
JMS-150 Property not supported
Cause: An attempt was made to use a property that is not supported
Action: Self-explanatory
JMS-151 Topics cannot be of type EXCEPTION
Cause: Topics cannot be of type AQjmsConstants.EXCEPTION
Action: Specify topics to be of type AQjmsConstants.NORMAL
JMS-153 Invalid System property type
Cause: The type of the value specified does not match the type defined for the system property being set
Action: Use the correct type for the setting the system property
JMS-154 Invalid value for sequence deviation
Cause: The sequence deviation is invalid
Action: Valid values are AQEnqueueOption.DEVIATION_BEFORE, AQEnqueueOption.DEVIATION_TOP
JMS-155 AQ Exception (string)
Cause: An error occurred in the AQ java layer
Action: See the message inside the JMSException and the linked exception for more information
JMS-156 Invalid Class (string)
Cause: Class specified is invalid
Action: Make sure your CLASSPATH has the specified class
JMS-157 IO Exception (string)
Cause: IO exception
Action: See message is JMSException for details
JMS-158 SQL Exception (string)
Cause: SQL Exception
Action: See message inside linked SQLException for details
JMS-159 Invalid selector (string)
Cause: The selector specified is either invalid or too long
Action: Check the syntax of the selector
JMS-160 EOF Exception (string)
Cause: EOF exception occurred while reading the byte stream
Action: Self-explanatory
JMS-161 MessageFormat Exception: (string)
Cause: An error occurred while converting the stream data to specified type
Action: Check the type of data expected on the stream and use the appropriate read method
JMS-162 Message not Readable
Cause: Message is in write-only mode
Action: Call the reset method to make the message readable
JMS-163 Message not Writeable
Cause: Message is in read-only mode
Action: Use the clearBody method to make the message writeable
JMS-164 No such element
Cause: Element with specified name was not found in the map message
Action: Self-explanatory
JMS-165 Maximum size of property value exceeded
Cause: The property value exceeded the maximum length allowed
Action: Values for JMS defined properties can be a maximum of length of 100, Values for User defined properties can have a maximum length of 2000
JMS-166 Topic must be specified
Cause: Topic specified was null
Action: Specify a non-null topic
JMS-167 Payload factory or Sql_data_class must be specified
Cause: Payload factory or Sql_data_class not specified for queues containing object payloads
Action: Specify a CustomDatumFactory or the SQLData class of the java object that maps to the ADT type defined for the queue.
JMS-168 Cannot specify both payload factory and sql_data_class
Cause: Both CustomDatumFactory and SQLData class were specified during dequeue
Action: Specify either the CustomDatumFactory or the SQLData class of the java object that maps to the ADT type defined for the queue.
JMS-169 Sql_data_class cannot be null
Cause: SQLData class specified is null
Action: Specify the SQLData class that maps to the ADT type defined for the queue
JMS-171 Message is not defined to contain (string)
Cause: Invalid payload type in message
Action: Check if the queue is defined to contain RAW or OBJECT payloads and use the appropriate payload type in the message
JMS-172 More than one queue table matches query (string)
Cause: More than one queue table matches the query
Action: Specify both owner and queue table name
JMS-173 Queue Table (string) not found
Cause: The specified queue table was not found
Action: Specify a valid queue table
JMS-174 Class must be specified for queues with object payloads\n. Use dequeue(deq_option,payload_fact) or dequeue(deq_option, sql_data_cl)
Cause: This dequeue method cannot be used to dequeue from queues with OBJECT payloads
Action: Use the either dequeue(deq_option, payload_fact) or dequeue(deq_option, sql_data_cl)
JMS-175 DequeueOption must be specified
Cause: DequeueOption specified is null
Action: Specify a non-null dequeue option
JMS-176 EnqueueOption must be specified
Cause: EnqueueOption specified is null
Action: Specify a non-null enqueue option
JMS-177 Invalid payload type: Use dequeue(deq_option) for raw payload queues
Cause: This method cannot be used to dequeue from queues with RAW payload
Action: Use the dequeue(deq_option) method
JMS-178 Invalid Queue name - (string)
Cause: The queue name specified is null or invalid
Action: Specify a queue name that is not null. The queue name must not be qualified with the schema name. The schema name must be specified as the value of the owner parameter
JMS-179 Invalid Queue Table name - (string)
Cause: The queue table name specified is null or invalid
Action: Specify a queue table name that is not null. The queue table name must not be qualified with the schema name. The schema name must be specified as the value of the owner parameter
JMS-180 Invalid Queue Type
Cause: Queue type is invalid
Action: Valid types are AQConstants.NORMAL or AQConstants.EXCEPTION
JMS-181 Invalid value for wait_time
Cause: Invalid value for wait type
Action: Wait time can be AQDequeueOption.WAIT_FOREVER, AQDequeueOption.WAIT_NONE or any value greater than 0
JMS-182 More than one queue matches query
Cause: More than one queue matches query
Action: Specify both the owner and name of the queue
JMS-183 No AQ driver registered
Cause: No AQDriver registered
Action: Make sure that the AQ java driver is registered. Use Class.forName("oracle.AQ.AQOracleDriver")
JMS-184 Queue object is invalid
Cause: The queue object is invalid
Action: The underlying JDBC connection may have been closed. Get the queue handle again
JMS-185 QueueProperty must be specified
Cause: AQQueueProperty specified is null
Action: Specify a non-null AQQueueProperty
JMS-186 QueueTableProperty must be specified
Cause: QueueTableProperty specified is null
Action: Specify a non-null AQQueueTableProperty
JMS-187 Queue Table must be specified
Cause: Queue Table specified is null
Action: Specify a non-null queue table
JMS-188 QueueTable object is invalid
Cause: The queue table object is invalid
Action: The underlying JDBC connection may have been closed. Get the queue table handle again
JMS-189 Byte array too small
Cause: The byte array given is too small to hold the data requested
Action: Specify a byte array that is large enough to hold the data requested or reduce the length requested
JMS-190 Queue (string) not found
Cause: The specified queue was not found
Action: Specify a valid queue
JMS-191 sql_data_cl must be a class that implements SQLData interface
Cause: The class specified does not support the java.sql.SQLData interface
Action: Self-explanatory
JMS-192 Invalid Visibility value
Cause: Visibility value specified is invalid
Action: Valid values areAQConstants.VISIBILITY_ONCOMMIT, AQConstants.VISIBILITY_IMMEDIATE
JMS-193 JMS queues cannot contain payload of type RAW
Cause: An attempt was made to create a JMS queue with RAW payload
Action: JMS queues/topics cannot contain RAW payload
JMS-194 Session object is invalid
Cause: Session object is invalid
Action: The underlying JDBC connection may have been closed. Create a new session
JMS-195 Invalid object type: object must implement CustomDatum or SQLData interface
Cause: Invalid object type specified
Action: Object must implement CustomDatum or SQLData interface
JMS-196 Cannot have more than one open QueueBrowser for the same destination on a JMS Session
Cause: There is already an open QueueBrowser for this queue on this session
Action: There cannot be more than one queue browser for the same queue in a particular session. Close the existing QueueBrowser and then open a new one
JMS-197 Agent address must be specified for remote subscriber
Cause: Address field is null for remote subscriber
Action: The address field must contain the fully qualified name of the remote topic
JMS-198 Invalid operation: Privileged message listener set for the Session
Cause: The client tried to use a message consumer to receive messages when the session message listener was set.
Action: Use the session's message listener to consume messages. The consumer's methods for receiving messages must not be used.
JMS-199 Registration for notification failed
Cause: Listener Registration failed
Action: See error message in linked Exception for details
JMS-200 Destination must be specified
Cause: Destination is null
Action: Specify a non-null destination
JMS-201 All Recipients in recipient_list must be specified
Cause: One or more elements in the recipient list are null
Action: All AQjmsAgents in the recipient list must be specified
JMS-202 Unregister for asynchronous receipt of messages failed
Cause: An error occurred while removing the registration of the consumer with the database for asynchronous receipt
Action: Check error message in linked exception for details
JMS-203 Payload Factory must be specified
Cause: Null Payload Factory was specified
Action: Specify a non null payload factory
JMS-204 An error occurred in the AQ JNI layer
Cause: JNI Error
Action: Check error message in linked exception for details
JMS-205 Naming Exception
Cause: Naming exception
Action: Check error message in linked exception for details
JMS-206 XA Exception XAError-{0} :: OracleError-{1}
Cause: An error occurred in the XA layer
Action: See the message inside the linked XAException for more information
JMS-207 JMS Exception {0}
Cause: An error occurred in the JMS layer
Action: See the message inside the linked JMSException for more information
JMS-208 XML SQL Exception
Cause: An error occurred in the XML SQL layer
Action: See the message inside the linked AQxmlException for more information
JMS-209 XML SAX Exception
Cause: An error occurred in the XML SAX layer
Action: See the message inside the linked AQxmlException for more information
JMS-210 XML Parse Exception
Cause: An error occurred in the XML Parser layer
Action: See the message inside the linked AQxmlException for more information
JMS-220 Connection no longer available
Cause: Connection to the database no longer available.
Action: Comment: This may happen if the database/network/machine is not accessible. This may be a transient failure.
JMS-221 Free physical database connection unavailable in connection pool
Cause: A free physical database connection was not available in the OCI connection pool in order to perform the specified operation.
Action: Try performing the operation later

AQ XML Servlet Error Messages

JMS-400 Destination name must be specified
Cause: A null Destination name was specified
Action: Specify a non-null destination name
JMS-402 Class not found: {0}
Cause: The specified class was not found
Action: Make sure your CLASSPATH contains the class specified in the error message
JMS-403 IO Exception {0}
Cause: IO exception
Action: See the message inside the linked AQxmlException for more information
JMS-404 XML Parse Exception
Cause: An error occurred in the XML Parser layer
Action: See the message inside the linked AQxmlException for more information
JMS-405 XML SAX Exception
Cause: An error occurred in the XML SAX layer
Action: See the message inside the linked AQxmlException for more information
JMS-406 JMS Exception {0}
Cause: An error occurred in the JMS layer
Action: See the message inside the linked JMSException for more information
JMS-407 Operation not allowed on {0}
Cause: The specified operation is not allowed on this object
Action: Check that the user performing the operation has the required privileges
JMS-408 Conversion failed - invalid property type
Cause: An error occurred while converting the property to the requested type
Action: Use the method corresponding to the property data type to retrieve it
JMS-409 No such element
Cause: Element with specified name was not found in the map message
Action: Specify a valid element name
JMS-410 XML SQL Exception
Cause: An error occurred in the JDBC SQL layer
Action: See the message inside the linked SQLException for more information
JMS-411 Payload body cannot be null
Cause: An invalid body string or document was specified
Action: Specify a non-null body string or document for the payload
JMS-412 Byte conversion failed
Cause: An invalid username/password was specified
Action: Specify a non-null username and password
JMS-413 Autocommit not allowed for operation
Cause: The autocommit flag cannot be set for this operation
Action: Do not set the autocommit flag
JMS-414 Destination owner must be specified
Cause: A null Destination owner was specified
Action: Specify a non-null destination name
JMS-415 Invalid Visibility value
Cause: Visibility value specified is invalid
Action: Valid values are AQxmlConstants.VISIBILITY_ONCOMMIT, AQxmlConstants.VISIBILITY_IMMEDIATE
JMS-416 Invalid Dequeue mode
Cause: Invalid dequeue mode was specified
Action: Valid Dequeue modes are AQxmlConstants.DEQUEUE_BROWSE, AQxmlConstants.DEQUEUE_REMOVE, AQxmlConstants.DEQUEUE_LOCKED, AQxmlConstants.DEQUEUE_REMOVE_NODATA
JMS-417 Invalid Navigation mode
Cause: An invalid navigation mode was specified
Action: The valid navigation modes are:
  • AQxmlConstants.NAVIGATION_FIRST_MESSAGE

  • AQxmlConstants.NAVIGATION_NEXT_MESSAGE

  • AQxmlConstants.NAVIGATION_NEXT_TRANSACTION

JMS-418 Invalid value for wait_time
Cause: Invalid value for wait type
Action: Wait time can be AQDequeueOption.WAIT_FOREVER, AQDequeueOption.WAIT_NONE, or any value greater than 0
JMS-419 Invalid ConnectionPoolDataSource
Cause: A null or invalid ConnectionPoolDataSource was specified
Action: Specify a valid OracleConnectionPoolDataSource object with the correct URL and user/password
JMS-420 Invalid value for cache_size
Cause: An invalid cache_size was specified
Action: Cache size must be greater than 0
JMS-421 Invalid value for cache_scheme
Cause: An invalid cache scheme was specified
Action: The valid cache schemes are:
  • OracleConnectionCacheImpl.DYNAMIC_SCHEME

  • OracleConnectionCacheImpl.FIXED_WAIT_SCHEME

JMS-422 Invalid tag - {0}
Cause: An invalid tag was encountered in the XML document
Action: Verify that the XML document conforms to the AQ schema
JMS-423 Invalid value
Cause: An invalid value was specified
Action: Verify that the value specified in the XML document conforms to those specified in the AQ schema
JMS-424 Invalid message header
Cause: The message header specified is null or invalid
Action: Specify a valid message header
JMS-425 Property name must be specified
Cause: Property name was null
Action: Specify a non-null property name
JMS-426 Property does not exist
Cause: Invalid property name specified. The property does not exist
Action: The property does not exist
JMS-427 Subscriber name must be specified
Cause: Subscriber name was null
Action: Specify a non-null subscription name
JMS-428 Valid message must be specified
Cause: Message was null
Action: Specify a non-null message
JMS-429 Register Option must be specified
Cause: Register option is null
Action: Specify a non-null Register Option
JMS-430 Database Link must be specified
Cause: DB Link is null
Action: Specify a non-null Register Option
JMS-431 Sequence Number must be specified
Cause: Register option is null
Action: Specify a non-null Register Option
JMS-432 Status must be specified
Cause: Status option is null
Action: Specify a non-null Register Option
JMS-433 User not authenticated
Cause: User is not authenticated
Action: Check that the user was authenticated by the webserver before connecting to the Servlet
JMS-434 Invalid data source
Cause: Data source is null or invalid
Action: Specify a valid data source for connecting to the database
JMS-435 Invalid schema location
Cause: Schema location is null or invalid
Action: Specify a valid URL for the schema
JMS-436 AQ Exception
Cause: An error occurred in the AQ java layer
Action: See the message inside the AQxmlException and the linked exception for more information
JMS-437 Invalid Destination
Cause: An invalid destination object was specified
Action: Specify a valid destination (Queue/Topic) object
JMS-438 AQ agent {0} not mapped to a valid database user
Cause: The AQ agent specified does not map to a database user which has privileges to perform the requested operation
Action: Use dbms_aqadm.enable_db_access to map the agent to a database user with the required queue privileges
JMS-439 Invalid schema document
Cause: The schema document specified is not valid
Action: Specify a valid URL for the schema document
JMS-440 Invalid operations - agent {0} maps to more than one database user
Cause: The AQ agent mapped to more than one database user in the same session
Action: Map the AQ agent to only one database user. Check the aq$internet_users view for database users that map to this agent.
PKd1n))PK-AOEBPS/jm_pblsh.htm Oracle JMS Publish/Subscribe

14 Oracle JMS Publish/Subscribe

This chapter describes the components of the Oracle Streams Advanced Queuing (AQ) Java Message Service (JMS) operational interface that are specific to publish/subscribe operations. Components that are shared by point-to-point and publish/subscribe are described in Chapter 15, "Oracle JMS Shared Interfaces".

This chapter contains these topics:

Creating a Connection with Username/Password

public javax.jms.Connection createConnection(
             java.lang.String username,
             java.lang.String password)
      throws JMSException

This method creates a connection supporting both point-to-point and publish/subscribe operations with the specified username and password. This method is new and supports JMS version 1.1 specifications. It has the following parameters:

ParameterDescription
usernameName of the user connecting to the database for queuing
passwordPassword for creating the connection to the server

Creating a Connection with Default ConnectionFactory Parameters

public javax.jms.Connection createConnection()
      throws JMSException

This method creates a connection supporting both point-to-point and publish/subscribe operations with default ConnectionFactory parameters. This method is new and supports JMS version 1.1 specifications. If the ConnectionFactory properties do not contain a default username and password, then it throws a JMSException.

Creating a TopicConnection with Username/Password

public javax.jms.TopicConnection createTopicConnection(
             java.lang.String username,
             java.lang.String password)
      throws JMSException

This method creates a TopicConnection with the specified username/password. It has the following parameters:

ParameterDescription
usernameName of the user connecting to the database for queuing
passwordPassword for creating the connection to the server

Example 14-1 Creating a TopicConnection with Username/Password

TopicConnectionFactory tc_fact = AQjmsFactory.getTopicConnectionFactory("sun123", "oratest", 5521, "thin");
/* Create a TopicConnection using a username/password */
TopicConnection tc_conn = tc_fact.createTopicConnection("jmsuser", "jmsuser");

Creating a TopicConnection with Open JDBC Connection

public static javax.jms.TopicConnection createTopicConnection(
              java.sql.Connection jdbc_connection)
       throws JMSException

This method creates a TopicConnection with open JDBC connection. It has the following parameter:

ParameterDescription
jdbc_connectionValid open connection to database

Example 14-2 Creating a TopicConnection with Open JDBC Connection

Connection db_conn;   /*previously opened JDBC connection */
TopicConnection tc_conn = 
AQjmsTopicConnectionFactory createTopicConnection(db_conn);

Example 14-3 Creating a TopicConnection with New JDBC Connection

OracleDriver ora = new OracleDriver();
TopicConnection tc_conn = 
AQjmsTopicConnectionFactory.createTopicConnection(ora.defaultConnection());

Creating a TopicConnection with an Open OracleOCIConnectionPool

public static javax.jms.TopicConnection createTopicConnection(
              oracle.jdbc.pool.OracleOCIConnectionPool cpool)
       throws JMSException

This method creates a TopicConnection with an open OracleOCIConnectionPool. It is static and has the following parameter:

ParameterDescription
cpoolValid open OCI connection pool to the database

Example 14-4 Creating a TopicConnection with Open OracleOCIConnectionPool

OracleOCIConnectionPool cpool; /* previously created OracleOCIConnectionPool */
TopicConnection tc_conn = 
AQjmsTopicConnectionFactory.createTopicConnection(cpool);

Creating a Session

public javax.jms.Session createSession(boolean transacted,
                                                 int ack_mode)
                                          throws JMSException

This method creates a Session supporting both point-to-point and publish/subscribe operations. It is new and supports JMS version 1.1 specifications. It has the following parameters:

ParameterDescription
transactedIf set to true, then the session is transactional
ack_modeIndicates whether the consumer or the client will acknowledge any messages it receives. It is ignored if the session is transactional. Legal values are Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, and Session.DUPS_OK_ACKNOWLEDGE.

Creating a TopicSession

public javax.jms.TopicSession createTopicSession(boolean transacted,
                                                 int ack_mode)
                                          throws JMSException

This method creates a TopicSession. It has the following parameters:

ParameterDescription
transactedIf set to true, then the session is transactional
ack_modeIndicates whether the consumer or the client will acknowledge any messages it receives. It is ignored if the session is transactional. Legal values are Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, and Session.DUPS_OK_ACKNOWLEDGE.

Example 14-5 Creating a TopicSession

TopicConnection tc_conn;
TopicSession t_sess = tc_conn.createTopicSession(true,0);

Creating a TopicPublisher

public javax.jms.TopicPublisher createPublisher(javax.jms.Topic topic)
                                         throws JMSException

This method creates a TopicPublisher. It has the following parameter:

ParameterDescription
topicTopic to publish to, or null if this is an unidentified producer

Publishing Messages with Minimal Specification

public void publish(javax.jms.Message message)
             throws JMSException

This method publishes a message with minimal specification. It has the following parameter:

ParameterDescription
messageMessage to send

The TopicPublisher uses the default values for message priority (1) and timeToLive (infinite).

Example 14-6 Publishing Without Specifying Topic

/* Publish without specifying topic */
TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              jms_sess;
TopicPublisher            publisher1;
Topic                     shipped_orders;
int                       myport = 5521;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME",
          "MYSID", 
           myport, 
          "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
/* create TopicSession */
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
/* get shipped orders topic */
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", 
          "Shipped_Orders_Topic");
publisher1 = jms_sess.createPublisher(shipped_orders);
/* create TextMessage */
TextMessage     jms_sess.createTextMessage();
/* publish without specifying the topic */
publisher1.publish(text_message);

Example 14-7 Publishing Specifying Correlation and Delay

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              jms_sess;
TopicPublisher            publisher1;
Topic                     shipped_orders;
int                       myport = 5521;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME",
          "MYSID", 
           myport, 
          "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", 
          "Shipped_Orders_Topic");
publisher1 = jms_sess.createPublisher(shipped_orders);
/* Create TextMessage */
TextMessage     jms_sess.createTextMessage();
/* Set correlation and delay */
/* Set correlation */
jms_sess.setJMSCorrelationID("FOO");
/* Set delay of 30 seconds */
jms_sess.setLongProperty("JMS_OracleDelay", 30);
/* Publish  */
publisher1.publish(text_message);

Publishing Messages Specifying Topic

public void publish(javax.jms.Topic topic, javax.jms.Message message)
             throws JMSException

This method publishes a message specifying the topic. It has the following parameters:

ParameterDescription
topicTopic to publish to
messageMessage to send

If the TopicPublisher has been created with a default topic, then the topic parameter may not be specified in the publish() call. If a topic is specified, then that value overrides the default in the TopicPublisher. If the TopicPublisher has been created without a default topic, then the topic must be specified with the publish() call.

Example 14-8 Publishing Specifying Topic

/* Publish specifying topic */
TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              jms_sess;
TopicPublisher            publisher1;
Topic                     shipped_orders;
int                       myport = 5521;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          'MYHOSTNAME', 'MYSID', myport, 'oci8');
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE); 
/* create TopicPublisher */
publisher1 = jms_sess.createPublisher(null);
/* get topic object */
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          'WS', 'Shipped_Orders_Topic');
/* create text message */
TextMessage     jms_sess.createTextMessage();
/* publish specifying the topic */
publisher1.publish(shipped_orders, text_message);

Publishing Messages Specifying Delivery Mode, Priority and TimeToLive

public void publish(javax.jms.Topic topic,
                    javax.jms.Message message,
                    oracle.jms.AQjmsAgent[] recipient_list,
                    int deliveryMode,
                    int priority,
                    long timeToLive)
             throws JMSException

This method publishes a message specifying delivery mode, priority and TimeToLive. It has the following parameters:

ParameterDescription
topicTopic to which to publish the message (overrides the default topic of the MessageProducer)
messageMessage to publish
recipient_listList of recipients to which the message is published. Recipients are of type AQjmsAgent.
deliveryModePERSISTENT or NON_PERSISTENT (only PERSISTENT is supported in this release)
priorityPriority for this message
timeToLiveMessage lifetime in milliseconds (zero is unlimited)

Example 14-9 Publishing Specifying Priority and TimeToLive

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              jms_sess;
TopicPublisher            publisher1;
Topic                     shipped_orders;
int                       myport = 5521;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", "Shipped_Orders_Topic");
publisher1 = jms_sess.createPublisher(shipped_orders);
/* Create TextMessage */
TextMessage     jms_sess.createTextMessage();
/* Publish  message with priority 1 and time to live 200 seconds */
publisher1.publish(text_message, DeliveryMode.PERSISTENT, 1, 200000);

Publishing Messages Specifying a Recipient List

public void publish(javax.jms.Message message,
                    oracle.jms.AQjmsAgent[] recipient_list)
             throws JMSException

This method publishes a message specifying a recipient list overriding topic subscribers. It has the following parameters:

ParameterDescription
messageMessage to publish
recipient_listList of recipients to which the message is published. Recipients are of type AQjmsAgent.

Example 14-10 Publishing Specifying a Recipient List Overriding Topic Subscribers

/* Publish specifying priority and timeToLive */
TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              jms_sess;
TopicPublisher            publisher1;
Topic                     shipped_orders;
int                       myport = 5521;
AQjmsAgent[]              recipList;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", "Shipped_Orders_Topic");
publisher1 = jms_sess.createPublisher(shipped_orders);
/* create TextMessage */
TextMessage     jms_sess.createTextMessage();
/* create two receivers */
recipList = new AQjmsAgent[2];
recipList[0] = new AQjmsAgent(
          "ES", "ES.shipped_orders_topic", AQAgent.DEFAULT_AGENT_PROTOCOL);
recipList[1] = new AQjmsAgent(
          "WS", "WS.shipped_orders_topic", AQAgent.DEFAULT_AGENT_PROTOCOL);
/* publish  message specifying a recipient list */
publisher1.publish(text_message, recipList);

Creating a DurableSubscriber for a JMS Topic Without Selector

public javax.jms.TopicSubscriber createDurableSubscriber(
             javax.jms.Topic topic,
             java.lang.String subs_name)
      throws JMSException

This method creates a DurableSubscriber for a JMS topic without selector. It has the following parameters:

ParameterDescription
topicNon-temporary topic to subscribe to
subs_nameName used to identify this subscription

Exclusive Access to Topics

CreateDurableSubscriber() and Unsubscribe() both require exclusive access to their target topics. If there are pending JMS send(), publish(), or receive() operations on the same topic when these calls are applied, then exception ORA - 4020 is raised. There are two solutions to the problem:

Example 14-11 Creating a Durable Subscriber for a JMS Topic Without Selector

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              jms_sess;
TopicSubscriber           subscriber1;
Topic                     shipped_orders;
int                       myport = 5521;
AQjmsAgent[]              recipList;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME",
          "MYSID", 
           myport, 
          "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", 
          "Shipped_Orders_Topic");
/* create a durable subscriber on the shipped_orders topic*/
subscriber1 = jms_sess.createDurableSubscriber(
          shipped_orders, 
         'WesternShipping');

Creating a DurableSubscriber for a JMS Topic With Selector

public javax.jms.TopicSubscriber createDurableSubscriber(
             javax.jms.Topic topic,
             java.lang.String subs_name,
             java.lang.String messageSelector,
             boolean noLocal)
      throws JMSException

This method creates a durable subscriber for a JMS topic with selector. It has the following parameters:

ParameterDescription
topicNon-temporary topic to subscribe to
subs_nameName used to identify this subscription
messageSelectorOnly messages with properties matching the messageSelector expression are delivered. A value of null or an empty string indicates that there is no messageSelector for the message consumer.
noLocalIf set to true, then it inhibits the delivery of messages published by its own connection

A client can change an existing durable subscription by creating a durable TopicSubscriber with the same name and a different messageSelector. An unsubscribe call is needed to end the subscription to the topic.


See Also:

"MessageSelector"

Example 14-12 Creating a Durable Subscriber for a JMS Topic With Selector

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              jms_sess;
TopicSubscriber           subscriber1;
Topic                     shipped_orders;
int                       myport = 5521;
AQjmsAgent[]              recipList;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", "Shipped_Orders_Topic");
/* create a subscriber */
/* with condition on JMSPriority and user property 'Region' */
subscriber1 = jms_sess.createDurableSubscriber(
          shipped_orders, 'WesternShipping', 
         "JMSPriority > 2 and Region like 'Western%'", false);

Creating a DurableSubscriber for an Oracle Object Type Topic Without Selector

public javax.jms.TopicSubscriber createDurableSubscriber(
             javax.jms.Topic topic,
             java.lang.String subs_name,
             java.lang.Object payload_factory)
      throws JMSException

This method creates a durable subscriber for an Oracle object type topic without selector. It has the following parameters:

ParameterDescription
topicNon-temporary topic to subscribe to
subs_nameName used to identify this subscription
payload_factoryCustomDatumFactory or ORADataFactory for the Java class that maps to the Oracle ADT


Note:

CustomDatum support will be deprecated in a future release. Use ORADataFactory payload factories instead.

Example 14-13 Creating a Durable Subscriber for an Oracle Object Type Topic Without Selector

/* Subscribe to an ADT queue */
TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              t_sess    = null;
TopicSession              jms_sess;
TopicSubscriber           subscriber1;
Topic                     shipped_orders;
int                       my[port = 5521;
AQjmsAgent[]              recipList;
/* the java mapping of the oracle object type created by J Publisher */
ADTMessage                message; 
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", "Shipped_Orders_Topic");
/* create a subscriber, specifying the correct CustomDatumFactory */
subscriber1 = jms_sess.createDurableSubscriber(
          shipped_orders, 'WesternShipping', AQjmsAgent.getFactory());

Creating a DurableSubscriber for an Oracle Object Type Topic With Selector

public javax.jms.TopicSubscriber createDurableSubscriber(
             javax.jms.Topic topic,
             java.lang.String subs_name,
             java.lang.String messageSelector,
             boolean noLocal,
             java.lang.Object payload_factory)
      throws JMSException

This method creates a durable subscriber for an Oracle object type topic with selector. It has the following parameters:

ParameterDescription
topicNon-temporary topic to subscribe to
subs_nameName used to identify this subscription
messageSelectorOnly messages with properties matching the messageSelector expression are delivered. A value of null or an empty string indicates that there is no messageSelector for the message consumer.
noLocalIf set to true, then it inhibits the delivery of messages published by its own connection
payload_factoryCustomDatumFactory or ORADataFactory for the Java class that maps to the Oracle ADT


Note:

CustomDatum support will be deprecated in a future release. Use ORADataFactory payload factories instead.

Example 14-14 Creating a Durable Subscriber for an Oracle Object Type Topic With Selector

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              jms_sess;
TopicSubscriber           subscriber1;
Topic                     shipped_orders;
int                       myport = 5521;
AQjmsAgent[]              recipList;
/* the java mapping of the oracle object type created by J Publisher */
ADTMessage                message; 
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", "Shipped_Orders_Topic");
/* create a subscriber, specifying correct CustomDatumFactory and selector */
subscriber1 = jms_sess.createDurableSubscriber(
          shipped_orders, "WesternShipping", 
         "priority > 1 and tab.user_data.region like 'WESTERN %'", false, 
          ADTMessage.getFactory());

Specifying Transformations for Topic Subscribers

A transformation can be supplied when sending/publishing a message to a queue/topic. The transformation is applied before putting the message into the queue/topic.

The application can specify a transformation using the setTransformation interface in the AQjmsQueueSender and AQjmsTopicPublisher interfaces.

Example 14-15 Sending Messages to a Destination Using a Transformation

Suppose that the orders that are processed by the order entry application should be published to WS_bookedorders_topic. The transformation OE2WS (defined in the previous section) is supplied so that the messages are inserted into the topic in the correct format.

public void ship_bookedorders(
   TopicSession jms_session, 
        AQjmsADTMessage adt_message)                             
{
    TopicPublisher  publisher;
    Topic           topic;

    try
    {
      /* get a handle to the WS_bookedorders_topic */
              topic = ((AQjmsSession)jms_session).getTopic("WS", "WS_bookedorders_topic");
      publisher = jms_session.createPublisher(topic);

      /* set the transformation in the publisher */
      ((AQjmsTopicPublisher)publisher).setTransformation("OE2WS");
      publisher.publish(topic, adt_message);
            }
            catch (JMSException ex)
            {
               System.out.println("Exception :" ex);
    }
}

A transformation can also be specified when creating topic subscribers using the CreateDurableSubscriber() call. The transformation is applied to the retrieved message before returning it to the subscriber. If the subscriber specified in the CreateDurableSubscriber() call already exists, then its transformation is set to the specified transformation.

Example 14-16 Specifying Transformations for Topic Subscribers

The Western Shipping application subscribes to the OE_bookedorders_topic with the transformation OE2WS. This transformation is applied to the messages and the returned message is of Oracle object type WS.WS_orders.

Suppose that the WSOrder java class has been generated by Jpublisher to map to the Oracle object WS.WS_order:

public AQjmsAdtMessage retrieve_bookedorders(TopicSession jms_session)
{
    TopicSubscriber     subscriber;
    Topic               topic;
    AQjmsAdtMessage     msg = null;

    try
    {
      /* get a handle to the OE_bookedorders_topic */
      topic = ((AQjmsSession)jms_session).getTopic("OE", "OE_bookedorders_topic");

      /* create a subscriber with the transformation OE2WS */
      subs = ((AQjmsSession)jms_session).createDurableSubscriber(
         topic, 'WShip', null, false, WSOrder.getFactory(), "OE2WS");
      msg = subscriber.receive(10);
    }
    catch (JMSException ex)
    {
        System.out.println("Exception :" ex);
    }
    return (AQjmsAdtMessage)msg;
}

Creating a Remote Subscriber for JMS Messages

public void createRemoteSubscriber(javax.jms.Topic topic,
                                   oracle.jms.AQjmsAgent remote_subscriber,
                                   java.lang.String messageSelector)
                            throws JMSException

This method creates a remote subscriber for topics of JMS messages. It has the following parameters:

ParameterDescription
topicTopic to subscribe to
remote_subscriberAQjmsAgent that refers to the remote subscriber
messageSelectorOnly messages with properties matching the messageSelector expression are delivered. A value of null or an empty string indicates that there is no messageSelector for the message consumer.


See Also:

"MessageSelector"

Oracle Streams Advanced Queuing allows topics to have remote subscribers, for example, subscribers at other topics in the same or different database. In order to use remote subscribers, you must set up propagation between the local and remote topic.

Remote subscribers can be a specific consumer at the remote topic or all subscribers at the remote topic. A remote subscriber is defined using the AQjmsAgent structure. An AQjmsAgent consists of a name and address. The name refers to the consumer_name at the remote topic. The address refers to the remote topic. Its syntax is schema.topic_name[@dblink].

To publish messages to a particular consumer at the remote topic, the subscription_name of the recipient at the remote topic must be specified in the name field of AQjmsAgent, and the remote topic must be specified in the address field. To publish messages to all subscribers of the remote topic, the name field of AQjmsAgent must be set to null.

Example 14-17 Creating a Remote Subscriber for Topics of JMS Messages

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              t_sess    = null;
TopicSession              jms_sess;
TopicSubscriber           subscriber1;
Topic                     shipped_orders;
int                       my[port = 5521;
AQjmsAgent                remoteAgent;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", "Shipped_Orders_Topic");
remoteAgent = new AQjmsAgent("WesternRegion", "WS.shipped_orders_topic", null);
/* create a remote subscriber (selector is null )*/
subscriber1 = ((AQjmsSession)jms_sess).createRemoteSubscriber(
          shipped_orders, remoteAgent, null);

Creating a Remote Subscriber for Oracle Object Type Messages

public void createRemoteSubscriber(javax.jms.Topic topic,
                                   oracle.jms.AQjmsAgent remote_subscriber,
                                   java.lang.String messageSelector,
                                   java.lang.Object payload_factory)
                            throws JMSException

This method creates a remote subscriber for topics of Oracle object type messages. It has the following parameters:

ParameterDescription
topicTopic to subscribe to
remote_subscriberAQjmsAgent that refers to the remote subscriber
messageSelectorOnly messages with properties matching the messageSelector expression are delivered. A value of null or an empty string indicates that there is no messageSelector for the message consumer.
payload_factoryCustomDatumFactory or ORADataFactory for the Java class that maps to the Oracle ADT


Note:

CustomDatum support will be deprecated in a future release. Use ORADataFactory payload factories instead.


See Also:

"MessageSelector"

Oracle Streams Advanced Queuing allows topics to have remote subscribers, for example, subscribers at other topics in the same or different database. In order to use remote subscribers, you must set up propagation between the local and remote topic.

Remote subscribers can be a specific consumer at the remote topic or all subscribers at the remote topic. A remote subscriber is defined using the AQjmsAgent structure. An AQjmsAgent consists of a name and address. The name refers to the consumer_name at the remote topic. The address refers to the remote topic. Its syntax is schema.topic_name[@dblink].

To publish messages to a particular consumer at the remote topic, the subscription_name of the recipient at the remote topic must be specified in the name field of AQjmsAgent, and the remote topic must be specified in the address field. To publish messages to all subscribers of the remote topic, the name field of AQjmsAgent must be set to null.

Example 14-18 Creating a Remote Subscriber for Topics of Oracle Object Type Messages

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              t_sess    = null;
TopicSession              jms_sess;
TopicSubscriber           subscriber1;
Topic                     shipped_orders;
int                       my[port = 5521;
AQjmsAgent                remoteAgent;
ADTMessage                message;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
/* create TopicSession */
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
/* get the Shipped order topic */
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", "Shipped_Orders_Topic");
/* create a remote agent */
remoteAgent = new AQjmsAgent("WesternRegion", "WS.shipped_orders_topic", null);
/* create a remote subscriber  with null selector*/
subscriber1 = ((AQjmsSession)jms_sess).createRemoteSubscriber(
          shipped_orders, remoteAgent, null, message.getFactory);

Note:

AQ does not support the use of multiple dblink to the same destination. As a workaround, use a single database link for each destination.

Specifying Transformations for Remote Subscribers

Oracle Streams Advanced Queuing allows a remote subscriber, that is a subscriber at another database, to subscribe to a topic.

Transformations can be specified when creating remote subscribers using the createRemoteSubscriber() call. This enables propagation of messages between topics of different formats. When a message published at a topic meets the criterion of a remote subscriber, Oracle Streams Advanced Queuing automatically propagates the message to the queue/topic at the remote database specified for the remote subscriber. If a transformation is also specified, then Oracle Streams Advanced Queuing applies the transformation to the message before propagating it to the queue/topic at the remote database.

Example 14-19 Specifying Transformations for Remote Subscribers

A remote subscriber is created at the OE.OE_bookedorders_topic so that messages are automatically propagated to the WS.WS_bookedorders_topic. The transformation OE2WS is specified when creating the remote subscriber so that the messages reaching the WS_bookedorders_topic have the correct format.

Suppose that the WSOrder java class has been generated by Jpublisher to map to the Oracle object WS.WS_order

public void create_remote_sub(TopicSession jms_session)
{
   AQjmsAgent          subscriber;
   Topic               topic;

   try
   {
     /* get a handle to the OE_bookedorders_topic */
     topic = ((AQjmsSession)jms_session).getTopic("OE", "OE_bookedorders_topic");
     subscriber = new AQjmsAgent("WShip", "WS.WS_bookedorders_topic");

     ((AQjmsSession )jms_session).createRemoteSubscriber(
        topic, subscriber, null, WSOrder.getFactory(),"OE2WS");
   }
   catch (JMSException ex)
   {
     System.out.println("Exception :" ex);
   }
}

Unsubscribing a Durable Subscription for a Local Subscriber

public void unsubscribe(javax.jms.Topic topic,
                        java.lang.String subs_name)
                 throws JMSException

This method unsubscribes a durable subscription for a local subscriber. It has the following parameters:

ParameterDescription
topicNon-temporary topic to unsubscribe
subs_nameName used to identify this subscription

Example 14-20 Unsubscribing a Durable Subscription for a Local Subscriber

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              jms_sess;
TopicSubscriber           subscriber1;
Topic                     shipped_orders;
int                       myport = 5521;
AQjmsAgent[]              recipList;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", "Shipped_Orders_Topic");
/* unsusbcribe "WesternShipping" from shipped_orders */
jms_sess.unsubscribe(shipped_orders, "WesternShipping");

Unsubscribing a Durable Subscription for a Remote Subscriber

public void unsubscribe(javax.jms.Topic topic,
                        oracle.jms.AQjmsAgent remote_subscriber)
                 throws JMSException

This method unsubscribes a durable subscription for a remote subscriber. It has the following parameters:

ParameterDescription
topicNon-temporary topic to unsubscribe
remote_subscriberAQjmsAgent that refers to the remote subscriber. The address field of the AQjmsAgent cannot be null.

Example 14-21 Unsubscribing a Durable Subscription for a Remote Subscriber

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              t_sess    = null;
TopicSession              jms_sess;
Topic                     shipped_orders;
int                       myport = 5521;
AQjmsAgent                remoteAgent;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "OE", "Shipped_Orders_Topic");
remoteAgent = new AQjmsAgent("WS", "WS.Shipped_Orders_Topic", null);
/* unsubscribe the remote agent from shipped_orders */
((AQjmsSession)jms_sess).unsubscribe(shipped_orders, remoteAgent);

Creating a TopicReceiver for a Topic of Standard JMS Type Messages

public oracle.jms.AQjmsTopicReceiver createTopicReceiver(
              javax.jms.Topic topic,
              java.lang.String receiver_name,
              java.lang.String messageSelector)
       throws JMSException

This method creates a TopicReceiver for a topic of standard JMS type messages. It has the following parameters:

ParameterDescription
topicTopic to access
receiver_nameName of message receiver
messageSelectorOnly messages with properties matching the messageSelector expression are delivered. A value of null or an empty string indicates that there is no messageSelector for the message consumer.


See Also:

"MessageSelector"

Oracle Streams Advanced Queuing allows messages to be sent to specified recipients. These receivers may or may not be subscribers of the topic. If the receiver is not a subscriber to the topic, then it receives only those messages that are explicitly addressed to it. This method must be used order to create a TopicReceiver object for consumers that are not durable subscribers.

Example 14-22 Creating a TopicReceiver for Standard JMS Type Messages

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              t_sess    = ull;
TopicSession              jms_sess;
Topic                     shipped_orders;
int                       myport = 5521;
TopicReceiver             receiver;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "WS", "Shipped_Orders_Topic");
receiver = ((AQjmsSession)jms_sess).createTopicReceiver(
          shipped_orders, "WesternRegion", null); 

Creating a TopicReceiver for a Topic of Oracle Object Type Messages

public oracle.jms.AQjmsTopicReceiver createTopicReceiver(
              javax.jms.Topic topic,
              java.lang.String receiver_name,
              java.lang.String messageSelector,
              java.lang.Object payload_factory)
       throws JMSException

This method creates a TopicReceiver for a topic of Oracle object type messages with selector. It has the following parameters:

ParameterDescription
topicTopic to access
receiver_nameName of message receiver
messageSelectorOnly messages with properties matching the messageSelector expression are delivered. A value of null or an empty string indicates that there is no messageSelector for the message consumer.
payload_factoryCustomDatumFactory or ORADataFactory for the Java class that maps to the Oracle ADT


Note:

CustomDatum support will be deprecated in a future release. Use ORADataFactory payload factories instead.


See Also:

"MessageSelector"

Oracle Streams Advanced Queuing allows messages to be sent to all subscribers of a topic or to specified recipients. These receivers may or may not be subscribers of the topic. If the receiver is not a subscriber to the topic, then it receives only those messages that are explicitly addressed to it. This method must be used order to create a TopicReceiver object for consumers that are not durable subscribers.

Example 14-23 Creating a TopicReceiver for Oracle Object Type Messages

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              t_sess    = null;
TopicSession              jms_sess;
Topic                     shipped_orders;
int                       myport = 5521;
TopicReceiver             receiver;
/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
          "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
          "WS", "Shipped_Orders_Topic");
receiver = ((AQjmsSession)jms_sess).createTopicReceiver(
          shipped_orders, "WesternRegion", null);

Creating a TopicBrowser for Standard JMS Messages

public oracle.jms.TopicBrowser createBrowser(javax.jms.Topic topic,
                                             java.lang.String cons_name,
                                             java.lang.String messageSelector)
                                      throws JMSException

This method creates a TopicBrowser for topics with TextMessage, StreamMessage, ObjectMessage, BytesMessage, or MapMessage message bodies. It has the following parameters:

ParameterDescription
topicTopic to access
cons_nameName of the durable subscriber or consumer
messageSelectorOnly messages with properties matching the messageSelector expression are delivered. A value of null or an empty string indicates that there is no messageSelector for the message consumer.
payload_factoryCustomDatumFactory or ORADataFactory for the Java class that maps to the Oracle ADT


See Also:

"MessageSelector"

Example 14-24 Creating a TopicBrowser Without a Selector

/* Create a browser without a selector */
TopicSession    jms_session;
TopicBrowser    browser;
Topic           topic;
browser = ((AQjmsSession) jms_session).createBrowser(topic, "SUBS1");

Example 14-25 Creating a TopicBrowser With a Specified Selector

/* Create a browser for topics with a specified selector */
TopicSession    jms_session;
TopicBrowser    browser;
Topic           topic;
/* create a Browser to look at messages with correlationID = RUSH  */
browser = ((AQjmsSession) jms_session).createBrowser(
          topic, "SUBS1", "JMSCorrelationID = 'RUSH'");

Creating a TopicBrowser for Standard JMS Messages, Locking Messages

public oracle.jms.TopicBrowser createBrowser(javax.jms.Topic topic,
                                             java.lang.String cons_name,
                                             java.lang.String messageSelector,
                                             boolean locked)
                                      throws JMSException

This method creates a TopicBrowser for topics with text, stream, objects, bytes or map messages, locking messages while browsing. It has the following parameters:

ParameterDescription
topicTopic to access
cons_nameName of the durable subscriber or consumer
messageSelectorOnly messages with properties matching the messageSelector expression are delivered. A value of null or an empty string indicates that there is no messageSelector for the message consumer.
lockedIf set to true, then messages are locked as they are browsed (similar to a SELECT for UPDATE)

Example 14-26 Creating a TopicBrowser Without a Selector, Locking Messages While Browsing

/* Create a browser without a selector */
TopicSession    jms_session;
TopicBrowser    browser;
Topic           topic;
browser = ((AQjmsSession) jms_session).createBrowser(
          topic, "SUBS1", true);

Example 14-27 Creating a TopicBrowser With a Specified Selector, Locking Messages

/* Create a browser for topics with a specified selector */
TopicSession    jms_session;
TopicBrowser    browser;
Topic           topic;
/* create a Browser to look at messages with correlationID = RUSH in
lock mode */
browser = ((AQjmsSession) jms_session).createBrowser(
          topic, "SUBS1", "JMSCorrelationID = 'RUSH'", true);

Creating a TopicBrowser for Oracle Object Type Messages

public oracle.jms.TopicBrowser createBrowser(javax.jms.Topic topic,
                                             java.lang.String cons_name,
                                             java.lang.String messageSelector,
                                             java.lang.Object payload_factory)
                                      throws JMSException

This method creates a TopicBrowser for topics of Oracle object type messages. It has the following parameters:

ParameterDescription
topicTopic to access
cons_nameName of the durable subscriber or consumer
messageSelectorOnly messages with properties matching the messageSelector expression are delivered. A value of null or an empty string indicates that there is no messageSelector for the message consumer.
payload_factoryCustomDatumFactory or ORADataFactory for the Java class that maps to the Oracle ADT


Note:

CustomDatum support will be deprecated in a future release. Use ORADataFactory payload factories instead.


See Also:

"MessageSelector"

The CustomDatumFactory for a particular Java class that maps to the SQL object type payload can be obtained using the getFactory static method. Assume the topic test_topic has payload of type SCOTT.EMPLOYEE and the Java class that is generated by Jpublisher for this Oracle object type is called Employee. The Employee class implements the CustomDatum interface. The CustomDatumFactory for this class can be obtained by using the Employee.getFactory() method.

Example 14-28 Creating a TopicBrowser for AdtMessage Messages

/* Create a browser for a Topic with AdtMessage messages of type EMPLOYEE*/
TopicSession jms_session
TopicBrowser browser;
Topic        test_topic;
browser = ((AQjmsSession) jms_session).createBrowser(
          test_topic, "SUBS1", Employee.getFactory());

Creating a TopicBrowser for Oracle Object Type Messages, Locking Messages

public oracle.jms.TopicBrowser createBrowser(javax.jms.Topic topic,
                                             java.lang.String cons_name,
                                             java.lang.String messageSelector,
                                             java.lang.Object payload_factory,
                                             boolean locked)
                                      throws JMSException

This method creates a TopicBrowser for topics of Oracle object type messages, locking messages while browsing. It has the following parameters:

ParameterDescription
topicTopic to access
cons_nameName of the durable subscriber or consumer
messageSelectorOnly messages with properties matching the messageSelector expression are delivered. A value of null or an empty string indicates that there is no messageSelector for the message consumer.
payload_factoryCustomDatumFactory or ORADataFactory for the Java class that maps to the Oracle ADT
lockedIf set to true, then messages are locked as they are browsed (similar to a SELECT for UPDATE)


Note:

CustomDatum support will be deprecated in a future release. Use ORADataFactory payload factories instead.


See Also:

"MessageSelector"

Example 14-29 Creating a TopicBrowser for AdtMessage Messages, Locking Messages

/* Create a browser for a Topic with AdtMessage messages of type EMPLOYEE* in
lock mode/
TopicSession jms_session
TopicBrowser browser;
Topic        test_topic;
browser = ((AQjmsSession) jms_session).createBrowser(
          test_topic, "SUBS1", Employee.getFactory(), true);

Browsing Messages Using a TopicBrowser

public void purgeSeen()
               throws JMSException

This method browses messages using a TopicBrowser. Use methods in java.util.Enumeration to go through the list of messages. Use the method purgeSeen in TopicBrowser to purge messages that have been seen during the current browse.

Example 14-30 Creating a TopicBrowser with a Specified Selector

/* Create a browser for topics with a specified selector */
public void browse_rush_orders(TopicSession jms_session)
TopicBrowser    browser;
Topic           topic;
ObjectMessage   obj_message
BolOrder        new_order;
Enumeration     messages;
/* get a handle to the new_orders topic */
topic = ((AQjmsSession) jms_session).getTopic("OE", "OE_bookedorders_topic");
/* create a Browser to look at RUSH orders */
browser = ((AQjmsSession) jms_session).createBrowser(
          topic, "SUBS1", "JMSCorrelationID = 'RUSH'");
/* Browse through the messages */
for (messages = browser.elements() ; message.hasMoreElements() ;)
{obj_message = (ObjectMessage)message.nextElement();}
/* Purge messages seen during this browse */
browser.purgeSeen() 
PKPK-AOEBPS/title.htmJ Oracle Streams Advanced Queuing User's Guide, 11g Release 2 (11.2)

Oracle® Streams

Advanced Queuing User's Guide

11g Release 2 (11.2)

E11013-04

July 2011


Oracle Streams Advanced Queuing User's Guide, 11g Release 2 (11.2)

E11013-04

Copyright © 1996, 2011, Oracle and/or its affiliates. All rights reserved.

Primary Authors: Denis Raphaely, Maitreyee Chaliha

Contributing Authors: Neerja Bhatt, Charles Hall

Contributor: Longxing Deng, Stella Kister, John Leinaweaver, Qiang Liu, Anil Madan, Abhishek Saxena, James Wilson

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle America, Inc., 500 Oracle Parkway, Redwood City, CA 94065.

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.

PKk޿PK-AOEBPS/jm_opers.htm Oracle JMS Basic Operations

12 Oracle JMS Basic Operations

This chapter describes the basic operational Java Message Service (JMS) administrative interface to Oracle Streams Advanced Queuing (AQ).

This chapter contains these topics:

EXECUTE Privilege on DBMS_AQIN

Users should never directly call methods in the DBMS_AQIN package, but they do need the EXECUTE privilege on DBMS_AQIN. Use the following syntax to accomplish this:

GRANT EXECUTE ON DBMS_AQIN to user; 

Registering a ConnectionFactory

You can register a ConnectionFactory four ways:

Registering Through the Database Using JDBC Connection Parameters

public static int registerConnectionFactory(java.sql.Connection connection,
                                            java.lang.String conn_name,
                                            java.lang.String hostname,
                                            java.lang.String oracle_sid,
                                            int portno,
                                            java.lang.String driver,
                                            java.lang.String type)
                                     throws JMSException

This method registers a QueueConnectionFactory or TopicConnectionFactory through the database to a Lightweight Directory Access Protocol (LDAP) server with JDBC connection parameters. This method is static and has the following parameters:

ParameterDescription
connectionJDBC connection used in registration
conn_nameName of the connection to be registered
hostnameName of the host running Oracle Streams Advanced Queuing
oracle_sidOracle system identifier
portnoPort number
driverJDBC driver type
typeConnection factory type (QUEUE or TOPIC)

The database connection passed to registerConnectionFactory must be granted AQ_ADMINISTRATOR_ROLE. After registration, you can look up the connection factory using Java Naming and Directory Interface (JNDI).

Example 12-1 Registering Through the Database Using JDBC Connection Parameters

String               url;
java.sql.connection  db_conn;

url = "jdbc:oracle:thin:@sun-123:1521:db1";
db_conn = DriverManager.getConnection(url, "scott", "tiger");
AQjmsFactory.registerConnectionFactory(
   db_conn, "queue_conn1", "sun-123", "db1", 1521, "thin", "queue");

Registering Through the Database Using a JDBC URL

public static int registerConnectionFactory(java.sql.Connection connection,
                                            java.lang.String conn_name,
                                            java.lang.String jdbc_url,
                                            java.util.Properties info,
                                            java.lang.String type)
                                     throws JMSException

This method registers a QueueConnectionFactory or TopicConnectionFactory through the database with a JDBC URL to LDAP. It is static and has the following parameters:

ParameterDescription
connectionJDBC connection used in registration
conn_nameName of the connection to be registered
jdbc_urlURL to connect to
infoProperties information
portnoPort number
typeConnection factory type (QUEUE or TOPIC)

The database connection passed to registerConnectionFactory must be granted AQ_ADMINISTRATOR_ROLE. After registration, you can look up the connection factory using JNDI.

Example 12-2 Registering Through the Database Using a JDBC URL

String                        url;
java.sql.connection           db_conn;

url = "jdbc:oracle:thin:@sun-123:1521:db1";
db_conn = DriverManager.getConnection(url, "scott", "tiger");
AQjmsFactory.registerConnectionFactory(
   db_conn, "topic_conn1", url, null, "topic");

Registering Through LDAP Using JDBC Connection Parameters

public static int registerConnectionFactory(java.util.Hashtable env,
                                            java.lang.String conn_name,
                                            java.lang.String hostname,
                                            java.lang.String oracle_sid,
                                            int portno,
                                            java.lang.String driver,
                                            java.lang.String type)
                                     throws JMSException

This method registers a QueueConnectionFactory or TopicConnectionFactory through LDAP with JDBC connection parameters to LDAP. It is static and has the following parameters:

ParameterDescription
envEnvironment of LDAP connection
conn_nameName of the connection to be registered
hostnameName of the host running Oracle Streams Advanced Queuing
oracle_sidOracle system identifier
portnoPort number
driverJDBC driver type
typeConnection factory type (QUEUE or TOPIC)

The hash table passed to registerConnectionFactory() must contain all the information to establish a valid connection to the LDAP server. Furthermore, the connection must have write access to the connection factory entries in the LDAP server (which requires the LDAP user to be either the database itself or be granted GLOBAL_AQ_USER_ROLE). After registration, look up the connection factory using JNDI.

Example 12-3 Registering Through LDAP Using JDBC Connection Parameters

Hashtable            env = new Hashtable(5, 0.75f);
/* the following statements set in hashtable env:
   * service provider package
   * the URL of the ldap server
   * the distinguished name of the database server
   * the authentication method (simple)
   * the LDAP username
   * the LDAP user password
*/
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://sun-456:389");
env.put("searchbase", "cn=db1,cn=Oraclecontext,cn=acme,cn=com");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=db1aqadmin,cn=acme,cn=com");
env.put(Context.SECURITY_CREDENTIALS, "welcome");

AQjmsFactory.registerConnectionFactory(env, 
                                       "queue_conn1", 
                                       "sun-123",
                                       "db1", 
                                       1521, 
                                       "thin", 
                                       "queue");

Registering Through LDAP Using a JDBC URL

public static int registerConnectionFactory(java.util.Hashtable env,
                                            java.lang.String conn_name,
                                            java.lang.String jdbc_url,
                                            java.util.Properties info,
                                            java.lang.String type)
                                     throws JMSException

This method registers a QueueConnectionFactory or TopicConnectionFactory through LDAP with JDBC connection parameters to LDAP. It is static and has the following parameters:

ParameterDescription
envEnvironment of LDAP connection
conn_nameName of the connection to be registered
jdbc_urlURL to connect to
infoProperties information
typeConnection factory type (QUEUE or TOPIC)

The hash table passed to registerConnectionFactory() must contain all the information to establish a valid connection to the LDAP server. Furthermore, the connection must have write access to the connection factory entries in the LDAP server (which requires the LDAP user to be either the database itself or be granted GLOBAL_AQ_USER_ROLE). After registration, look up the connection factory using JNDI.

Example 12-4 Registering Through LDAP Using a JDBC URL

String               url;
Hashtable            env = new Hashtable(5, 0.75f);

/* the following statements set in hashtable env:
   * service provider package
   * the URL of the ldap server
   * the distinguished name of the database server
   * the authentication method (simple)
   * the LDAP username
   * the LDAP user password
*/
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://sun-456:389");
env.put("searchbase", "cn=db1,cn=Oraclecontext,cn=acme,cn=com");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=db1aqadmin,cn=acme,cn=com");
env.put(Context.SECURITY_CREDENTIALS, "welcome");
url = "jdbc:oracle:thin:@sun-123:1521:db1";
AQjmsFactory.registerConnectionFactory(env, "topic_conn1", url, null, "topic");

Unregistering a Queue/Topic ConnectionFactory

You can unregister a queue/topic ConnectionFactory in LDAP two ways:

Unregistering Through the Database

public static int unregisterConnectionFactory(java.sql.Connection connection,
                                              java.lang.String conn_name)
                                       throws JMSException

This method unregisters a QueueConnectionFactory or TopicConnectionFactory in LDAP. It is static and has the following parameters:

ParameterDescription
connectionJDBC connection used in registration
conn_nameName of the connection to be registered

The database connection passed to unregisterConnectionFactory() must be granted AQ_ADMINISTRATOR_ROLE.

Example 12-5 Unregistering Through the Database

String               url;
java.sql.connection  db_conn;

url = "jdbc:oracle:thin:@sun-123:1521:db1";
db_conn = DriverManager.getConnection(url, "scott", "tiger");
AQjmsFactory.unregisterConnectionFactory(db_conn, "topic_conn1");

Unregistering Through LDAP

public static int unregisterConnectionFactory(java.util.Hashtable env,
                                              java.lang.String conn_name)
                                       throws JMSException

This method unregisters a QueueConnectionFactory or TopicConnectionFactory in LDAP. It is static and has the following parameters:

ParameterDescription
envEnvironment of LDAP connection
conn_nameName of the connection to be registered

The hash table passed to unregisterConnectionFactory() must contain all the information to establish a valid connection to the LDAP server. Furthermore, the connection must have write access to the connection factory entries in the LDAP server (which requires the LDAP user to be either the database itself or be granted GLOBAL_AQ_USER_ROLE).

Example 12-6 Unregistering Through LDAP

Hashtable            env = new Hashtable(5, 0.75f);

/* the following statements set in hashtable env:
   * service provider package
   * the distinguished name of the database server
   * the authentication method (simple)
   * the LDAP username
   * the LDAP user password
*/
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://sun-456:389");
env.put("searchbase", "cn=db1,cn=Oraclecontext,cn=acme,cn=com");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=db1aqadmin,cn=acme,cn=com");
env.put(Context.SECURITY_CREDENTIALS, "welcome");
url = "jdbc:oracle:thin:@sun-123:1521:db1";
AQjmsFactory.unregisterConnectionFactory(env, "queue_conn1");

Getting a QueueConnectionFactory or TopicConnectionFactory

This section contains these topics:

Getting a QueueConnectionFactory with JDBC URL

public static javax.jms.QueueConnectionFactory getQueueConnectionFactory(
              java.lang.String jdbc_url,
              java.util.Properties info)
       throws JMSException

This method gets a QueueConnectionFactory with JDBC URL. It is static and has the following parameters:

ParameterDescription
jdbc_urlURL to connect to
infoProperties information

Example 12-7 Getting a QueueConnectionFactory with JDBC URL

 String      url          = "jdbc:oracle:oci10:internal/oracle"
 Properties  info         = new Properties();
 QueueConnectionFactory   qc_fact;

 info.put("internal_logon", "sysdba");
 qc_fact = AQjmsFactory.getQueueConnectionFactory(url, info);

Getting a QueueConnectionFactory with JDBC Connection Parameters

public static javax.jms.QueueConnectionFactory getQueueConnectionFactory(
              java.lang.String hostname,
              java.lang.String oracle_sid,
              int portno,
              java.lang.String driver)
       throws JMSException

This method gets a QueueConnectionFactory with JDBC connection parameters. It is static and has the following parameters:

ParameterDescription
hostnameName of the host running Oracle Streams Advanced Queuing
oracle_sidOracle system identifier
portnoPort number
driverJDBC driver type

Example 12-8 Getting a QueueConnectionFactory with JDBC Connection Parameters

 String      host         = "dlsun";
 String      ora_sid      = "rdbms10i"
 String      driver       = "thin";
 int         port         = 5521;
 QueueConnectionFactory   qc_fact;

 qc_fact = AQjmsFactory.getQueueConnectionFactory(host, ora_sid, port, driver);

Getting a TopicConnectionFactory with JDBC URL

public static javax.jms.QueueConnectionFactory getQueueConnectionFactory(
              java.lang.String jdbc_url,
              java.util.Properties info)
       throws JMSException

This method gets a TopicConnectionFactory with a JDBC URL. It is static and has the following parameters:

ParameterDescription
jdbc_urlURL to connect to
infoProperties information

Example 12-9 Getting a TopicConnectionFactory with JDBC URL

 String      url          = "jdbc:oracle:oci10:internal/oracle"
 Properties  info         = new Properties();
 TopicConnectionFactory   tc_fact;

 info.put("internal_logon", "sysdba");
 tc_fact = AQjmsFactory.getTopicConnectionFactory(url, info);

Getting a TopicConnectionFactory with JDBC Connection Parameters

public static javax.jms.TopicConnectionFactory getTopicConnectionFactory(
              java.lang.String hostname,
              java.lang.String oracle_sid,
              int portno,
              java.lang.String driver)
       throws JMSException

This method gets a TopicConnectionFactory with JDBC connection parameters. It is static and has the following parameters:

ParameterDescription
hostnameName of the host running Oracle Streams Advanced Queuing
oracle_sidOracle system identifier
portnoPort number
driverJDBC driver type

Example 12-10 Getting a TopicConnectionFactory with JDBC Connection Parameters

String      host         = "dlsun";
String      ora_sid      = "rdbms10i"
String      driver       = "thin";
int         port         = 5521;
TopicConnectionFactory   tc_fact;

tc_fact = AQjmsFactory.getTopicConnectionFactory(host, ora_sid, port, driver);

Getting a QueueConnectionFactory or TopicConnectionFactory in LDAP

This method gets a QueueConnectionFactory or TopicConnectionFactory from LDAP.

Example 12-11 Getting a QueueConnectionFactory or TopicConnectionFactory in LDAP

Hashtable              env = new Hashtable(5, 0.75f);
DirContext             ctx;
queueConnectionFactory qc_fact;

/* the following statements set in hashtable env:
   * service provider package
   * the URL of the ldap server
   * the distinguished name of the database server
   * the authentication method (simple)
   * the LDAP username
   * the LDAP user password
*/
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://sun-456:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=db1aquser1,cn=acme,cn=com");
env.put(Context.SECURITY_CREDENTIALS, "welcome");

ctx = new InitialDirContext(env);
ctx = (DirContext)ctx.lookup("cn=OracleDBConnections,cn=db1,cn=Oraclecontext,cn=acme,cn=com");
qc_fact = (queueConnectionFactory)ctx.lookup("cn=queue_conn1");

Getting a Queue or Topic in LDAP

This method gets a queue or topic from LDAP.

Example 12-12 Getting a Queue or Topic in LDAP

Hashtable              env = new Hashtable(5, 0.75f);
DirContext             ctx;
topic                  topic_1;

/* the following statements set in hashtable env:
   * service provider package
   * the URL of the ldap server
   * the distinguished name of the database server
   * the authentication method (simple)
   * the LDAP username
   * the LDAP user password
*/
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://sun-456:389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=db1aquser1,cn=acme,cn=com");
env.put(Context.SECURITY_CREDENTIALS, "welcome");

ctx = new InitialDirContext(env);
ctx = (DirContext)ctx.lookup("cn=OracleDBQueues,cn=db1,cn=Oraclecontext,cn=acme,cn=com");
topic_1 = (topic)ctx.lookup("cn=topic_1");

Creating a Queue Table

public oracle.AQ.AQQueueTable createQueueTable(
                 java.lang.String owner,
                 java.lang.String name,
                 oracle.AQ.AQQueueTableProperty property)
          throws JMSException

This method creates a queue table. It has the following parameters:

ParameterDescription
ownerQueue table owner (schema)
nameQueue table name
propertyQueue table properties

If the queue table is used to hold queues, then the queue table must not be multiconsumer enabled (default). If the queue table is used to hold topics, then the queue table must be multiconsumer enabled.

CLOB, BLOB, and BFILE objects are valid attributes for an Oracle Streams Advanced Queuing object type load. However, only CLOB and BLOB can be propagated using Oracle Streams Advanced Queuing propagation in Oracle8i and after.

Example 12-13 Creating a Queue Table

QueueSession              q_sess    = null;
AQQueueTable              q_table   = null;
AQQueueTableProperty      qt_prop   = null;

qt_prop = new AQQueueTableProperty("SYS.AQ$_JMS_BYTES_MESSAGE");
q_table = ((AQjmsSession)q_sess).createQueueTable(
    "boluser", "bol_ship_queue_table", qt_prop);

Getting a Queue Table

public oracle.AQ.AQQueueTable getQueueTable(java.lang.String owner,
                                            java.lang.String name)
                                     throws JMSException

This method gets a queue table. It has the following parameters:

ParameterDescription
ownerQueue table owner (schema)
nameQueue table name

If the caller that opened the connection is not the owner of the queue table, then the caller must have Oracle Streams Advanced Queuing enqueue/dequeue privileges on queues/topics in the queue table. Otherwise the queue table is not returned.

Example 12-14 Getting a Queue Table

QueueSession              q_sess;
AQQueueTable              q_table;

q_table = ((AQjmsSession)q_sess).getQueueTable(
   "boluser", "bol_ship_queue_table");

Creating a Queue

This section contains these topics:

Creating a Point-to-Point Queue

public javax.jms.Queue createQueue(
             oracle.AQ.AQQueueTable q_table,
             java.lang.String queue_name,
             oracle.jms.AQjmsDestinationProperty dest_property)
      throws JMSException

This method creates a queue in a specified queue table. It has the following parameters:

ParameterDescription
q_tableQueue table in which the queue is to be created. The queue table must be single-consumer.
queue_nameName of the queue to be created
dest_propertyQueue properties

This method is specific to OJMS. You cannot use standard Java javax.jms.Session objects with it. Instead, you must cast the standard type to the OJMS concrete class oracle.jms.AQjmsSession.

Example 12-15 Creating a Point-to-Point Queue

QueueSession             q_sess;
AQQueueTable             q_table;
AqjmsDestinationProperty dest_prop;
Queue                    queue;

queue = ((AQjmsSession)q_sess).createQueue(q_table, "jms_q1", dest_prop);

Creating a Publish/Subscribe Topic

public javax.jms.Topic createTopic(
             oracle.AQ.AQQueueTable q_table,
             java.lang.String topic_name,
             oracle.jms.AQjmsDestinationProperty dest_property)
      throws JMSException

This method creates a topic in the publish/subscribe model. It has the following parameters:

ParameterDescription
q_tableQueue table in which the queue is to be created. The queue table must be multiconsumer.
queue_nameName of the queue to be created
dest_propertyQueue properties

This method is specific to OJMS. You cannot use standard Java javax.jms.Session objects with it. Instead, you must cast the standard type to the OJMS concrete class oracle.jms.AQjmsSession.

Example 12-16 Creating a Publish/Subscribe Topic

TopicSession             t_sess;
AQQueueTable             q_table;
AqjmsDestinationProperty dest_prop;
Topic                    topic;

topic = ((AQjmsSessa)t_sess).createTopic(q_table, "jms_t1", dest_prop);

In Example 12-17, if an order cannot be filled because of insufficient inventory, then the transaction processing the order is terminated. The bookedorders topic is set up with max_retries = 4 and retry_delay = 12 hours.Thus, if an order is not filled up in two days, then it is moved to an exception queue.

Example 12-17 Specifying Max Retries and Max Delays in Messages

public BolOrder process_booked_order(TopicSession jms_session)
  {
    Topic            topic;
    TopicSubscriber  tsubs;
    ObjectMessage    obj_message;
    BolCustomer      customer;
    BolOrder         booked_order = null;
    String           country;
    int              i = 0;

    try
    {
      /* get a handle to the OE_bookedorders_topic */
      topic = ((AQjmsSession)jms_session).getTopic("WS",
                                                   "WS_bookedorders_topic");

      /* Create local subscriber - to track messages for Western Region  */
      tsubs = jms_session.createDurableSubscriber(topic, "SUBS1",
                                       "Region = 'Western' ",
                                                   false);

       /* wait for a message to show up in the topic */
       obj_message = (ObjectMessage)tsubs.receive(10);

       booked_order = (BolOrder)obj_message.getObject();

       customer = booked_order.getCustomer();
       country    = customer.getCountry();

       if (country == "US")
       {
          jms_session.commit();
       }
       else
       {
          jms_session.rollback();
          booked_order = null;
       }
    }catch (JMSException ex)
    { System.out.println("Exception " + ex) ;}

     return booked_order;
   }

Granting and Revoking Privileges

This section contains these topics:

Granting Oracle Streams Advanced Queuing System Privileges

public void grantSystemPrivilege(java.lang.String privilege,
                                 java.lang.String grantee,
                                 boolean admin_option)
                          throws JMSException

This method grants Oracle Streams Advanced Queuing system privileges to a user or role.

ParameterDescription
privilegeENQUEUE_ANY, DEQUEUE_ANY or MANAGE_ANY
granteeGrantee (user, role, or PUBLIC)
admin_optionIf this is set to true, then the grantee is allowed to use this procedure to grant the system privilege to other users or roles

Initially only SYS and SYSTEM can use this procedure successfully. Users granted the ENQUEUE_ANY privilege are allowed to enqueue messages to any queues in the database. Users granted the DEQUEUE_ANY privilege are allowed to dequeue messages from any queues in the database. Users granted the MANAGE_ANY privilege are allowed to run DBMS_AQADM calls on any schemas in the database.

Example 12-18 Granting Oracle Streams Advanced Queuing System Privileges

TopicSession             t_sess;

((AQjmsSession)t_sess).grantSystemPrivilege("ENQUEUE_ANY", "scott", false);

Revoking Oracle Streams Advanced Queuing System Privileges

public void revokeSystemPrivilege(java.lang.String privilege,
                                  java.lang.String grantee)
                           throws JMSException

This method revokes Oracle Streams Advanced Queuing system privileges from a user or role. It has the following parameters:

ParameterDescription
privilegeENQUEUE_ANY, DEQUEUE_ANY or MANAGE_ANY
granteeGrantee (user, role, or PUBLIC)

Users granted the ENQUEUE_ANY privilege are allowed to enqueue messages to any queues in the database. Users granted the DEQUEUE_ANY privilege are allowed to dequeue messages from any queues in the database. Users granted the MANAGE_ANY privilege are allowed to run DBMS_AQADM calls on any schemas in the database.

Example 12-19 Revoking Oracle Streams Advanced Queuing System Privileges

TopicSession             t_sess;

((AQjmsSession)t_sess).revokeSystemPrivilege("ENQUEUE_ANY", "scott");

Granting Publish/Subscribe Topic Privileges

public void grantTopicPrivilege(javax.jms.Session session,
                                java.lang.String privilege,
                                java.lang.String grantee,
                                boolean grant_option)
                         throws JMSException

This method grants a topic privilege in the publish/subscribe model. Initially only the queue table owner can use this procedure to grant privileges on the topic. It has the following parameters:

ParameterDescription
sessionJMS session
privilegeENQUEUE, DEQUEUE, or ALL (ALL means both.)
granteeGrantee (user, role, or PUBLIC)
grant_optionIf this is set to true, then the grantee is allowed to use this procedure to grant the system privilege to other users or roles

Example 12-20 Granting Publish/Subscribe Topic Privileges

TopicSession             t_sess;
Topic                    topic;

((AQjmsDestination)topic).grantTopicPrivilege(
   t_sess, "ENQUEUE", "scott", false);

Revoking Publish/Subscribe Topic Privileges

public void revokeTopicPrivilege(javax.jms.Session session,
                                 java.lang.String privilege,
                                 java.lang.String grantee)
                          throws JMSException

This method revokes a topic privilege in the publish/subscribe model. It has the following parameters:

ParameterDescription
sessionJMS session
privilegeENQUEUE, DEQUEUE, or ALL (ALL means both.)
granteeRevoked grantee (user, role, or PUBLIC)

Example 12-21 Revoking Publish/Subscribe Topic Privileges

TopicSession             t_sess;
Topic                    topic;

((AQjmsDestination)topic).revokeTopicPrivilege(t_sess, "ENQUEUE", "scott");

Granting Point-to-Point Queue Privileges

public void grantQueuePrivilege(javax.jms.Session session,
                                java.lang.String privilege,
                                java.lang.String grantee,
                                boolean grant_option)
                         throws JMSException

This method grants a queue privilege in the point-to-point model. Initially only the queue table owner can use this procedure to grant privileges on the queue. It has the following parameters:

ParameterDescription
sessionJMS session
privilegeENQUEUE, DEQUEUE, or ALL (ALL means both.)
granteeGrantee (user, role, or PUBLIC)
grant_optionIf this is set to true, then the grantee is allowed to use this procedure to grant the system privilege to other users or roles

Example 12-22 Granting Point-to-Point Queue Privileges

QueueSession             q_sess;
Queue                    queue;

((AQjmsDestination)queue).grantQueuePrivilege(
   q_sess, "ENQUEUE", "scott", false);

Revoking Point-to-Point Queue Privileges

public void revokeQueuePrivilege(javax.jms.Session session,
                                 java.lang.String privilege,
                                 java.lang.String grantee)
                          throws JMSException

This method revokes queue privileges in the point-to-point model. Initially only the queue table owner can use this procedure to grant privileges on the queue. It has the following parameters:

ParameterDescription
sessionJMS session
privilegeENQUEUE, DEQUEUE, or ALL (ALL means both.)
granteeRevoked grantee (user, role, or PUBLIC)

To revoke a privilege, the revoker must be the original grantor of the privilege. Privileges propagated through the GRANT option are revoked if the grantor privilege is also revoked.

Example 12-23 Revoking Point-to-Point Queue Privileges

QueueSession             q_sess;
Queue                    queue;

((AQjmsDestination)queue).revokeQueuePrivilege(q_sess, "ENQUEUE", "scott");

Managing Destinations

This section contains these topics:

Starting a Destination

public void start(javax.jms.Session session,
                  boolean enqueue,
                  boolean dequeue)
           throws JMSException

This method starts a destination. It has the following parameters:

ParameterDescription
sessionJMS session
enqueueIf set to TRUE, then enqueue is enabled
dequeueIf set to TRUE, then dequeue is enabled

Example 12-24 Starting a Destination

TopicSession t_sess;
QueueSession q_sess;
Topic        topic;
Queue        queue;

(AQjmsDestination)topic.start(t_sess, true, true);
(AQjmsDestination)queue.start(q_sess, true, true);

Stopping a Destination

public void stop(javax.jms.Session session,
                 boolean enqueue,
                 boolean dequeue,
                 boolean wait)
          throws JMSException

This method stops a destination. It has the following parameters:

ParameterDescription
sessionJMS session
enqueueIf set to TRUE, then enqueue is disabled
dequeueIf set to TRUE, then dequeue is disabled
waitIf set to true, then pending transactions on the queue/topic are allowed to complete before the destination is stopped

Example 12-25 Stopping a Destination

TopicSession t_sess;
Topic        topic;

((AQjmsDestination)topic).stop(t_sess, true, false);

Altering a Destination

public void alter(javax.jms.Session session,
                  oracle.jms.AQjmsDestinationProperty dest_property)
           throws JMSException

This method alters a destination. It has the following properties:

ParameterDescription
sessionJMS session
dest_propertyNew properties of the queue or topic

Example 12-26 Altering a Destination

QueueSession q_sess;
Queue        queue;
TopicSession t_sess;
Topic        topic;
AQjmsDestionationProperty dest_prop1, dest_prop2;

((AQjmsDestination)queue).alter(dest_prop1);
((AQjmsDestination)topic).alter(dest_prop2);

Dropping a Destination

public void drop(javax.jms.Session session)
          throws JMSException

This method drops a destination. It has the following parameter:

ParameterDescription
sessionJMS session

Example 12-27 Dropping a Destination

QueueSession q_sess;
Queue        queue;
TopicSession t_sess;
Topic        topic;

((AQjmsDestionation)queue).drop(q_sess);
((AQjmsDestionation)topic).drop(t_sess);

Propagation Schedules

This section contains these topics:

Scheduling a Propagation

public void schedulePropagation(javax.jms.Session session,
                                java.lang.String destination,
                                java.util.Date start_time,
                                java.lang.Double duration,
                                java.lang.String next_time,
                                java.lang.Double latency)
                         throws JMSException

This method schedules a propagation. It has the following parameters:

ParameterDescription
sessionJMS session
destinationDatabase link of the remote database for which propagation is being scheduled. A null string means that propagation is scheduled for all subscribers in the database of the topic.
start_timeTime propagation starts
durationDuration of propagation
next_timeNext time propagation starts
latencyLatency in seconds that can be tolerated. Latency is the difference between the time a message was enqueued and the time it was propagated.

If a message has multiple recipients at the same destination in either the same or different queues, then it is propagated to all of them at the same time.

Example 12-28 Scheduling a Propagation

TopicSession t_sess;
Topic        topic;

((AQjmsDestination)topic).schedulePropagation(
   t_sess, null, null, null, null, new Double(0));

Enabling a Propagation Schedule

public void enablePropagationSchedule(javax.jms.Session session,
                                      java.lang.String destination)
                               throws JMSException

This method enables a propagation schedule. It has the following parameters:

ParameterDescription
sessionJMS session
destinationDatabase link of the destination database. A null string means that propagation is to the local database.

Example 12-29 Enabling a Propagation Schedule

TopicSession             t_sess;
Topic                    topic;

((AQjmsDestination)topic).enablePropagationSchedule(t_sess, "dbs1");

Altering a Propagation Schedule

public void alterPropagationSchedule(javax.jms.Session session,
                                     java.lang.String destination,
                                     java.lang.Double duration,
                                     java.lang.String next_time,
                                     java.lang.Double latency)
                              throws JMSException

This method alters a propagation schedule. It has the following parameters:

ParameterDescription
sessionJMS session
destinationDatabase link of the remote database for which propagation is being scheduled. A null string means that propagation is scheduled for all subscribers in the database of the topic.
durationDuration of propagation
next_timeNext time propagation starts
latencyLatency in seconds that can be tolerated. Latency is the difference between the time a message was enqueued and the time it was propagated.

Example 12-30 Altering a Propagation Schedule

TopicSession             t_sess;
Topic                    topic;

((AQjmsDestination)topic).alterPropagationSchedule(
   t_sess, null, 30, null, new Double(30));

Disabling a Propagation Schedule

public void disablePropagationSchedule(javax.jms.Session session,
                                       java.lang.String destination)
                                throws JMSException

This method disables a propagation schedule. It has the following parameters:

ParameterDescription
sessionJMS session
destinationDatabase link of the destination database. A null string means that propagation is to the local database.

Example 12-31 Disabling a Propagation Schedule

TopicSession             t_sess;
Topic                    topic;

((AQjmsDestination)topic).disablePropagationSchedule(t_sess, "dbs1");

Unscheduling a Propagation

public void unschedulePropagation(javax.jms.Session session,
                                  java.lang.String destination)
                           throws JMSException

This method unschedules a previously scheduled propagation. It has the following parameters:

ParameterDescription
sessionJMS session
destinationDatabase link of the destination database. A null string means that propagation is to the local database.

Example 12-32 Unscheduling a Propagation

TopicSession   t_sess;
Topic          topic;

((AQjmsDestination)topic).unschedulePropagation(t_sess, "dbs1");
PK3KwgfPK-AOEBPS/componet.htm Basic Components

2 Basic Components

This chapter describes the Oracle Streams Advanced Queuing (AQ) basic components.

This chapter contains the following topics:

Object Name

object_name := VARCHAR2
object_name := [schema_name.]name

This component names database objects. This naming convention applies to queues, queue tables, and object types.

Names for objects are specified by an optional schema name and a name. If the schema name is not specified, then the current schema is assumed. The name must follow the reserved character guidelines in Oracle Database SQL Language Reference. The schema name, agent name, and the object type name can each be up to 30 bytes long. However, queue names and queue table names can be a maximum of 24 bytes.

Type Name

type_name := VARCHAR2
type_name := object_type | "RAW"

This component defines queue types. The maximum number of attributes in the object type is limited to 900.

To store payloads of type RAW, Oracle Streams Advanced Queuing creates a queue table with a LOB column as the payload repository. The size of the payload is limited to 32K bytes of data. Because LOB columns are used for storing RAW payload, the Oracle Streams Advanced Queuing administrator can choose the LOB tablespace and configure the LOB storage by constructing a LOB storage string in the storage_clause parameter during queue table creation time.


Note:

Payloads containing LOBs require users to grant explicit Select, Insert and Update privileges on the queue table for doing enqueues and dequeues.

AQ Agent Type

TYPE AQ$_AGENT IS OBJECT (
   name            VARCHAR2(30), 
   address         VARCHAR2(1024),
   protocol        NUMBER);

This component identifies a producer or a consumer of a message.

All consumers that are added as subscribers to a multiconsumer queue must have unique values for the AQ$_AGENT parameters. Two subscribers cannot have the same values for the NAME, ADDRESS, and PROTOCOL attributes for the AQ$_AGENT type. At least one of the three attributes must be different for two subscribers.

You can add subscribers by repeatedly using the DBMS_AQADM.ADD_SUBSCRIBER procedure up to a maximum of 1024 subscribers for a multiconsumer queue.

This type has three attributes:

AQ Recipient List Type

TYPE AQ$_RECIPIENT_LIST_T IS TABLE OF aq$_agent
           INDEX BY BINARY_INTEGER;
 

This component identifies the list of agents that receive a message.

AQ Agent List Type

TYPE AQ$_AGENT_LIST_T IS TABLE OF aq$_agent 
           INDEX BY BINARY INTEGER; 

This component identifies the list of agents for DBMS_AQ.LISTEN to listen for.

AQ Subscriber List Type

TYPE AQ$_SUBSCRIBER_LIST_T IS TABLE OF aq$_agent
          INDEX BY BINARY INTEGER;

This component identifies the list of subscribers that subscribe to this queue.

AQ Registration Information List Type

TYPE AQ$_REG_INFO_LIST AS VARRAY(1024) OF sys.aq$_reg_info;

This component identifies the list of registrations to a queue.

AQ Post Information List Type

TYPE AQ$_POST_INFO_LIST AS VARRAY(1024) OF sys.aq$_post_info;

This component identifies the list of anonymous subscriptions to which messages are posted.

AQ Registration Information Type

TYPE SYS.AQ$_REG_INFO IS OBJECT (
   name                              VARCHAR2(128),
   namespace                         NUMBER,
   callback                          VARCHAR2(4000),
   context                           RAW(2000)  DEFAULT NULL,
   qosflags                          NUMBER,
   timeout                           NUMBER
   ntfn_grouping_class               NUMBER,
   ntfn_grouping_value               NUMBER    DEFAULT 600,
   ntfn_grouping_type                NUMBER,
   ntfn_grouping_start_time          TIMESTAMP WITH TIME ZONE,
   ntfn_grouping_repeat_count   NUMBER);

This component identifies a producer or a consumer of a message. Its attributes are described in the following list. Attributes qosflags and timeout are part of Oracle Streams Advanced Queuing 10g Release 2 (10.2) notification enhancements.

Table 2-1 AQ$_REG_INFO Type Attributes

AttributeDescription

name

Specifies the name of the subscription. The subscription name is of the form schema.queue if the registration is for a single consumer queue or schema.queue:consumer_name if the registration is for a multiconsumer queues.

namespace

Specifies the namespace of the subscription. To receive notification from Oracle Streams AQ queues, the namespace must be DBMS_AQ.NAMESPACE_AQ. To receive notifications from other applications through DBMS_AQ.POST or OCISubscriptionPost(), the namespace must be DBMS_AQ.NAMESPACE_ANONYMOUS.

callback

Specifies the action to be performed on message notification. For HTTP notifications, use http://www.company.com:8080. For e-mail notifications, use mailto://xyz@company.com. For raw message payload for the PLSQLCALLBACK procedure, use plsql://schema.procedure?PR=0. For user-defined type message payload converted to XML for the PLSQLCALLBACK procedure, use plsql://schema.procedure?PR=1

context

Specifies the context that is to be passed to the callback function

qosflags

Can be set to one or more of the following values to specify the notification quality of service:

  • NTFN_QOS_RELIABLE- This value specifies that reliable notification is required. Reliable notifications persist across instance and database restarts.

  • NTFN_QOS_PAYLOAD - This value specifies that payload delivery is required. It is supported only for client notification and only for RAW queues.

  • NTFN_QOS_PURGE_ON_NTFN - This value specifies that the registration is to be purged automatically when the first notification is delivered to this registration location.

ntfn_grouping_class

Currently, only the following flag can be set to specify criterion for grouping. The default value will be 0. If ntfn_grouping_class is 0, all other notification grouping attributes must be 0.

  • NTFN_GROUPING_CLASS_TIME - Notifications grouped by time, that is, the user specifies a time value and a single notification gets published at the end of that time.

ntfn_grouping_value

Time-period of grouping notifications specified in seconds, meaning the time after which grouping notification would be sent periodically until ntfn_grouping_repeat_count is exhausted.

ntfn_grouping_type

  • NTFN_GROUPING_TYPE_SUMMARY - Summary of all notifications that occurred in the time interval. (Default)

  • NTFN_GROUPING_TYPE_LAST - Last notification that occurred in the interval.

ntfn_grouping_start_time

Notification grouping start time. Notification grouping can start from a user-specified time that should a valid timestamp with time zone. If ntfn_grouping_start_time is not specified when using grouping, the default is to current timestamp with time zone

ntfn_grouping_repeat_count

Grouping notifications will be sent as many times as specified by the notification grouping repeat count and after that revert to regular notifications. The ntfn_grouping_repeat_count, if not specified, will default to

  • NTFN_GROUPING_FOREVER - Keep sending grouping notifications forever.


AQ Notification Descriptor Type

TYPE SYS.AQ$_DESCRIPTOR IS OBJECT (
   queue_name      VARCHAR2(61),
   consumer_name   VARCHAR2(30),
   msg_id          RAW(16),
   msg_prop        MSG_PROP_T,
   gen_desc        AQ$_NTFN_DESCRIPTOR,
   msgid_array     SYS.AQ$_NTFN_MSGID_ARRAY, 
   ntfnsRecdInGrp  NUMBER);

This component specifies the Oracle Streams Advanced Queuing descriptor received by Oracle Streams Advanced Queuing PL/SQL callbacks upon notification. It has the following attributes:

Table 2-2 AQ$_DESCRIPTOR Attributes

AttributeDescription

queue_name

Name of the queue in which the message was enqueued which resulted in the notification

consumer_name

Name of the consumer for the multiconsumer queue

msg_id

Identification number of the message

msg_prop

Message properties specified by the MSG_PROP_T type

gen_desc

Indicates the timeout specifications

msgid_array

Group notification message ID list

ntfnsRecdInGrp

Notifications received in group


AQ Message Properties Type

The message properties type msg_prop_t has the following components:

TYPE AQ$_MSG_PROP_T IS OBJECT(
   priority         number,
   delay            number,
   expiration       number,
   correlation      varchar2(128),
   attempts         number,
   recipent_list    aq$_recipient_list_t,
   exception_queue  varchar2(51),
   enqueue_time     date,
   state            number,
   sender_id        aq$_agent,
   original_misgid  raw(16),
   delivery_mode    number);

See Also:

"MESSAGE_PROPERTIES_T Type" in Oracle Database PL/SQL Packages and Types Reference

The timeout specifications type AQ$_NTFN_DESCRIPTOR has a single component:

TYPE AQ$_NTFN_DESCRIPTOR IS OBJECT(
   NTFN_FLAGS   number);

NTFN_FLAGS is set to 1 if the notifications are already removed after a stipulated timeout; otherwise the value is 0.

AQ Post Information Type

TYPE SYS.AQ$_POST_INFO IS OBJECT (
  name       VARCHAR2(128),
  namespace  NUMBER,
  payload    RAW(2000));

This component specifies anonymous subscriptions to which you want to post messages. It has three attributes:

AQ$_NTFN_MSGID_ARRAY Type

TYPE SYS.AQ$_NTFN_MSGID_ARRAY   AS VARRAY(1073741824)OF RAW(16);

This component is for storing grouping notification data for AQ namespace, value 230 which is the max varray size.

Enumerated Constants in the Oracle Streams Advanced Queuing Administrative Interface

When enumerated constants such as INFINITE, TRANSACTIONAL, and NORMAL_QUEUE are selected as values, the symbol must be specified with the scope of the packages defining it. All types associated with the administrative interfaces must be prepended with DBMS_AQADM. For example:

DBMS_AQADM.NORMAL_QUEUE

Table 2-3 lists the enumerated constants in the Oracle Streams Advanced Queuing administrative interface.

Table 2-3 Enumerated Constants in the Oracle Streams Advanced Queuing Administrative Interface

ParameterOptions

retention

0,1,2...INFINITE

message_grouping

TRANSACTIONAL, NONE

queue_type

NORMAL_QUEUE, EXCEPTION_QUEUE,NON_PERSISTENT_QUEUE

delivery_mode

BUFFERED, PERSISTENT, PERSISTENT_OR_BUFFERED



Note:

Nonpersistent queues are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2). Oracle recommends that you use buffered messaging instead.

Enumerated Constants in the Oracle Streams Advanced Queuing Operational Interface

When using enumerated constants such as BROWSE, LOCKED, and REMOVE, the PL/SQL constants must be specified with the scope of the packages defining them. All types associated with the operational interfaces must be prepended with DBMS_AQ. For example:

DBMS_AQ.BROWSE

Table 2-4 lists the enumerated constants in the Oracle Streams Advanced Queuing operational interface.

Table 2-4 Enumerated Constants in the Oracle Streams Advanced Queuing Operational Interface

ParameterOptions

visibility

IMMEDIATE, ON_COMMIT

dequeue mode

BROWSE, LOCKED, REMOVE, REMOVE_NODATA

navigation

FIRST_MESSAGE, NEXT_MESSAGE, NEXT_TRANSACTION

state

WAITING, READY, PROCESSED, EXPIRED

wait

FOREVER, NO_WAIT

delay

NO_DELAY

expiration

NEVER

namespace

NAMESPACE_AQ, NAMESPACE_ANONYMOUS

delivery_mode

BUFFERED, PERSISTENT, PERSISTENT_OR_BUFFERED

quosflags

NTFN_QOS_RELIABLE, NTFN_QOS_PAYLOAD, NTFN_QOS_PURGE_ON_NTFN

ntfn_grouping_class

NFTN_GROUPING_CLASS_TIME

ntfn_grouping_type

NTFN_GROUPING_TYPE_SUMMARY, NTFN_GROUPING_TYPE_LAST

ntfn_grouping_repeat_count

NTFN_GROUPING_FOREVER


AQ Background Processes

Queue Monitor Processes

A number of Streams AQ or Streams tasks are executed in the background. These include converting messages with DELAY specified into the READY state, expiring messages, moving messages to exception queues, spilling and recovering of buffered messages, and similar operations.

These are executed by a set of AQ background process. These include a coordinator process, name QMNC (link), which dynamically spawns subordinate processes Qxx as needed. The number of subordinate processes is determined automatically and tuned constantly.

It is no longer necessary to set AQ_TM_PROCESSES when Oracle Streams AQ or Streams is used. If a value is specified, that value is taken into account when starting the Qxx processes. However, the number of Qxx processes can be different from what was specified by AQ_TM_PROCESSES.

QMNC only runs when you use queues and create new queues. It affects Streams Replication and Messaging users.

No separate API is needed to disable or enable the background processes. This is controlled by setting AQ_TM_PROCESSES to zero or nonzero. Oracle recommends, however, that you leave the AQ_TM_PROCESSES parameter unspecified and let the system autotune.


Note:

If you want to disable the Queue Monitor Coordinator, then you must set AQ_TM_PROCESSES = 0 in your pfile or spfile. Oracle strongly recommends that you do NOT set AQ_TM_PROCESSES = 0. If you are using Oracle Streams, then setting this parameter to zero (which Oracle Database respects no matter what) can cause serious problems.

Job Queue Processes

Propagation and PL/SQL notifications are handled by job queue (Jnnn) processes. The parameter JOB_QUEUE_PROCESSES no longer needs to be specified. The database scheduler automatically starts the job queue processes that are needed for the propagation and notification jobs.

PKѴYi_PK-AOEBPS/internet.htm Internet Access to Oracle Streams Advanced Queuing

6 Internet Access to Oracle Streams Advanced Queuing

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 Advanced Queuing operations. IDAP defines XML message structure for the body of the SOAP request. An IDAP-structured message is transmitted over the Internet using HTTP.

Users can register for notifications using the IDAP interface.

This chapter contains these topics:


See Also:


Overview of Oracle Streams Advanced Queuing Operations over the Internet

This section contains these topics:

Oracle Streams Advanced Queuing Internet Operations Architecture

Figure 6-1 shows the architecture for performing Oracle Streams Advanced Queuing operations over HTTP. The major components are:

  • Oracle Streams Advanced Queuing client program

  • Web server/servlet runner hosting the Oracle Streams Advanced Queuing servlet

  • Oracle Database server

A Web browser or any other HTTP client can serve as an Oracle Streams Advanced Queuing client program, sending XML messages conforming to IDAP to the Oracle Streams Advanced Queuing servlet, which interprets the incoming XML messages. The Oracle Streams Advanced Queuing servlet connects to the Oracle Database server and performs operations on user queues.

Figure 6-1 Architecture for Performing Oracle Streams Advanced Queuing Operations Using HTTP

Description of Figure 6-1 follows
Description of "Figure 6-1 Architecture for Performing Oracle Streams Advanced Queuing Operations Using HTTP"

Internet Message Payloads

Oracle Streams Advanced Queuing supports messages of three types: RAW, Oracle object, and Java Message Service (JMS). All these message types can be accessed using SOAP and Web services. If the queue holds messages in RAW, Oracle object, or JMS format, then 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 queue type on which the operation is being performed:

RAW Queues

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

Oracle Object Type Queues

For Oracle object type 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 content of the XML elements must map to the attributes of the object type of the queue table.

JMS Type Queues/Topics

For queues with JMS types (that is, those with payloads of type AQ$_JMS_*), there are four XML elements, depending on the JMS type. IDAP supports queues or topics with the following JMS types:

  • TextMessage

  • MapMessage

  • BytesMessage

  • ObjectMessage

JMS queues with payload type StreamMessage are not supported through IDAP.

Configuring the Web Server to Authenticate Users Sending POST Requests

After the servlet is installed, the Web server must be configured to authenticate all users that send POST requests to the Oracle Streams Advanced Queuing servlet. The Oracle Streams Advanced Queuing 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 Advanced Queuing servlet, the username that is used to connect to the Web server is known as the Oracle Streams Advanced Queuing HTTP agent or Oracle Streams Advanced Queuing Internet user.

Client Requests Using HTTP

An Oracle Streams Advanced Queuing client begins a request to the Oracle Streams Advanced Queuing servlet using HTTP by opening a connection to the server. The client logs in to the server using HTTP basic authentication (with or without SSL) or SSL certificate-based client authentication. The client constructs an XML message representing the send, publish, receive or register request.

The client sends an HTTP POST to the servlet at the remote server.


See Also:

Table 1-3, "Oracle Streams Advanced Queuing XML Demonstrations" for the locations of AQ XML demonstrations illustrating POST requests using HTTP

User Sessions and Transactions

After a client is authenticated and connects to the Oracle Streams Advanced Queuing 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 the client is using a Java or C client to post requests, then this must be accomplished programmatically.


See Also:

Table 1-3, "Oracle Streams Advanced Queuing XML Demonstrations" for the locations of AQ XML demonstrations illustrating a Java program used to post requests as part of the same session

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 Advanced Queuing operations.

Oracle Streams Advanced Queuing Servlet Responses Using HTTP

The server accepts the client HTTP(S) connection and authenticates the user (Oracle Streams Advanced Queuing agent) specified by the client. The server receives the POST request and invokes the Oracle Streams Advanced Queuing servlet.

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.

The servlet determines which object (queue/topic) the agent is trying to perform operations on. The servlet looks through the list of database users that map to this Oracle Streams Advanced Queuing agent. If any one of these users has privileges to access the queue/topic specified in the request, then the Oracle Streams Advanced Queuing servlet superuser creates a session on behalf of this user.

If no transaction is active in the HTTP session, then a new database transaction is started. Subsequent requests in the session are part of the same transaction until an explicit COMMIT or ROLLBACK request is made. 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.

The requested operation is performed. The response is formatted as an XML message and sent back the client. The response also includes the session ID in the HTTP headers as a cookie.

Oracle Streams Advanced Queuing Propagation Using HTTP and HTTPS

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. The background process doing propagation pushes messages to an Oracle Streams Advanced Queuing servlet that enqueues them into the destination database, as shown in Figure 6-2.

Figure 6-2 HTTP Oracle Streams Advanced Queuing Propagation

Description of Figure 6-2 follows
Description of "Figure 6-2 HTTP Oracle Streams Advanced Queuing Propagation"

You can set up any application to use Oracle Streams Advanced Queuing HTTP propagation without any change to the existing code. An application using Oracle Streams Advanced Queuing 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.

Deploying the Oracle Streams Advanced Queuing XML Servlet

Follow these steps to deploy the AQ XML servlet using OC4J:

  1. For JDK1.2.x or JDK1.3.x, include the following in your CLASSPATH:

    ORACLE_HOME/jdbc/lib/classes12.zip 
    ORACLE_HOME/jdbc/lib/nls_charset12.zip
    ORACLE_HOME/jlib/javax-ssl-1_1.jar 
    ORACLE_HOME/jlib/jndi.jar 
    ORACLE_HOME/jlib/jssl-1_1.jar 
    ORACLE_HOME/jlib/jta.jar 
    ORACLE_HOME/jlib/orai18n.jar
    ORACLE_HOME/jlib/orai18n-collation.jar
    ORACLE_HOME/jlib/orai18n-mapping.jar
    ORACLE_HOME/jlib/orai18n-utility.jar
    ORACLE_HOME/lib/http_client.jar 
    ORACLE_HOME/lib/lclasses12.zip
    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 
    ORACLE_HOME/rdbms/jlib/xdb.jar 
    ORACLE_HOME/rdbms/jlib/xsu12.jar 
    
  2. For JDK1.4.x, include the following in your CLASSPATH:

    ORACLE_HOME/jdbc/lib/ojdbc14.jar 
    ORACLE_HOME/jlib/javax-ssl-1_1.jar 
    ORACLE_HOME/jlib/jndi.jar 
    ORACLE_HOME/jlib/jssl-1_1.jar 
    ORACLE_HOME/jlib/jta.jar 
    ORACLE_HOME/jlib/orai18n.jar
    ORACLE_HOME/jlib/orai18n-collation.jar
    ORACLE_HOME/jlib/orai18n-mapping.jar
    ORACLE_HOME/jlib/orai18n-utility.jar
    ORACLE_HOME/lib/http_client.jar 
    ORACLE_HOME/lib/lclasses12.zip
    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 
    ORACLE_HOME/rdbms/jlib/xdb.jar 
    

    Note:

    http_client.jar, jssl-1_1.jar, and javax-ssl-1_1.jar are required by HTTPClient used in AQHttp.java and AQHttpRq.java.

  3. Compile AQHttpRq.java:

    cd ORACLE_HOME/rdbms/demo
    javac AQHttpRq.java AQHttp.java
    
  4. Set the following database initialization parameters to the indicated values:

    job_queue_processes=2
    compatible=10.2.0
    
  5. Restart the database and listener.

  6. Set up queues and authenticate users for restricted access.


    See Also:

    aqxmlREADME.txt and aqxmldmo.sql in ORACLE_HOME/rdbms/demo for additional information.

  7. Deploy the servlet and start the OC4J instance:

    cd ORACLE_HOME/bin
    sh aqxmlctl deploy
    sh aqxmlctl start
    

    Note:

    Use sh aqxmlctl stop to stop the OC4J instance. The deploy servlet and start OC4J instance steps might have been done during your Oracle Database installation. You can verify this in the following steps.

  8. Check the status of the servlet and information on the protocol and port number used for deploying the servlet in the following files:

    ORACLE_HOME/rdbms/demo/aqxml.ini
    ORACLE_HOME/oc4j/j2ee/OC4J_AQ/config/rmi.xml
    ORACLE_HOME/oc4j/j2ee/OC4J_AQ/config/http-web-site.xml
    
  9. Point a web browser to the following URL:

    https://hostname:portnumber/aqserv/servlet/AQDemoServlet
    

    where hostname is the server name, and portnumber is the value discovered in the previous step. After you respond to a username/password prompt, the servlet displays:

    Sample AQ Servlet 
    AQxmlServlet is working!
    
  10. Create an SSL Certificate and generate a keystore. The following files provide examples:

    ORACLE_HOME/rdbms/demo/aqxmloc4j.cert
    ORACLE_HOME/rdbms/demo/keystore
    

    The following tags in ORACLE_HOME/oc4j/j2ee/OC4J_AQ/config/http-web-site.xml indicate that the Web site is secure and keystore is used for SSL authentication:

    <web-site port="443" secure="true">
    ....
       <ssl-config 
          keystore="ORACLE_HOME/oc4j/j2ee/home/keystore" 
          keystore-password="welcome" />
    </web-site>
    

    To make the site access only HTTP requests, remove secure="true" and <ssl-config> from http-web-site.xml.

  11. Stop and restart the AQ XML servlet:

    sh aqxmlctl stop
    sh aqxmlctl start
    

Internet Data Access Presentation (IDAP)

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:

SOAP Envelope

This is the root or top element in an XML tree. Its tag 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 this attribute 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 Header

This is the first element under the root. Its tag is SOAP:Header. A SOAP header passes necessary information, such as the transaction identifier. 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.

SOAP Body

This is the Oracle Streams Advanced Queuing XML document. Its tag is SOAP:Body, and it 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. The Oracle Streams Advanced Queuing 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.

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 is of the form URI#method name. For example:

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. The method name must not include the "#" character.

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 contents are XML documents consisting of the root and mandatory body elements. These XML documents are referred to as SOAP payloads in the rest of this chapter.

A 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 Advanced Queuing 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.

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 never contains both a result and an error.

Request and Response 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. The body represents:

This section contains these topics:

IDAP Client Requests for Enqueue

Client send and publish requests use AQXmlSend to enqueue to a single-consumer queue and AQXmlPublish to enqueue to multiconsumer queues/topics

AQXmlSend and AQXmlPublish contain the following elements:

producer_options

This is a required element. It contains the following child elements:

  • destination

    This element is required. It specifies the queue/topic to which messages are to be sent. It has an optional lookup_type attribute, which determines how the destination value is interpreted. If lookup_type is DATABASE, which is the default, then the destination is interpreted as schema.queue_name. If lookup_type is LDAP, then the LDAP server is used to resolve the destination.

  • visibility

    This element is optional. It determines when an enqueue becomes visible. The default is ON_COMMIT, which makes the enqueue visible when the current transaction commits. If IMMEDIATE is specified, then the 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

    This element is optional. It specifies the PL/SQL transformation to be invoked before the message is enqueued.

message_set

This is a required element and contains one or more messages. Each message consists of a message_header and a message_payload.

message_header

This element is optional. It contains the following child elements:

  • sender_id

    If a message_header element is included, then it must contain a sender_id element, which specifies an application-specific identifier. The sender_id element can contain agent_name, address, protocol, and agent_alias elements. The agent_alias element resolves to a name, address, and protocol using LDAP.

  • message_id

    This element is optional. It is a unique identifier of the message, supplied during dequeue.

  • correlation

    This element is optional. It is the correlation identifier of the message.

  • delay

    This element is optional. It specifies the duration in seconds after which a message is available for processing.

  • expiration

    This element is optional. It specifies the duration in seconds that a message is available for dequeuing. This parameter is an offset from the delay. By default messages never expire. If a message is not dequeued before it expires, then it is moved to an exception queue in the EXPIRED state.

  • priority

    This element is optional. It specifies the priority of the message. The priority can be any number, including negative numbers. A smaller number indicates higher priority.

  • recipient_list

    This element is optional. It is a list of recipients which overrides the default subscriber list. Each recipient is represented in recipient_list by a recipient element, which can contain agent_name, address, protocol, and agent_alias elements. The agent_alias element resolves to a name, address, and protocol using LDAP.

  • message_state

    This element is optional. It specifies the state of the message. It is filled in automatically during dequeue. If message_state is 0, then the message is ready to be processed. If it is 1, then the message delay has not yet been reached. If it is 2, then the message has been processed and is retained. If it is 3, then the message has been moved to an exception queue.

  • exception_queue

    This element is optional. It specifies the name of the queue to which the message is moved if 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.

    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 log. If the default exception queue is used, then the parameter returns a NULL value at dequeue time.

message_payload

This is a required element. It can contain different elements based on the payload type of the destination queue/topic. The different payload types are described in "IDAP Client Requests for Dequeue".

AQXmlCommit

This is an optional empty element. If it is included, then the transaction is committed at the end of the request.


See Also:

"Internet Message Payloads" for an explanation of IDAP message payloads

IDAP Client Requests for Dequeue

Client requests for dequeue use AQXmlReceive, which contains the following elements:

consumer_options

This is a required element. It contains the following child elements:

  • destination

    This element is required. It specifies the queue/topic from which messages are to be received. The destination element has an optional lookup_type attribute, which determines how the destination value is interpreted. If lookup_type is DATABASE, which is the default, then the destination is interpreted as schema.queue_name. If lookup_type is LDAP, then the LDAP server is used to resolve the destination.

  • consumer_name

    This element is optional. It specifies the 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

    This element is optional. It specifies the number of seconds to wait if there is no message currently available which matches the search criteria.

  • selector

    This element is optional. It specifies criteria used to select the message. It can contain child elements correlation, message_id, or condition.

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

    To specify dequeue conditions on a message 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.

    A dequeue condition element cannot exceed 4000 characters.


    Note:

    When a dequeue condition or correlation identifier is used, the order of the messages dequeued is indeterminate, and the sort order of the queue is not honored.

  • visibility

    This element is optional. It determines when a dequeue becomes visible. The default is ON_COMMIT, which makes the dequeue visible when the current transaction commits. If IMMEDIATE is specified, then the 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

    This element is optional. It specifies the locking action associated with the dequeue. The possible values are REMOVE, BROWSE, and LOCKED.

    REMOVE is the default and causes the message to be read and deleted. The message can be retained in the queue table based on the retention properties. BROWSE reads the message without acquiring any lock on it. This is equivalent to a select statement. LOCKED reads the message and obtains a write lock on it. The lock lasts for the duration of the transaction. This is equivalent to a select for update statement.

  • navigation_mode

    This element is optional. It 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. Possible values are FIRST_MESSAGE, NEXT_MESSAGE, and NEXT_TRANSACTION.

    FIRST_MESSAGE retrieves the first message which is available and which matches the search criteria. This resets the position to the beginning of the queue. NEXT_MESSAGE is the default and retrieves the next message which is available and which matches the search criteria. If the previous message belongs to a message group, then Oracle Streams Advanced Queuing retrieves the next available message which matches the search criteria and which belongs to the message group.NEXT_TRANSACTION skips the remainder of the current transaction group and retrieves the first message of the next transaction group. This option can only be used if message grouping is enabled for the current queue.

  • transformation

    This element is optional. It specifies the PL/SQL transformation to be invoked after the message is dequeued.

AQXmlCommit

This is an optional empty element. If it is included, then the transaction is committed at the end of the request.

IDAP Client Requests for Registration

Client requests for registration use AQXmlRegister, which must contain a register_options element. The register_options element contains the following child elements:

  • destination

    This element is required. It specifies the queue/topic on which notifications are registered. The destination element has an optional lookup_type attribute, which determines how the destination value is interpreted. If lookup_type is DATABASE, which is the default, then the destination is interpreted as schema.queue_name. If lookup_type is LDAP, then the LDAP server is used to resolve the destination.

  • consumer_name

    This element is optional. It specifies the consumer name for multiconsumer queues or topics. This parameter must not be specified for single-consumer queues.

  • notify_url

    This element is required. It specifies where notification is sent when a message is enqueued. The form can be http://url, mailto://email address or plsql://pl/sql procedure.

IDAP Client Requests to Commit a Transaction

A request to commit all actions performed by the user in a session uses AQXmlCommit. 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>

IDAP Client Requests to Roll Back a Transaction

A request to roll back all actions performed by the user in a session uses AQXmlRollback. Actions performed with IMMEDIATE visibility are not rolled back. An IDAP client 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>

IDAP Server Response to an Enqueue Request

The response to an enqueue request to a single-consumer queue uses AQXmlSendResponse. It contains the following elements:

  • status_response

    This element contains child elements status_code, error_code, and error_message. The status_code element takes value 0 for success or -1 for failure. The error_code element contains an Oracle error code. The error_message element contains a description of the error.

  • send_result

    This element contains child elements destination and message_id. The destination element specifies where the message was sent. The message_id element uniquely identifies every message sent.

The response to an enqueue request to a multiconsumer queue or topic uses AQXmlPublishResponse. It contains the following elements:

  • status_response

    This element contains child elements status_code, error_code, and error_message. The status_code element takes value 0 for success or -1 for failure. The error_code element contains an Oracle error code. The error_message element contains a description of the error.

  • publish_result

    This element contains child elements destination and message_id. The destination element specifies where the message was sent. The message_id element uniquely identifies every message sent.

IDAP Server Response to a Dequeue Request

The response to a dequeue request uses AQXmlReceiveResponse. It contains the following elements:

  • status_response

    This element contains child elements status_code, error_code, and error_message. The status_code element takes value 0 for success or -1 for failure. The error_code element contains an Oracle error code. The error_message element contains a description of the error.

  • receive_result

    This element contains child elements destination and message_set. The destination element specifies where the message was sent. The message_set element specifies the set of messages dequeued.

IDAP Server Response to a Register Request

The response to a register request uses AQXmlRegisterResponse. It contains the status_response element described in "IDAP Server Response to a Dequeue Request".

IDAP Commit Response

The response to a commit request uses AQXmlCommitResponse. It contains the status_response element described in "IDAP Server Response to a Dequeue Request". 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>

IDAP Rollback Response

The response to a rollback request uses AQXmlRollbackResponse. It contains the status_response element described in "IDAP Server Response to a Dequeue Request".

IDAP 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 using AQXmlNotification. It contains the following elements:

  • notification_options

    This element has child elements destination and consumer_name. The destination element specifies the destination queue/topic on which the event occurred. The consumer_name element specifies the consumer name for which the even occurred. It applies only to multiconsumer queues/topics.

  • message_set

    This element specifies the set of message properties.

IDAP Response in Case of Error

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

  • faultcode

    This element specifies the error code for the fault.

  • faultstring

    This element indicates a client error or a server error. A client error means that the request is not valid. A server error indicates that the Oracle Streams Advanced Queuing servlet has not been set up correctly.

  • detail

    This element contains the status_response element, which is described in "IDAP Server Response to a Dequeue Request".

Notification of Messages by e-mail

Here are the steps for setting up your database for e-mail notifications:

  1. Set the SMTP mail host by invoking DBMS_AQELM.SET_MAILHOST as an Oracle Streams Advanced Queuing administrator.

  2. Set the SMTP mail port by invoking DBMS_AQELM.SET_MAILPORT as an Oracle Streams Advanced Queuing administrator. If not explicit, set defaults to 25.

  3. Set the SendFrom address by invoking DBMS_AQELM.SET_SENDFROM.

  4. After setup, you can register for e-mail notifications using the Oracle Call Interface (OCI) or PL/SQL API.

PK]5+PK-AOEBPS/glossary.htm Glossary

Glossary

ADT

Abstract data type.

API

See application programming interface.

application programming interface

The calling conventions by which an application program accesses operating system and other services.

approximate CSCN

An approximate system change number value, based on the current SCN of the database when a transaction that has enqueued messages into a commit-time queue is committed.

asynchronous

A process in a multitasking system is asynchronous if its execution can proceed independently in the background. Other processes can be started before the asynchronous process has finished. The opposite of synchronous.

BFILE

An external binary file that exists outside the database tablespaces residing in the operating system.

binary large object

A large object datatype whose content consists of binary data. This data is considered raw, because its structure is not recognized by the database.

BLOB

See binary large object.

broadcast

A publish/subscribe mode in which the message producer does not know the identity of any message consumer. This mode is similar to a radio or television station.

buffered queue

Buffered queues support queuing of messages with buffered attributes (buffered messages) and materialize them in memory. If the memory devoted to a buffered message is required for a newer message, or if a buffered message has exceeded a stipulated duration in memory, then that buffered message is swapped to the underlying queue table. The memory for buffered messages comes from a separate pool called the streams pool. Buffered messages cannot be recovered if the database is bounced. Messages that have no buffered attributes set are queued as persistent messages in the underlying persistent queue.

canonical

The usual or standard state or manner of something.

character large object

The large object datatype whose value is composed of character data corresponding to the database character set. A character large object can be indexed and searched by the Oracle Text search engine.

ConnectionFactory

A ConnectionFactory encapsulates a set of connection configuration parameters that has been defined by an administrator. A client uses it to create a connection with a Java Message Service provider.

CLOB

See character large object.

commit-time queue

A queue in which messages are ordered by their approximate CSCN values.

consumer

A user or application that can dequeue messages.

data manipulation language

Data manipulation language (DML) statements manipulate database data. For example, querying, inserting, updating, and deleting rows of a table are all DML operations; locking a table or view and examining the execution plan of an SQL statement are also DML operations.

Database Configuration Assistant

An Oracle Database tool for creating and deleting databases and for managing database templates.

DBCA

See Database Configuration Assistant.

dequeue

To retrieve a message from a queue

DML

See data manipulation language.

enqueue

To place a message in a queue. The JMS equivalent of enqueue is send.

exception queue

Messages are transferred to an exception queue if they cannot be retrieved and processed for some reason.

IDAP

See Internet Data Access Presentation.

index-organized table

Unlike an ordinary table whose data is stored as an unordered collection, data for an index-organized table is stored in a B-tree index structure sorted on a primary key. Besides storing the primary key column values of an index-organized table row, each index entry in the B-tree stores the nonkey column values as well.

Internet Data Access Presentation

The Simple Object Access Protocol (SOAP) specification for Oracle Streams Advanced Queuing operations. IDAP defines the XML message structure for the body of the SOAP request. An IDAP-structured message is transmitted over the Internet using HTTP(S).

Inter-process Communication

Exchange of data between one process and another, either within the same computer or over a network. It implies a protocol that guarantees a response to a request.

IOT

See index-organized table.

IPC

See Inter-process Communication.

Java Database Connectivity

An industry-standard Java interface for connecting to a relational database from a Java program, defined by Sun Microsystems.

Java Message Service

A messaging standard defined by Sun Microsystems, Oracle, IBM, and other vendors. JMS is a set of interfaces and associated semantics that define how a JMS client accesses the facilities of an enterprise messaging product.

Java Naming and Directory Interface

A programming interface from Sun for connecting Java programs to naming and directory services.

Java Virtual Machine

The Java interpreter that converts the compiled Java bytecode into the machine language of the platform and runs it. JVMs can run on a client, in a browser, in a middle tier, on an intranet, on an application server such as Oracle Application Server 10g, or in a database server such as Oracle Database 10g.

JDBC

See Java Database Connectivity.

JDBC driver

The vendor-specific layer of Java Database Connectivity that provides access to a particular database. Oracle Database provides three JDBC drivers--Thin, OCI, and KPRB.

JMS

See Java Message Service.

JMS connection

An active connection of a client to its JMS provider, typically an open TCP/IP socket (or a set of open sockets) between a client and a provider's service daemon.

JMS message

JMS messages consist of a header, one or more optional properties, and a message payload.

JMS session

A single threaded context for producing and consuming messages.

JMS topic

Equivalent to a multiconsumer queue in the other Oracle Streams Advanced Queuing interfaces.

JNDI

See Java Naming and Directory Interface.

Jnnn

Job queue process

JServer

The Java Virtual Machine that runs within the memory space of Oracle Database.

JVM

See Java Virtual Machine

large object

The class of SQL datatype consisting of BFILE, BLOB, CLOB, and NCLOB objects.

LDAP

See Lightweight Directory Access Protocol

Lightweight Directory Access Protocol

A standard, extensible directory access protocol. It is a common language that LDAP clients and servers use to communicate. The framework of design conventions supporting industry-standard directory products, such as the Oracle Internet Directory.

LOB

See large object

local consumer

A local consumer dequeues the message from the same queue into which the producer enqueued the message.

logical change record

An object with a specific format that describes a database change, captured from the redo log by a capture process or user application. Capture processes enqueue messages containing logical change records (LCRs) only into ANYDATA queues. For improved performance, these LCRs are always stored in a buffered queue.

message

The smallest unit of information inserted into and retrieved from a queue. A message consists of control information (metadata) and payload (data).

multicast

A publish/subscribe mode in which the message producer knows the identity of each consumer. This mode is also known as point-to-multipoint.

national character large object

The large object datatype whose value is composed of character data corresponding to the database national character set.

NCLOB

See national character large object.

nonpersistent

Nonpersistent queues store messages in memory. They are generally used to provide an asynchronous mechanism to send notifications to all users that are currently connected. Nonpersistent queues are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2). Oracle recommends that you use buffered messaging instead.

nontransactional

Allowing enqueuing and dequeuing of only one message at a time.

object type

An object type encapsulates a data structure along with the functions and procedures needed to manipulate the data. When you define an object type using the CREATE TYPE statement, you create an abstract template that corresponds to a real-world object.

OCI

See Oracle Call Interface.

OJMS

See Oracle Java Message Service.

OLTP

See Online Transaction Processing.

Online Transaction Processing

Online transaction processing systems are optimized for fast and reliable transaction handling. Compared to data warehouse systems, most OLTP interactions involve a relatively small number of rows, but a larger group of tables.

OO4O

See Oracle Objects for OLE.

Oracle Call Interface

An application programming interface that enables data and schema manipulation in Oracle Database.

Oracle Java Message Service

Oracle Java Message Service (OJMS) provides a Java API for Oracle Streams Advanced Queuing based on the Java Message Service (JMS) standard. OJMS supports the standard JMS interfaces and has extensions to support the Oracle Streams Advanced Queuing administrative operations and other Oracle Streams Advanced Queuing features that are not a part of the standard.

Oracle Objects for OLE

A custom control (OCX or ActiveX) combined with an object linking and embedding (OLE) in-process server that lets you plug native Oracle Database functionality into your Windows applications.

producer

A user or application that can enqueue messages.

propagation

Copying messages from one queue to another (local or remote) queue.

publish/subscribe

A type of messaging in which a producer enqueues a message to one or more multiconsumer queues, and then the message is dequeued by several subscribers. The published message can have a wide dissemination mode called broadcast or a more narrowly aimed mode called multicast.

QMNC

Queue monitor coordinator. It dynamically spawns slaves qXXX depending on the system load. The slaves do various background tasks.

QMNn

Queue monitor process.

queue

The abstract storage unit used by a messaging system to store messages.

queue table

A database table where queues are stored. Each queue table contains a default exception queue.

recipient

An agent authorized by the enqueuer or queue administrator to retrieve messages. The enqueuer can explicitly specify the consumers who can retrieve the message as recipients of the message. A queue administrator can specify a default list of recipients who can retrieve messages from a queue. A recipient specified in the default list is known as a subscriber. If a message is enqueued without specifying the recipients, then the message is sent to all the subscribers. Specific messages in a queue can be directed toward specific recipients, who may or may not be subscribers to the queue, thereby overriding the subscriber list.

If only the name of the recipient is specified, then the recipient must dequeue the message from the queue in which the message was enqueued. If the name and an address of the recipient are specified with a protocol value of 0, then the address should be the name of another queue in the same database or another installation of Oracle Database. If the recipient's name is NULL, then the message is propagated to the specified queue in the address and can be dequeued by any subscriber of the queue specified in the address. If the protocol field is nonzero, then the name and address are not interpreted by the system, and the message can be dequeued by a special consumer.

remote consumer

A remote consumer dequeues from a queue that is different from the queue where the message was enqueued.

rules

Boolean expressions that define subscriber interest in subscribing to messages. The expressions use syntax similar to the WHERE clause of a SQL query and can include conditions on: message properties (currently priority and correlation identifier), user data properties (object payloads only), and functions. If a rule associated with a subscriber evaluates to TRUE for a message, then the message is sent to that subscriber even if the message does not have a specified recipient.

rules engine

Oracle Database software that evaluates rules. Rules are database objects that enable a client to perform an action when an event occurs and a condition is satisfied. Rules are similar to conditions in WHERE clauses of SQL queries. Both user-created applications and Oracle Database features, such as Oracle Streams Advanced Queuing, can be clients of the rules engine.

schema

A collection of database objects, including logical structures such as tables, views, sequences, stored procedures, synonyms, indexes, clusters, and database links. A schema has the name of the user who controls it.

send

The JMS equivalent of enqueue.

servlet

A Java program that runs as part of a network service and responds to requests from clients. It is typically an HTTP server.

SGA

See System Global Area.

Simple Object Access Protocol

A minimal set of conventions for invoking code using XML over HTTP defined by World Wide Web Consortium.

SOAP

See Simple Object Access Protocol.

subscriber

An agent authorized by a queue administrator to retrieve messages from a queue.

System Global Area

A group of shared memory structures that contain data and control information for one Oracle Database instance. The SGA and Oracle Database processes constitute an Oracle Database instance. Oracle Database automatically allocates memory for an SGA whenever you start an instance and the operating system reclaims the memory when you shut down the instance. Each instance has one and only one SGA.

synchronous

Two or more processes are synchronous if they depend upon the occurrences of specific events such as common timing signals. The opposite of asynchronous.

transactional

Allowing simultaneous enqueuing or dequeuing of multiple messages as part of a group.

transformation

A mapping from one Oracle data type to another, represented by a SQL function that takes the source data type as input and returns an object of the target data type. A transformation can be specified during enqueue, to transform the message to the correct type before inserting it into the queue. It can be specified during dequeue to receive the message in the wanted format. If specified with a remote consumer, then the message is transformed before propagating it to the destination queue.

user queue

A queue for normal message processing.

VARRAY

An ordered set of data elements. All elements of a given array are of the same datatype. Each element has an index, which is a number corresponding to the element's position in the array. The number of elements in an array is the size of the array. Oracle Database allows arrays to be of variable size.

wildcard

A special character or character sequence which matches any character in a string comparison.

workflow

The set of relationships between all the activities in a project or business transaction, from start to finish. Activities are related by different types of trigger relations. Activities can be triggered by external events or by other activities.

PK߇ՇPK-AOEBPS/preface.htmT Preface

Preface

This guide describes features of application development and integration using Oracle Streams Advanced Queuing (AQ). This information applies to versions of the Oracle Database server that run on all platforms, unless otherwise specified.

This Preface contains these topics:

Audience

This guide is intended for programmers who develop applications that use Oracle Streams Advanced Queuing.

To use this document, you need knowledge of an application development language and object-relational database management concepts.

Documentation Accessibility

For information about Oracle's commitment to accessibility, visit the Oracle Accessibility Program website at http://www.oracle.com/pls/topic/lookup?ctx=acc&id=docacc.

Access to Oracle Support

Oracle customers have access to electronic support through My Oracle Support. For information, visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=info or visit http://www.oracle.com/pls/topic/lookup?ctx=acc&id=trs if you are hearing impaired.

Related Documents

For more information, see these Oracle resources:

Many of the examples in this book use the sample schemas, which are installed by default when you select the Basic Installation option with an Oracle Database installation. Refer to Oracle Database Sample Schemas for information on how these schemas were created and how you can use them yourself.

Conventions

The following text conventions are used in this document:

ConventionMeaning
boldfaceBoldface type indicates graphical user interface elements associated with an action, or terms defined in text or the glossary.
italicItalic type indicates book titles, emphasis, or placeholder variables for which you supply particular values.
monospaceMonospace type indicates commands within a paragraph, URLs, code in examples, text that appears on the screen, or text that you enter.

PK WPK-AOEBPS/index.htm Index

Index

A  B  C  D  E  F  G  H  I  J  L  M  N  O  P  Q  R  S  T  U  V  W  X 

Symbols

(G)V$BUFFERED_PUBLISHERS
All Buffered Publishers in the Instance, 9.26
(G)V$BUFFERED_SUBSCRIBERS
Subscribers for All Buffered Queues in the Instance, 9.25
(G)V$PERSISTENT_PUBLISHERS
All Active Publishers of the Persistent Queues in the Database, 9.30
(G)V$PERSISTENT_QMN_CACHE
Performance Statistics on Background Tasks for Persistent Queues, 9.28
(G)V$PERSISTENT_QUEUES
All Active Persistent Queues in the Database, 9.27
(G)V$PERSISTENT_SUBSCRIBERS
All Active Subscribers of the Persistent Queues in the Database, 9.29
(G)V$PROPAGATION_RECEIVER
Buffer Queue Propagation Schedules on the Receiving (Destination) Side, 9.32
(G)V$PROPAGATION_SENDER
Buffer Queue Propagation Schedules on the Sending (Source) Side, 9.31
(G)V$STREAMSMETRIC
Streams Metrics for the Most Recent Interval, 9.35
(G)V$STREAMSMETRIC_HISTORY
Streams Metrics Over Past Hour, 9.36
(G)V$SUBSCR_REGISTRATION_STATS
Diagnosability of Notifications, 9.33

A

access
object types, 4.2.1.3
access control
destination level in JMS, 11.1.4
queue-level, 1.2
system level, 1.2
in JMS, 11.1.3
adding subscribers, 8.5.1
administration
Messaging Gateway, 17.3.1
administrative interfaces to Oracle Streams AQ
comparison, 3.8.1
AdtMessage
about, 11.2.3.6
creating, 15.1.13
agent user
creating Messaging Gateway agent, 18.2.6
agents
AQjms agent
creating, 15.5
Messaging Gateway
about, 17.3.2
configuring agent, 19.1
monitoring, 21.2
running agent on Oracle RAC, 19.2.4
shutting down agent, 19.2.2
starting agent, 19.2.1
alias
adding to LDAP server, 8.8
deleting from LDAP server, 8.9
parameters
alias, 8.8
obj_location, 8.8
ALL_QUEUE_SUBSCRIBERS, 9.15
ALL_QUEUE_TABLES
Queue Tables Queue Accessible to the Current User, 9.3
ALL_QUEUES, 9.6
altering
AQ agents, 8.7.2
propagations, 8.6.3
queue tables, 8.1.2
queues, 8.2.2
subscribers, 8.5.2
transformations, 8.3.2
ANYDATA datatype
apply process, configuring, 23.4
dequeuing
examples, 22.4, 23.7
explicit, configuring, 23.5
using JMS, 22.1.2.4
using OCI, 22.1.2.4
using PL/SQL, 22.1.2.3
enqueuing
examples, 22.3, 23.6
procedures, creating, 23.3
using JMS, 22.1.2.2
using OCI, 22.1.2.2
using PL/SQL, 22.1.2.1
message propagation, 22.2
propagation examples, 22.5, 22.6
queue table, 8.1.1
queues
about, 22.1
creating, 23.2
wrapper for messages, 22.1.1
ANYDATA.ConvertObject, 22.1.2.1
application development
about, 1.3
client/server communication, 1.3.1
Internet operations, 1.3
publish/subscribe, 1.3.4
third-party messaging, 1.3
workflows, 1.3.3
apply process
configuring, 23.4
query for applied messages, 23.7
AQ agents
adding to LDAP server, 10.10
altering, 8.7.2
creating, 8.7.1
dropping, 8.7.3
parameters
agent_name, 8.7.1
certificate_location, 8.7.1
enable_anyp, 8.7.1
enable_http, 8.7.1
removing from LDAP server, 10.11
AQ Message Properties Type, 2.11
AQ servlet
deploying, 6.2
responses using HTTP, 6.1.5
AQ system privilege
granting, 8.4.1
in JMS, 12.9.1
revoking, 8.4.2
in JMS, 12.9.2
AQ$_AGENT, 2.3
AQ$_AGENT_LIST_T, 2.5
AQ$_POST_INFO_LIST, 2.8, 2.8
AQ$_QUEUE_TABLE_NAME_D, 8.1.1
AQ$_QUEUE_TABLE_NAME_E, 8.1.1
AQ$_QUEUE_TABLE_NAME_H, 8.1.1
AQ$_QUEUE_TABLE_NAME_I, 8.1.1
AQ$_QUEUE_TABLE_NAME_P, 8.1.1
AQ$_QUEUE_TABLE_NAME_S, 8.1.1
AQ$_QUEUE_TABLE_NAME_T, 8.1.1
AQ$_RECIPIENT_LIST_T, 2.4
AQ$_REG_INFO_LIST, 2.7
AQ$_SUBSCRIBER_LIST_T, 2.6
AQ$INTERNET_USERS, 9.22
AQ$QUEUE_TABLE_NAME, 9.10
AQ$QUEUE_TABLE_NAME_R, 9.12
AQ$QUEUE_TABLE_NAME_S, 9.11
AQ_ADMINISTRATOR_ROLE
and LDAP, 11.1.1.3
and registerConnectionFactory, 12.2.2
definition, 4.2.1.1
needed for JMS, 3.6.1
security, 4.2.1
AQ_MsgProperties, 19.7.5
AQ_TM_PROCESSES parameter, 2.16.1
AQ_USER_ROLE
definition, 4.2.1.2
needed for JMS, 3.6.1
security, 4.2.1
AQjms agent
creating, 15.5
AQXmlPublish method, 6.4.1
AQXmlReceive method, 6.4.2
AQXmlSend method, 6.4.1
architecture
application development, 1.3
Internet operations, 1.10, 6.1.1
Messaging Gateway, 17.3
arrays
dequeuing
about, 1.7
buffered messages, 10.6
demonstration, 1.12
syntax, 10.6
enqueuing
about, 1.6
demonstration, 1.12
syntax, 10.3
asynchronous notifications
about, 1.5
buffered messages, 1.5
designated port, 1.5
purge following, 1.5
RAW payload delivery, 1.5
reliability, 1.5
timeout, 1.5
asynchronous receive in JMS, 11.6.6

B

batch dequeuing, 10.6
batch enqueuing, 10.3
BFILE objects
propagating, 4.7.2
Boolean message property (JMS)
getting, 15.10.1
setting, 15.2.1
broadcasting
definition, 1.3.4
buffered messages
about, 1.4
dequeuing, 1.4
options, 1.4
enqueuing, 1.4
exception handling, 1.4
flow control, 1.4
listen_delivery_mode, 10.4
MSG_STATE parameter, 9.10
notification, 1.5
ordering, 1.4
propagation, 1.4
queue-to-queue propagation, 1.4
restrictions, 1.4
tuning, 5.4
types supported, 1.4
views, 1.4
visibility, 1.4
with Messaging Gateway, 17.5
with Oracle JMS, 11.2.5
with Oracle Real Application Clusters, 1.4
buffered queues, 8.1.1
byte message property (JMS)
getting, 15.10.6
setting, 15.2.6
BytesMessage
about, 11.2.3.2
creating, 15.1.7
example, 16.2

C

catxlcr.sql, 22.1.2.2
CLASSPATH
Messaging Gateway, 18.6.2
closing
JMS Connection, 15.11.5
JMS Session, 15.11.4
message consumer, 15.11.2
MessageProducer, 15.11.1
commit
all operations in JMS Session, 15.1.3
transaction, 6.4.4
commit-time ordering
about, 1.6, 1.6
example, 8.1.1
requirements, 8.1.1
compatibility
about, 4.1
and Oracle Real Application Clusters, 1.2
migrating queue tables, 8.1.5
nonpersistent queues, A.3
security, 4.2.2
concurrent processes
tuning for Oracle Streams AQ, 5.2.4
Connection (JMS)
creating
with default ConnectionFactory parameters, 13.2, 14.2
with username/password, 13.1, 14.1
getting JDBC connection from JMS Session, 15.1.5
ConnectionFactory
getting
in LDAP, 12.4.5
objects, 11.1.1.1
registering
through database using JDBC connection parameters, 12.2.1
through database using JDBC URL, 12.2.2
through LDAP using JDBC connection parameters, 12.2.3
through LDAP using JDBC URL, 12.2.4
unregistering
in LDAP through LDAP, 12.3.2
in LDAP through the database, 12.3.1
through database, 12.3.1
through LDAP, 12.3.2
using JNDI to look up, 11.1.1.3
conversion
JMS messages, about, 20.4
message headers, 20.1.3
non-JMS messages, about, 20.1.1
TIB/Rendezvous messages, 20.3
WebSphere MQ messages, 20.2
correlation identifier
about, 1.6, 1.7
and transaction grouping, 1.7
and Virtual Private Database, 4.6.8
as dequeue condition, 10.5
as message property, 10.2
as MessageSelector, 11.3
dequeuing by specifying, 1.7
getting in JMS, 15.9.1
setting in JMS, 15.1.14
with queue table indexes, 5.2.6
creating
AQ agents, 8.7.1
AQjms agent, 15.5
DurableSubscriber, 14.13, 14.14, 14.15, 14.16
JMS AdtMessage, 15.1.13
JMS BytesMessage, 15.1.7
JMS Connection, 13.1, 13.2, 14.1, 14.2
JMS MapMessage, 15.1.8
JMS Message, 15.1.12
JMS ObjectMessage, 15.1.10
JMS Session, 13.7, 14.6
JMS StreamMessage, 15.1.9
JMS TextMessage, 15.1.11
Messaging Gateway administration user, 18.2.5
Messaging Gateway agent user, 18.2.6
Messaging Gateway propagation subscriber, 19.5.2
nonpersistent queues, A.1
point-to-point queue in JMS, 12.8.1
propagations, 8.6.1
publish/subscribe Topic in JMS, 12.8.2
queue tables, 8.1.1
in JMS, 12.6
QueueBrowser, 13.12, 13.13, 13.14
QueueConnection, 13.3, 13.4, 13.5, 13.6
QueueReceiver, 13.16, 13.17
queues, 8.2.1
in JMS, 12.8
QueueSender, 13.9
QueueSession, 13.8
subscribers, 8.5.1
TIB/Rendezvous link, 19.3.4
TopicConnection, 14.3, 14.4, 14.5
TopicPublisher, 14.8
TopicSession, 14.7
transformations, 8.3.1
WebSphere MQ base Java link, 19.3.1
WebSphere MQ JMS link, 19.3.2

D

data pump, 4.3.3
database
disabling access, 8.7.5
enabling access, 8.7.4
database connection
configuring Messaging Gateway connection information, 18.2.7
Messaging Gateway, 19.1.3
DBA_ATTRIBUTE_TRANSFORMATIONS, 9.17
DBA_HIST_QUEUEMETRIC
Queue Metric History, 9.38
DBA_HIST_STREAMSMETRIC
Streams Metric History, 9.37
DBA_QUEUE_SCHEDULES, 9.7, 9.7
DBA_QUEUE_SUBSCRIBERS, 9.13
DBA_QUEUE_TABLES
All Queue Tables in Database, 9.1
DBA_QUEUES, 9.4
DBA_SUBSCR_REGISTRATIONS
All Subscription Registrations, 9.20
DBA_TRANSFORMATIONS, 9.16
DBMS_AQ procedures
BIND_AGENT, 10.10
DEQUEUE, 10.5
DEQUEUE_ARRAY, 10.6
ENQUEUE, 10.2
ENQUEUE_ARRAY, 10.3
LISTEN, 10.4
POST, 10.9
REGISTER, 10.7
UNBIND_AGENT, 10.11
UNREGISTER, 10.8
DBMS_AQADM procedures
ADD_ALIAS_TO_LDAP, 8.8
ADD_SUBSCRIBER, 8.5.1
ALTER_AQ_AGENT, 8.7.2
ALTER_PROPAGATION_SCHEDULE, 8.6.3
ALTER_QUEUE, 8.2.2
ALTER_QUEUE_TABLE, 8.1.2
ALTER_SUBSCRIBER, 8.5.2
CREATE_AQ_AGENT, 8.7.1
CREATE_NP_QUEUE, A.1
CREATE_QUEUE, 8.2.1
CREATE_QUEUE_TABLE, 8.1.1
CREATE_TRANSFORMATION, 8.3.1
DEL_ALIAS_FROM_LDAP, 8.9
DISABLE_DB_ACCESS, 8.7.5
DISABLE_PROPAGATION_SCHEDULE, 8.6.5
DROP_AQ_AGENT, 8.7.3
DROP_QUEUE, 8.2.5
DROP_QUEUE_TABLE, 8.1.3
DROP_TRANSFORMATION, 8.3.3
ENABLE_DB_ACCESS, 8.7.4
ENABLE_JMS_TYPES, 22.1.2.2
ENABLE_PROPAGATION_SCHEDULE, 8.6.4
GRANT_QUEUE_PRIVILEGE, 8.4.3
GRANT_SYSTEM_PRIVILEGE, 8.4.1
MIGRATE_QUEUE_TABLE, 8.1.5
MODIFY_TRANSFORMATION, 8.3.2
PURGE_QUEUE_TABLE, 8.1.4
REMOVE_SUBSCRIBER, 8.5.3
REVOKE_QUEUE_PRIVILEGE, 8.4.4
REVOKE_SYSTEM_PRIVILEGE, 8.4.2
SCHEDULE_PROPAGATION, 8.6.1
START_QUEUE, 8.2.3
STOP_QUEUE, 8.2.4
UNSCHEDULE_PROPAGATION, 8.6.6
VERIFY_QUEUE_TYPES, 1.8, 8.6.2
DBMS_AQ.BUFFERED, 10.4
DBMS_AQIN, 12.1
DBMS_AQ.PERSISTENT, 10.4
DBMS_AQ.PERSISTENT_OR_BUFFERED, 10.4
DBMS_MGWADM package
about, 17.3.1
ADD_SUBSCRIBER, 19.5.2, 19.7.5
ALTER_AGENT, 19.1.4
ALTER_MSGSYSTEM_LINK, 19.3.5, 19.7.3
ALTER_SUBSCRIBER, 19.7.5
CREATE_MSGSYSTEM_LINK, 19.3.1, 19.3.2, 19.3.4, 19.7.3
DB_CONNECT_INFO, 18.2.7, 19.1.3
DISABLE_PROPAGATION_SCHEDULE, 19.5.3
DOMAIN_QUEUE, 19.4.1
DOMAIN_TOPIC, 19.4.1
ENABLE_PROPAGATION_SCHEDULE, 19.5.3
JMS_CONNECTION, 19.3.2
JMS_QUEUE_CONNECTION, 19.3.2
JMS_TOPIC_CONNECTION, 19.3.2
MQSERIES_BASE_JAVA_INTERFACE, 19.3.1
REGISTER_FOREIGN_QUEUE, 19.4.1, 19.7.4
REMOVE_MSGSYSTEM_LINK, 19.3.6
RESET_SUBSCRIBER, 19.5.4
SHUTDOWN, 19.2.2
STARTUP, 19.2.1
UNREGISTER_FOREIGN_QUEUE, 19.4.2
DBMS_MGWMSG.LCR_TO_XML, 20.1.5
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE, 23.2
DBMS_STREAMS_ADM.SET_UP_QUEUE, 22.1.2.2, 23.2
DBMS_TRANSFORM.CREATE_TRANSFORMATION, 22.5
delays
during dequeuing, 1.7
specifying in JMS, 11.5.2
demonstrations
about, 1.12
Oracle Streams AQ, 1.12
Oracle Streams AQ JMS, 1.12
Oracle Streams AQ XML, 1.12
dequeue condition
and Virtual Private Database, 4.6.8
with queue table indexes, 5.2.6
dequeuing
ANYDATA queues
examples, 22.4, 23.7, 23.8
using JMS, 22.1.2.4
using OCI, 22.1.2.4
using PL/SQL, 22.1.2.3
buffered messages, 1.4
by multiple consumers, 1.3.2
concurrent processes, 1.7
demonstration, 1.12
features, 1.7
IDAP client request, 6.4.2
IDAP server response to request, 6.4.7
message arrays, 1.7, 10.6
message states, 1.7
messages, 10.5
methods, 1.7
modes
about, 1.7
navigation of messages, 1.7
options, 10.5
buffered messages, 1.4
parameters
array_size, 10.6
dequeue_options, 10.5, 10.6
retries with delays, 1.7
transaction protection, 1.7
waiting for messages, 1.7
destination (JMS)
altering, 12.10.3
dropping, 12.10.4
starting, 12.10.1
stopping, 12.10.2
disabling
database access, 8.7.5
propagations, 8.6.5
double message property (JMS)
getting, 15.10.4
setting, 15.2.4
dropping
AQ agents, 8.7.3
propagations, 8.6.6
queue tables, 8.1.3
queues, 8.2.5
transformations, 8.3.3
DurableSubscriber
about, 11.4.2
creating
for JMS Topic, 14.13, 14.14
for Oracle object type Topic, 14.15, 14.16
unsubscribing
for a local subscriber, 14.21
for a remote subscriber, 14.22

E

e-mail notification, 6.5
demonstration, 1.12
enabling
database access, 8.7.4
propagations, 8.6.4
enqueuing
ANYDATA queues
examples, 22.3, 23.6, 23.8
procedures, creating, 23.3
using JMS, 22.1.2.2
using OCI, 22.1.2.2
using PL/SQL, 22.1.2.1
buffered messages, 1.4
client request for, 6.4.1
correlation identifier, 1.6
demonstration, 1.12
features, 1.6
IDAP client request, 6.4.1
IDAP server response to request, 6.4.6
message array, 1.6, 10.3
message expiration, 1.6
message grouping, 1.6
message properties, 10.2
messages, 10.2
options, 10.2
parameters
array_size, 10.3
enqueue_options, 10.2
message_properties, 10.2
message_properties_array, 10.3
payload, 10.2
payload_array, 10.3
priority and ordering of messages, 1.6
sender identification, 1.6
enumerated constants
about, 2.14
delay, 2.15
delivery_mode, 2.15, 2.15, 2.15, 2.15
dequeue mode, 2.15
expiration, 2.15
message_grouping, 2.14
namespace, 2.15, 2.15
navigation, 2.15
operational interface, 2.15
queue_type, 2.14
retention, 2.14
state, 2.15
visibility, 2.15
wait, 2.15
environment variables
CLASSPATH, 18.6.2
Messaging Gateway, 18.6.2
MGW_PRE_PATH, 18.6.2
ORACLE_SID, 18.6.2
error conditions
Messaging Gateway, 21.2.3
error handling
error messages, 7.2
IDAP, 6.4.12
propagations, 1.8
error messages, 7.2
Messaging Gateway, 21.2.2
Messaging Gateway agent, 21.4
errors (JMS)
getting codes, 15.12.1
getting number, 15.12.2
event journals, 1.10
exception (JMS)
exception linked to a JMS exception, getting, 15.12.3
exception listener
getting, 15.12.6
setting, 15.12.5
printing stack trace, 15.12.4
exception handling
buffered messages, 1.4
exception queues, 1.7, 11.6.7
Messaging Gateway, 21.1.2
propagations in JMS, 11.7.4
exception queues
about, 1.7
in JMS, 11.6.7
expiration
setting during enqueuing, 1.6
specifying in JMS, 11.5.3
exporting
queue tables
about, 4.3.1
data pump, 4.3.3
modes, 4.3.1
multiple recipients, 4.3.1

F

float message property (JMS)
getting, 15.10.5
setting, 15.2.5
flow control
about, 1.4

G

getting (JMS)
ConnectionFactory, 12.4
correlation identifier, 15.9.1
error codes, 15.12.1
error numbers, 15.12.2
exceptions, 15.12.3
JDBC connection, 15.1.5
JMS Connection, 15.1.2
message identifier, 15.9.2
OracleOCIConnectionPool, 15.1.6
Queue in LDAP, 12.5
queue table, 12.7
QueueConnectionFactory, 12.4
in LDAP, 12.4.5
with JDBC connection parameters, 12.4.2
with JDBC URL, 12.4.1
Topic in LDAP, 12.5
TopicConnectionFactory, 12.4
with JDBC connection parameters, 12.4.4
with JDBC URL, 12.4.3
GLOBAL_AQ_USER_ROLE
and registerConnectionFactory, 11.1.1.3, 12.2.3
granting
AQ system privilege, 8.4.1
in JMS, 12.9.1
queue privilege, 8.4.3
in JMS, 12.9.5
Topic privilege in JMS, 12.9.3
grouping
messages, 1.6
GV$AQ, 11.1.7

H

HTTP
AQ operations over, 6.1.1
AQ servlet responses, 6.1.5
client requests, 6.1.4
headers, 6.3.2.1
propagation, 6.1.6, 6.1.6
propagation using, 1.8
response, 6.3.2.3
transactions, 6.1.4.1
user sessions, 6.1.4.1

I

IDAP
client request
commit transaction, 6.4.4
dequeue, 6.4.2
enqueue, 6.4.1
registration, 6.4.3
roll back transaction, 6.4.5
error handling, 6.4.12
message, 6.4, 6.4
notification, 6.4.11
request and response documents, 6.4
server response
commit transaction, 6.4.9
dequeue request, 6.4.7
enqueue request, 6.4.6
register request, 6.4.8
roll back transaction, 6.4.10
importing
queue tables
about, 4.3.2
data pump, 4.3.3
IGNORE parameter, 4.3.2
multiple recipients, 4.3.2
inboxes, 1.8
indexes
tuning for Oracle Streams AQ, 5.2.6
initialization parameters
Messaging Gateway, 18.6.1
INIT.ORA parameter, 2.16
integer message property (JMS)
getting, 15.10.3
setting, 15.2.3
interfaces to Oracle Streams AQ
about, 1.11
administrative, 3.8.1
AQ XML servlet, 3.7
comparison, 3.1, 3.8
JMS, 3.6
OCCI, 3.4
OCI, 3.3
OCI security, 4.2.4
OO4O, 3.5
operational, 3.8.2
PL/SQL, 3.2
Internet Data Access Presentation
about, 6.3
Internet operations
and application development, 1.3
AQ servlet responses, 6.1.5
architecture, 1.10, 6.1.1
client requests, 6.1.4
deploying AQ servlet, 6.2
IDAP client request
commit transaction, 6.4.4
dequeue, 6.4.2
enqueue, 6.4.1
registration, 6.4.3
roll back transaction, 6.4.5
IDAP errors, 6.4.12
IDAP notification, 6.4.11
IDAP request and response documents, 6.4
IDAP server response
commit transaction, 6.4.9
dequeue request, 6.4.7
enqueue request, 6.4.6
register request, 6.4.8
roll back transaction, 6.4.10
Internet Data Access Presentation, 6.3
JMS types, 6.1.2
notification by e-mail, 6.5
object type queues, 6.1.2
payloads, 6.1.2
propagation, 6.1.6
RAW queues, 6.1.2
SOAP
body, 6.3.1.3
envelope, 6.3.1.1
message structure, 6.3.1
method invocation, 6.3.2
transactions, 6.1.4.1
user authentication, 6.1.3
user sessions, 6.1.4.1
I/O
configuring for Oracle Streams AQ, 5.2.3

J

J2EE compliance, 11.9
Java properties
Messaging Gateway, 18.6.3
oracle.mgw.batch_size, 18.6.3
oracle.mgw.polling_interval, 18.6.3
oracle.mgw.tibrv.advMsgCallback, 18.6.3, 18.6.3
oracle.mgw.tibrv.encoding, 18.6.3
oracle.mgw.tibrv.intraProcAdvSubjects, 18.6.3
JDBC connection
getting from JMS Session, 15.1.5
registering ConnectionFactory using JDBC parameters through the database, 12.2.1
using to register ConnectionFactory through LDAP, 12.2.3
JDBC OCI driver
needed for JMS, 3.6.1
JDBC thin driver
needed for JMS, 3.6.1
JDBC URL
registering ConnectionFactory using JDBC URL through LDAP, 12.2.4
registering through the database, 12.2.2, 12.2.2
JMS
about, 11.1
and Oracle Real Application Clusters, 11.1.6
ANYDATA messages
dequeuing, 23.8
enqueuing, 23.8
asynchronous receive, 11.6.6
buffered messages, 11.2.5
Connection, 11.1.1
exception queues, 11.6.7
J2EE compliance, 11.9
JDBC OCI driver needed, 3.6.1
JDBC thin driver needed, 3.6.1
message bodies, 11.2.3
message consumer features, 11.6
message headers, 11.2.1
message properties, 11.2.2
message types, 11.2
MessageProducer features, 11.5
point-to-point features, 11.3
propagation schedules, 12.11
publish/subscribe features, 11.4
queue tables
creating, 12.6
getting, 12.7
queues. creating, 12.8
recipient lists, 11.4.5
Session, 11.1.1
statistics views support, 11.1.7
structured payloads, 11.2
troubleshooting, 15.12
JMS Connection
about, 11.1.1.4
closing, 15.11.5
getting, 15.1.2
getting OracleOCIConnectionPool from, 15.1.6
starting, 15.1.1
stopping, 15.11.3
JMS correlation identifier
setting, 15.1.14
JMS Destination
about, 11.1.2
managing, 12.10
methods, 11.1.2.3
using JMS Session to obtain, 11.1.2.1
using JNDI to look up, 11.1.2.2
JMS examples
BytesMessage, 16.2
MapMessage, 16.4
setting up, 16.1.1
StreamMessage, 16.3
TextMessage, 16.5
JMS message property
Boolean, 15.2.1, 15.10.1
byte, 15.2.6, 15.10.6
double, 15.2.4, 15.10.4
float, 15.2.5, 15.10.5
integer, 15.2.3, 15.10.3
long, 15.2.7, 15.10.7
object, 15.2.9, 15.10.9
short, 15.2.8, 15.10.8
string, 15.2.2, 15.10.2
JMS messages
browsing, 11.6.3
with a TopicBrowser, 14.29
correlation identifier, 15.9.1
creating
AdtMessage, 15.1.13
BytesMessage, 15.1.7
JMS Message, 15.1.12
MapMessage, 15.1.8
ObjectMessage, 15.1.10
StreamMessage, 15.1.9
TextMessage, 15.1.11
delay, specifying, 11.5.2
expiration, specifying, 11.5.3
grouping, 11.5.4
message consumer, closing, 15.11.2
message identifier, 15.9.2
message listener
specifying at JMS Session, 15.8.2
specifying at message consumer, 15.8.1
message property
getting, 15.10
setting, 15.2
MessageProducer, closing, 15.11.1
navigating in receive, 11.6.2
navigation mode for receiving, specifying, 15.7
Priority
setting default, 15.4
priority and ordering, 11.5.1
propagation with Messaging Gateway
inbound, 20.4.2
outbound, 20.4.1
publishing
specifying a recipient list, 14.12
specifying delivery mode, priority, and time to live, 14.11
specifying Topic, 14.10
with minimal specification, 14.9
QueueBrowser for, creating, 13.12, 13.13, 13.14
QueueReceiver for, creating, 13.16, 13.17
receiving
about, 11.6.1
asynchronously, 15.8.1, 15.8.2
from a destination using a transformation, 15.6.3
synchronously, 15.6.1, 15.6.2, 15.6.3
with a message consumer, 15.6.1, 15.6.2
remote subscribers for, creating, 14.18
remove no data, 11.6.4
retry with delay, 11.6.5
sending using a QueueSender, 13.10, 13.11
TimeToLive
setting default, 15.3
TopicBrowser for, creating, 14.25, 14.26
TopicReceiver for, creating, 14.23, 14.24
transformation with JMS AQ, 11.8
JMS propagations
about, 11.7
altering, 12.11.3
disabling, 12.11.4
enabling, 12.11.2
exception handling, 11.7.4
RemoteSubscriber, 11.7.1
scheduling, 11.7.2, 12.11.1
unscheduling, 12.11.5
JMS publish/subscribe
setting up, 11.4.8
JMS Session
about, 11.1.1.5
closing, 15.11.4
committing all operations, 15.1.3
creating, 13.7, 14.6
getting JDBC connection from, 15.1.5
rolling back all operations, 15.1.4
specifying message listener, 15.8.2
using to obtain Destination object, 11.1.2.1
JMS type queues/topics, 6.1.2
JMS types
ANYDATA queues, 22.1.2.2
Internet operations, 6.1.2
JMS_DeliveryMode, 19.7.5
JMS_NoLocal, 19.7.5
JNDI
using to look up ConnectionFactory objects, 11.1.1.3
using to look up Destination object, 11.1.2.2
JOB_QUEUE_PROCESSES, 4.7.3

L

LDAP
and AQ_ADMINISTRATOR_ROLE, 11.1.1.3
queue/topic connection factory, 12.4.5
registering ConnectionFactory, 12.2.4
unregistering ConnectionFactory, 12.3.1
LDAP server
adding alias, 8.8
adding AQ agents, 10.10
deleting alias, 8.9
removing AQ agents, 10.11
links
altering, 19.3.5
configuring Messaging Gateway links, 19.3
MGW_LINKS view, 19.3.7
MGW_MQSERIES_LINK view, 19.3.7
MGW_TIBRV_LINKS view, 19.3.7
removing, 19.3.6
TIB/Rendezvous, creating, 19.3.4
WebSphere MQ base Java, creating, 19.3.1
WebSphere MQ JMS, creating, 19.3.2
listener.ora
modifying for Messaging Gateway, 18.2.2, 18.2.3
modifying for TIB/Rendezvous, 18.3.1
modifying for WebSphere MQ, 18.3.2
listening
about, 1.7
application development, 1.3.4
demonstration, 1.12
parameters
agent_list, 10.4
listen_delivery_mode, 10.4
wait, 10.4
syntax, 10.4
LOBs
propagation, 1.8
log file
Messaging Gateway, 21.1
log_directory, 18.6.1
log_level, 18.6.1
logical change records
Messaging Gateway, 20.1.5
long message property (JMS)
getting, 15.10.7
setting, 15.2.7

M

managing
nonpersistent queues, A.2
propagations, 4.7, 8.6
queue tables, 8.1
queues, 8.2
subscribers, 8.5
transformations, 8.3
MapMessage
about, 11.2.3.3
creating, 15.1.8
example, 16.4
message headers
conversion with Messaging Gateway, 20.1.3
WebSphere MQ mappings, 20.2.1
message identifier
about, 1.7
and transaction grouping, 1.7
getting in JMS, 15.9.2
message properties
TIB/Rendezvous, 20.3.1
using with message types in JMS, 11.2.4
message types in JMS
about, 11.2
AdtMessage, 11.2.3.6
BytesMessage, 11.2.3.2
MapMessage, 11.2.3.3
ObjectMessage, 11.2.3.5
StreamMessage, 11.2.3.1
TextMessage, 11.2.3.4
MessageListener, 11.6.6
MessageProducer
closing, 15.11.1
features, 11.5, 11.8
setting default Priority, 15.4
setting default TimeToLive, 15.3
messages
array dequeuing, 1.7, 10.6
array enqueuing, 1.6, 10.3
bodies in JMS, 11.2.3
browsing in JMS, 11.6.3, 14.29
correlation identifier
about, 1.7
correlation identifiers, 1.6
in JMS, 15.9.1
creating in JMS, 15.1.7, 15.1.8, 15.1.9, 15.1.10, 15.1.11, 15.1.12, 15.1.13
creating remote subscribers in JMS, 14.19
delay, specifying in JMS, 11.5.2
dequeuing
features, 1.7
methods, 1.7
modes, 1.7
syntax, 10.5
using JMS, 23.8
with concurrent processes, 1.7
enqueuing
features, 1.6
options, 10.2
syntax, 10.2
using JMS, 23.8
exception queues, 1.7
expiration
about, 1.6
specifying in JMS, 11.5.3
format transformations, 1.9
grouping, 1.6
in JMS, 11.5.4
header conversion with Messaging Gateway, 20.1.3
headers in JMS, 11.2.1
history and retention in JMS, 11.1.5
identifier
about, 1.7
JMS message conversion, 20.4
JMS message property
getting, 15.10
JMS message property, setting, 15.2
message consumer in JMS, closing, 15.11.2
message identifier in JMS, 15.9.2
MessageProducer in JMS, closing, 15.11.1
navigating in JMS, 11.6.2
navigation during dequeuing, 1.7
navigation in receive, 11.6.2
navigation mode, specifying in JMS, 15.7
non-JMS message conversion, 20.1.1
nonrepudiation, 1.10
object type support, 1.2
ordering
buffered messages, 1.4
ordering during propagation, 1.8
payload restrictions, 4.6.4
persistence
for security, 1.2
metadata analysis, 1.2
scheduling, 1.2
priority and ordering, 1.6
in JMS, 11.5.1
priority during propagation, 1.8
Priority, setting in JMS, 15.4
propagation
ANYDATA, 22.2
errors, 1.8
features, 1.8
inboxes and outboxes, 1.8
LOBs, 1.8
remote consumers, 1.8
scheduling, 1.8
statistics, 1.8
using HTTP, 1.8
with Oracle RAC, 1.8
properties, 10.2
in JMS, 11.2.2
publishing in JMS, 14.9, 14.10, 14.11, 14.12
QueueBrowser for, creating, 13.12, 13.13, 13.14
QueueReceiver for, creating, 13.16, 13.17
receiving in JMS, 11.6.1
receiving synchronously in JMS, 15.6.1, 15.6.2, 15.6.3
recipients
about, 1.3.2
remote subscirbers, creating in JMS, 14.18
remove no data in JMS, 11.6.4
retention and history, 1.10
retries during dequeuing, 1.7
retry with delay in JMS, 11.6.5
sender identification, 1.6
sending in JMS, 13.10, 13.11
states during dequeuing, 1.7
third-party propagation support, 1.8
TIB/Rendezvous conversion, 20.3
TimeToLive, setting in JMS, 15.3
TopicBrowser for, creating, 14.25, 14.26, 14.27, 14.28
TopicReceiver for, creating, 14.23, 14.24
tracking, 1.10
transaction protection, 1.7
transformations, 1.9
in JMS, 11.8
using types with properties in JMS, 11.2.4
waiting during dequeuing, 1.7
WebSphere MQ conversion, 20.2
XML transformations, 1.9
MessageSelector
about, 11.3
Messaging Gateway
about, 17.1
administration, 17.3.1
administration user
creating, 18.2.5
agent
about, 17.3.2
configuring, 19.1
error messages, 21.4
shutting down, 19.2.2
starting, 19.2.1
agent user
creating, 18.2.6
and JMS, 17.2
and non-Oracle messaging systems, 17.3.4
architecture, 17.3
buffered messages, 17.5
canonical types, 20.1.2
database connection, 19.1.3
database connection information, configuring, 18.2.7
environment variables, 18.6.2
error conditions, 21.2.3
error messages, 21.2.2
exception handling, 21.1.2
features, 17.2
in a Oracle RAC environment, 18.2.8
initialization file, 18.2.4
about, 18.6
initialization parameters, 18.6.1
integration with Oracle Database, 17.3.3
Java properties, 18.6.3
links
altering, 19.3.5
loading, 18.2
log file, 21.1
logical change records, 20.1.5
message conversion (JMS), 20.4
message conversion (non-JMS), 20.1.1
messaging system links
configuring, 19.3
modifying listener.ora, 18.2.2, 18.2.3
monitoring agent status, 21.2
non-Oracle messaging
configuration properties, 19.7
optional link configuration properties, 19.7.3
non-Oracle messaging queues
configuring, 19.4
non-Oracle queue
unregistering, 19.4.2
optional foreign queue configuration properties, 19.7.4
optional subscriber configuration properties, 19.7.5
propagation, 17.4
propagation disabling, 19.5.3
propagation enabling, 19.5.3
propagation resetting, 19.5.4
propagation schedule
removing, 19.5.6
propagation subscriber
creating, 19.5.2
removing, 19.5.6
propagation subscribers, 19.5.1
propagations, 19.5
monitoring, 21.3
registering non-Oracle queue, 19.4.1
removing a link, 19.3.6
resource limits, 19.1.4
running agent on Oracle RAC, 19.2.4
setting up for TIB/Rendezvous, 18.3.1
setting up for WebSphere MQ, 18.3.2
setting up third-party messaging, 18.3
setup
procedure, 18.2
verifying, 18.4
unloading, 18.5
view for non-Oracle queues, 19.4.3
views, 21.2.1
views for links, 19.3.7
Messaging Gateway user
and MGW_AGENT_ROLE, 18.2.6
MGW_ADMINISTRATOR_ROLE
and Messaging Gateway administration user, 18.2.5
creating, 18.2.1
MGW_AGENT_OPTIONS
Supplemental Options and Properties, 9.40
MGW_AGENT_ROLE, 19.1.3
and Messaging Gateway user, 18.2.6
creating, 18.2.1
MGW_BASIC_MSG_T, 20.1.2
MGW_FOREIGN_QUEUES, 19.4.3
Foreign Queues, 9.44
MGW_GATEWAY, 19.2.2, 21.2.1
Configuration and Status Information, 9.39
MGW_JOBS
Messaging Gateway Propagation Jobs, 9.45
MGW_LINKS, 19.3.7
Names and Types of Messaging System Links, 9.41
MGW_MQSERIES_LINK, 19.3.7
MGW_MQSERIES_LINKS
WebSphere MQ Messaging System Links, 9.42
MGW_PRE_PATH, 18.6.2
MGW_SCHEDULES
Information about Schedules, 9.47
MGW_SUBSCRIBERS
Information for Subscribers, 9.46
MGW_TIBRV_LINKS, 19.3.7
TIB/Rendezvous Messaging System Links, 9.43
MGW_TIBRV_MSG_T, 20.1.2
mgw.ora
about, 18.6
comment lines, 18.6.4
environment variables, 18.6.2
Java properties, 18.6.3
modifying for TIB/Rendezvous, 18.3.1
modifying for WebSphere MQ, 18.3.2
parameters, 18.6.1
setting up, 18.2.4
migrating
queue tables, 8.1.5
modifying
listener.ora for Messaging Gateway, 18.2.2, 18.2.3
transformations, 8.3.2
monitoring
Messaging Gateway, 21.1
propagations, 21.3
Messaging Gateway agent status, 21.2
MQ_BrokerControlQueue, 19.7.3
MQ_BrokerPubQueue, 19.7.3
MQ_BrokerQueueManager, 19.7.3
MQ_BrokerVersion, 19.7.3
MQ_ccsid, 19.7.3, 19.7.3
MQ_CharacterSet, 19.7.4
MQ_JmsDurSubQueue, 19.7.3, 19.7.4
MQ_JmsTargetClient, 19.7.4
MQ_openOptions, 19.7.4
MQ_PubAckInterval, 19.7.3
MQ_ReceiveExit, 19.7.3
MQ_ReceiveExitInit, 19.7.3
MQ_SecurityExit, 19.7.3
MQ_SecurityExitInit, 19.7.3
MQ_SendExit, 19.7.3
MQ_SendExitInit, 19.7.3, 19.7.3, 19.7.3, 19.7.3, 19.7.3, 19.7.3
MsgBatchSize, 19.7.5
multicasting
definition, 1.3.4
multiconsumer dequeuing, 1.3.2

N

names
queue tables
length, 8.1.1
mixed case, 8.1.1
queues
length, 8.2.1
mixed case, 8.2.1
navigation
during dequeuing, 1.7
modes
FIRST_MESSAGE, 1.7
NEXT_MESSAGE, 1.7
NEXT_TRANSACTION, 1.7
specifying mode in JMS, 15.7
nonpersistent queues
compatibility, A.3
creating, A.1
managing, A.2
notifications, A.4
restrictions, A.5
nonrepudiation
about, 1.10
notifications
about, 1.5
buffered messages, 1.5
designated port, 1.5
e-mail, 6.5
IDAP, 6.4.11
nonpersistent queues, A.4
parameters
post_count, 10.9
post_list, 10.9
reg_count, 10.7
reg_list, 10.7
posting, 10.9
purge following, 1.5
RAW payload delivery, 1.5
registering, 10.7
reliability, 1.5
timeout, 1.5
unregistering, 10.8

O

object message property (JMS)
getting, 15.10.9
setting, 15.2.9
object types
access, 4.2.1.3
support for, 1.2
synonyms, 4.6.6
object_name, 2.1
ObjectMessage
about, 11.2.3.5
creating, 15.1.10
OCCI
interface to Oracle Streams AQ, 3.4
Oracle type translator, 3.3
OCI
interface to Oracle Streams AQ, 3.3
Oracle type translator, 3.3
OO4O
interface to Oracle Streams AQ, 3.5
operational interfaces to Oracle Streams AQ, 3.8.2
options
dequeuing, 10.5
enqueuing, 10.2
Oracle AQ Views, 9
Oracle Enterprise Manager
and Oracle Streams AQ, 1.10
support for, 4.4, 4.4
Oracle Internet Directory
and Oracle Streams AQ, 1.10
Oracle Streams AQ integration, 1.2
Oracle JMS
about, 11.1
Oracle Messaging Gateway Views, 9
Oracle object (ADT) type queues
Internet operations, 6.1.2
Oracle RAC
buffered messages, 1.4
configuring Messaging Gateway, 18.2.8
performance with Oracle Streams AQ, 5.1.1
queue service name, 1.4
running Messaging Gateway agent, 19.2.4
Oracle Real Application Clusters
and JMS, 11.1.6
message propagation, 1.8
support for, 1.2
Oracle type translator, 3.3
ORACLE_SID
Messaging Gateway, 18.6.2
oracle.mgw.batch_size, 18.6.3
oracle.mgw.polling_interval, 18.6.3
oracle.mgw.tibrv.advMsgCallback, 18.6.3, 18.6.3
oracle.mgw.tibrv.encoding, 18.6.3
oracle.mgw.tibrv.intraProcAdvSubjects, 18.6.3
OracleOCIConnectionPool
getting from JMS Connection, 15.1.6
ordering
commit-time, 1.6
during propagation, 1.8
messages in JMS, 11.5.1
specifying during enqueuing, 1.6
outboxes, 1.8

P

parameters
admin_option, 8.4.1
agent_list, 10.4
agent_name, 8.7.1, 8.7.4
alias, 8.8
AQ_TM_PROCESSES, 2.16.1
array_size, 10.3, 10.6
attempts, 10.2
attribute_number, 8.3.2
certificate, 10.10, 10.10
certificate_location, 8.7.1
comment, 8.1.1, 8.2.1
compatibility, 4.1
compatible, 8.1.1
consumer_name, 10.5
correlation, 10.2, 10.5
db_username, 8.7.4
delay, 10.2
delivery_mode, 8.5.1, 10.2, 10.2, 10.5
deq_condition, 10.5
dequeue, 8.2.3, 8.2.4
dequeue_mode, 10.5
dequeue_options, 10.5, 10.6
dest_queue_name, 8.6.2
destination, 8.6.1, 8.6.2
destination_queue, 8.6.1
duration, 8.6.1
enable_anyp, 8.7.1
enable_http, 8.7.1
enqueue, 8.2.3, 8.2.4
enqueue_options, 10.2
enqueue_time, 10.2
exception_queue, 10.2
expiration, 10.2
from_schema, 8.3.1
from_type, 8.3.1
grant_option, 8.4.3
grantee, 8.4.1
latency, 8.6.1
listen_delivery_mode, 10.4, 10.4, 10.4
log_directory, 18.6.1
log_level, 18.6.1
max_retries, 8.2.1
message_grouping, 8.1.1
message_properties, 10.2
message_properties_array, 10.3, 10.3
MSG_STATE, 9.10
msgid, 10.5
multiple_consumers, 8.1.1
name, 10.9
namespace, 10.9
navigation, 10.5
next_time, 8.6.1
obj_location, 8.8
original_msgid, 10.2
OWNER_INSTANCE, 1.4
payload, 10.2, 10.9
payload_array, 10.3
post_count, 10.9
post_list, 10.9
primary_instance, 8.1.1
priority, 10.2
purge_condition, 8.1.4
purge_options, 8.1.4
queue_name, 8.2.1
queue_payload_type, 8.1.1
queue_table, 8.1.1, 8.2.1
queue_to_queue, 8.5.1
queue_type, 8.2.1
recipient_list, 10.2
reg_count, 10.7, 10.7
reg_list, 10.7, 10.7
relative_msgid, 10.2
REMOTE_LISTENER, 1.4
retention_time, 8.2.1
retry_delay, 8.2.1
rule, 8.5.1
secondary_instance, 8.1.1
secure, 8.1.1
sender_id, 10.2
sequence_deviation, 10.2
sort_list, 8.1.1
src_queue_name, 8.6.2
start_time, 8.6.1
state, 10.2
storage_clause, 8.1.1
streams_pool_size, 1.4
to_schema, 8.3.1
to_type, 8.3.1
transaction_group, 10.2
transformation, 8.3.1, 8.5.1, 10.5
user_property, 10.2
visibility, 10.2, 10.5
wait, 10.4, 10.5
payloads
ANYDATA wrappers for, 22.1.1
Internet operations, 6.1.2
restrictions, 4.6.4
structured, 1.2
transformations with Messaging Gateway, 20.1.4
XMLType, 1.2
performance
about, 1.2
buffered messages, 5.4
concurrent processes, 5.2.4
configuring I/O, 5.2.3
Oracle Streams AQ and Oracle RAC, 5.1.1
persistent messaging, 5.1
propagation tuning, 5.3
queue table indexes, 5.2.6
serial processes, 5.2.5
shared servers, 5.1.2
storage parameters, 5.2.2
persistent messaging
compared to buffered, 1.4
performance, 5.1
tuning, 5.2
point-to-point messages
about, 11.3
port
designated for notification, 1.5
posting for notification, 10.9
PreserveMessageID, 19.7.5
priority
during propagation, 1.8
specifying during enqueuing, 1.6
Priority (JMS)
about, 11.5.1
setting for all messages from a MessageProducer, 15.4
privileges
AQ system privilege
granting, 8.4.1
granting in JMS, 12.9.1
revoking, 8.4.2
revoking in JMS, 12.9.2
DBMS_AQIN, 12.1
parameters
admin_option, 8.4.1
grant_option, 8.4.3
grantee, 8.4.1
queue privilege
granting, 8.4.3
granting in JMS, 12.9.5
revoking, 8.4.4
revoking in JMS, 12.9.6
required for propagation, 4.7.1
security, 4.2.3
SELECT_ANY_DICTIONARY, 23.2
Topic privileges
granting in JMS, 12.9.3
revoking in JMS, 12.9.4
programmatic interfaces
about, 1.11
ANYDATA queues, 22.1.2
AQ XML servlet, 3.7
comparison, 3.1, 3.8
JMS, 3.6
OCCI, 3.4
OCI, 3.3
OCI security, 4.2.4
OO4O, 3.5
PL/SQL, 3.2
propagations
about, 1.8
in JMS, 11.7
altering, 8.6.3
in JMS, 12.11.3
ANYDATA queues
about, 22.2
examples, 22.5, 22.6
BFILE objects, 4.7.2
buffered messages, 1.4
creating, 8.6.1
debugging, 7.1
disabling, 8.6.5
in JMS, 12.11.4
with Messaging Gateway, 19.5.3
dropping, 8.6.6
enabling, 8.6.4
in JMS, 12.11.2
with Messaging Gateway, 19.5.3
error handling, 1.8
in JMS, 11.7.4
features, 1.8
inboxes and outboxes, 1.8
JMS messages with Messaging Gateway
inbound, 20.4.2
outbound, 20.4.1
managing, 4.7, 8.6
messages with LOBs, 1.8
Messaging Gateway
configuring for, 19.5
monitoring, 21.3
resetting with, 19.5.4
subscribers, about, 19.5.1
subscribers, creating, 19.5.2
subscribers, removing, 19.5.6
optimizing, 4.7.3
parameters
destination, 8.6.1
destination_queue, 8.6.1
duration, 8.6.1
latency, 8.6.1
next_time, 8.6.1
start_time, 8.6.1
priority and ordering of messages, 1.8
privileges required, 4.7.1
queue-to-dblink
about, 1.8
scheduling, 1.8
with Oracle RAC, 1.8
queue-to-queue
about, 1.8
buffered messages, 1.4
scheduling, 1.8
with Oracle RAC, 1.8
remote consumers
about, 1.8
schedules
about, 1.8
altering, 1.8
creating syntax, 8.6.1
in JMS, 11.7.2, 12.11
removing with Messaging Gateway, 19.5.6
scheduling
in JMS, 12.11.1
security, 4.2.5
statistics, 1.8
third-party support, 1.8
TIB/Rendezvous, 20.3.2, 20.3.3
tuning, 5.3
unscheduling, 8.6.6
in JMS, 12.11.5
using HTTP, 1.8, 6.1.6
using HTTP and HTTPS, 6.1.6
WebSphere MQ, 20.2.2, 20.2.3
with Messaging Gateway, 17.4
with Oracle RAC, 1.8
publishing JMS messages
specifying a recipient list, 14.12
specifying delivery mode, priority, and time to live, 14.11
specifying Topic, 14.10
with minimal specification, 14.9
publish/subscribe, 11.4
about, 1.3.4
setting up, 1.3.4, 11.4.8
purge
following notification, 1.5
purging
queue tables, 8.1.4

Q

Queue (JMS)
getting in LDAP, 12.5
queue monitor coordinator, 1.10
queue privilege
granting, 8.4.3
in JMS, 12.9.5
revoking, 8.4.4
in JMS, 12.9.6
queue tables
altering, 8.1.2
creating, 8.1.1
in JMS, 12.6
data pump, 4.3.3
dropping, 8.1.3
export
modes, 4.3.1
exporting
about, 4.3, 4.3.1
getting in JMS, 12.7
importing
about, 4.3, 4.3.2
IGNORE parameter, 4.3.2
multiple recipients, 4.3.2
managing, 8.1
migrating, 8.1.5
multiple recipients
exporting, 4.3.1
names
length, 8.1.1
mixed case, 4.1, 8.1.1
parameters
comment, 8.1.1
compatible, 8.1.1
message_grouping, 8.1.1
multiple_consumers, 8.1.1
primary_instance, 8.1.1
queue_payload type, 8.1.1
queue_table, 8.1.1
secondary_instance, 8.1.1
secure, 8.1.1
sort_list, 8.1.1
storage_clause, 8.1.1
payload types, 8.1.1
purging, 8.1.4
restrictions, 4.6.5
security, 8.1.1
sort key, 8.1.1
storage clause, 8.1.1
tuning indexes for performance, 5.2.6
QUEUE_PRIVILEGES, 9.9
QueueBrowser
about, 11.3
creating for Oracle object type messages, 13.14
creating for standard JMS type messages, 13.12, 13.13
QueueConnection
creating with default ConnectionFactory parameters, 13.5
creating with open JDBC connection, 13.4
creating with open OracleOCIConnectionPool, 13.6
creating with username/password, 13.3
QueueConnectionFactory
getting
in LDAP, 12.4.5
getting with JDBC connection parameters, 12.4.2
getting with JDBC URL, 12.4.1
registering
through database using JDBC connection parameters, 12.2.1
through database using JDBC URL, 12.2.2
through LDAP using JDBC connection parameters, 12.2.3
through LDAP using JDBC URL, 12.2.4
unregistering
through database, 12.3.1
through LDAP, 12.3.2
QueueReceiver
about, 11.3
creating for Oracle object type messages, 13.17
creating for standard JMS type messages, 13.16
queues
altering, 8.2.2
ANYDATA
about, 22.1
creating, 23.2
JMS types supported, 22.1.2.2
programmatic interfaces, 22.1.2
propagation, 22.2
cleaning up, 1.10
creating, 8.2.1
in JMS, 12.8
dropping, 8.2.5
exception, 1.7
in JMS, 11.6.7
listening, 10.4
management restrictions, 4.6
managing, 8.2
monitor coordinator, 1.10
names
length, 8.2.1
mixed case, 4.1, 8.2.1
non-Oracle
configuring, 19.4
registering, 19.4.1
nonpersistent, A.1
compatibility, A.3
managing, A.2
notifications, A.4
restrictions, A.5
parameters
comment, 8.2.1
dequeue, 8.2.3, 8.2.4
enqueue, 8.2.3, 8.2.4
max_retries, 8.2.1
queue_name, 8.2.1
queue_table, 8.2.1
queue_type, 8.2.1
retention_time, 8.2.1
retry_delay, 8.2.1
point-to-point
creating in JMS, 12.8.1
restrictions, 4.6.3, 4.6.5
secure, 10.1
security, 4.2.3
starting, 8.2.3
stopping, 8.2.4
subscribers
about, 1.3.2
type, verifying, 8.6.2
QueueSender
about, 11.3
creating, 13.9
sending messages and specifying options, 13.11
sending messages with default options, 13.10
QueueSession
creating, 13.8
queue/topic connection factory
getting in LDAP, 12.4.5
queuing
and Oracle Database, 1.2
definition, 1.1

R

RAW
payload delivery with notification, 1.5
using RAW queues for Internet operations, 6.1.2
recipients
about, 1.3.2
recipient lists in JMS, 11.4.5
recovery
restrictions, 4.6.7
REF payloads
restrictions, 4.6.3
registerConnectionFactory
and AQ_ADMINISTRATOR_ROLE, 12.2.2
and GLOBAL_AQ_USER_ROLE, 12.2.3
using JDBC connection parameters through LDAP, 12.2.3
using JDBC connection parameters through the database, 12.2.1
using JDBC URL through LDAP, 12.2.4
registering
for notification, 10.7
through the database, JDBC URL, 12.2.2
registration
client request for, 6.4.1
IDAP client request, 6.4.3
IDAP server response to request, 6.4.8
reliability
notifications, 1.5
remote consumers
propagation, 1.8
remote subscribers
restrictions, 4.6.1
RemoteSubscriber, 11.4.3, 11.7.1
resource limits
Messaging Gateway, 19.1.4
restrictions
buffered messages, 1.4
message payloads, 4.6.4
nonpersistent queues, A.5
point-in-time recovery, 4.6.7
queue management, 4.6
REF payloads, 4.6.3
remote subscribers, 4.6.1
subscribers, 4.6.1
synonyms, 4.6.5
virtual private database, 4.6.8
retention
of messages, 1.10
in JMS, 11.1.5
retries
during dequeuing, 1.7
multiple sessions dequeuing, 1.7
revoking
AQ system privilege, 8.4.2
in JMS, 12.9.2
queue privilege, 8.4.4
in JMS, 12.9.6
roles
AQ_ADMINISTRATOR_ROLE, 3.6.1, 4.2.1.1, 12.2.2
AQ_USER_ROLE, 3.6.1, 4.2.1.2
GLOBAL_AQ_USER_ROLE, 11.1.1.3, 12.2.3
MGW_ADMINISTRATOR_ROLE, 18.2.1, 18.2.5
MGW_AGENT_ROLE, 18.2.1, 18.2.6
SELECT_CATALOG_ROLE, 23.2
rollback
all operations in JMS Session, 15.1.4
RV_discardAmount, 19.7.5
RV_limitPolicy, 19.7.5
RV_maxEvents, 19.7.5

S

scalability
about, 1.2
schedules
enabling and disabling propagation with Messaging Gateway, 19.5.3
scheduling
about propagation scheduling, 1.8
propagations using SCHEDULE_PROPAGATION, 8.6.1
secure queues, 10.1
security, 4.2.1
at destination level in JMS, 11.1.4
at system level in JMS, 11.1.3
compatibility parameter, 4.2.2
message persistence, 1.2
OCI applications, 4.2.4
propagations, 4.2.5
queue privileges, 4.2.3
queue tables
secure parameter, 8.1.1
roles, 4.2.1
sender identification
during enqueuing, 1.6
serial processes
tuning for Oracle Streams AQ, 5.2.5
Session (JMS)
creating, 13.7, 14.6
shared servers
performance with Oracle Streams AQ, 5.1.2
short message property (JMS)
getting, 15.10.8
setting, 15.2.8
SOAP
ANYDATA queues, 22.2
body, 6.3.1.3
envelope, 6.3.1.1
header, 6.3.1.2
message structure, 6.3.1
method invocation, 6.3.2
stack trace
printing in JMS, 15.12.4
starting
JMS Connection, 15.1.1
Messaging Gateway agent, 19.2.1
queues, 8.2.3
statistics
propagation, 1.8
stopping
JMS Connection, 15.11.3
queues, 8.2.4
storage parameters
tuning Oracle Streams AQ, 5.2.2
StreamMessage
about, 11.2.3.1
creating, 15.1.9
example, 16.3
string message property (JMS)
getting, 15.10.2
setting, 15.2.2
structured payloads, 1.2
about, 1.2
in JMS, 11.2
subscribers
about, 1.3.2
adding, 8.5.1
altering, 8.5.2
creating, 8.5.1
creating JMS remote subscriber for Oracle object type messages, 14.19
creating remote subscriber for JMS messages, 14.18
creating with Messaging Gateway, 19.5.2
in Messaging Gateway propagations, 19.5.1
managing, 8.5
names
mixed case, 4.1
ordering, 1.3.2
parameters
delivery_mode, 8.5.1
queue_to_queue, 8.5.1
rule, 8.5.1
transformation, 8.5.1
removing, 8.5.3
restrictions, 4.6.1
specifying transformations for in JMS, 14.17, 14.20
unsubscribing DurableSubscribers, 14.21, 14.22
synonyms
restrictions, 4.6.5
SYS.AQ$_DESCRIPTOR, 2.10
SYS.AQ$_POST_INFO, 2.12
SYS.AQ$_REG_INFO, 2.9
SYS.MGW_MQSERIES_PROPERTIES, 19.7.1
SYS.MGW_TIBRV_PROPERTIES, 19.7.2
system privilege
granting, 8.4.1
in JMS, 12.9.1
revoking, 8.4.2
in JMS, 12.9.2

T

TextMessage
about, 11.2.3.4
creating, 15.1.11, 15.1.12
example, 16.5
third-party messaging
and application development, 1.3
and Messaging Gateway, 17.3.4
configuration properties, 19.7
optional foreign queue configuration properties, 19.7.4
optional link configuration properties, 19.7.3
optional subscriber configuration properties, 19.7.5
queues
configuring, 19.4
registering, 19.4.1
unregistering, 19.4.2
setting up, 18.3
view for registered queues, 19.4.3
TIB/Rendezvous
AQ_MsgProperties, 19.7.5
links
creating, 19.3.4
listener.ora, modifying, 18.3.1
message conversion, 20.3
message property mapping, 20.3.1
Messaging Gateway. setting up for, 18.3.1
mgw.ora, modifying, 18.3.1
MsgBatchSize, 19.7.5
PreserveMessageID, 19.7.5
propagation
inbound, 20.3.3
outbound, 20.3.2
RV_discardAmount, 19.7.5
RV_limitPolicy, 19.7.5
RV_maxEvents, 19.7.5
Subject
registering, 19.4.1.3
unregistering, 19.4.2
system properties, 19.7.2
time specification
during enqueuing, 1.6
timeout
notifications, 1.5
TimeToLive
setting for all messages from a MessageProducer, 15.3
Topic
creating DurableSubscriber for, 14.13, 14.14, 14.15, 14.16
creating in JMS, 12.8.2
getting in LDAP, 12.5
granting Topic privilege in JMS, 12.9.3
revoking Topic privilege in JMS, 12.9.4
specifying transformations for subscribers, 14.17
TopicBrowser, 11.4.7
browsing messages using, 14.29
creating for Topic of Oracle type messages, 14.27, 14.28
creating for Topic of standard JMS type messages, 14.25, 14.26
TopicConnection
creating with open JDBC connection, 14.4
creating with open OracleOCIConnectionPool, 14.5
creating with username/password, 14.3
TopicConnectionFactory
getting
in LDAP, 12.4.5
with JDBC connection parameters, 12.4.4
with JDBC URL, 12.4.3
registering
through database using JDBC connection parameters, 12.2.1
through database using JDBC URL, 12.2.2<7/a>
through LDAP using JDBC connection parameters, 12.2.3
through LDAP using JDBC URL, 12.2.4
unregistering
through database, 12.3.1
through LDAP, 12.3.2
TopicPublisher
about, 11.4.4
creating, 14.8
TopicReceiver
about, 11.4.6
creating for Topic of Oracle object type messages, 14.24
creating for Topic of standard JMS type messages, 14.23
TopicSession
creating, 14.7
transaction
IDAP client request
commit, 6.4.4
roll back, 6.4.5
protection during dequeuing, 1.7
transformations
about, 1.9
altering, 8.3.2
creating, 8.3.1
dropping, 8.3.3
for remote subscribers, specifying in JMS, 14.20
for Topic subscribers, specifying in JMS, 14.17
managing, 8.3
Messaging Gateway, 20.1.4
modifying, 8.3.2
parameters
attribute_number, 8.3.2
from_schema, 8.3.1
from_type, 8.3.1
to_schema, 8.3.1
to_type, 8.3.1
transformation, 8.3.1
XML, 1.9
troubleshooting
in JMS, 15.12
tuning
buffered messages, 5.4
persistent messaging, 5.2
type_name, 2.2
types
access, 4.2.1.3
AQ agent, 2.3
AQ agent list, 2.5
AQ notification descriptor, 2.10
AQ post informatin list, 2.8
AQ post information, 2.12
AQ post information list, 2.8
AQ recipient list, 2.4
AQ registration information, 2.9
AQ registration information list, 2.7
AQ subscriber list, 2.6
aq$_purge_options_t, 8.1.4
buffered messaging support, 1.4
Messaging Gateway, 20.1.2
MGW_BASIC_MSG_T, 20.1.2
MGW_TIBRV_MSG_T, 20.1.2
oracle.xdb.XMLType, 22.1.2.4
support for, 1.2
SYS.LCR$_DDL_RECORD, 22.1.2.1
SYS.LCR$_ROW_RECORD, 22.1.2.1

U

unregistering
ConnectionFactory in LDAP, 12.3.1, 12.3.2
notification, 10.8
unscheduling
propagations, 8.6.6
in JMS, 12.11.5
user authentication
Internet operations, 6.1.3
USER_ATTRIBUTE_TRANSFORMATIONS
User Transformation Functions, 9.19
USER_QUEUE_SCHEDULES, 9.8
USER_QUEUE_SUBSCRIBERS, 9.14
USER_QUEUE_TABLES, 9.2
USER_QUEUES, 9.5
USER_SUBSCR_REGISTRATIONS
User Subscription Registrations, 9.21
USER_TRANSFORMATIONS, 9.18
users
Messaging Gateway agent, 18.2.6

V

V$METRICGROUP
Information about the Metric Group, 9.34
verifying
Messaging Gateway setup, 18.4
queue type, 8.6.2
views
all propagation schedules, 9.7, 9.7
all queue subscribers in database, 9.13
all queues in database, 9.4
all transformation functions, 9.17
all transformations, 9.16
AQ agents registered for Internet access, 9.22
messages in queue table, 9.10
Messaging Gateway, 19.2.2
Messaging Gateway agent, 21.2.1
Messaging Gateway links, 19.3.7
propagation schedules in user schema, 9.8
queue subscribers, 9.11
queue subscribers and their rules, 9.12
queue subscribers for queues where user has queue privileges, 9.15
queue subscribers in user schema, 9.14
queue tables in user schema, 9.2
queues for which user has any privilege, 9.6
queues for which user has queue privilege, 9.9
queues in user schema, 9.5
registered non-Oracle queues, 19.4.3
user transformations, 9.18
virtual private database
restrictions, 4.6.8
visibility
about, 6.4.1, 6.4.2
buffered messages, 1.4
dequeue options, 10.5
enqueue options, 10.2
rollback opertations, 6.4.5

W

waiting
during dequeuing, 1.7
WebSphere MQ
base Java link, creating, 19.3.1
base Java queue
registering, 19.4.1.1
unregistering, 19.4.2
JMS link, creating, 19.3.2
JMS Queue or Topic
registering, 19.4.1.2
unregistering, 19.4.2
JMS_DeliveryMode, 19.7.5
JMS_NoLocal, 19.7.5
listener .ora, modifying, 18.3.2
message conversion, 20.2
message header mappings, 20.2.1
Messaging Gateway, setting up for, 18.3.2
mgw.ora, modifying, 18.3.2
MQ_BrokerControlQueue, 19.7.3
MQ_BrokerPubQueue, 19.7.3
MQ_BrokerQueueManager, 19.7.3
MQ_BrokerVersion, 19.7.3
MQ_ccsid, 19.7.3, 19.7.3
MQ_CharacterSet, 19.7.4
MQ_JmsDurSubQueue, 19.7.3, 19.7.4
MQ_JmsTargetClient, 19.7.4
MQ_openOptions, 19.7.4
MQ_PubAckInterval, 19.7.3
MQ_ReceiveExit, 19.7.3
MQ_ReceiveExitInit, 19.7.3
MQ_SecurityExit, 19.7.3
MQ_SecurityExitInit, 19.7.3
MQ_SendExit, 19.7.3
MQ_SendExitInit, 19.7.3, 19.7.3, 19.7.3, 19.7.3, 19.7.3, 19.7.3
MsgBatchSize, 19.7.5
optional link configuration properties, 19.7.3
PreserveMessageID, 19.7.5
propagation
inbound, 20.2.3
outbound, 20.2.2
system properties, 19.7.1

X

XA
using with Oracle Streams AQ, 4.5
XML, 6
deploying AQ servlet, 6.2
message format transformations, 1.9
PK`PK-AOEBPS/mg_work.htm Working with Oracle Messaging Gateway

19 Working with Oracle Messaging Gateway

After Oracle Messaging Gateway (MGW) is loaded and set up, it is ready to be configured and run. You can use DBMS_MGWADM.ALTER_AGENT to set the username, password, database specifier, and connection type the Messaging Gateway agent will use for creating database connections.

This chapter contains these topics:


Note:

All commands in the examples must be run as a user granted MGW_ADMINISTRATOR_ROLE.


See Also:

"DBMS_MGWADM" and "DBMS_MGWMSG" in Oracle Database PL/SQL Packages and Types Reference

Configuring the Oracle Messaging Gateway Agent

Messages are propagated between Oracle Streams Advanced Queuing and non-Oracle messaging systems by the Messaging Gateway agent. The Messaging Gateway agent runs as an external process of the Oracle Database server.

Messaging Gateway supports multiple agents for a given database. A default agent is automatically created that has the name of DEFAULT_AGENT. Additional named agents can be created to provide propagation job isolation and grouping, and scaling in a Oracle RAC environment. The default agent is usually sufficient for single instance, non-Oracle RAC, environments.

This section contains these topics:

Creating a Messaging Gateway Agent

You can use DBMS_MGWADM.CREATE_AGENT to create additional Messaging Gateway agents. The Messaging Gateway default agent, DEFAULT_AGENT, is automatically created when Messaging Gateway is installed and will always exist.

Agents can be configured with an agent user, connection information, database service, and resource limits when the agent is created, or at a later time using DBMS_MGWADM.ALTER_AGENT. A Messaging Gateway agent must be configured with a database user that has been granted the role MGW_AGENT_ROLE before the agent can be started.

Example 19-1 creates the agent named myagent and specifies the database connection information for the agent user. Default values are used for all other parameters.

Example 19-1 Creating a Messaging Gateway Agent

SQL> exec DBMS_MGWADM.CREATE_AGENT(
                         agent_name  => 'myagent',
                         username    => 'mgwagent',
                         password    => 'mgwagent_password',
                         database    => 'mydatabase');

Removing a Messaging Gateway Agent

A Messaging Gateway agent can be removed by calling DBMS_MGWADM.REMOVE_AGENT. Before an agent can be removed, all Messaging Gateway links associated with the agent must be removed and the agent shut down. The default agent, DEFAULT_AGENT, cannot be removed. Example 19-2 removes the agent named myagent.

Example 19-2 Removing a Messaging Gateway Agent

SQL> exec DBMS_MGWADM.REMOVE_AGENT(agent_name   => 'myagent');

Database Connection

The Messaging Gateway agent runs as a process external to the database. To access Oracle Streams Advanced Queuing and the Messaging Gateway packages, the Messaging Gateway agent needs to establish connections to the database. You can use DBMS_MGWADM.ALTER_AGENT to set the username, password and the database connect string that the Messaging Gateway agent will use for creating database connections. The user must be granted the role MGW_AGENT_ROLE before the Messaging Gateway agent can be started.

Example 19-3 shows the Messaging Gateway default agent being configured for user mgwagent with password mgwagent_password using net service name mydatabase.

Example 19-3 Setting Database Connection Information

SQL> exec DBMS_MGWADM.ALTER_AGENT (
                             agent_name => 'default_agent',
                             username   => 'mgwagent', 
                             password   => 'mgwagent_password',
                             database   => 'mydatabase');

Resource Limits

You can use DBMS_MGWADM.ALTER_AGENT to set resource limits for the Messaging Gateway agent. For example, you can set the heap size of the Messaging Gateway agent process and the number of propagation threads used by the agent process. The default values are 64 MB of memory heap and one propagation thread. For named agents, these values can also be specified when the agent is created by DBMS_MGWADM.CREATE_AGENT.

Example 19-4 sets the heap size to 96 MB and two propagation threads for the agent myagent.

Example 19-4 Setting the Resource Limits

SQL> exec DBMS_MGWADM.ALTER_AGENT(
                        agent_name  => 'myagent',
                        max_memory  => 96,
                        max_threads => 2);

The memory heap size and the number of propagation threads cannot be altered when the Messaging Gateway agent is running.

Starting and Shutting Down the Oracle Messaging Gateway Agent

This section contains these topics:

Starting the Oracle Messaging Gateway Agent

After the Messaging Gateway agent is configured, you can start the agent with DBMS_MGWADM.STARTUP. Example 19-5 shows how to start the default agent and agent myagent.

Example 19-5 Starting the Messaging Gateway Agent

SQL> exec DBMS_MGWADM.STARTUP;
SQL> exec DBMS_MGWADM.STARTUP ('myagent');

You can use the MGW_GATEWAY view to check the status of the Messaging Gateway agent, as described in Chapter 21, "Monitoring Oracle Messaging Gateway".

Shutting Down the Oracle Messaging Gateway Agent

You can use DBMS_MGWADM.SHUTDOWN to shut down the Messaging Gateway agent. Example 19-6 shows how to shut down the Messaging Gateway default agent and agent myagent.

Example 19-6 Shutting Down the Messaging Gateway Agent

SQL> exec DBMS_MGWADM.SHUTDOWN;
SQL> exec DBMS_MGWADM.SHUTDOWN ('myagent');

You can use the MGW_GATEWAY view to check if the Messaging Gateway agent has shut down successfully, as described in Chapter 21, "Monitoring Oracle Messaging Gateway".

Oracle Messaging Gateway Agent Scheduler Job

Messaging Gateway uses a Scheduler job to start the Messaging Gateway agent. This job is created when procedure DBMS_MGWADM.STARTUP is called. When the job is run, it calls an external procedure that creates the Messaging Gateway agent in an external process. The job is removed after:

  • The agent shuts down because DBMS_MGWADM.SHUTDOWN was called

  • The agent terminates because a non-restartable error occurs

Messaging Gateway uses DBMS_SCHEDULER to create a repeatable Scheduler job with a repeat interval of one minute. The job is owned by SYS. A repeatable job enables the Messaging Gateway agent to restart automatically when a given job instance ends because of a database shutdown, database malfunction, or a restartable error. Only one instance of a Messaging Gateway agent job runs at a given time.

Each agent uses a Scheduler job class to specify the service affinity for the agent's Scheduler job. The job class will be configured with the database service specified by DBMS_MGWADM.CREATE_AGENT or DBMS_MGWADM.ALTER_AGENT. A database administrator is responsible for setting up the database service. If no database service is specified, the default database service that maps to every instance is used.

The name of the Scheduler job class used by the Messaging Gateway default agent is SYS.MGW_JOBCLS_DEFAULT_AGENT. The Scheduler job used by the default agent is SYS.MGW_JOB_DEFAULT_AGENT.

The name of the Scheduler job class used by a Messaging Gateway named agent is SYS.MGW_JOBCLS_<agent_name>. The Scheduler job used by a named agent is SYS.MGW_JOB_<agent_name>.

If the agent job encounters an error, then the error is classified as either a restartable error or non-restartable error. A restartable error indicates a problem that might go away if the agent job were to be restarted. A non-restartable error indicates a problem that is likely to persist and be encountered again if the agent job restarts. ORA-01089 (immediate shutdown in progress) and ORA-28576 (lost RPC connection to external procedure) are examples of restartable errors. ORA-06520 (error loading external library) is an example of a non-restartable error.

Messaging Gateway uses a database shutdown trigger. If the Messaging Gateway agent is running on the instance being shut down, then the trigger notifies the agent of the shutdown, and upon receipt of the notification, the agent will terminate the current run. The job scheduler will automatically schedule the job to run again at a future time.

If a Messaging Gateway agent job instance ends because of a database malfunction or a restartable error detected by the agent job, then the job will not be removed and the job scheduler will automatically schedule the job to run again at a future time.

The MGW_GATEWAY view shows the agent status, database service, and the database instance on which the Messaging Gateway agent is current running. The Oracle Scheduler views provide information about Scheduler jobs, job classes, and job run details.

Running the Oracle Messaging Gateway Agent on Oracle RAC

While the Messaging Gateway job startup and shutdown principles are the same for Oracle Real Application Clusters (Oracle RAC) and non-Oracle RAC environments, there are some things to keep in mind for a Oracle RAC environment.

A single process of each configured Messaging Gateway agent can be running, even in a Oracle RAC environment. For example, if the default agent and two named agents have been configured with an agent user, then one instance of all three agents could be running at the same time. The database service associated with each agent determines the service affinity of the agent's Scheduler job, and thus, the database instance on which the agent process can run.

When a database instance is shut down in a Oracle RAC environment, the Messaging Gateway shutdown trigger will notify the agent to shut down only if the Messaging Gateway agent is running on the instance being shut down. The job scheduler will automatically schedule the job to be run again at a future time, either on another instance, or if the job can only run on the instance being shut down, when that instance is restarted.

Oracle recommends that all database connections made by the Messaging Gateway agent be made to the instance on which the Messaging Gateway agent process is running. This ensures correct failover behavior in a Oracle RAC environment.

If a Messaging Gateway agent has been associated with a database service, the agent's Scheduler job will not run unless that service is current enabled on a running instance. When you shut down a database Oracle stops all services to that database and you may need to manually restart the services when you start the database.

Configuring Messaging System Links

Running as a client of non-Oracle messaging systems, the Messaging Gateway agent communicates with non-Oracle messaging systems through messaging system links. A messaging system link is a set of connections between the Messaging Gateway agent and a non-Oracle messaging system.

To configure a messaging system link of a non-Oracle messaging system, users must provide information for the agent to make connections to the non-Oracle messaging system. Users can specify the maximum number of messaging connections.

An agent name will be associated with each messaging system link. This is done when the link is created and cannot be changed. The agent associated with the link is then responsible for processing all propagation jobs that use a registered queue associated with that link. The Messaging Gateway default agent will be used if an agent name is not specified when the messaging system link is created.

When configuring a messaging system link for a non-Oracle messaging system that supports transactions and persistent messages, the native name of log queues for inbound and outbound propagation must be specified in order to guarantee exactly-once message delivery. The log queues should be used only by the Messaging Gateway agent. No other programs should enqueue or dequeue messages of the log queues. The inbound log queue and outbound log queue can refer to the same physical queue, but better performance can be achieved if they refer to different physical queues.

One and only one Messaging Gateway agent should access a propagation log queue. This insures that a given log queue contains log records for only those propagation jobs processed by that agent and that the agent is free to discard any other log records it might encounter.

When configuring a messaging system link, users can also specify an options argument. An options argument is a set of {name, value} pairs of type SYS.MGW_PROPERTY.

This section contains these topics:

Creating a WebSphere MQ Base Java Link

A WebSphere MQ Base Java link is created by calling DBMS_MGWADM.CREATE_MSGSYSTEM_LINK with the following information provided:

  • Interface type: DBMS_MGWADM.MQSERIES_BASE_JAVA_INTERFACE

  • WebSphere MQ connection information:

    • Host name and port number of the WebSphere MQ server

    • Queue manager name

    • Channel name

    • User name and password

  • Maximum number of messaging connections allowed

  • Log queue names for inbound and outbound propagation

  • Optional information such as:

    • Send, receive, and security exits

    • Character sets

Example 19-7 configures a WebSphere MQ Base Java link mqlink. The link is configured to use the WebSphere MQ queue manager my.queue.manager on host myhost.mydomain and port 1414, using WebSphere MQ channel mychannel.

This example also sets the option to register a WebSphere MQ SendExit class. The class mySendExit must be in the CLASSPATH set in mgw.ora. The Messaging Gateway default agent (DEFAULT_AGENT) is responsible for the link and all propagation jobs using the link.

Example 19-7 Configuring a WebSphere MQ Base Java Link

DECLARE
  v_options sys.mgw_properties;
  v_prop sys.mgw_mqseries_properties;
BEGIN
  v_prop := sys.mgw_mqseries_properties.construct();
  
  v_prop.interface_type := dbms_mgwadm.MQSERIES_BASE_JAVA_INTERFACE;
  v_prop.max_connections := 1;
  v_prop.username := 'mqm';
  v_prop.password := 'mqm';
  v_prop.hostname := 'myhost.mydomain';
  v_prop.port     := 1414;
  v_prop.channel  := 'mychannel';
  v_prop.queue_manager := 'my.queue.manager';
  v_prop.outbound_log_queue := 'mylogq';
  
  -- Specify a WebSphere MQ send exit class 'mySendExit' to be associated with
  -- the queue. 
  -- Note that this is used as an example of how to use the options parameter, 
  -- but is not an option that is usually set.
  v_options := sys.mgw_properties(sys.mgw_property('MQ_SendExit',
                                                   'mySendExit'));
  dbms_mgwadm.create_msgsystem_link(
      linkname => 'mqlink', agent_name=>'default_agent', properties => v_prop, 
      options => v_options );
END;

See Also:


Creating a WebSphere MQ JMS Link

A WebSphere MQ JMS link is created by calling DBMS_MGWADM.CREATE_MSGSYSTEM_LINK with the following information provided:

  • Interface type

    Java Message Service (JMS) distinguishes between queue and topic connections. The Sun Microsystem JMS 1.1 standard supports domain unification that allows both JMS queues and topics to be accessed by a single JMS connection:

    • A WebSphere MQ JMS link created with interface type DBMS_MGWADM.JMS_CONNECTION can be used to access both JMS queues and topics. This is the recommended interface for a WebSphere MQ JMS link.

    • A WebSphere MQ JMS link created with interface type DBMS_MGWADM.JMS_QUEUE_CONNECTION can be used to access only JMS queues.

    • A WebSphere MQ JMS link created with interface type DBMS_MGWADM.JMS_TOPIC_CONNECTION can be used to access only JMS topics.

  • WebSphere MQ connection information:

    • Host name and port number of the WebSphere MQ server

    • Queue manager name

    • Channel name

    • User name and password

  • Maximum number of messaging connections allowed

    A messaging connection is mapped to a JMS session.

  • Log destination (JMS queue or JMS topic) for inbound and outbound propagation

    The log destination type must be valid for the link type. JMS unified links and JMS queue links must use JMS queues for log destinations, and JMS topic links must use topics:

    • For a WebSphere MQ JMS unified or queue link, the log queue name must be the name of a physical WebSphere MQ JMS queue created using WebSphere MQ administration tools.

    • For a WebSphere MQ JMS topic link, the log topic name must be the name of a WebSphere MQ JMS topic. The physical WebSphere MQ queue used by that topic must be created using WebSphere MQ administration tools. By default, the physical queue used is SYSTEM.JMS.D.SUBSCRIBER.QUEUE. A link option can be used to specify a different physical queue.

  • Optional information such as:

    • Send, receive, and security exits

    • Character sets

    • WebSphere MQ publish/subscribe configuration used for JMS topics

Example 19-8 configures a Messaging Gateway link to a WebSphere MQ queue manager using a JMS topic interface. The link is named mqjmslink and is configured to use the WebSphere MQ queue manager my.queue.manager on host myhost.mydomain and port 1414, using WebSphere MQ channel mychannel.

This example also uses the options parameter to specify a nondefault durable subscriber queue to be used with the log topic. The Messaging Gateway agent myagent is responsible for the link and all propagation jobs using the link.

Example 19-8 Configuring a WebSphere MQ JMS Link

DECLARE
  v_options sys.mgw_properties;
  v_prop sys.mgw_mqseries_properties;
BEGIN
  v_prop := sys.mgw_mqseries_properties.construct();
  v_prop.max_connections := 1;
  
  v_prop.interface_type := DBMS_MGWADM.JMS_TOPIC_CONNECTION;
  v_prop.username := 'mqm';
  v_prop.password := 'mqm';
  v_prop.hostname := 'myhost.mydomain';
  v_prop.port     := 1414;
  v_prop.channel  := 'mychannel';
  v_prop.queue_manager := 'my.queue.manager'; 
  
  v_prop.outbound_log_queue := 'mylogtopic' 
  
  -- Specify a WebSphere MQ durable subscriber queue to be used with the
  -- log topic.
  v_options := sys.mgw_properties(
  sys.mgw_property('MQ_JMSDurSubQueue', 'myDSQueue'));
  
  DBMS_MGWADM.CREATE_MSGSYSTEM_LINK(
      linkname     =>  'mqjmslink', 
      agent_name   =>  'myagent',
      properties   =>   v_prop, 
      options      =>   v_options );
END;

See Also:


Creating a WebSphere MQ Link to Use SSL

Messaging Gateway allows SSL support for IBM WebSphere MQ and WebSphere MQ JMS connections. This section describes how to configure Messaging Gateway to use SSL for a WebSphere MQ Base Java link and the same information applies to a WebSphere MQ JMS link. There are no differences in terms of the Messaging Gateway configuration.

The following are needed in order to use SSL for WebSphere MQ connections:

  • A WebSphere MQ channel configured to use SSL.

  • A truststore and optionally a keystore file that are in a location accessible to the Messaging Gateway agent process. In a Oracle RAC environment, these files must be accessible to all instances on which the Messaging Gateway agent process might run, using the same path specification.

  • Use DBMS_MGWADM.CREATE_MSGSYSTEM_LINK to create a WebSphere MQ link with the desired SSL related link options. At minimum, the MQ_SSLCIPHERSUITE property should be set to specify the SSL ciphersuite used by the channel.

  • Use DBMS_MGWADM.SET_OPTION to set certain JSSE Java properties for the Messaging Gateway agent assigned to the link.

JSEE related properties:

  • java.net.ssl.keyStore

    This property is used to specify the location of the keystore. A keystore is a database of key material used for various purposes, including authentication and data integrity.

  • java.net.ssl.keyStorePassword

    This property is used to specify the password of the keystore. This password is used to check the integrity of the data in the keystore before accessing it.

  • java.net.ssl.trustStore

    This property is used to specify the location of the truststore. A truststore is a keystore that is used when making decisions about which clients and servers are trusted.

  • java.net.ssl.trustStorePassword

    This property is used to specify the password of the truststore. This password is used to check the integrity of the data in the truststore before accessing it.

The java.net.ssl.keyStore and java.net.ssl.keyStorePassword properties are only needed if the WebSphere MQ channel is configured to use SSL client authentication.

Example 19-9 configures a WebSphere MQ Base Java link mqssllink to use SSL connections using the SSL_RSA_WITH_RC4_128_MD5 ciphersuite. It assumes the channel has been configured for SSL client authentication so the Messaging Gateway agent associated with the link, DEFAULT_AGENT, is configured with Java properties for both a keystore and a truststore.

This configuration should be done when the Messaging Gateway agent is shut down since the Java properties set by DBMS_MGWADM.SET_OPTION are set only when the agent first starts. If the agent is running when the configuration is done it will need to be shutdown and restarted before the SSL connections will be used.

Example 19-9 Configuring a WebSphere MQ Base Java Link for SSL

DECLARE
  v_options sys.mgw_properties;
  v_prop sys.mgw_mqseries_properties;
  v_agent varchar2(30) := 'default_agent';
BEGIN
     v_prop := sys.mgw_mqseries_properties.construct();
     v_prop.interface_type := DBMS_MGWADM.MQSERIES_BASE_JAVA_INTERFACE;
     v_prop.max_connections := 1;
     v_prop.username := 'mqm';
     v_prop.password := 'mqm';
     v_prop.hostname := 'myhost.mydomain';
     v_prop.port := 1414;
     v_prop.channel := 'mysslchannel';
     v_prop.queue_manager := 'my.queue.manager';
     v_prop.outbound_log_queue := 'mylogq';
    
   -- specify the SSL ciphersuite
     v_options := sys.mgw_properties(
        sys.mgw_property('MQ_SSLCIPHERSUITE','SSL_RSA_WITH_RC4_128_MD5') );
 
     -- create the MQSeries link
    DBMS_MGWADM.CREATE_MSGSYSTEM_LINK(linkname => 'mqssllink', 
                                    agent_name => v_agent, 
                                    properties => v_prop, 
                                    options => v_options);
 
   -- set Java properties for the agent that specify the JSSE security
   -- properties for the keystore and truststore; the paths will be 
   -- saved as cleartext and the passwords encrypted
 
   DBMS_MGWADM.SET_OPTION(target_type  => DBMS_MGWADM.AGENT_JAVA_PROP,
                       target_name  => v_agent,
                       option_name  => 'javax.net.ssl.keyStore',
                       option_value => '/tmp/mq_ssl/key.jks',
                       encrypted    => false);

   DBMS_MGWADM.SET_OPTION(target_type  => DBMS_MGWADM.AGENT_JAVA_PROP,
                       target_name  => v_agent,
                       option_name  => 'javax.net.ssl.keyStorePassword',
                       option_value => 'welcome',
                       encrypted    => true);

   DBMS_MGWADM.SET_OPTION(target_type  => DBMS_MGWADM.AGENT_JAVA_PROP,
                       target_name  => v_agent,
                       option_name  => 'javax.net.ssl.trustStore',
                       option_value => '/tmp/mq_ssl/trust.jks',
                       encrypted    => false);

   DBMS_MGWADM.SET_OPTION(target_type  => DBMS_MGWADM.AGENT_JAVA_PROP,
                       target_name  => v_agent,
                       option_name  => 'javax.net.ssl.trustStorePassword',
                       option_value => 'welcome',
                       encrypted    => true);
END;

Creating a TIB/Rendezvous Link

A TIB/Rendezvous link is created by calling DBMS_MGWADM.CREATE_MSGSYSTEM_LINK with three parameters (service, network and daemon) for the agent to create a corresponding transport of TibrvRvdTransport type.

A TIB/Rendezvous message system link does not need propagation log queues. Logging information is stored in memory. Therefore, Messaging Gateway can only guarantee at-most-once message delivery.

Example 19-10 configures a TIB/Rendezvous link named rvlink that connects to the rvd daemon on the local computer. An agent name is not specified for the link so the Messaging Gateway default agent (DEFAULT_AGENT) is responsible for the link and all propagation jobs using the link.

Example 19-10 Configuring a TIB/Rendezvous Link

DECLARE
  v_options sys.mgw_properties;
  v_prop     sys.mgw_tibrv_properties;
BEGIN
  v_prop := sys.mgw_tibrv_properties.construct();
  
  DBMS_MGWADM.CREATE_MSGSYSTEM_LINK(linkname => 'rvlink', properties => v_prop);
END;

Altering a Messaging System Link

Using DBMS_MGWADM.ALTER_MSGSYSTEM_LINK, you can alter some link information after the link is created. You can alter link information with the Messaging Gateway agent running or shut down. Example 19-11 alters the link mqlink to change the max_connections property.

Example 19-11 Altering a WebSphere MQ Link

DECLARE
  v_options sys.mgw_properties;
  v_prop sys.mgw_mqseries_properties;
BEGIN
  -- use alter_construct() for initialization
  v_prop := sys.mgw_mqseries_properties.alter_construct();
  v_prop.max_connections := 2;
  
  DBMS_MGWADM.ALTER_MSGSYSTEM_LINK(
    linkname => 'mqlink', properties => v_prop);
END;

See Also:

"Configuration Properties" for restrictions on changes when the Messaging Gateway agent is running

Removing a Messaging System Link

You can remove a Messaging Gateway link to a non-Oracle messaging system with DBMS_MGWADM.REMOVE_MSGSYSTEM_LINK, but only if all registered queues associated with this link have already been unregistered. The link can be removed with the Messaging Gateway agent running or shut down. Example 19-12 removes the link mqlink.

Example 19-12 Removing a Messaging Gateway Link

BEGIN
  dbms_mgwadm.remove_msgsystem_link(linkname =>'mqlink');
END;

Views for Messaging System Links

You can use the MGW_LINKS view to check links that have been created. It lists the name and link type, as shown in Example 19-13.

Example 19-13 Listing All Messaging Gateway Links

SQL> select link_name, link_type from MGW_LINKS;
 
LINK_NAME     LINK_TYPE 
------------------------
MQLINK        MQSERIES
RVLINK        TIBRV

You can use the MGW_MQSERIES_LINKS and MGW_TIBRV_LINKS views to check messaging system type-specific configuration information, as shown in Example 19-14.

Example 19-14 Checking Messaging System Link Configuration Information

SQL> select link_name, queue_manager, channel, hostname from mgw_mqseries_links;
 
LINK_NAME   QUEUE_MANAGER      CHANNEL     HOSTNAME
----------------------------------------------------------
MQLINK      my.queue.manager  mychannel  myhost.mydomain
 
SQL> select link_name, service, network, daemon from mgw_tibrv_links;
 
LINK_NAME   SERVICE      NETWORK     DAEMON
-----------------------------------------------------
RVLINK 

Configuring Non-Oracle Messaging System Queues

All non-Oracle messaging system queues involved in propagation as a source queue, destination queue, or exception queue must be registered through the Messaging Gateway administration interface. You do not need to register Oracle Streams Advanced Queuing queues involved in propagation.

This section contains these topics:

Registering a Non-Oracle Queue

You can register a non-Oracle queue using DBMS_MGWADM.REGISTER_FOREIGN_QUEUE. Registering a non-Oracle queue provides information for the Messaging Gateway agent to access the queue. However, it does not create the physical queue in the non-Oracle messaging system. The physical queue must be created using the non-Oracle messaging system administration interfaces before the Messaging Gateway agent accesses the queue.

The following information is used to register a non-Oracle queue:

  • Name of the messaging system link used to access the queue

  • Native name of the queue (its name in the non-Oracle messaging system)

  • Domain of the queue

    • DBMS_MGWADM.DOMAIN_QUEUE for a point-to-point queue

    • DBMS_MGWADM.DOMAIN_TOPIC for a publish/subscribe queue

  • Options specific to the non-Oracle messaging system

    These options are a set of {name, value} pairs, both of which are strings.

Example 19-15 shows how to register the WebSphere MQ Base Java queue my_mq_queue as a Messaging Gateway queue destq.

Example 19-15 Registering a WebSphere MQ Base Java Queue

BEGIN
  DBMS_MGWADM.REGISTER_FOREIGN_QUEUE(
    name            => 'destq',
    linkname        => 'mqlink',
    provider_queue  => 'my_mq_queue',
    domain          => dbms_mgwadm.DOMAIN_QUEUE);
END;

Registering a WebSphere MQ Base Java Queue

The domain must be DBMS_MGWADM.DOMAIN_QUEUE or NULL, because only point-to-point queues are supported for WebSphere MQ.

Registering a WebSphere MQ JMS Queue or Topic

When registering a WebSphere MQ JMS queue, the domain must be DBMS_MGWADM.DOMAIN_QUEUE, and the linkname parameter must refer to a WebSphere MQ JMS unified link or queue link.

When registering a WebSphere MQ JMS topic, the domain must be DBMS_MGWADM.DOMAIN_TOPIC, and the linkname parameter must refer to a WebSphere MQ JMS unified link or topic link. The provider_queue for a WebSphere MQ JMS topic used as a propagation source may include wildcards. See WebSphere MQ documentation for wildcard syntax.

Registering a TIB/Rendezvous Subject

When registering a TIB/Rendezvous subject with Messaging Gateway, the provider_queue parameter specifies a TIB/Rendezvous subject name. The domain of a registered TIB/Rendezvous queue must be DBMS_MGWADM.DOMAIN_TOPIC or NULL.

A registered TIB/Rendezvous queue with provider_queue set to a wildcard subject name can be used as a propagation source queue for inbound propagation. It is not recommended to use queues with wildcard subject names as propagation destination queues or exception queues. As documented in TIB/Rendezvous, sending messages to wildcard subjects can trigger unexpected behavior. However, neither Messaging Gateway nor TIB/Rendezvous prevents you from doing so.

Unregistering a Non-Oracle Queue

A non-Oracle queue can be unregistered with DBMS_MGWADM.UNREGISTER_FOREIGN_QUEUE, but only if there are no propagation jobs referencing it.

Example 19-16 unregisters the queue destq of the link mqlink.

Example 19-16 Unregistering a Non-Oracle Queue

BEGIN
  DBMS_MGWADM.UNREGISTER_FOREIGN_QUEUE(name =>'destq', linkname=>'mqlink');
END;

View for Registered Non-Oracle Queues

You can use the MGW_FOREIGN_QUEUES view to check which non-Oracle queues are registered and what link each uses, as shown in Example 19-17.

Example 19-17 Checking Which Queues Are Registered

SELECT name, link_name, provider_queue FROM MGW_FOREIGN_QUEUES;
 
NAME   LINK_NAME   PROVIDER_QUEUE
------------------------------------
DESTQ  MQLINK      my_mq_queue

Configuring Oracle Messaging Gateway Propagation Jobs

Propagating messages between an Oracle Streams AQ queue and a non-Oracle messaging system queue requires a propagation job. Each propagation job will have a unique propagation type, source, and destination triplet.

You can create a propagation job to propagate messages between JMS destinations. You can also create a propagation job to propagate messages between non-JMS queues. Messaging Gateway does not support message propagation between a JMS destination and a non-JMS queue.

This section contains these topics:

Propagation Job Overview

A propagation job specifies what messages are propagated and how the messages are propagated.

Messaging Gateway allows bidirectional message propagation. An outbound propagation moves messages from Oracle Streams Advanced Queuing to non-Oracle messaging systems. An inbound propagation moves messages from non-Oracle messaging systems to Oracle Streams Advanced Queuing.

If the propagation source is a queue (point-to-point), then the Messaging Gateway agent moves all messages from the source queue to the destination queue. If the propagation source is a topic (publish/subscribe), then the Messaging Gateway agent creates a subscriber of the propagation source queue in the messaging system. The agent only moves messages that are published to the source queue after the subscriber is created.

When propagating a message, the Messaging Gateway agent converts the message from the format in the source messaging system to the format in the destination messaging system. Users can customize the message conversion by providing a message transformation. If message conversion fails, then the message will be moved to an exception queue, if one has been provided, so that the agent can continue to propagate messages for the subscriber.

A Messaging Gateway exception queue is different from an Oracle Streams Advanced Queuing exception queue. Messaging Gateway moves a message to a Messaging Gateway exception queue when message conversion fails. Oracle Streams Advanced Queuing moves a message to an Oracle Streams Advanced Queuing exception queue after MAX_RETRIES dequeue attempts on the message.

Messages moved to an Oracle Streams Advanced Queuing exception queue may result in irrecoverable failures on the associated Messaging Gateway propagation job. To avoid the problem, the MAX_RETRIES parameter of any Oracle Streams Advanced Queuing queue that is used as the propagation source of a Messaging Gateway propagation job should be set to a value much larger than 16.

If the messaging system of the propagation source queue supports message selection, then a message selection rule can be specified for a propagation subscriber. Only messages that satisfy the message selector will be propagated.

Users can also specify propagation job options to control how messages are propagated, such as options for JMS message delivery mode and TIB/Rendezvous queue policies.

The MGW_JOBS view can be used to check the configuration and status of Messaging Gateway propagation jobs.

Creating an Oracle Messaging Gateway Propagation Job

Messaging Gateway propagation jobs are created by DBMS_MGWADM.CREATE_JOB.

If the propagation source for non-JMS propagation is an Oracle Streams AQ queue, then the queue can be either a single consumer queue or multiple consumer queue. If it is a multiple consumer queue, Messaging Gateway creates a corresponding Oracle Streams AQ subscriber MGW_job_name for the propagation job job_name when DBMS_MGWADM.CREATE_JOB is called.

If the propagation source is a JMS topic, such as an Oracle Java Message Service (OJMS) topic or a WebSphere MQ JMS topic, then a JMS subscriber MGW_job_name is created on the topic in the source messaging system by the Messaging Gateway agent. If the agent is not running, then the subscriber will not be created until the agent is restarted.

If the propagation source is a queue, then only one propagation job can be created using that queue as the propagation source. If the propagation source is a topic, then multiple propagation jobs can be set up using that topic as the propagation source with each propagation job having its own corresponding subscriber on the topic in the messaging system.

Example 19-18 creates Messaging Gateway propagation job job_aq2mq.

Example 19-18 Creating a Messaging Gateway Propagation Job

BEGIN
   DBMS_MGWADM.CREATE_JOB(
     job_name            =>  'job_aq2mq',
     propagation_type    =>   DBMS_MGWADM.OUTBOUND_PROPAGATION,
     source              =>  'mquser.srcq',
     destination         =>  'deqq@mqlink');
END;

Note:

If a WebSphere MQ JMS topic is involved in a propagation job and the interface type of the link is DBMS_MGWADM.JMS_TOPIC_CONNECTION, then a durable subscriber MGL_subscriber_id is created on the log topic. The durable subscriber is removed when the Messaging Gateway propagation job is successfully removed.

Enabling and Disabling a Propagation Job

A propagation job can be initially enabled or disabled when it is created by DBMS_MGWADM.CREATE_JOB. By default, a job is enabled when it is created. You can use DBMS_MGWADM.ENABLE_JOB to enable a propagation job and DBMS_MGWADM.DISABLE_JOB to disable a job. No propagation processing will occur when the job is disabled.

Example 19-19 enables the propagation for propagation job job_aq2mq.

Example 19-19 Enabling a Messaging Gateway Propagation Job

BEGIN
  DBMS_MGWADM.ENABLE_JOB(job_name => 'job_aq2mq');
END;

Example 19-20 disables the propagation for propagation job job_aq2mq.

Example 19-20 Disabling a Messaging Gateway Propagation Job

BEGIN
  DBMS_MGWADM.DISABLE_JOB(job_name => 'job_aq2mq');
END;

Resetting a Propagation Job

When a problem occurs with a propagation job, the Messaging Gateway agent retries the failed operation up to 16 times in an exponential backoff scheme before the propagation job stops. You can use DBMS_MGWADM.RESET_JOB to reset the failure count to zero to allow the agent to retry the failed operation immediately.

Example 19-21 resets the failure count for propagation job job_aq2mq.

Example 19-21 Resetting a Propagation Job

BEGIN
  DBMS_MGWADM.RESET_JOB (job_name => 'job_aq2mq');
END;

Altering a Propagation Job

After a propagation job is created you can alter the selection rule, transformation, exception queue, job options, and poll interval of the job using DBMS_MGWADM.ALTER_JOB. The job can be altered with the Messaging Gateway running or shut down.

Example 19-22 adds an exception queue for a propagation job.

Example 19-22 Altering Propagation Job by Adding an Exception Queue

BEGIN
    DBMS_MGWADM.ALTER_JOB(
       job_name         =>  'job_aq2mq',        exception_queue  =>  'mgwuser.my_ex_queue');
END;

Example 19-23 changes the polling interval for a propagation job. The polling interval determines how soon the agent can discover the available messages in the propagation source queue. The default polling interval is 5 seconds or the value set for oracle.mgw.polling_interval in the Messaging Gateway initialization file.

Example 19-23 Altering Propagation Job by Changing the Polling Interval

BEGIN
    DBMS_MGWADM.ALTER_JOB(
        job_name       =>  'job_aq2mq',         poll_interval  =>  2);
END;

Removing a Propagation Job

You can remove a Messaging Gateway propagation job by calling DBMS_MGWADM.REMOVE_JOB.

Before removing the propagation job from the Messaging Gateway configuration, Messaging Gateway does the following cleanup:

  • Removes from the messaging system the associated subscriber that may have been created by Messaging Gateway

  • Removes propagation log records from log queues for the job being removed

Messaging Gateway may fail to do the cleanup because:

  • The Messaging Gateway agent is not running

  • Non-Oracle messaging system is not running

  • The Messaging Gateway agent is unable to interact with the source or destination messaging system

If the Messaging Gateway cleanup fails for any reason, then the propagation job being removed is placed in a DELETE_PENDING state. The Messaging Gateway agent tries to clean up propagation jobs in a DELETE_PENDING state when:

  • DBMS_MGWADM.REMOVE_JOB is called and the Messaging Gateway agent is running.

  • The Messaging Gateway agent is starting and finds a propagation job in a DELETE_PENDING state.

DBMS_MGWADM.REMOVE_JOB has a force parameter that allows you to force the propagation job to be removed from the Messaging Gateway configuration without placing it in DELETE_PENDING state. This is useful in case of cleanup failures or if you want to remove a propagation job when the Messaging Gateway agent is not running.

Forcing a propagation job to be removed may result in obsolete log records being left in the log queues, and subscriptions in the messaging systems that may cause unnecessary message accumulation. Oracle recommends that the force option not be used for DBMS_MGWADM.REMOVE_JOB if possible.

Example 19-24 removes a propagation job in a non-forced manner.

Example 19-24 Removing a Propagation Job

BEGIN
    DBMS_MGWADM.REMOVE_JOB (job_name  =>  'job_aq2mq');
END;

Propagation Jobs, Subscribers, and Schedules

Subprograms are provided as part of the DBMS_MGWADM package that simplify the creation and management of propagation jobs. Those subprograms allow a user to configure a propagation job rather than a disjoint subscriber and schedule as was done in prior releases. Oracle recommends that you use the propagation job procedures but still supports the subscriber and schedule procedures for backward compatibility.

Table 19-1 lists the Messaging Gateway propagation job procedures and shows which subscriber and/or schedule procedures it replaces. All procedures are from the DBMS_MGWADM package.

Table 19-1 Messaging Gateway Propagation Job Subprograms

Job ProcedureReplaces Subscriber, Schedule Procedure

CREATE_JOB

ADD_SUBSCRIBER, SCHEDULE_PROPAGATION

ALTER_JOB

ALTER_SUBSCRIBER, ALTER_PROPAGATION_SCHEDULE

REMOVE_JOB

REMOVE_SUBSCRIBER, UNSCHEDULE_PROPAGATION

ENABLE_JOB

ENABLE_PROPAGATION_SCHEDULE

DISABLE_JOB

DISABLE_PROPAGATION_SCHEDULE

RESET_JOB

RESET_SUBSCRIBER


This section contains the following topics:

Propagation Job, Subscriber, Schedule Interface Interoperability

The user can create two types of propagation jobs, a new style job or an old style job. A new style job is created by DBMS_MGWADM.CREATE_JOB. An old style job is created by calling DBMS_MGWADM.ADD_SUBSCRIBER and DBMS_MGWADM.SCHEDULE_PROPAGATION using the same {propagation_type, source, destination} triplet. A subscriber that does not have a matching schedule, or a schedule that does not have a matching subscriber, is not considered to be a propagation job.

For new style job, the job name will serve as both the subscriber ID and the schedule ID. For an old style job, the subscriber ID is used as the job name.

Both the propagation job subprograms and the subscriber/schedule subprograms can be used for old style propagation jobs. Oracle recommends that you use the job subprograms to create and manage propagation jobs. The job subprograms cannot be used for an unmatched subscriber or schedule since those do not constitute a propagation job.

Only the new job subprograms can be used for new style propagation jobs. An error will occur if a user tries to call a subscriber or scheduler procedure on a new style job.

Other than DBMS_MGWADM.REMOVE_JOB, calling the job subprograms for an old style job is straightforward and the results are effectively the same as calling the corresponding subscriber/schedule subprograms. There may be certain restrictions in the future but there are none at this time.

The DBMS_MGWADM.REMOVE_JOB procedure can be used to remove both new style and old style jobs. A forced and non-forced remove is supported. If the Messaging Gateway agent is not running when a non-forced remove is done, the job will be flagged as delete pending and neither the underlying subscriber nor schedule will be removed at that time. The job (subscriber /schedule pair) will be removed once the agent is restarted and performs its cleanup work or a forced DBMS_MGWADM.REMOVE_JOB is performed. In order to insure that the subscriber/schedule pair is removed at the same time, an error will occur if you first call DBMS_MGWADM.REMOVE_JOB and subsequently attempt to call DBMS_MGWADM.REMOVE_SUBSCRIBER or DBMS_MGWADM.UNSCHEDULE_PROPAGATION for an old style job.

Once DBMS_MGWADM.REMOVE_JOB as been called for a job and it has been flagged as delete pending, all job procedures, other than DBMS_MGWADM.REMOVE_JOB, will fail for both new style and old style jobs. In addition, all subscriber and schedule subprograms will fail if the propagation job happens to be an old style job.DBMS_MGWADM.REMOVE_SUBSCRIBER and DBMS_MGWADM.UNSCHEDULE_PROPAGATION can be used for an old style job as long as DBMS_MGWADM.REMOVE_JOB has not been called for that job. If DBMS_MGWADM.UNSCHEDULE_PROPAGATION is called for an old style job, the schedule is immediately removed and it ceases to be a propagation job and DBMS_MGWADM.REMOVE_SUSCRIBER must be used to remove the subscriber. If DBMS_MGWADM.REMOVE_SUBSCRIBER is called for an old style job, the user can subsequently call DBMS_MGWADM.REMOVE_JOB as long as the subscriber exists.

Propagation Job, Subscriber, Schedule Views

The MGW_JOBS view shows information for the current propagation jobs, both new style jobs and old style jobs, and includes all the pertinent information shown by the MGW_SUBSCRIBERS and MGW_SCHEDULES views. The MGW_SUBSCRIBERS and MGW_SCHEDULES views are still useful for finding an unmatched subscriber or schedule since they don't constitute a propagation job and will not show up in the MGW_JOBS view.

Single Consumer Queue As Propagation Source

Messaging Gateway allows an Oracle Streams AQ multiple consumer queue or a single consumer queue to be a propagation source for an outbound new style job created by DBMS_MGWADM.CREATE_JOB. A multiple consumer queue must be used for the propagation source for an outbound old style job. An error will occur if an administrator attempts to call DBMS_MGWADM.ADD_SUBSCRIBER and the source is a single consumer queue.

An Oracle Streams AQ dequeue condition is not supported for native (non-JMS) outbound propagation when the propagation source is a single consumer queue.

Configuration Properties

This section summarizes basic and optional properties related to Messaging Gateway links, foreign queues, and propagation jobs.

This section contains these topics:

WebSphere MQ System Properties

Table 19-2 summarizes the basic configuration properties for a WebSphere MQ messaging link. The table indicates which properties of SYS.MGW_MQSERIES_PROPERTIES are optional (NULL allowed), which can be altered, and if alterable, which values can be dynamically changed.


See Also:

"SYS.MGW_MQSERIES_PROPERTIES Type" in Oracle Database PL/SQL Packages and Types Reference

Table 19-2 WebSphere MQ Link Properties

AttributeNULL Allowed?Alter Value?Dynamic?

queue_manager

no

no

no

hostname

yes (1)

no

no

port

yes (1)

no

no

channel

yes (1), (6)

yes

no

interface_type

yes (2)

no

no

max_connections

yes (3)

yes

yes

username

yes

yes

yes

password

yes

yes

yes

inbound_log_queue

yes (4)

yes(4)

yes

outbound_log_queue

yes (5)

yes(5)

yes


Notes on Table 19-2

  1. If hostname is NULL, then the port and channel must be NULL. If the hostname is not NULL, then the port must be not NULL. If the hostname is NULL, then a WebSphere MQ bindings connection is used; otherwise a client connection is used.

  2. If interface_type is NULL, then a default value of DBMS_MGWADM.MQSERIES_BASE_JAVA_INTERFACE is used.

  3. If max_connections is NULL, then a default value of 1 is used.

  4. Attribute inbound_log_queue can be NULL if the link is not used for inbound propagation. The log queue can be altered only when no inbound propagation job references the link.

  5. Attribute outbound_log_queue can be NULL if the link is not used for outbound propagation. The log queue can be altered only when no outbound propagation job references the link.

  6. The channel attribute must be NULL if a client channel definition table (CCDT) is used. The MQ_ccdtURL link option can be used to specify a CCDT.

Table 19-3 summarizes the optional configuration properties supported when a WebSphere MQ Base Java interface is used to access the WebSphere MQ messaging system. Table 19-4 summarizes the optional configuration properties supported when a WebSphere MQ JMS interface is used. Each table lists the property name, where that property applies, whether the property can be altered, and if alterable, whether the value can be dynamically changed. Only the properties listed in the tables are supported, and any extra properties are ignored.

Table 19-3 Optional Configuration Properties for WebSphere MQ Base Java

Property NameUsed ForAlter Value?Dynamic?

MQ_ccdtUrl


link

yes

no

MQ_ccsid


link

yes

no

MQ_ReceiveExit


link

yes

no

MQ_SecurityExit


link

yes

no

MQ_SendExit


link

yes

no

MQ_SSLCipherSuite


link

yes

no

MQ_SSLFipsRequired


link

yes

no

MQ_SSLPeerName


link

yes

no

MQ_SSLResetCount


link

yes

no

MQ_openOptions


foreign queue

no

no

MsgBatchSize


job

yes

yes

PreserveMessageID


job

yes

yes


Table 19-4 Optional Configuration Properties for WebSphere MQ JMS

Property NameUsed ForAlter Value?Dynamic?

MQ_BrokerControlQueue


link

yes

no

MQ_BrokerPubQueue


link

yes

no

MQ_BrokerQueueManager


link

yes

no

MQ_BrokerVersion


link

yes

no

MQ_ccdtUrl


link

yes

no

MQ_ccsid


link

yes

no

MQ_JmsDurSubQueue


link

no

no

MQ_PubAckInterval


link

yes

no

MQ_ReceiveExit


link

yes

no

MQ_ReceiveExitInit


link

yes

no

MQ_SecurityExit


link

yes

no

MQ_SecurityExitInit


link

yes

no

MQ_SendExit


link

yes

no

MQ_SendExitInit


link

yes

no

MQ_SSLCipherSuite


link

yes

no

MQ_SSLCrl


link

yes

no

MQ_SSLFipsRequired


link

yes

no

MQ_SSLPeerName


link

yes

no

<p/td>

MQ_SSLResetCount


link

yes

no

MQ_CharacterSet


foreign queue

no

no

MQ_JmsDurSubQueue


foreign queue

no

no

MQ_JmsTargetClient


foreign queue

no

no

JMS_DeliveryMode


job

yes

yes

JMS_NoLocal


job

no

no

MsgBatchSize


job

yes

yes

PreserveMessageID


job

yes

yes


TIB/Rendezvous System Properties

Table 19-5 summarizes the basic configuration properties for a TIB/Rendezvous messaging link. It indicates which properties of SYS.MGW_TIBRV_PROPERTIES are optional (NULL allowed), which can be altered, and if alterable, which values can be dynamically changed.


See Also:

"SYS.MGW_TIBRV_PROPERTIES Type" in Oracle Database PL/SQL Packages and Types Reference

Table 19-5 TIB/Rendezvous Link Properties

AttributeNULL allowed?Alter value?Dynamic?

service

yes(1)

no

no

daemon

yes(1)

no

no

network

yes(1)

no

no

cm_name

yes(2)

no

no

cm_ledger

yes(2)

no

no


Notes on Table 19-5:

  1. System default values will be used if service, daemon, or network are NULL.

  2. The cm_name and cm_ledger attributes are reserved for future use when TIB/Rendezvous certified messages are supported. At present, a NULL must be specified for these parameters when a TIB/Rendezvous link is configured.

Table 19-6 summarizes the optional configuration properties supported when a TIB/Rendezvous messaging system is used. The table lists the property name, where that property applies, whether the property can be altered, and if alterable, whether the value can be dynamically changed. Only the properties listed in the table are supported, and any extra properties will be ignored.

Table 19-6 Optional Properties for TIB/Rendezvous

Property NameUsed ForAlter Value?Dynamic?

AQ_MsgProperties


job

yes

yes

MsgBatchSize


job

yes

yes

PreserveMessageID


job

yes

yes

RV_discardAmount

job

yes

no

RV_limitPolicy


job

yes

no

RV_maxEvents


job

yes

no


Optional Link Configuration Properties

This section describes optional link properties you can specify using the options parameter of DBMS_MGWADM.CREATE_MSGSYSTEM_LINK and DBMS_MGWADM.ALTER_MSGSYSTEM_LINK. Each listing also indicates which messaging system might use that property.

MQ_BrokerControlQueue

This property is used by WebSphere MQ JMS. It specifies the name of the broker control queue and corresponds to WebSphere MQ JMS administration tool property BROKERCONQ. The WebSphere MQ default is SYSTEM.BROKER.CONTROL.QUEUE.

MQ_BrokerPubQueue

This property is used by WebSphere MQ JMS. It specifies the name of the broker publish queue and corresponds to WebSphere MQ JMS administration tool property BROKERPUBQ. The WebSphere MQ default is SYSTEM.BROKER.DEFAULT.STREAM.

MQ_BrokerQueueManager

This property is used by WebSphere MQ JMS. It specifies the name of the broker queue manager and corresponds to WebSphere MQ administration tool property BROKERQMGR. If it is not set, then no default is used.

MQ_BrokerVersion

This property is used by WebSphere MQ JMS. It specifies the broker version number and corresponds to WebSphere MQ JMS administration tool property BROKERVER. The WebSphere MQ default is 0.

MQ_ccdtUrl

This property is used by WebSphere MQ Base Java and WebSphere MQ JMS. It specifies the URL string of a client channel definition table (CCDT) to be used. If not set, a CCDT is not used. If a CCDT is used, then the SYS.MGW_MQSERIES_PROPERTIES.channel link property must be NULL.

MQ_ccsid

This property is used by WebSphere MQ Base Java and WebSphere MQ JMS. It specifies the character set identifier to be used to translate information in the WebSphere MQ message header. This should be the integer value of the character set (for example, 819) rather than a descriptive string. If it is not set, then the WebSphere MQ default character set 819 is used.

MQ_JmsDurSubQueue

This property is used by WebSphere MQ JMS. It applies to WebSphere MQ JMS topic links only. The SYS.MGW_MQSERIES_PROPERITES attributes, inbound_log_queue and outbound_log_queue, specify the names of WebSphere MQ JMS topics used for propagation logging. This property specifies the name of the WebSphere MQ queue from which durable subscription messages are retrieved by the log topic subscribers. The WebSphere MQ default queue is SYSTEM.JMS.D.SUBSCRIBER.QUEUE.

MQ_PubAckInterval

This property is used by WebSphere MQ JMS. It specifies the interval, in number of messages, between publish requests that require acknowledgment from the broker and corresponds to WebSphere MQ JMS administration tool property PUBACKINT. The WebSphere MQ default is 25.

MQ_ReceiveExit

This property is used by WebSphere MQ Base Java and WebSphere MQ JMS. It specifies the fully qualified Java classname of a class implementing the MQReceiveExit interface. This class must be in the CLASSPATH of the Messaging Gateway agent. There is no default.

MQ_ReceiveExitInit

This initialization string is used by WebSphere MQ JMS. It is passed by WebSphere MQ JMS to the constructor of the class specified by MQ_ReceiveExit and corresponds to WebSphere MQ JMS administration tool property RECEXITINIT. There is no default.

MQ_SecurityExit

This property is used by WebSphere MQ Base Java and WebSphere MQ JMS. It specifies the fully qualified Java classname of a class implementing the MQSecurityExit interface. This class must be in the CLASSPATH of the Messaging Gateway agent. There is no default.

MQ_SecurityExitInit

This initialization string is used by WebSphere MQ JMS. It is passed by WebSphere MQ JMS to the constructor of the class specified by MQ_SecurityExit and corresponds to WebSphere MQ JMS administration tool property SECEXITINIT. There is no default.

MQ_SendExit

This property is used by WebSphere MQ Base Java and WebSphere MQ JMS. It specifies the fully qualified Java classname of a class implementing the MQSendExit interface. This class must be in the CLASSPATH of the Messaging Gateway agent. There is no default.

MQ_SendExitInit

This initialization string is used by WebSphere MQ JMS. It is passed by WebSphere MQ JMS to the constructor of the class specified by MQ_SendExit. It corresponds to WebSphere MQ JMS administration tool property SENDEXITINIT. There is no default.

MQ_SSLCipherSuite

This property is used by WebSphere MQ Base Java and WebSphere MQ JMS. It specifies the CipherSuite to be used; for example, SSL_RSA_WITH_RC4_128_MD5. This corresponds to the WebSphere MQ SSLCIPHERSUITE administration property.

MQ_SSLCrl

This property is used by WebSphere MQ JMS. It specifies a space-delimited list of LDAP servers that can be used for certificate revocation list (CRL) checking. If not set, no CRL checking is done. This corresponds to the WebSphere MQ SSLCRL administration property. This option is not supported for WebSphere MQ Base Java, and instead, a client channel definition table (CCDT) must be used if CRL checking is needed.

MQ_SSLFipsRequired

This property is used by WebSphere MQ Base Java and WebSphere MQ JMS. It indicates whether the CipherSuite being used is supported by the IBM Java JSSE FIPS provider (IBMSJSSEFIPS). The value should be TRUE or FALSE. The default value is FALSE. This corresponds to the WebSphere MQ SSLFIPSREQUIRED administration property.

MQ_SSLPeerName

This property is used by WebSphere MQ Base Java and WebSphere MQ JMS. It specifies a distinguished name (DN) pattern that the queue manager certificate must match in order for a connection to be established. If not set, no DN check is performed. This corresponds to the WebSphere MQ SSLPEERNAME administration property.

MQ_SSLResetCount

This property is used by WebSphere MQ Base Java and WebSphere MQ JMS. It specifies the total number of bytes sent and received before the secret key is renegotiated. If not set, the key is not renegotiated. This corresponds to the WebSphere MQ SSLRESETCOUNT administration property.

Optional Foreign Queue Configuration Properties

This section describes optional foreign queue properties that you can specify using the options parameter of DBMS_MGWADM.REGISTER_FOREIGN_QUEUE. Each listing also indicates which messaging system might use that property.

MQ_CharacterSet

This property is used by WebSphere MQ JMS. It is used only for outbound propagation to a JMS queue or topic. It specifies the character set to be used to encode text strings sent to the destination. It should be the integer value of the character set (for example, 1208) rather than a descriptive string. The default value used by Messaging Gateway is 1208 (UTF8).

MQ_JmsDurSubQueue

This property is used by WebSphere MQ JMS. It is a string representing the name of the WebSphere MQ queue from which durable subscription messages are retrieved by subscribers on this topic. It applies only to WebSphere MQ JMS topics. The WebSphere MQ default queue is SYSTEM.JMS.D.SUBSCRIBER.QUEUE.

MQ_JmsTargetClient

This property is used by WebSphere MQ JMS. It is used only for outbound propagation to a JMS queue or topic. Supported values are TRUE and FALSE. TRUE indicates that WebSphere MQ should store the message as a JMS message. FALSE indicates that WebSphere MQ should store the message in non-JMS format so that non-JMS applications can access it. Default is TRUE.

MQ_openOptions

This property is used by WebSphere MQ Base Java. It specifies the value used for the openOptions argument of the WebSphere MQ Base Java MQQueueManager.accessQueue method. No value is required. But if one is given, then the Messaging Gateway agent adds MQOO_OUTPUT to the specified value for an enqueue (put) operation. MQOO_INPUT_SHARED is added for a dequeue (get) operation. The default is MQOO_OUTPUT for an enqueue/put operation; MQOO_INPUT_SHARED for a dequeue/get operation.

Optional Job Configuration Properties

This section describes optional propagation job properties that you can specify using the options parameter of DBMS_MGWADM.CREATE_JOB and DBMS_MGWADM.ALTER_JOB.

AQ_MsgProperties

This property is used by TIB/Rendezvous. It specifies how Oracle Streams AQ message properties will be used during message propagation. Supported values are TRUE and FALSE. The default value is FALSE.

For an outbound propagation job, if the value is TRUE (case insensitive), then the Messaging Gateway agent will add a field for most Oracle Streams AQ message properties to the message propagated to the TIB/Rendezvous subject.

For an inbound propagation job, if the value is TRUE (case insensitive), then the Messaging Gateway agent will search the source message for a field with a reserved name, and if it exists, use its value to set the corresponding Oracle Streams AQ message property. A default value will be used if the field does not exist or does not have an expected datatype.

JMS_DeliveryMode

This property is used by WebSphere MQ JMS and Oracle JMS. You can use this property when the propagation destination is a JMS messaging system. It sets the delivery mode of messages enqueued to the propagation destination queue by a JMS MessageProducer. The default is PRESERVE_MSG. Supported values and their associated delivery modes are:

  • PERSISTENT (DeliveryMode.PERSISTENT)

  • NON_PERSISTENT (DeliveryMode.NON_PERSISTENT)

  • PRESERVE_MSG (delivery mode of the source JMS message is used)

JMS_NoLocal

This property is used by WebSphere MQ JMS and Oracle JMS. You can use it when the propagation source is a JMS messaging system. It sets the noLocal parameter of a JMS TopicSubscriber. TRUE indicates that messages that have been published to this topic through the same Messaging Gateway link will not be propagated. The default value FALSE indicates that such messages will be propagated from the topic.

MsgBatchSize

This property can be used by any supported messaging system. It specifies the maximum number of messages, if available, to be propagated in one transaction. The default is 30.

PreserveMessageID

This property is used by WebSphere MQ Base Java, WebSphere MQ JMS, TIB/Rendezvous, and Oracle JMS. It specifies whether Messaging Gateway should preserve the original message identifier when the message is propagated to the destination messaging system. The exact details depend on the capabilities of the messaging systems involved. Supported values are TRUE and FALSE. The default value is FALSE.

RV_discardAmount

This property is used by TIB/Rendezvous. It specifies the discard amount of a queue. It is meaningful only for an inbound propagation job. The default is 0.

RV_limitPolicy

This property is used by TIB/Rendezvous. It specifies the limit policy for resolving overflow of a queue limit. It is meaningful only for an inbound propagation job. The default is DISCARD_NONE. Supported values and their associated limit policies are: DISCARD_NONE, DISCARD_FIRST, DISCARD_LAST and DISCARD_NEW.

  • DISCARD_NONE (TibrvQueue.DISCARD_NONE)

  • DISCARD_FIRST (TibrvQueue.DISCARD_FIRST)

  • DISCARD_LAST (TibrvQueue.DISCARD_LAST)

  • DISCARD_NEW (TibrvQueue.DISCARD_NEW)

RV_maxEvents

This property is used by TIB/Rendezvous. It specifies the maximum event limit of a queue. It is meaningful only for an inbound propagation job. The default is 0.

PK_,PK-AOEBPS/perform.htmwI Oracle Streams Advanced Queuing Performance and Scalability

5 Oracle Streams Advanced Queuing Performance and Scalability

This chapter discusses performance and scalability issues relating to Oracle Streams Advanced Queuing (AQ).

This chapter contains the following topics:

Persistent Messaging Performance Overview

When persistent messages are enqueued, they are stored in database tables. The performance characteristics of queue operations on persistent messages are similar to underlying database operations. The code path of an enqueue operation is comparable to SELECT and INSERT into a multicolumn queue table with three index-organized tables. The code path of a dequeue operation is comparable to a SELECT operation on the multi-column table and a DELETE operation on the dequeue index-organized table. In many scenarios, for example when Oracle Real Application Clusters (Oracle RAC) is not used and there is adequate streams pool memory, the dequeue operation is optimized and is comparable to a SELECT operation on a multi-column table.


Note:

Performance is not affected by the number of queues in a table.

Oracle Streams Advanced Queuing and Oracle Real Application Clusters

Oracle Real Application Clusters (Oracle RAC) can be used to ensure highly available access to queue data. The entry and exit points of a queue, commonly called its tail and head respectively, can be extreme hot spots. Because Oracle RAC may not scale well in the presence of hot spots, limit usual access to a queue from one instance only. If an instance failure occurs, then messages managed by the failed instance can be processed immediately by one of the surviving instances.

You can associate Oracle RAC instance affinities with 8.1-compatible queue tables. If you are using q1 and q2 in different instances, then you can use ALTER_QUEUE_TABLE or CREATE_QUEUE_TABLE on the queue table and set primary_instance to the appropriate instance_id.

Oracle Streams Advanced Queuing in a Shared Server Environment

Queue operation scalability is similar to the underlying database operation scalability. If a dequeue operation with wait option is applied, then it does not return until it is successful or the wait period has expired. In a shared server environment, the shared server process is dedicated to the dequeue operation for the duration of the call, including the wait time. The presence of many such processes can cause severe performance and scalability problems and can result in deadlocking the shared server processes. For this reason, Oracle recommends that dequeue requests with wait option be applied using dedicated server processes. This restriction is not enforced.


See Also:

"DEQUEUE_OPTIONS_T Type" in Oracle Database PL/SQL Packages and Types Reference for more information on the wait option

Persistent Messaging Basic Tuning Tips

Oracle Streams Advanced Queuing table layout is similar to a layout with ordinary database tables and indexes.


See Also:

Oracle Database Performance Tuning Guide for tuning recommendations

Memory Requirements

Streams pool size should be at least 20 MB for optimal multi-consumer dequeue performance in a non-RACdatabase. Persistent queuing dequeue operations use the streams pool to optimize performance, especially under concurrency situations. This is, however, not a requirement and the code automatically switches to a less optimal code path.

Using Storage Parameters

Storage parameters can be specified when creating a queue table using the storage_clause parameter. Storage parameters are inherited by other IOTs and tables created with the queue table. The tablespace of the queue table should have sufficient space to accommodate data from all the objects associated with the queue table. With retention specified, the history table as well as the queue table can grow to be quite big.

Oracle recommends you use automatic segment-space management (ASSM). Otherwise initrans, freelists and freelist groups must be tuned for AQ performance under high concurrency.

Increasing PCTFREE will reduce the number of messages in a queue table/IOT block. This will reduce block level contention when there is concurrency.

Storage parameters specified at queue table creation are shared by the queue table, IOTs and indexes. These may be individually altered by an online redefinition using DBMS_REDEFINTION.

I/O Configuration

Because Oracle Streams Advanced Queuing is very I/O intensive, you will usually need to tune I/O to remove any bottlenecks.


See Also:

"I/O Configuration and Design" in Oracle Database Performance Tuning Guide

Running Enqueue and Dequeue Processes Concurrently in a Single Queue Table

Some environments must process messages in a constant flow, requiring that enqueue and dequeue processes run concurrently. If the message delivery system has only one queue table and one queue, then all processes must work on the same segment area at the same time. This precludes reasonable performance levels when delivering a high number of messages.

The best number for concurrent processes depends on available system resources. For example, on a four-CPU system, it is reasonable to start with two concurrent enqueue and two concurrent dequeue processes. If the system cannot deliver the wanted number of messages, then use several subscribers for load balancing rather than increasing the number of processes.

Tune the enqueue and dequeue rates on the queue so that in the common case the queue size remains small and bounded. A queue that grows and shrinks considerably will have indexes and IOTs that are out of balance, which will affect performance.

With multi-consumer queues, using several subscribers for load balancing rather than increasing the number of processes will reduce contention. Multiple queue tables may be used garnering horizontal scalability.

Running Enqueue and Dequeue Processes Serially in a Single Queue Table

When enqueue and dequeue processes are running serially, contention on the same data segment is lower than in the case of concurrent processes. The total time taken to deliver messages by the system, however, is longer than when they run concurrently. Increasing the number of processes helps both enqueuing and dequeuing. The message throughput rate may be higher for enqueuers than for dequeuers when the number of processes is increased, especially with single consumer queues. Dequeue processes on multi-consumer queues scale much better.

Creating Indexes on a Queue Table

Creating an index on a queue table is useful if you:

  • Dequeue using correlation ID

    An index created on the column corr_id of the underlying queue table AQ$_QueueTableName expedites dequeues.

  • Dequeue using a condition

    This is like adding the condition to the where-clause for the SELECT on the underlying queue table. An index on QueueTableName expedites performance on this SELECT statement.

Other Tips

  • Ensure that statistics are being gathered so that the optimal query plans for retrieving messages are being chosen. By default, queue tables are locked out from automatic gathering of statistics. The recommended use is to gather statistics with a representative queue message load and lock them.

  • The queue table indexes and IOTs are automatically coalesced by AQ background processes. However, they must continue to be monitored and coalesced if needed. In 10.2, with automatic space segment management (ASSM), an online shrink operation may be used for the same purpose. A well balanced index reduces queue monitor CPU consumption, and ensures optimal enqueue-dequeue performance.

  • Ensure that there are enough queue monitor processes running to perform the background tasks. The queue monitor must also be running for other crucial background activity. Multiple qmn processes share the load; make sure that there are enough of them. These are auto-tuned, but can be forced to a minimum number, if needed.

  • It is recommended that dequeue with a wait time is only used with dedicated server processes. In a shared server environment, the shared server process is dedicated to the dequeue operation for the duration of the call, including the wait time. The presence of many such processes can cause severe performance and scalability problems and can result in deadlocking the shared server processes.

  • Long running dequeue transactions worsen dequeue contention on the queue, and must be avoided.

  • Batching multiple dequeue operations on multi-consumer queues into a single transaction gives best throughput.

  • Use NEXT as navigation mode, if not using message priorities. This offers the same semantics but improved performance.

  • Use the REMOVE_NODATA dequeue mode if dequeuing in BROWSE mode followed by a REMOVE.

Propagation Tuning Tips

Propagation can be considered a special kind of dequeue operation with an additional INSERT at the remote (or local) queue table. Propagation from a single schedule is not parallelized across multiple job queue processes. Rather, they are load balanced. For better scalability, configure the number of propagation schedules according to the available system resources (CPUs).

Propagation rates from transactional and nontransactional (default) queue tables vary to some extent because Oracle Streams Advanced Queuing determines the batching size for nontransactional queues, whereas for transactional queues, batch size is mainly determined by the user application.

Optimized propagation happens in batches. If the remote queue is in a different database, then Oracle Streams Advanced Queuing uses a sequencing algorithm to avoid the need for a two-phase commit. When a message must be sent to multiple queues in the same destination, it is sent multiple times. If the message must be sent to multiple consumers in the same queue at the destination, then it is sent only once.

Buffered Messaging Tuning

Buffered messaging operations in a Oracle Real Application Clusters environment will be fastest on the OWNER_INSTANCE of the queue.

Performance Views

Oracle provides views to monitor system performance and troubleshooting:

These views are integrated with the Automatic Workload Repository (AWR). Users can generate a report based on two AWR snapshots to compute enqueue rate, dequeue rate, and other statistics per queue/subscriber.

PKaV|IwIPK-AOEBPS/jm_share.htm Oracle JMS Shared Interfaces

15 Oracle JMS Shared Interfaces

This chapter describes the Java Message Service (JMS) operational interface (shared interfaces) to Oracle Streams Advanced Queuing (AQ).

This chapter contains these topics:

Oracle Streams Advanced Queuing JMS Operational Interface: Shared Interfaces

This section discusses Oracle Streams Advanced Queuing shared interfaces for JMS operations.

This section contains these topics:

Starting a JMS Connection

public void start()
          throws JMSException

AQjmsConnection.start() starts a JMS connection for receiving messages.

Getting a JMS Connection

public oracle.jms.AQjmsConnection getJmsConnection()
                                            throws JMSException

AQjmsSession.getJmsConnection() gets a JMS connection from a session.

Committing All Operations in a Session

public void commit()
           throws JMSException

AQjmsSession.commit() commits all JMS and SQL operations performed in a session.

Rolling Back All Operations in a Session

public void rollback()
              throws JMSException

AQjmsSession.rollback() terminates all JMS and SQL operations performed in a session.

Getting the JDBC Connection from a Session

public java.sql.Connection getDBConnection()
                                    throws JMSException

AQjmsSession.getDBConnection() gets the underlying JDBC connection from a JMS session. The JDBC connection can be used to perform SQL operations as part of the same transaction in which the JMS operations are accomplished.

Example 15-1 Getting Underlying JDBC Connection from JMS Session

java.sql.Connection db_conn;
QueueSession     jms_sess;
db_conn = ((AQjmsSession)jms_sess).getDBConnection();

Getting the OracleOCIConnectionPool from a JMS Connection

public oracle.jdbc.pool.OracleOCIConnectionPool getOCIConnectionPool()

AQjmsConnection.getOCIConnectionPool() gets the underlying OracleOCIConnectionPool from a JMS connection. The settings of the OracleOCIConnectionPool instance can be tuned by the user depending on the connection usage, for example, the number of sessions the user wants to create using the given connection. The user should not, however, close the OracleOCIConnectionPool instance being used by the JMS connection.

Example 15-2 Getting Underlying OracleOCIConnectionPool from JMS Connection

oracle.jdbc.pool.OracleOCIConnectionPool cpool;
QueueConnection jms_conn;
cpool = ((AQjmsConnection)jms_conn).getOCIConnectionPool();

Creating a BytesMessage

public javax.jms.BytesMessage createBytesMessage()
                                          throws JMSException

AQjmsSession.createBytesMessage() creates a bytes message. It can be used only if the queue table that contains the destination queue/topic was created with the SYS.AQ$_JMS_BYTES_MESSAGE or AQ$_JMS_MESSAGE payload types.

Creating a MapMessage

public javax.jms.MapMessage createMapMessage()
                                      throws JMSException

AQjmsSession.createMapMessage() creates a map message. It can be used only if the queue table that contains the destination queue/topic was created with the SYS.AQ$_JMS_MAP_MESSAGE or AQ$_JMS_MESSAGE payload types.

Creating a StreamMessage

public javax.jms.StreamMessage createStreamMessage()
                                            throws JMSException

AQjmsSession.createStreamMessage() creates a stream message. It can be used only if the queue table that contains the destination queue/topic was created with the SYS.AQ$_JMS_STREAM_MESSAGE or AQ$_JMS_MESSAGE payload types.

Creating an ObjectMessage

public javax.jms.ObjectMessage createObjectMessage(java.io.Serializable object)
                                            throws JMSException

AQjmsSession.createObjectMessage() creates an object message. It can be used only if the queue table that contains the destination queue/topic was created with the SYS.AQ$_JMS_OBJECT_MESSAGE or AQ$_JMS_MESSAGE payload types.

Creating a TextMessage

public javax.jms.TextMessage createTextMessage()
                                        throws JMSException

AQjmsSession.createTextMessage() creates a text message. It can be used only if the queue table that contains the destination queue/topic was created with the SYS.AQ$_JMS_TEXT_MESSAGE or AQ$_JMS_MESSAGE payload types.

Creating a JMS Message

public javax.jms.Message createMessage()
                                throws JMSException

AQjmsSession.createMessage() creates a JMS message. You can use the AQ$_JMS_MESSAGE construct message to construct messages of different types. The message type must be one of the following:

  • DBMS_AQ.JMS_TEXT_MESSAGE

  • DBMS_AQ.JMS_OBJECT_MESSAGE

  • DBMS_AQ.JMS_MAP_MESSAGE

  • DBMS_AQ.JMS_BYTES_MESSAGE

  • DBMS_AQ.JMS_STREAM_MESSAGE

You can also use this ADT to create a header-only JMS message.

Creating an AdtMessage

public oracle.jms.AdtMessage createAdtMessage()
                                       throws JMSException

AQjmsSession.createAdtMessage() creates an AdtMessage. It can be used only if the queue table that contains the queue/topic was created with an Oracle ADT payload type. An AdtMessage must be populated with an object that implements the CustomDatum interface. This object must be the Java mapping of the SQL ADT defined as the payload for the queue/topic. Java classes corresponding to SQL ADT types can be generated using the Jpublisher tool.

Setting JMS Correlation Identifier

public void setJMSCorrelationID(java.lang.String correlationID)
                         throws JMSException

AQjmsMessage.setJMSCorrelationID() specifies the message correlation identifier.

Specifying JMS Message Properties

Property names starting with JMS are provider-specific. User-defined properties cannot start with JMS.

The following provider properties can be set by clients using text, stream, object, bytes or map messages:

The following properties can be set on AdtMessage

This section contains these topics:

Setting a Boolean Message Property

public void setBooleanProperty(java.lang.String name,
                               boolean value)
                        throws JMSException

AQjmsMessage.setBooleanProperty() specifies a message property as Boolean. It has the following parameters:

ParameterDescription
nameName of the Boolean property
valueBoolean property value to set in the message

Setting a String Message Property

public void setStringProperty(java.lang.String name,
                              java.lang.String value)
                       throws JMSException

AQjmsMessage.setStringProperty() specifies a message property as string. It has the following parameters:

ParameterDescription
nameName of the string property
valueString property value to set in the message

Setting an Integer Message Property

public void setIntProperty(java.lang.String name,
                           int value)
                    throws JMSException

AQjmsMessage.setIntProperty() specifies a message property as integer. It has the following parameters:

ParameterDescription
nameName of the integer property
valueInteger property value to set in the message

Setting a Double Message Property

public void setDoubleProperty(java.lang.String name,
                              double value)
                       throws JMSException

AQjmsMessage.setDoubleProperty() specifies a message property as double. It has the following parameters:

ParameterDescription
nameName of the double property
valueDouble property value to set in the message

Setting a Float Message Property

public void setFloatProperty(java.lang.String name,
                             float value)
                      throws JMSException

AQjmsMessage.setFloatProperty() specifies a message property as float. It has the following parameters:

ParameterDescription
nameName of the float property
valueFloat property value to set in the message

Setting a Byte Message Property

public void setByteProperty(java.lang.String name,
                            byte value)
                     throws JMSException

AQjmsMessage.setByteProperty() specifies a message property as byte. It has the following parameters:

ParameterDescription
nameName of the byte property
valueByte property value to set in the message

Setting a Long Message Property

public void setLongProperty(java.lang.String name,
                            long value)
                     throws JMSException

AQjmsMessage.setLongProperty() specifies a message property as long. It has the following parameters:

ParameterDescription
nameName of the long property
valueLong property value to set in the message

Setting a Short Message Property

public void setShortProperty(java.lang.String name,
                             short value)
                      throws JMSException

AQjmsMessage.setShortProperty() specifies a message property as short. It has the following parameters:

ParameterDescription
nameName of the short property
valueShort property value to set in the message

Setting an Object Message Property

public void setObjectProperty(java.lang.String name,
                              java.lang.Object value)
                       throws JMSException

AQjmsMessage.setObjectProperty() specifies a message property as object. Only objectified primitive values are supported: Boolean, byte, short, integer, long, float, double and string. It has the following parameters:

ParameterDescription
nameName of the Java object property
valueJava object property value to set in the message

Setting Default TimeToLive for All Messages Sent by a MessageProducer

public void setTimeToLive(long timeToLive)
                   throws JMSException

This method sets the default TimeToLive for all messages sent by a MessageProducer. It is calculated after message delay has taken effect. This method has the following parameter:

ParameterDescription
timeToLiveMessage time to live in milliseconds (zero is unlimited)

Example 15-3 Setting Default TimeToLive for All Messages Sent by a MessageProducer

/* Set default timeToLive value to 100000 milliseconds for all messages sent by the QueueSender*/
QueueSender sender;
sender.setTimeToLive(100000);

Setting Default Priority for All Messages Sent by a MessageProducer

public void setPriority(int priority)
                 throws JMSException

This method sets the default Priority for all messages sent by a MessageProducer. It has the following parameter:

ParameterDescription
priorityMessage priority for this message producer. The default is 4.

Priority values can be any integer. A smaller number indicates higher priority. If a priority value is explicitly specified during a send() operation, then it overrides the default value set by this method.

Example 15-4 Setting Default Priority Value for All Messages Sent by QueueSender

/* Set default priority value to 2 for all messages sent by the QueueSender*/
QueueSender sender;
sender.setPriority(2);

Example 15-5 Setting Default Priority Value for All Messages Sent by TopicPublisher

/* Set default priority value to 2 for all messages sent by the TopicPublisher*/
TopicPublisher publisher;
publisher.setPriority(1);

Creating an AQjms Agent

public void createAQAgent(java.lang.String agent_name,
                          boolean enable_http,
                   throws JMSException

This method creates an AQjmsAgent. It has the following parameters:

ParameterDescription
agent_nameName of the AQ agent
enable_httpIf set to true, then this agent is allowed to access AQ through HTTP

Receiving a Message Synchronously

You can receive a message synchronously by specifying Timeout or without waiting. You can also receive a message using a transformation:

Using a Message Consumer by Specifying Timeout

public javax.jms.Message receive(long timeout)
                          throws JMSException

This method receives a message using a message consumer by specifying timeout.

ParameterDescription
timeoutTimeout value in milliseconds

Example 15-6 Using a Message Consumer by Specifying Timeout

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              t_sess    = null;
TopicSession              jms_sess;
Topic                     shipped_orders;
int                       myport = 5521;

/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
   "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
   "WS", "Shipped_Orders_Topic");

/* create a subscriber, specifying the correct CustomDatumFactory  and
selector */
subscriber1 = jms_sess.createDurableSubscriber(
   shipped_orders, 'WesternShipping', 
   " priority > 1 and tab.user_data.region like 'WESTERN %'",
   false, AQjmsAgent.getFactory());
/* receive, blocking for 30 seconds if there were no messages */
Message = subscriber.receive(30000);

Example 15-7 JMS: Blocking Until a Message Arrives

public BolOrder get_new_order1(QueueSession jms_session)
 {
   Queue            queue;
   QueueReceiver    qrec;
   ObjectMessage    obj_message;
   BolCustomer      customer;
   BolOrder         new_order = null;
   String           state;

   try
   {
   /* get a handle to the new_orders queue */
    queue = ((AQjmsSession) jms_session).getQueue("OE", "OE_neworders_que");
    qrec = jms_session.createReceiver(queue);

    /* wait for a message to show up in the queue */
    obj_message = (ObjectMessage)qrec.receive();
    new_order = (BolOrder)obj_message.getObject();
    customer = new_order.getCustomer();
    state    = customer.getState();
    System.out.println("Order:  for customer " + customer.getName()); 
   }
  catch (JMSException ex)
   {
     System.out.println("Exception: " + ex);
   }
   return new_order;
 }

Using a Message Consumer Without Waiting

public javax.jms.Message receiveNoWait()
                                throws JMSException

This method receives a message using a message consumer without waiting.

Example 15-8 JMS: Nonblocking Messages

public BolOrder poll_new_order3(QueueSession jms_session)
 {
   Queue            queue;
   QueueReceiver    qrec;
   ObjectMessage    obj_message;
   BolCustomer      customer;
   BolOrder         new_order = null;
   String           state;

   try
   {
    /* get a handle to the new_orders queue */
    queue = ((AQjmsSession) jms_session).getQueue("OE", "OE_neworders_que");
    qrec = jms_session.createReceiver(queue);

    /* check for a message to show in the queue */
    obj_message = (ObjectMessage)qrec.receiveNoWait();
    new_order = (BolOrder)obj_message.getObject();
    customer = new_order.getCustomer();
    state    = customer.getState();

    System.out.println("Order:  for customer " + customer.getName()); 
   }
   catch (JMSException ex)
   {
     System.out.println("Exception: " + ex);
   }
   return new_order;
 }

Receiving Messages from a Destination Using a Transformation

A transformation can be applied when receiving a message from a queue or topic. The transformation is applied to the message before returning it to JMS application.

The transformation can be specified using the setTransformation() interface of the AQjmsQueueReceiver, AQjmsTopicSubscriber or AQjmsTopicReceiver.

Example 15-9 JMS: Receiving Messages from a Destination Using a Transformation

Assume that the Western Shipping application retrieves messages from the OE_bookedorders_topic. It specifies the transformation OE2WS to retrieve the message as the Oracle object type WS_order. Assume that the WSOrder Java class has been generated by Jpublisher to map to the Oracle object WS.WS_order:

public AQjmsAdtMessage retrieve_bookedorders(TopicSession jms_session)
  AQjmsTopicReceiver  receiver;
  Topic               topic;
  Message             msg = null;

  try
  {
    /* get a handle to the OE_bookedorders_topic */
    topic = ((AQjmsSession)jms_session).getTopic("OE", "OE_bookedorders_topic");

    /* Create a receiver for WShip */
    receiver = ((AQjmsSession)jms_session).createTopicReceiver(
       topic, "WShip, null, WSOrder.getFactory());

    /* set the transformation in the publisher */
    receiver.setTransformation("OE2WS");
    msg = receiver.receive(10);
  }
  catch (JMSException ex)
  {
     System.out.println("Exception :", ex);
  }
       return (AQjmsAdtMessage)msg;
}

Specifying the Navigation Mode for Receiving Messages

public void setNavigationMode(int mode)
                       throws JMSException

This method specifies the navigation mode for receiving messages. It has the following parameter:

ParameterDescription
modeNew value of the navigation mode

Example 15-10 Specifying Navigation Mode for Receiving Messages

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              t_sess    = null;
TopicSession              jms_sess;
Topic                     shipped_orders;
int                       myport = 5521;

/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
   "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic("WS", "Shipped_Orders_Topic");

/* create a subscriber, specifying the correct CustomDatumFactory and selector */
subscriber1 = jms_sess.createDurableSubscriber(
   shipped_orders, 'WesternShipping', 
   "priority > 1 and tab.user_data.region like 'WESTERN %'", false,
   AQjmsAgent.getFactory());
subscriber1.setNavigationMode(AQjmsConstants.NAVIGATION_FIRST_MESSAGE);

/* get message for the subscriber, returning immediately if there was nomessage */
Message = subscriber.receive();

Receiving a Message Asynchronously

You can receive a message asynchronously two ways:

Specifying a Message Listener at the Message Consumer

public void setMessageListener(javax.jms.MessageListener myListener)
                        throws JMSException

This method specifies a message listener at the message consumer. It has the following parameter:

ParameterDescription
myListenerSets the consumer message listener

Example 15-11 Specifying Message Listener at Message Consumer

TopicConnectionFactory    tc_fact   = null;
TopicConnection           t_conn    = null;
TopicSession              t_sess    = null;
TopicSession              jms_sess;
Topic                     shipped_orders;
int                       myport = 5521;
MessageListener           mLis = null;

/* create connection and session */
tc_fact = AQjmsFactory.getTopicConnectionFactory(
   "MYHOSTNAME", "MYSID", myport, "oci8");
t_conn = tc_fact.createTopicConnection("jmstopic", "jmstopic");
jms_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
shipped_orders = ((AQjmsSession )jms_sess).getTopic(
    "WS", "Shipped_Orders_Topic");

/* create a subscriber, specifying the correct CustomDatumFactory and selector */
subscriber1 = jms_sess.createDurableSubscriber(
   shipped_orders, 'WesternShipping',
   "priority > 1 and tab.user_data.region like 'WESTERN %'",
   false, AQjmsAgent.getFactory());
mLis = new myListener(jms_sess, "foo");

/* get message for the subscriber, returning immediately if there was nomessage */
subscriber.setMessageListener(mLis);
The definition of the myListener class
import oracle.AQ.*;
import oracle.jms.*;
import javax.jms.*;
import java.lang.*;
import java.util.*;
public class myListener implements MessageListener
{
   TopicSession   mySess;
   String         myName;
   /* constructor */
   myListener(TopicSession t_sess, String t_name)
   {
      mySess = t_sess;
      myName = t_name;
   }
   public onMessage(Message m)
   {
      System.out.println("Retrieved message with correlation: " ||
m.getJMSCorrelationID());
      try{
        /* commit the dequeue */
        mySession.commit();
      } catch (java.sql.SQLException e)
      {System.out.println("SQL Exception on commit"); }
   }
}

Specifying a Message Listener at the Session

public void setMessageListener(javax.jms.MessageListener listener)
                        throws JMSException

This method specifies a message listener at the session.

ParameterDescription
listenerMessage listener to associate with this session

Getting Message ID

This section contains these topics:

Getting the Correlation Identifier

public java.lang.String getJMSCorrelationID()
          throws JMSException

AQjmsMessage.getJMSCorrelationID() gets the correlation identifier of a message.

Getting the Message Identifier

public byte[] getJMSCorrelationIDAsBytes()
          throws JMSException

AQjmsMessage.getJMSMessageID() gets the message identifier of a message as bytes or a string.

Getting JMS Message Properties

This section contains these topics:

Getting a Boolean Message Property

public boolean getBooleanProperty(java.lang.String name)
          throws JMSException

AQjmsMessage.getBooleanProperty() gets a message property as Boolean. It has the following parameter:

ParameterDescription
nameName of the Boolean property

Getting a String Message Property

public java.lang.String getStringProperty(java.lang.String name)
          throws JMSException

AQjmsMessage.getStringProperty() gets a message property as string. It has the following parameter:

ParameterDescription
nameName of the string property

Getting an Integer Message Property

public int getIntProperty(java.lang.String name)
          throws JMSException

AQjmsMessage.getIntProperty() gets a message property as integer. It has the following parameter:

ParameterDescription
nameName of the integer property

Getting a Double Message Property

public double getDoubleProperty(java.lang.String name)
                         throws JMSException

AQjmsMessage.getDoubleProperty() gets a message property as double. It has the following parameter:

ParameterDescription
nameName of the double property

Getting a Float Message Property

public float getFloatProperty(java.lang.String name)
          throws JMSException

AQjmsMessage.getFloatProperty() gets a message property as float. It has the following parameter:

ParameterDescription
nameName of the float property

Getting a Byte Message Property

public byte getByteProperty(java.lang.String name)
          throws JMSException

AQjmsMessage.getByteProperty() gets a message property as byte. It has the following parameter:

ParameterDescription
nameName of the byte property

Getting a Long Message Property

public long getLongProperty(java.lang.String name)
          throws JMSException

AQjmsMessage.getLongProperty() gets a message property as long. It has the following parameter:

ParameterDescription
nameName of the long property

Getting a Short Message Property

public short getShortProperty(java.lang.String name)
                       throws JMSException

AQjmsMessage.getShortProperty() gets a message property as short. It has the following parameter:

ParameterDescription
nameName of the short property

Getting an Object Message Property

public java.lang.Object getObjectProperty(java.lang.String name)
                                   throws JMSException

AQjmsMessage.getObjectProperty() gets a message property as object. It has the following parameter:

ParameterDescription
nameName of the object property

Example 15-12 Getting Message Property as an Object

TextMessage message;
message.getObjectProperty("empid", new Integer(1000);

Closing and Shutting Down

This section contains these topics:

Closing a MessageProducer

public void close()
           throws JMSException

AQjmsProducer.close() closes a MessageProducer.

Closing a Message Consumer

public void close()
           throws JMSException

AQjmsConsumer.close() closes a message consumer.

Stopping a JMS Connection

public void stop()
          throws JMSException

AQjmsConnection.stop() stops a JMS connection.

Closing a JMS Session

public void close()
           throws JMSException

AQjmsSession.close() closes a JMS session.

Closing a JMS Connection

public void close()
          throws JMSException

AQjmsConnection.close() closes a JMS connection and releases all resources allocated on behalf of the connection. Because the JMS provider typically allocates significant resources outside the JVM on behalf of a connection, clients should close them when they are not needed. Relying on garbage collection to eventually reclaim these resources may not be timely enough.

Troubleshooting

This section contains these topics:

Getting a JMS Error Code

public java.lang.String getErrorCode()

AQjmsException.getErrorCode() gets the error code for a JMS exception.

Getting a JMS Error Number

public int getErrorNumber()

AQjmsException.getErrorNumber() gets the error number for a JMS exception.


Note:

This method will be deprecated in a future release. Use getErrorCode() instead.

Getting an Exception Linked to a JMS Exception

public java.lang.String getLinkString()

AQjmsException.getLinkString() gets the exception linked to a JMS exception. In general, this contains the SQL exception raised by the database.

Printing the Stack Trace for a JMS Exception

public void printStackTrace(java.io.PrintStream s)

AQjmsException.printStackTrace() prints the stack trace for a JMS exception.

Setting an Exception Listener

public void setExceptionListener(javax.jms.ExceptionListener listener)
                          throws JMSException

AQjmsConnection.setExceptionListener() specifies an exception listener for a connection. It has the following parameter:

ParameterDescription
listenerException listener

If an exception listener has been registered, then it is informed of any serious problem detected for a connection. This is accomplished by calling the listener onException() method, passing it a JMS exception describing the problem. This allows a JMS client to be notified of a problem asynchronously. Some connections only consume messages, so they have no other way to learn the connection has failed.

Example 15-13 Specifying Exception Listener for Connection

//register an exception listener
Connection jms_connection;
jms_connection.setExceptionListener(
    new ExceptionListener() {
        public void onException (JMSException jmsException) {
            System.out.println("JMS-EXCEPTION: " + jmsException.toString());
        }
    };
  );

Getting an Exception Listener

public javax.jms.ExceptionListener getExceptionListener()
                                                 throws JMSException

AQjmsConnection.getExceptionListener() gets the exception listener for the connection.

Example 15-14 Getting the Exception Listener for the Connection

//Get the exception listener
Connection jms_connection;
ExceptionListener el = jms_connection.getExceptionListener();
PKwZKPK-AOEBPS/img/adque449.gifHjGIF89apR忿???@@@ŀAAArrrӁΟooo///___"!"OOOaaa212qqqvvv거QQQ gggۑڱܠ;;;```000999PPP444555777BAA333:::>>>pppkkk|||www222XXXJJJ,,,л666sss888#"" rqqtttȼ...[[[baa---RQQ<<{ ~~W bvAm`P0Vhfv ! |Sx,:b)2,:2/8 )F$92bKER RCAȸP`bO8&N(fQ**POaSr֔fx4 )f4 (LwjL{STV4*g&'-aJY蟠)P#@jkL3P@zGF P@&0 "T2Dԫ)0@0f=<N0Cp,B@ *{Q@Jآn>@> 0 41 O+P Tl+"d2A`> <,A K"|44KI 9c ($4 0 Y49@lC -xmr4Yn08>>[ ʛ1o _@h^o.8C($.-CA z: HQn 4w(䳂 *H0 凟C>(АO@ObSfP@Z?e*' bsP;kX>jnyPa!0!] g,]<kc'9C `ݩ˃#$ )ػe \ .lQ[TAҽ$ L0  S$7phã>`Y@+QV>Lx=<c)_.Ʋ8L`4ѥPuBeJC:D cwƪ`@uD0/}\bԇ)U Ĕ1Ёt<]GԞQ\ g 5L40$ H'Lẇ) bdCɮk՛B%Ʌq8HХQzi*AW]˨;u ]t:02Y/"twD8A<֋fMh/{k\SvRFlZO$&h % @~$ `DZQ $=?}H?)Ё6^;~8M2g$A}4. 5H"V ="U)iD@tbLAEq ӁB%1AVIli:i鰬0x08¼E@1+~\k>\K%DU;.++38v;AO٥bcSX i49^5Vf;YOV!3LIi]ep݊db7baB@:U*HⳫ2nJ]5d PI aʄMȖncWA*!OW6'e a рygD((&`XGg:3 iŒzpu O@IQs hmdL _=DѬqaB^Djz4䀆]W*9bk*WT,-!f۳3@\e6QmtOm$"AbGZtAŐB-wSևob_j0&?xB{VR3Dׇ 6 hI`{fTMm6A |o6VM z:V7JhWH\-06HL G@vrm"7m}#Q# 0 e kUo68̎ V51Vo-Ep1 s@&,ky>w}( P@N@~3 {0rڽ ;NWH %j,?!x |WcT>UC*\bO5c5h>'˕?V䣆#komh|?,Odw`_gC^C@nC"dS> sx]!Fi$Ezg(Zm?F"7Nbg0`]81XHrhMEo > ^c8wa鸎XG}yR1Yy͑lTW($"*,ْ.02)WP Q!yOFlnB*>F<a632y6$QdNAp|4Xc:6&3o')PoL)1!(5n|D9*x>lD*U 6s6UU[5Hs,5s{D4&sіQrt.0(guY@w:g>}{6X35cgy@ O?))qF(%VetYO0! Ȯy*` 6ylȹ@Iٜ ޤR!ַq^%?D@!睆iHXzz)&h)q9!ʟ  I' &7{z4UUuyOJXӡV>9PUiq#o%Zỏ; 3Ѣ& >TvInȥ\ i9S&9%\0O5nJXWq۳oRTV* 9 r!hV#iy0z~dU$F6)&h?ةVN;٧*Cn(!hTh*zf֠Ipah aѫ_㪨ڤpG!N#/X!G\jjJ.~{ߚᢋK ,Q)w& vv׵(F&?+0&-G6>rx0(@"E7bU'v4 &6(}tyY*6V6{P:[jm#qzZ70UujG(-0UOdCo7ئE'+`H--JU4ˠ VGrX(05rKu k0uVjhT6`G7CUԸh:uN[on+H!VYUU鷵ʚ^k+`k-b*f&ZbCD)b\#6hչ GֹU B!!;\k +;,KPs6mˌhK{Gzy55ۺٹw6kZ3'[*+;›S78H0Vq-@U7PH+E7\CGcF\.۴hjHkڽx}Y7Z f{+kƚZcrkiKwCVukhڒI&Ft^C*1N{GfɌPG_cHÉ)˭*ZF|HJLNPAg+1YbW= P jlnprƼ0Z0xzlSk+ b.Q4 C @<ɔ\ɖ|ɘɓ ɠʢ|k+Iƃɣ˲ ʜ<˸ˡ\xʃ*≮\˷LȌ̼W)BY|؜ڼL  <\9F^ qs &\ &@lR U<3 @2CЦ}4=H0QT5(ON,.,)=x 6}6=3M8>7:q`JLNG|@SQ\V}XZ\m[P"ݴiG X"8SCp$Q&q}q}֮KՀ~AN p`ݭSֿ|h}-a@e{̘ ANʼ؃؍ X`2<M"!+|{]ɜ !BRj5=]5d5@ۗ,+Qۚ|۟ڏ]ME(q֕։|{Q 5ǼH}؍q!Rhsu}q߳ FqˬL\,,1 !YzaOV+ =ԩ1a(!Q";\lu -pYٷ&8:H]? s纱p-. "vQ'VI_RGc)g75t"N4-:DYraA=* "6  hn#6iEx>Y_X3w&߿"I)a,j noVzGҕ.r5(/*+,.2J했W5G(A{qHծS]WQSW̾>VU7hZuXjnanp/. N/Yκw~z7c[Eҗ 2XHaD kZOxhV7qNCOxUCXζhw7l9+wddROIXFaG/ \˱+&bڳl $8@>.da|L405nP@>TXI)Ux _,eΤYf/T6s6bQ9 H|0Y@o002Od 6}(> qv*4>(2‹CI<=+ać]Lc9_B(ϡ  hA 4H |4|əWaոyi^@(2֥hq{Q|6iǐ)Oyqٵ7s;Awif^|-]6 }$Nl3@8C`$"c(/詁,` B2܏ۢ;KD:ST'L 3`}hP?H [-4 m" #6[A"JpĆD H tZ05"0 B [`EBoBPDşě<8(0t,h!ZZ!aHC!r+m8}:9]*ȁhWrpk/YNAsKJ[ mT[-wd%d% E* *,lm2ׂh/} ͎6L`Aꤏb!c%,@e 2la,m}Lfh+m3ͥW؍8 GVZI2$8TA bʂ;$&lKWIer%f']BQ 7& C#p6=,_;ċ+gDY4Vg5a"q'`@9:.&-3!-4 rv"i:G2m$MQVQ+_;L^NǗ&A~h),UPR!z̏>#-xORT/0j)f&n͂ 4 5)LcIl@ HONʬS&-Rj,LS詧 t ,jsaH;!?-ct_u捀Wː>;QϤ)V˅RȨ42l ?O p[ 8g wDTuI $ l8WU:X2:fZP&dUwK\BY"B?!i!lI6o11m+J,yI3jڠbNp %% )yI[[*-֕ jIveR*prD8NhQ -|yXlrl%0 橺R%畝jTDh[":9݈%X·@ K0#T0MP /B h./Q !h#QR{ %bܴU7q@ X| aˍU ̥7i"\H) kA(lU\Y0c ~FԐ#֕fPmŜ}ܵS&wh2@m9W-w#i5U0==m&5dzE6 SծyXM1U>L> :H󨵝"b (n-W3Ac}2֔wmtP6l~(<IfIQ<00(ʊ7S\dun SpV0Ӿu$wAtځEİ<7̉>>d>m{' 1p{_c荏2“_a~|3 i@} ~k:!eBu~ ~1A˟ @+4@ԿD 7rI@?[@$>LAd> FAːA\?AABA #ԇ$$%l'$ 4!"*+TB!=IXTB+B-$D>4D@DDA,D$FGdD&tD}BC2[@DP EQER,RS$E XEWEӈxEZE[OE*_l]ԇ`E^@ƖQƂ`Fpc FihF}emElgpnLrlsF(DS'2Lpc)H7к Ȃ@D=B71c.ȬzGS5(IrH LɁC:hȲiHȈH_HIHɗY+I  Bx8؃0ʇ00T@TD<)*d|,9I0D1I2KD@ 4x2208Jd0x䀖?xT0 $ԉ+9 Dټ:LhL 2@GJJ0xSL}p$L4>x>40@ {|ԇtI@c΁x0޼DL?K!H@KBPt<8T88Cƌ|G؃(4K,:Ot8,}`PӜC}O6tx!]G-тؼ5]BU%сbK"m#RU҂hQ 5$$%)%+&EқL,ԇ:LHN}PS'L'xD29N' ^ F. x! "PXbvښaᲹa"ꌁ 8&! "G},؁ *.] ؁1.3bRT'#N$ޗ%`(&8Ё1Fvd (p!(և.؁cdN9* Ύ.<6=>n((v Q"p_f8&c}8fcOF/0TV`T_;֥W.X>%(dx(8v1vuc}p@(fe|gB.j&Ulm&n&oև\vAf]KM&Ef  g~gi耆 VNg"p~g]p62"X j`" @EvHjnjk^iii#bيrY+ևafkvH`4fkgvFܪjjjrYikSN&lB{irBled~&m-j/8~m؎mٞmڮm۾mئK6 .N ֈ>nȯIynnnn> B-mmj&p`lAc8*Xo()X+8<,8+X)o22*np!phN=>`T܎[.79 'q'q|q'+@.X$O!ϾF4618f!Kc&@'vhNԶ&>IC(رxσq>s?ȃ 7hslJr\[rnrN$ &eցNf"pkp"X6&.sN*i@Ftzp(+|%ȃsavb%(0Z/Ֆ 6G0N⤦|L*Vg.> h.$nr4on2[eX3vVoW6x`񒐐DBup9(v?G;kᤆoL癩юo=kwptzSw>5p2FedR'w|f룮 E7!ڍ' 9 7`xo{By4.2aKg-{hH W':`yDyȐD!aQ&OfxFe&8W/OpMgwɐ{ Z"/w{}|+ȇ ɓD'!xJ~`( Ox \gFy p6wAGKnvƏpe'_fgb"O&KbD887j8bG}"#ʔ*= @@J>7' ߊ$$GBPb2m' R]@>:Nq+ذbǒMt -S0NY>1C v-ht">cC& ]0fe%)" {_ Uj*%PC>Au *U YaE`0kum4bwP@LpT &[UiBji$Ç m1ZX"$B 2$Bs5DXM$TYyV%IHM) Az?p $ا + @aOTSE9,x`VXqWN̑r 0(YylQZztWErT9bF uzkt"2МF"@7 $ 1h:gΙ [& %BZ7UV[`aij*9B TE]ĊЩf&ij*-G Ad f2مs"8D%, Ky>W-SCLЎ-K 9c. KQO9)o10Y[Б]8deG>h5\{)[^ WEN^Ýmc@;8E:Ç"$;6q^{[I7%;}{NS D$n|%V-VvX7䣄Wo`Q+q=0Ve'f<#Ө57d5؊r-l p >P =ހ[#q ?@7H*q6@ d + A6t(شT)#3>j oΖ6DlR62 :&2e2Ǽ'LOUr@\SGAɎD' }q閍 |(D!-@~ H5fL%I (NyΝ 2# W|3Gp>:/G P,M =*RK-hXMeEpѦ|H[*4.1;_;<6@BE1%vh6xF.x@sdD8xbaƲHC8ח M'GU%U*gCډ q `! ӡ~`+^at4ƭk돇+Gݮg#繼W]d UR όL̑`a  !!*!:!J!Z!J *Ie#Nb!#@dP $B DB>@x#!xl8N\ouG6)JxF, uUS<* FVaiٹOA0ND#P f(eaRF|II@G؊GH%hVr*XKW !\`MM$Y2N6d[$0B( Rn &e^-DPe@aBeKp`bc"GUWhS_Z^Bd0DqTS Fd0FxAPt6k`̽gJhVhd>Nwm&{2Sz IQg#B'҄i uHm DvWwcz=>%\eNk>f(@{Ƨ'|.Hf~NĬ L̰Ep>(MJZQzfE(XMj>_Peh -i m h_'\GWfFDhe~׺iULLj䄾 |܉)iN  PΥ&|E~`FjQl)6I,GEVAstjsL@PYv'&MbP ((ũG̩'UZ'b(z #JNVH$D@0l5I+H$LB0kt"P&eI Zgʩ&❒y*\a kJLja\glS.he収 )iʦjBfƦlҦ @~^J􅸢Wn'lnN:V^haڦ dBB9aN 9j!aAIKAhKFee;p9D ,¢²YA-ȆAp)l_:}EbdL$஄uh -KklS,[X(L&\-Vl^2mY,T DW6JtIG ]1.(:.\,h)BjB+Ʋڦ\a$]AmrhCDǤfDJ ^dBGFdQrlQhf›ۻj-󲭏](L/…-b@mrUcpL VD| d Ku*huLDpڴ)]\kn(,,amQjeD`8s I8ķƶ.oDT6"BXn a.± " oH*IM쀩pTC4G 3F OB0wGX^oj))^l*i"Xqa '%G&\8'TI +>Ht 8&k Wn^.jmPЊ.$+4#eJDDʊqhQ`` HCD`#0 Iwd0L2('Q55W+l0XB$4A89r&4Gʼn kz |!Sjt+AXĆҪJQ g%Jgi&l./lR LtE-AKB00)e+TN-4U44?47 [$($rҊfqUV-W" /--5`bV96C*6qm [ @nVX9S,1nUpv990Xȅ"XђXPlf\Pp7qq7r'rg@0#/*K*3t+ $e;Mf,Զ(ww,uKl{umLiYxAgӞ~o\1fz^8go8w8sS(6߰pUp P/L. xAw]wMQ,@YӿLN`AYFIJ99?iSp]{l@k NYkQaAW^ \ʓLf^w`e/66CqhEx]X#AzLAmä?@5W@D:9Wz`tSwvuf vXT%8{8@0tz[Е{T}O.]۰]8^׹U@>M|Y9{y< @NДW;E |ã17Kx~@R v1Pp,A>I.9?4HX WK@X @+S~|D|.\@_B *6Vl8-v7 J-B(HfL3CgN;yhPo9sJ>'B6uTxw4C Pv '_/WzmZ4Èb(H$A,6  i|sN':)ы̣!Dz.Svlٳi׶}7-xPÉ7OD7/.ƄΩ#rd"NVngo$Vȷwo\.P+IH <\h!-}Lp@ RN 0$P2N0ẽ{q|ȏF:aȑ@JQ| (H7 kC\̫H=t-M? >8o3%m0(4S`3+)9-K$ɇS^c6c^Sn؂N?Jϊ|TLzƚL,¹@ %XHꁇ(l}# x53PUGѓn:WѾ|5e ? Zp5|`-7ۄ͗6HM|x|PPa<]-h;Bᮾ>qY\W;j]ƐNwׂw&C\25F 4ЀH#fx *Xp lɀ(BN8" (x|@ n()X (# *a FH `1&1% 4d쐘3*, 9L\('ȇcg#:](bݥUuY-ܢM(Z+T}ZhFZiZjZk[lF[m݆[n[oM@;:xq7ݧb%1,f?}\`#[x5b"9]賺 8C[JuT)A$ÃBN!.d h0ȁdH &w y=YІV%miM{ZԦ]-k[6-mkk6-o{ \8aȒ1!`>9'y @(UȀ$;dU@8 lv7P FN#BLh&dч^ i5!!`0dB|yE|9zQwEiq|]47@pę卢c:`{h v$nX`?,.sxM2;!9dwDU*OLqcJNI`9`@ 45 T Z<=MRVyG'bO۫-ϋ F C <7?gB-98܄Zh> ;O3= jx :jAעI:䢈B}ƇU Jh }EC,R%HG?`ΕB$PALsIL*gD%qzL7EY{YE1yD1izꓶYX,頄<?7pBi^LC}Z#V249cG/q tlB3prP4y}M4ڀm]#ل"h>¥6$XK$$NmKL *3[Th7Ԭ4w?BRP]h4ƃ|9!vx׸B[5ի,W׍rma Vf Vb_%3:TkN @0.`#% e@k.LRڐ Zbg H (2Kg'hT-pB0@jl+(ߴ Ab VCsG'o%薄1"131fl sG1m8[s6 pn; x~ZPBt>@A V>Ј'\l"NnH Mfo55Ja<~B.P'c߾q~q6!RA%H6\|# I[nģQAi h@K1 +u Cb:J9>v8[Tkg\5b]%VfEJD$C`ur XS0YKgKQvg:/417uhBLEDVT9WBduZu~]]5R0fon-gq5]-gwfhh1AidzݲiYϢb+kac9[cBl5nclU6\Y6k"ULV۵nG ^"WVS h- 0aa5qjmtwkk;*&J+&.W( zstIWztg?g5Ch?h]paWf`laa;j?"wsw7xCB>$ltd{mny!yr %L?6 vz8SbX_C8` !h|Q6q#Vb77V8L6dwlAdQ/ wKL@J{6>hV!XqWo3r6  jMG2+>/k * @޽79U[׹ |aCs߶w7T;W0GK?Ͽ뽽A <0] 80H%}&x2 }!B |r#|>TbÈ  (1 3Ex`Q&H,} 5aID5֭\z5"j} 7 92B$ւ|jlܠ3AfA͢%`tgU@ b8g?  (C%RQ>" iJ{L&N<}(ؤ/Zպܻ{J)nY/_S#湸q lsˬVi\>PwPDUtQFeUIyL5ݔN}Eag*h27^~zU{F cxmhڏW`0M,a"=ZU(Jar6\9W%pɢ0i"䙇~ h#h| h#T Y9Ve5’u)HMd RX,QD 5hm¨õdk&!sGH&_CU>1B˝6];^a٘6ELj_%PHekq9x[Q܅c^Uf:7K%K-Tr6 W G\brۣ*'7x@)YoT`)7Х%$ &EHpBu -tKlvOT{eZ5MWWӂ5:%ȍ}" %[~q=ٖu\6(HrF14r&P`]4BV'tE>_yoyyWhZSl^c :Ltj|pkK$N*%!uw~o)H:Â} -8Q>OߟERA`o+Yy45z,o?i1|rRnː@#eJz0ui_X,>al4_wp4 op ̀j;p=TAeeOjR՚4H5{pF«CJ!Ѐ2FaT8qt<Ƒ@R@${ eGBv t^h -bZIȚ_P@c5t{\BHI?E7x>*/ ̬WlgH#ickdƑRJ:I47*sii; ߪ-p<7Ka"@t|sP ke*;U(\hЎ4Rkl1l$SPrN0N$#|&>$"YϘʔG "zBC3MNq@ V`lsS.<2ӥj3TP/rY;3)PSB TLG3 6UZHH@\?PH.#B13w.ބ1h 6D n B}-(X {X3D ޙB>T@׾T/_F`CX&p!21ަX]v 3Ư01=0&ld 'y []j7 8{ ySA>T׾/ ` ^p Wp,([ z| 8#9}li!gGAj))@7l  [irUUL^` V1 @GA>|ғ@ .pPa /o [7(oH|ǀ5Si嶰E<^ Pgl] wrNv7 k{ ՀgM+(*Y=6zDfrg pZZSoG {/ pWrwrp@| x-  wwvWx+@| I~%u# y?mffEG&p9Є9PAoqx 0@ T0 l "hv$v6 |~0Z0 @ p lxS @ 3iP hO.TZ!p8H P l yhzᅣw Wx m[q{a'/"ȍэh"DH8ȎhQ8؏p?` J x9o`V `;0 ` x5 `E y&9[YƐ98'fC# ]9Yɐ;9`@ip !0n`1 )瘗븗uw9ɗy闅َ  Q ]49@ 2=m?Up 9 23=gIe34Q ! ٠ ] TіsI1⨎qiɘٞ뉟 )A6E8?R5!b6 &63|WOt6E ʠ *bI@naJV,j>UkO@?E #WҢF7)`}ʤMJ16B'aF0GeO QPHPGT`fPaf`hzG@N *Jjʨꨏ *JjK p01 W`hX OL:PW7KQS @{کɚip^5\0VXۚW:FQ d950X5lU}抮K V*6{ 3USXZ ۬ `pS}W z:PzjHP5u"&; 1^) ̊"gaBU[^P1 [9XڰjW S55eh UZ*WHHP9:kڶ:vŪlQ\VڊVZWkP#kOŊS ڭZUf9PQkl lpW`.۹ CZS2Ź95pYKT\p{.`皭5ljf{9\PT'5P ;aFQͪXp:[Y㪬-f[ 0?X^FU kq>:[GܹܹWãzP^}SЮkž;c+,<غliZ\hڊH bpLpܵlk̽ |[ulxX*ۭbe|zZ5зiLʣ#ӿj;ýlūze>lhZl˲{zZhSP œ<S[S\ D7;1K>>+aB\=q(܌Jt PѲl؊9 фʿk <\bD<BöS$ -ÿ۽;ڭL|9pQښWkuMC Z] ˫@ѻZ]>C˟aƳ P O-sM'Q t Z[ÜʦJkigV< &;t ّ]XZt`۫X ֵ-q*j=+٭`[՜՚ݬ\ ˾|6i |W1Lb7|ݬ<7- m9Q][ԼӃ6 1ҠS*✪]\]`=0% .Nnq;PK&R&SMjHjPK-AOEBPS/img/adque042.gifGIF87aP?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU,P H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]?8П?O@O@ϟ(?(?o@ O@ O@8?8?8П?O@O@ϟ? 4xaB 6tbD)O@ϟ(?(?o@ O@ O@8?8?8П?O@O@ϟ(?(?o@O@ DPB >QD-^ĘQFqȑ#G9rȑ#G9rȑ#G9rȑ#G9rȑ#A8rȑ#G9rȑ#G!̗/_>~ !Ǒ#G9rȑ#G0@}Coc|9rȑ#G9rϟ?'p_|˗߾| /_>O |/?Ǒ#G9rȑ#G _> _> ߾}/|_}qȑB8rȑ#G'_>'0~o`>'0>~ 7p| H*\ȰÇ"D!B"D O`} '0>~O`} /w0D!Bq?!B"D!Ba _>/|'0?>"D!B\D!B"D!Bt/_|/ӗ_>˗ϟ@}_|˗o| H*\ȰÇ#JHŋ3jȱǏ CIHL4iҤI&MϟI&M4iҤI?~8`A&TaC,h „ 2l!Ĉ'Rџ?ӗ/>}П <0… 2Ǐ?}˷?$XA .dC%NXq? ˗o_?-Zh?~g?-ZhѢE-V̧ϟE-ZO>hѢE-Zh|-Zhb>}gѢE-Zh"E,Zh"E}YE-ZhѢEhѢEg?-ZhѢE-RϢE-RԗoE-ZhѢE-ϢE-RԗoE-ZhѢEHП>-ZHQ_}-ZhѢE-F"A,Zh"E}YhѢE,""ȟ?$X`A0߿~ _}˷ϢE-ZhѢňY$OŇO_}˷O`˗?~/˗|3_> g?-ZhѢE-R|߿}o߾o?/|'Pg0?},2ԗoYhѢE-ZHџ>o|70߿|7П@ '0_> ?~  '0߾}O`> B}YϟE-ZhѢEp_˗/?'0߿||O˗|o`?}˷ϢE-ZhѢEgb,ZP_}-ZhѢE-F"A,VW0E˷ϢE-ZhѢňY$OE-Z/>-ZhѢE#g?} H!D|!D!Bӗo,h „ 2l!Ĉ'RhП?0ŁgbE}YhѢE-Zh? ӗo|/?/|O | ̷|3/_~O`>}ӗ/_?O_~/_>~P_}gѢE-Zh"E o߾O>~_>_ _>~ }o@}/_>O`>_ _>~ g@'p "Lp!ÆB(q"Ŋ 郘o`#/| /@ _>|G0߿|׏`>O`/C}YϟE-ZhѢE郘o`#/| /_A߿O_@/|˷O`>O` /$/߾ ,h „ 2l!Ĉ'RП>_> o߾_ O?G0_?ԷO` _>O` '0|߿|gѢE-ZhѢE郘/_>~ ܗ/?o_>}ӗ/_?'0~㧏@'p_|_| ܗO_>O| P_}-ZhѢE-F"A hѢEgѢE-ZhbD,? ? 4xaB 6tP_}>|Ç>|C=\OÇ>|B}=|Ç>|Çp?}>|Ç Ç>|Ç>dÅ=|Ç*ԗoC=|Ç>|ÇÇ>|P_}Ç>|Ç>|OÇ>|B}=DÇ>|Ç>||>|Ç˗oC=|Ç>|Ç/?>| ˗/?$XР@8`A&TaC!F8bŅ˗O>~hѢʼnO| <0… :|1ĉ+Z`> O@ DPB 'p O@ DPB >QDgQ?~'p "Lp!Æ,h „ 2l!Ĉ'RП?'p@$XA .d? H*\ȰÇ#JHD,Z4`>'p "Lp!ÆB(q"Ŋ/bП?'p@$XA .dC%NXE? <0…cȐ!Â1dȐ!C 2dȐ!C 2dȐ!C8p ,h „  /? 2$C 2dȐ!C 2dȐ!C 2d`>'p "Lp|cȐ!C1dȐ!C 2dȐ!C 2dȐ!C8p ,h „ ӗ/_|2dp? 2dȐ!C 2dȐ!C 2dȐ? <0…8,h „O@ DPB >QD-.08`A&T|  <0… :|1ĉ+Z? <0B H? 4xaB 6tbD)VП O H*L`> O@ DPB >QD-&E8p ,h „ O@'p "Lp!ÆB(q"Ŋw"A 8? 4xaB'p A H*\ȰÇ#JHE]H|O@ DPA H>$XA .dC%NXE 'p@$XA O@O@ DП?$XA .dC%NXB 8? 4xaB'p 'p "D,h „ 2l!Ĉ'Rhq? <0B8` H <0… :|1ĉ+Z\`>'p "L>$X>$XAO@ DPB >QD-.08`A&T`>O@ DPB >QD-^|O@ DPB? 4xaB 6tbD)VП O H*T0'p "Lp!ÆB(q"Ŋw"A 8? 4xaB 8p`? ̗/_>~ H*\ȰÇ#JHE,Z4`>'p "LP!|@ <0… :|1ĉ+VϢE8p ,h „ 'p~ o?}O| '0?~O`> <0… :|1ĉW"B 8? 4xaB 8p`? 7_ o߾ '0}O` O? H*\ȰÇ#JHŅ8p ,h „ 'p~ o| /| ̗o ?} /@~ <0… :|1ĉ+Z\`>'p "LP!|@`>/߿#8_#(?8`A&TaC!F8bE 'p@$XA *O(0@}'}'0߿~߿|@~ <0… :|1ĉ+Z\`>'p "LP!|@o| ԗ/_>o_|˧/},h „ 2l!Ĉ'Rhq? <0B 8,h_>$XA .dC%NXE8p ,h „ 'p~ H8`A&TaC!F8bńYh|O@ DPB? 4xaB 6tbD)VП O H*T0'p "Lp!ÆB(q"Ŋw"A 8? 4xaB 8p`?$XA .dC%NXѢB.^$`>'p "LP!| <0… :|1ĉ+ZTŋ'p@$XA *O8`A&$ϟB *TPB *TPB *L0@8`A08`A&T`>O@ D? *TPB *TPB *T0a> *$`>'p "LP!| <0!A*TPB *TPB *TPa|O| '0@~O`>G|O@ DPB? 4xaB)TPB *TPB *TP„ /߿}'0|߿|O`>~'p@$XA *O8`A&$ϟB *TPB *TPB *L0@/߿|_?~/߿|߿ <0B 8,h „ 2l!Ĉ'Rh1b>o`>07p@$XA *O8`A&TaC!F8bE +`>_>O?_ o? <0B 8,h „ 2l!Ĉ'RhQ?(߿|Oӗ߿}/|߿ 8? 4xaB 8p`?$XA .dC%NXѢB*X|O@ DPB? 4xaB 6tbD)VП.08`A&T`>O@ DPB >QD-^|O@ DPB? 4xaB'p "Lp!ÆB(q"ŊO H*T0'p "LHП?$XA .dC%NXB 8? 4xaB 8p`?$XA  <0… :|1ĉ+Z,>8p }'p "L | <0!A8`A&TaC!F8bE8`8`A&TH`>O@ DPB >QD-^Ĩ|,H? 4xaB8p`?$XA .dC%NXѢB.^0  <0‚ 8,h „ 2l!Ĉ'RhQ?/0 O@ DPA? 4xaB 6tbD)VП'p A8`A&Tx`>O@ DPB >QD-*E8@$XA "O8`A&TaC!F8bE xq>$,h „ 'p~ H? 4xaB 6tbD)VP| <0„ 8,h „O@ DPB >QD-2O@8`A&T`>O@ D? H*\ȰÇ#JHE80?$XA *O8`A&$,h „ 2l!Ĉ'Rh>  <0… 8,h „O@ DPB >QD-:̗/_>}/VO8`A&TaC!F8bE1J/_%'p~ H*\ȰÇ#JHE]_>/ZO8`A&TaC!F8bE x1/'p~ H*\ȰÇ#JHE]xE 8,h „ 2l!Ĉ'RhQ?'p "L ,`> 4xaB'p "Lp!ÆB(q"Ŋ80?$XA ? ܗ? 4xaBO@ ? 4xaB 6tbD)VDϟE {/E ϟ?-ZhѢE'g"CW? 4xaB o8P? H*\ȰÇ#JH"|,Zd/} 'p "L(?8p ? 4xaB 6tbD)VDϟE {/_A$XA 'P`}8p@'p "Lp!ÆB(q"Ŋh|+П <0@ ̷? 4xaB 6tbD)V0p_ H O|8`A&TaC!F8bEYϟE {/_A$XA 'P`} H*\ȰÇ#JHA,ϢE=ܗ @,h „(0>$XA .dC%NXѠ?g"CW? 4xaB o,h „ 2l!Ĉ'RhП?h|ha}-ZhѢE-ZϟE {/E ϟ?-ZhѢE'g"CO@ DP!A} HA'p "Lp!ÆB(q"Ŋh|ha}gѢE-Zh|,Zd/},ZloYhѢE-Z81?p_ H O|8`A&TaC!F8bE xQ|+П <0@ ̷? 4xaB 6tbD)V4ϟŁY_O@ DP  <0… :|1ĉ+|,Zd/} 'p "L(?O@ DPB >QD gq`>-2|8`A&@'p "Lp!ÆB(q"Ŋ80?p_ H O|8`A&TaC!F8bEYϟE {/_A$XA 'P`}8p@'p "Lp!ÆB(q"Ŋh|+П <0@ ̷o(П?$XA .dC%NXa>-2|-6̷?,ZhѢE-ZϟE {/E ϟ?-ZhѢE''p "L ,`> 4xaB'p  <0… :|1ĉ+"ϢE=ϢņYhѢE-Zhb~-2!?}-6ϢE-ZhѢňY_A$XA | H ?} ,X` ,h „ 2l!Ĉ'RhП?+П <0? 䧯` ,X`O@ DPB >QD gq`~8`A&߿'p ,X` ,XP>~ H*\ȰÇ#JHA,ׯ @,h „_>$X ,X` ? 4xaB 6tbD)V4ϟŁO@ DP W` ,X`A,X@8`A&TaC!F8bEO@ DP W` ,X`A,X@8`A&TaC!F8bEO@ DP W` ,X`A,X@8`A&TaC!F8bEO@ DP W` ,X`A,X@8`A&TaC!F8bEY_YP?hѢE-Zhqb~-2!?}-6ϢE-ZhѢE8`A&TX? 䧯` ,X`O@ DPB >QD gq`~-2!?}-6ϢE-ZhѢňYE {OE hѢE-Zh1?W? 4xaB/,O_ ,X` <0… :|1ĉ+| 'p "L(߿O@+X` ,X@}8`A&TaC!F8bE +П <0? 䧯` ,X`+X`'p "Lp!ÆB(q"Ŋ+П <0? 䧯` ,X`+X`'p "Lp!ÆB(q"Ŋ+П <0? 䧯` ,X`+X`'p "Lp!ÆB(q"Ŋ+П <0? 䧯` ,X`+X`'p "Lp!ÆB(q"Ŋ+П <0? 䧯` ,X`O@ DPB >QD-.ׯ @,h „_>$X ,X` ? 4xaB 6tbD)V4ϟŁY_YP?-ZhѢE#gq`~-2!?}-6ϢE-ZhѢňY0 <0‚ H ?} ,X` ,h „ 2l!Ĉ'RhП?h|h>~-ZhѢE-F|,Zd/C~,ZlYhѢE-Z81_ H ?8`A~ ,X` ,(P ,h „ 2l!Ĉ'R0_ H ?8`A~ ,X` ,(P ,h „ 2l!Ĉ'R0_ H ?8`A~ ,X` ,(P ,h „ 2l!Ĉ'R0_ H ?8`A~ ,X` ,(P ,h „ 2l!Ĉ'R0_ H ?8`A~ ,X` ,(P?$XA .dC%NX| 'p "L(߿O@+X` ,X@}8`A&TaC!F8bEY_A$XA | H ?} ,X` ,h „ 2l!Ĉ'RhП?+П <0? 䧯` ,X`O@ DPB >QD gq`~-2!?}-6ϢE-ZhѢňYE {OE hѢE-Zh1?'p "L ,O_ ,X`W`O@ DPB >QDg"CgbC},ϢE-ZhѢʼnY_YP?hѢE-Zhqb>-2!?}-6?,ZhѢE-ZϟE {OE ϟ?-ZhѢE'g"CgbC},ZhѢE-Zh1?>gѢE-ZhbD,ϢE=ϢņYhѢE-Zџ?h|h>~-ZhѢE-Fȟ?$X |QD gq`>-2!?}-6ϢE-ZhѢEh|h>~gѢE-Zh|,Zd/C~,ZlYhѢE-Z81?,!?}!g1>~gѢE-Zh|'_> g|郘a> ϟ?-ZhѢE'p?'0?}˧/>߾-!?} ̧/_?'_|?} H?}8`A&TaC!F8bE [`O`~O>~o|郘O`>~ ߾} _>Aŋ/^xŃ]|'0| ̗`c/C~ O`>G0?Eŋ/^xŃ]B}/| 70_>Ǐ|郘O`>/|Q/^xŋwQ`> '_>O`>o>_> H| 䧯` '0|o}_ <0… :|1ĉ+|ۗ/~ӗO>}O|_| {O| 'P_|˗?~Q?-ZhѢE#gq`>-2!?}-6?,ZhѢE-ZϟE {OE ϟ?-ZhѢE'g"CgbC},ϢE-ZhѢʼnY_YP?hѢE-Zhqb>-2!?}-6?,ZhѢE-ZP> 4xaB8`A~ H*$? 4xaB 6tbD)V? 4x0_~<? П <0B H*\ȰÇ#JHA,ZL/?-"gѢE-ZhѢEh1|,Zxp_>-ZhѢE-Z(П?ϢEgѢE-ZhѢEh1|,Zhp_|YhѢE-Zh?,ZL/?-̗/_>}-ϢE-ZhѢEϢE'P?$XA  <0… :|1ĉ+Zt// O@} H? 4xaB 6tbD)VP_>/^`>'p "LXП?$XA .dC%NXѢC}]xQ?E]xŋ/^xѡ|.^HP_>/^xŋ/^xѢ|.^HP_>/^xŋ/^lŋwExŋ/^xbC.^/^$/ wŋ.袋."җ,h „ ԗC !C 2dȐ!C 2dȐ!C 2/? 2d|2dp?2dȐ!C 2dȐ!C .O@ϟ(?(?o@}o@ O@8?8?8П?O@ԗ?  7p?'p "Lp!ÆB(q"ł 7p @'p @'p? /_? П@ ϟ?'P 'P  o@8?8?8П?ϟ?$XA .dC%NXѢC}]x|.^xŋ/^xE}]x|.^xŋ/^xE}]x|.^xŋ/^xE}]x|.^xŋ/^xE}]x|.^xŋ/^xE}]x|.^xŋ/^xE}]x|.^xŋ/^xD~ ? 4xaB ? 4xaB 6tbD)VxD ? 4xaB ? 4xaB 6tbD)VxD} ? 4xaB ? 4xaB 6tbD)VxD  <0… <0… :|1ĉ+Z|˘Ѣ|2f̘1cƌ3f̘|U?~'p|Ǐ~'p  <0… :|1ĉ+Z|o|O>~ПǏ}˗/_>}? 4xaB 6tbD)VxcEO_|ϟ Ǐ|ǯA}e̘1cƌ3f̘1c˗/>~e}?}e̘1cƌ3f̘1~˷/_|e̘1cƌ3f̘1D˷_ƌ˗O?3f̘1cƌ3f̸|/@/>˘߾|˘1cƌ3f̘1cƂ˷@~2/_/?2W߾|˘12(2(/߾~ /,h`} o`} /~ <0… :|1ĉ+Z8߾|%@70_| _>SO_}0bĈ#F1bĈQ?}[#}O`|˧F1bĈ#F-ӗ|0O}߾}߾|8`A<(_|8`A&TaC!F8bE ӗ~a/_? _|'0F"˗F1bĈ#F/|7_~˗/?|$˧#F1bĈ#F 7_?è0?È#F1bĈcB}aĈ@}*˗F1bĈ#F ˷>}1b4E~aĈ#F1bĈq |*#F/_>1bĈ#F1bܗϟ|0bĈ_>#F1#0 }'p w|/$XA .dC%NX}.g1߾~w"B~.ԗOŋ/^xŋ w|o_|O | /?'_|/.ԗOŋ/^xŋ"|,o|/?_>ӗ_>Q|]xŋ/^xQ`>w1߿|'0|70>~O`|. //^xŋ/w@ HA_>'߾|ۗO|o`w|O| '0?o_G>ϢE-ZhѢEO_>/_˗o@~/_>~߿~_|,~hѢE-Zh"|ϢŇϢA~Y/_>~-ZhѢE-Z4oE-J/>Ϣ}hѢE-ZhѢA}*ϢEgQ`|hѢE-",*|8`O@ DPB 0a|9tСC:tСC:LA}̗/_~*'П> ԗCСC:tСC:t| 0a>9t0@9t8p_>˗/C:tСC:tСÄܗÄ_'0| ܗ/_?߾|˗/˗o| ?˗ϟC:tСC:tСC9/> o`|o߾o߿~_>~ϟ|_o߿| o˗,h „ 2l!Ĉ'RP?Y/_|'0| '?~_?~ 70|70~E/_|,ZhѢE-ZHp?Y,`o`>'0|O`_,D~gѢE-ZhѢł5ԗł?~>'P_>?~"}˗/_>-ZhѢE-o!|,w0@`>~O_>~/_|?}|߿8`Aw |'p "Lp!ÆB(q"ŊcϢŁ_>o|gѢE-ZhѢŃOE1/>-&_B  <0… :|1ĉ+NϠ|YX0E |O@ DPB >QD)W_>-Zhѡ| O@ H*\ȰÇ#JHb|gѢE%G|O@ DPB >QD-ׯ_>}C/&h>}'p ,h „ 2l!Ĉ'RhQ`|]Ta>Mw@ (,h „ 2l!Ĉ'RhQ|]TO`~˗//_~_|O`˗߿|o`/_>O~ H*\ȰÇ#JHE˗ońo_˗_> _> ̗/|_~ 70߿|߾'p`?$XA .dC%NXѢ@/ 70߿|؏|70|_>o` '0E'p`?$XA .dC%NXѢ@#/ 70߿| ̷_>'0| /_| /|X|󷏟?$XA .dC%NX|O? 70߿| _>O`>_>o`>o>YO| ? H*\ȰÇ#JHbDK/> 70߿| ԗ_>O|O߿|O|˧_˗oŁ80߾#(,h „ 2l!Ĉ'R_|˗E-Z$`>?'p "Lp!ÆB(q"Ŋ ˧|YhѢE~ (pO~ H*\ȰÇ#JH"C鋨/_}-Z(| ?O@$XA .dC%NX|M/_},Zha} 80@8`A&TaC!F8bEgџ|hQ?'p ~ Hp`|˧? 4xaB 6tbD)VD/_>}ۗ/_>}Y߾|˗ņ'p@}8`~˗O,h „ 2l!Ĉ'Rh_|,0@'p ",/_>~_}&L菟>$,h|'p "Lp!ÆB(q"Ŋ˷Ϣ~(p? H?~C`} H0~ H <0… :|1ĉ+ />O}'p ۗOB?~8@}8`A˧? 4xaB 6tbD)V/߾O| /˷@O@O@ $XA .dC%N8_|*V菟>? H?~ ,_}`> ,h  <0… :|1ĉ!˗o_Ŋ0Ǐ_?_>} H?`> ,_?$XA? 4xaB 6tbD):/߾`> 4P'p  ,h „? 4xaB 6tbD)2/߾'O|,h „? 4xaBo… .\p… .\p… ˷o… .?~O@ ԧO}'p "L|-\p… .\p… .\0a|-\p…G? ˷? 4xaBo… .\p… .\p…˷o… .4O_|-\_|.\p!B}[p… .\p… .\pa~[p… 0 H˷!B"DxP_|8`A&TaC!F8~X"~ ? 4x|!D!B˗,h „ 2l!Ĉ'R/>)60@8`A˗oB"D|'p "Lp!ÆB(q~H~  )ܗ/_?)RH"E ˗E˗o߿~Q/_})R/_~)RH"E) /_?):/߾(R/_})R/_~)RH"E)˗E˗oE˷"E׏"E)RH~H~HQ|QHq|QH"E)R/_~)Rt/_})2/>)ܗ/_?)RH"E,h „ "/> 24/_>} 2dp|1dȐ!C 2dȐ!C ˗C 2d(_|2d|1dȐ!Áǐ!C 2d?8П?O@O@ϟ(?(?o@ ߾| 7p @'p @'p? П@ П@ /_}'P 'P   ߿'?(?(?o@ O@ O@7P @'p @'p? П@ П@ ϟ?'P 'P П@ ϟ?'P 'P   7p @/_~'p? П@ П@ ϟ?'P 'P ˗o(?(?o@ O@ O@7p @'p @'p? П@ П@ ߾| П@ П@ ϟ?'P 'P   ? 4xaB *ܗ/_ 6l_|6lP|5lذB~kذaÆ aÆ 6lp_|6lذa~kذaCװaÆ ׯaÆ 6_Æ 6l0|5lذaÄװaÆ ˗O_Æ ./ 6l? 6lذaCװaÆ ˗o_Æ 6/_>} 6l_|6lذaC6lذaÆׯaÆ &/߾ 6lX_|6lpa|5lذaÆ 6lذh_|8`A&Ta|1dȐ!Cǐ!C ˗oC 2dȐ!|_| 2T/_~ 2dȐ~cȐ!C ˗OC 2/_} 2dȐ!C1o>~%ǐ@~c8p_|2dȐ!Cǐ!C /> 2d8_|2dȐ!Cc/@˗߿|/_~˗߿}/_>~`1/_~ 2dȐ~cȐ!C ˗OC 2/_} H*\? /?/?o߾~'0?߾5ܗ/ 6l_|6lذaCװaÆ ˷aÆ 6<_|Ǐ_>/|Ǐ_>O`>c/_> 6l0a|5lذaÆ˧aÆ ˗o_Æ 64_Æ/>~o| />~ۗO|+/>װaÆ ˗o_Æ 6lh_|6lpa?O@ DPB1d(0@}/|O`~| 'p@}˷|1dȐ!C˷!C 2d(_|2dȐ@cȐ!C cP`|/||_|/'_|˗/_ǐ!C  /> 2dȐ!AcȐ!C˷!C "!C 2dHP_|2dȐ!Cǐ!C 24/_>} 2dp|1dȐ!Ã'p "Lp!ÄװaÆ ˗o_Æ 6l| װaÆ˧aÆ 6lذaÆ/_> 6l0a|5lذaÆ ˗O߿}5lذAkذaÆ kذaÆӧ/_> 6l0a|5lذaÆ O@$XA / .\p? .\p@~ ? 4xaB ˗oC 2dȐ@ ? 4xaB˧o… .T… .\(P|'p "Lp!~cȐ!C 2`>'p "LР|-\p… [p… 'p>$XA .4/_} 2dȐ!C'p`>$XA / .\? .\p?~ ? 4xaB ˗oC 2dȐaA~ ? 4xaB˧o… o… .\8P_|[p… ˗o… .\p‚˗… .D/_>} .\? .\p[p… ˗o… .\p„[p… ˧o… o… .\p… ./_} .\p… .\p…ӷp… p… 'p "L ,@~,h`| 480_|<(0?$XA8`A&TX,/@},h|"D/?$XA .dh0߾ 6,_C5lذa|6l80 6,_C5lذaA}6l8П ˷aÆ P>~ 6lX0 ̧aÆ P ?} 6lXP aÆ+П <0@ o <0B-\0a>}8`A&@ 8p@~8`A&T(P &o…+П <0@ o <0B-\0a>}8`A&@ 8p@~8`A&T(P &o…+П <0@ o <0B-\0a>}8`A&@ 8p@~8`A&T(P &o…+П <0@ o <0B-\0a>}8`A&@ 8p@~8`A&T(P p… +П <0@ o <0B-\0a>}8`A&@ 8p@~8`A&T(P p… +П <0@ o <0B-\0a>}8`A&@ 8p@~8`A&T(P p… +П <0@ o <0B-\0a>}8`A&@ 8p@~8`A&T(P p… +П <0@ o <0B-\0a>}8`A&@ 8p@~8`A&T(P .\p|.\p|o…  o… [p…[H .\(P .\p|8`A&T(0?$XP ,X` ` ,XP`| H*,O_ ,X`W` ,(П ,X`A$XA  W` ,X`A,X` ̗> 4xaBO@+X` ,X@} ,X`W` ,o_ ,X`W`A} ,X` ,(0 ,X`A,X` ,XP`~ 䧯` ,X`+X` _ ,X`} ,X` _+X` ,X| ,X`W` ,X`A,X ,X` ǯ` ,XP? ,X`O@ DP 7pO@ DP|.\0 H O|8p ?} H*…[p„O@ DP 7pO@ DP|.\0 H O|8p ?} H*…[p„O@ DP 7pO@ DP|.\0 H O|8p ?} H*…[p„O@ DP 7pO@ DP|.\0 H O|8p ?} H*…[p„O@ DP 7pO@ DP|.\0 H O|8p ?} H*…[p„O@ DP 7pO@ DP|.\0 H O|8p ?} H*… .\`}8`A&@ 8p@}8`A&T(0 &̧ @,h „(0_O,h „ p„-\`}8`A&@ 8p@}8`A&T(0 &̧o…  o!A~.\p@}.\П ̷o…  o!A}.\p|.\0 .\(0_[p…[paB.\x0>$XA  ? Է? 4xaBO@ Dh0_>$XA  ? ? 4xaBO@ DhП &$/@},h „  P <0B'p "4O@~,h „  P <0B'p "4_„ /a„ &_B%L0a„K0aB%L0a„Khp_ &Lp`} &_„ &D_„ &L80K0a„ 0a„K0a„ | &L0|&L(П &LP &Lp`> W? 4xaB ,h B%L0a„Khp_ H O|8`A!B!B"D/?+П <0@ ? 4xA}&L0a%4/_A$XA 'P`} HC!B !B"ƒO@ DP  <Р>~ &L0|ܗ @,h „(0>$X!D!BC!B| 'p "L(?O@ DhP &Lp`> W? 4xaB o,h „ 24_Æ 篡| 'p "L(?O@ DhP &Lp`> W? 4xaB o,h B%L0!A}&L0a%4O_A$XA 'P`~ H 0a„ /} 'p "L(?O@ DhП &$_„ &L80+П <0@ ? 4xA}&L0a%4/_A$XA 'P`} H 0a„K0a„ `>}8`A&@'p "4_„ &L80+П <0@ ̷? 4xA&L>~ &L0|̧/a„ &_„ /a„ &_B%L0a„K0aB%L0!A}&L0a%4/~,h „  <Р>~ &L0|ܗ`? 4xaBO@ B"DXP?"D|O@ DPa~ H 0a„ /A} H*$? 4x?"DaA}"D!BCx0>"D|"D@}"D!BCxp_>"D|"DXП?"D>~"D!!~"D!!~ &L0|ܗ @,h „(0>$XAK0aB%L0a„Kh0 H O|8`A/a„ &_BO@ DP  <Р? &LHP &Lp`> W? 4xaB ,h B%L0a„Khp_ H O|8`A/a„ 0a„ /| 'p "L(?O@ DhP &Lp`> W? 4xaB o,h?"D!‚!D!B`>}8`A&@'p "4_„ &L80+П <0@ ̷? 4x?"DaA}"D!BCx0>"D|"D@}"D!BCxp_>"D|"DXП?"D>~"D!!~ &L0|ܗ`? 4xaBO@ B"DXP?"D|O@ DPa~ H 0a„ /A} H*$? 4x?"DaA}"D!BCx0>"D|"D@}"D!BCxp_>"D|"D!B"$B"D_>Ӈ!B"B"B"D_>ˇ!B"oB"B"!B"D/?+П <0@ ? 4xA}&L0a%4/_A$XA 'P`} H 0a„K0a„ `>}8`A&@'p "4_„ &L80+П <0@ ̷? 4xA&L>~ &L0|̧ @,h „(0_?$XAK0a„ |8`A&@'p "4_„ /a„ &_BO@ DP  <Р>~ &L0|ܗ @,h „(0>$XAK0aB%L0a„Kh0 H O|8`A/a„ &_BO@ DP  <ϟ?"D>~"D!!W? 4xaB ,h B%L0a„Khp_ H O|8`A!B!B"D/?C!B!B !B"D/?C!B˷!BC!B !B"ƒ'p "LP`~ H 0a„ /}8`A&T(0>$XA .dhP 6,_C'p "LP`> H 0a„ /A~8`A&T(0>$XAK0aB%L0a„KhP &Lp`> &LhP &Lp`> ӗ0a„ /a„ 0a„K0a„ Р>~ &L0|&L>~ &L0|/a„ &_„ /a„ 0a„ /A}&L0a%L0A}&L0a%4O_„ &L8P &4_„ /a„ &_B%L0a„K0aB%L0a„Kh@} H*… pƒ-\pB-$… .… p…  ?} .\P>~ o… p… 󷐠>~ .\P`> .L… .B-\pB-\xП .L… .B-\pB-\0>~ .\P`> ӷp… pA.\0>~ .\P`> p… p„-\pB-$O… .…[p„ <0B-$… .… p…  ?} .\P>~ .\pƒ-\pB-$… .… p…  ?} .\P>~ .\pƒ-,a 󷐠>~ ˗O?[`> .L‚[0a> ӷP|CO` p„-\>~ Co„-$ |-\X0 &oa|-\0[/?O#H A <Р? &LHP ̧/_?'_|ϟKhP#o߿|ӗO߿|/_>~O_%L0A}'0|ӗo@~o?/A~ Ǐ`} O_>}˷O |?} 0a„K0aB%~ ߾} _>%<_B%`O`~O>~/|&LР>~ ߿|o>~_>'p 3hp ?} 3_>߿}߿|3hP? 4hР? 4h A} $O`>/|g`|  O`>/|g| 4hРA4H0| 70_>˷Ϡ48>/| 70_>˷Ϡ4h`A 4hРA g | '0|/? g@} Ǐ?} '0|#|8| ,X`W`O`_>~ _+X>~O`>/|W@} ,X A ,X` _O`>o>/ `,_>~/߿~?~?}+XP`> ,X`+X| '0'pW`,XO|/|Ǐ߾}_> HP>~ ,X? ,X` ǯ` '0@}/_>~/_W`A} o_| ܗO_>ӗ/?߾,(0 ,X`A,X_>/_>~}+X| ,O_˗O_?'P'p_|_W` W` ,X@} ,X` ,(0 W` ,X`A,X` ǯ`TPATPA,O_ ,X`W` W` ,X@} ,X` ,(0 W` ,X`A,X` ` ,X`+X ?} ,X` ,h „ 24_Æ 篡@}6lذ`> 6_Æ 篡@~6lذ>~ 6_Æ װaÆk(P 6,_Æ װaÆk( 6,_Æ װa5lذa| ǯaÆ װaÁ5lذa| 䧯aÆ װaÁ3f5l>~ 6lX0kذa5lp>~ 6lX0kذaÂ5lp? 6O@~,h „   <0B'p "4O@~,h „   <0B'p "4_„ P $08`A'p 8`A&TH,h B8`A8p @},h?$X@},h „ O@ B"D!ƒ 8? 4xaB 6tbĈ 8,h „ 2lB B!|O@ DPB >1"| <0… :|П?!B|08`A&TaC!F0'p "Lp!Æ*"D'p@$XA .OC 2dȐ@? 4xaB ǐ!C cȐ!C 'p@$XA ./_} 2dȐ!C8p`?$XA ./_>} 2dȐ!C 2D08`A&T|ǐ!C 2d`>O@ DP˷!C .!C O H*\`>8`A&TaC 8,h „ O@ H*\HП? 2dh`>'p "Lp> <0… O8`A&Tp|O@ DPB1dȐ!C 8? 4xaB 'p} H*\Ȱ!A? 4xaB 'p@} H*\8П? 2dh`>'p "L0?$? 4xaB 60'p "L0!| <0…cȐ!C8p ,h „ 'p A H*\Ȱ@? 4xaB'p |8`A&LϟB *T0!|O@ DP!B} HP>$XA .dP | <0ƒ8@$XA PB *L08`A&Txp|$? 4xaB 60'p "L ?$Hp,h „SPB &O H*4`> ? 4xaB 6O8`A&Th`> ? 4xaƒ)TPB 'p@$XA O@'p "Lp!Æ 8,h „ O@'p "Lp!Æ6O H*,`> ? 4xaB 2O8`A&THp|,8P,h „ 2l!C <0B8`8`A&TB? 4xaB'p 'p "L? .\p!|O@ DP!AO@  <0… 'p~ H*p H>8`A&TП .\`>'p "LP>? 4xaB 6$0'p "L0>? 4xaB ǐ!C 'p@$XA *0'p "Lp!Æ8p`?$XA &0'p "Lp@2dA <0B8P>$XA .dؐ | <0„8P>$XA o… .\(`>'p "LP>? 4xaB 6$0'p "L0>? 4xaB[p…  O H*T`>O@  <0… 'p~ H*L`>O@  <0? &L0a„8p ,h „ O@(0,h „ 2\0'p "L0>?'p "LXП? *TPaB <0B8P> 7p`>} ܗO_>/_>~ '_|8`A&$0'p "L0>? O_~ӗO`>˗| /? 4xaB O H*T`>O|/߿}'0|߿|O`>~ HO8`A&Tp| @_O`>'0o|8`A&T!C <0B8P> O@_/߿?}_ <0@? 4xaB 'p} 0@/߿|_?~/߿|? 4ϟ0 HO8`A&Tp| @'0߿| '0?߿|O@  7p`>_>O?_ ? 4xa 8,h „ O@(0o?/?}/߿~'8p?8`A&T`>'p "LP>?(߿|Oӗ߿}/|? 4xaB 8,h „ O@(`>_ o_>}'P߿>8`A;x<8`>'p "LP>? 4ϠA 4hРA'p~ H*L`>O@ 3hРA ϠA 4hРA 8? 4xaB 'p} H| 4hРA 4`>O@ DPa} (p,h0A $ϟA 4hРA 08`A&Tp|  <0… O8`A&Tp|  <0-\p… 'p@$XA *0'p "Lp!Æ8p`?$XA &0'p "L? .\pB 8? 4xaB 'p} H*\Ȱ!A? 4xaB 'p} H*… .\P |O@ DP} (p,h „ 2lH`>O@ DPa} (p,h „ p… .08`A&Tp|  <0… O8`A&Tp|  <0… ˗/ O H*T`>O@ D`|SP 8,h „ O@8`A&Tp? C 'p@$XA *0'p "LH0@}*T`>O@ DPa} (p,h „ |/_>~ӗO`>˗| / 8? 4xaB 'p} H7П'p_>}O | '0@~+0'p "L0>? 4xaB `>'0}'0|߿|O`>~8p ,h „ O@8`A&$`>~o?}O` Ǐ | <0„8P>$XA .Ão ?}O`/| 䧏 |O@ DP} (p,h „̗o ?}O`/| 䧏 | <0„8P>$XA .Ã`>/߿#H0,h „ O@8`A&$o?߿|/?/? |8`A&Tp|  <0-\0@}'}'0߿~'O?O H*T`>O@ D`'}'0߿~'O?O8`A&Tp|  <0-\0_| ܗ/>'p_>}˗O}/_>}8p ,h „ O@8`A&$/_|˗O@}/|˧O| ܗ/ 8,h O@8`A&Tϟ .,oƒ 8? 4xaB 'p} H*Toƒ 8,h „ O@8`A&Tϟ .,oƒ 8? 4xaB 'p} H*Toƒ 8,h „ O@8`A&TaC!O H*T`>O@ DPB 'p~ H*L`>O@ DPB >`>'p "LP>? 4xaB 6$0'p "L0>? 4xaB ǐ!C 'p 'p "Lp>? 4xaB .0  <08P>$XA .C 20  <0B8P>$XA .dp|,HP,h „ O@8`A&Tp? 2d|,H? 4xaB'p} H*\Ȑ>$Xp ,h „ O@8`A&Tp? 2d?$XP?$XA 0'p "Lp! H@~ H*,`>O@ DP?.\p„8`A~ H*4`>O@ DPB 'p 8`A&Thp|  <0-\p… 'p 8`A&Txp|  <0… 0O@ DP} (p,h „ p… .O@8`A&Tp|  <0…  0O@ DP} (p,h „ p… .0O@ DP!} (p,h „ 2l8`>  <0B8P>$XA o… .\o| <0„8P>$XA .dp ?? 4xaB 'p} H*\ȰÇO|8`A&Tp|  <0… 08`A&Tp|  <0…cȐ!C80,h „ O@8`A&TaÂ8,h „ O@8`A&Tp? 2d`?  <08P>$XA .d |O@ DP} (p,h „ !C "ܗ/_} 2d>? 4xaB 64/_|:tp>? 4xaB ǐ!C ˧!C "0'p "Lp!ÆСC 'p} H*\8П? 2d0C 2L`>O@ DPB СC 'p} H*… .\p… .T`>O@ DPB >>? 4xaB[p… .\p… 'p} H*\ȰÇ#B0'p "L? .\p?'p "Lp!Â8P>ϟ? H*\HП?8`A&TaA} (P@~ ϟ?$XAK0a„ O_|'P @~,h „ 2lH>(P>~8`A&T(}˗>8`A&TaC /_| ~%L0a„ &L0!A˗/? &L0a„ ˷_ &L0a„ &~ &LP`|%L0a„ &L0aƒۗ0a„ K0aB%L0a„ &L0a„0a„ 0a„ &L0a„ ԧ/a„ 0a„K0a„ &L0a„ /a„ K0a„ &L0a„ o,h ƒ%L0aA&L0a„ &L0aBK0a„&L0a„ &L0aBK0aƒ%L0aA&L0a„ &L0aBK0a„&L0a„ &L0aBK0aƒ%L0aA&L0a„ &L0aBK0a„&L0a„ &L0aBK0@&L0aB&L0a„ &L0aBK0a„&L0a„ &L0aBK0@&L0aB&L0a„ &L0aB/>$XA %L0a„ &L0a„˗0a%L0a„%L0@}_B`|K0A}%L0a| &L(P㗐%D/_} &} /@~/_~/?~O_~!B˗!B"D!B!Da|߿}o߾o?/|'PW0@~"DP|"Da|"DX0?}o߾۷__'0| _>~̇!Bˇ!B!BӇ!Bo||/O`> _> 0@8`A ˧!Ḃ!Bo|70߿|7П@ '0_>`>"4/_>"D8П?"Dϟ>"$0@__߿~__@ }"D`>"$0@__߿~__@ ۷O>~ W>!D?~!D!!D!!D}/_|˗|/_~ۧo?}/_>~ W0_|!D@}!D!‚"Dp~/_|˗/ϟ|˗o}߾|߿| /_} Hˇ!B!D!BC!Ḃ!B"D|"Da|"Dp`"D!B"/B !B!BW0B"D!BC!B!D! C!B"D_|"4B"DhП>"D!B"D!BC!B!D!B"D!B /B !B!B"DP|!D0BԗOB",!B!B |'p  ;xA;xA}/_~ '0|'_|Ǐ`>̧/>/_>~ӗO`>˗@~oww@~/_>~?}O`>/_?'0>~/ӗo|/?'0|| ̷˗? 4xA&L?} _ /_>|o|+/>o߿|'P}O`}_BK0a„|߿|?O`>~}A3߿}>_>o?߿|/_„ /a„ ӗ`#/|G0| '0߿|@@O` '0| /@~8p@O@ D0_B`o_O`>O߿|_O`> '0| o ?}%,/_ &<_„ /|̗O`>'0| '0?@/@O` '0| 0'p A+X` ,` #_>o߿| '0|8__?}(0| 7_| '0߿|'p| H | ,X`W` ,ϟ '0߿}O` '0߿~O` /_|W0'p>/|o|߿| ԗO_ ,X`| ԷO` _>'0߿|O`>''P_> o߾ _ ̧@~+X | ,X`W` ,ϟ ӗ/_?/@˗/_ӗ߿|/߿/˗/?}˗/?˗?}/|˗}o˧? 4xa| ӗ/_?'0|˗߿}O`>˗O|˗>~O`'P_|˧/?o_|KX_| &_„ &LO_„ &L0!| &L|&L0a &L0aB&L0!B~%Lp? &L0?} &L0a„%L0aBK0a„&L0a„ K0a„˗0a%L0a„%L0a„ &L0a„ӗ0a„ %L0J(J(" ~'p  !B"4OB"D!B"D@}!D!‚"D!B"D!B˗!BC!B Ӈ!B"D!B"D(P_>}"D`>"D!B"D!BC!B"DР?}"D!B"D!BӇ!B C!B"D!B"/_>"D8П?"Dϟ>"D!B"D!BC!B!D!B"D!B /B"4@'p ",/_„ &L0a„ &LH0_>} &L0 &L0a„ &Lp|&L? &Lhp_>~ &L0a„ &L?~ӗ0a„ /a„ &L0a„ "/_| &LxП &  <0~ (P>} H*\Ȱ!}O@'p !B"D8?$XA .dC'p "L?} H*\ȰÇ } <0BO>$XA .dذ>}? 4x@8`A&TaC!F8bE1fԸ?9rȑ#G9rȑ#G9rȑ#G9rȑ#G9rȑ#G9r<G9rȑ#G9rhП?9rȑ#G9rѠ?9rȑ#G9rȑA8rȑ#G9rȑcE8rȑ#G9rȑ#Gqȑ#G9rȑ#Gȑ#G9rȑ#G ?(?8?8?(?8?8?(?8?8?(?8?8?(?8?8?(?8?8?(?8?8?(?8?8?(?8?8?(?8?8?(?8?8?(?8?(ПП@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ П}@ П@ ? 4xaB 6tbD)VxcF9vdH#I4yeJ+YtfL3iִygN;yhPC5ziRK6ujTSVzkV[v;;PK񡣳PK-AOEBPS/img/adque445.gifsHGIF89aեzyyXlllfffvvvbbb666.-."!"VVVQQQFEE>>>ƴJII%%%jjj111NMMk^@@@***^^^rrrppp888nnnhhhXXX;;;ZZZ|||444<<<\\\DBBBᮬ867HFGDDDoookkk978(''423TST_]_AAA\Z[TRS___///777???999555ӣ྾333}}}CCC(&'OOO###WWW===dddKJJIGH{{{=;<]]]0./qqq߽ꏏҋ,++omottt緷mmmxxxؗ@>?[[[KKKɹiiiꘗ nnlbh`YYY~å}tqpc$$$GGG756poo?|{{Წ[sTgggwww!, H*\ȰÇ#JHŋ3jȱǏ CIɓ(S Kh͛8T-ʙ^(\ʔO֟'jD>!hJF }D3`x#b`?q&f$&A~ CiA>M;ߟjM, BYw~X! οÊES@7J# ˴f@E 7?Gda&7A[+&Vfl8#@F⢉T`pA'̑L,p?R,E-aY~zJ TA I_ڦVAaTQ9||Ă?'x0FR?A?O1ψ%Ȇla]F'-P@KI&:,0b 8 N) $?p,0<O-nc%a`p@`@,PAX?1P/ H(V  ?8O Tl$0,JZX0vC  @b'.Bt?= !PBx1vT?3%0ىjt0kFt/w R,)p-eB!{Bt=SU V`HB Q"!/s?xGY(|.M ô%Dij}XЂ=ܰ@1p ?AN ׭sG{r萚?;" *8)~O?@9h`HϿ7K}|  08@ p g`0 rX&xE@$f$4Xi@ȁ|40XF( P2 v@6XVЂ/8v2h^8<BHGEK؄d8P(TtXDž3X|9=f8jXȆLNS؇wy{|1hhn8؇Xc艞胣]ht(%((ȋxdĨxWȌX()!@ )B5P5GK/ rBx+@ 8p1 tPs` p$ȍXyhpP i[]BB d[a- @KJb$P%~aa *) GP&YgPh0"QɑWI 7`  7npq8'V@-`0=9;[Eb@@zqy `0 K0S`Ț&ؕ! 6P0jqzpPeE ѰU m# `}]҇} /`(lC !8 pZ ,\0 ~`pp u P ~ q={ yw>u€vc`  }q  lp0rKI*qʇm y<~v0' p@"1l[0 L2KPrpMY4 d`m 0 Z?c](ED~Pw n'rz^7 I &7rzxBN%by"?@%j )o t ΠhRkȞ.g{{g`z 8+A:.IN΀|mp^~a`P M$qꪎoN$8~?~N-n TpI 7QH,QNw!. u +mH"*dxpA_>0pÁ6l@l!GDRCHqrCHz2;iCř2T'el!ԣY9WmܹsyЏ,2n*f:'GH$hh`E.[qTNܠ4*2!$Xa^0)c w^ppq)*hw80 #UZ02H2 =]I&l ,2(@NC4jqɖ4a 9<@I@,.c Ra(}3q 2۬8~=<Q~@b06= Bݭ߂laUgA0`*`5.W3FxA }jC w_"pE CN$YAa `fCSF L)q}t0 ĨE& >iƙj"PE 6"L I2`4ƟT D)̃` p*2d\W<ŀ\襂0YCq$@`+g@P8 +X=@Oh!YD 0l1W`IN8} pj @R S!(P+fdPFĸ6q*:qhưF` L„YHCgV.`>f3 ! ^^ XI뙴*t((CrY6!R@͚㘫e?IH96'^B* )qwS02 P vx8 cxr~(([BTa}ȏ r`?FBG 1 `p;(ЏA 0 U$ :`/ఆ #pHC C#X`$';O2HL!d BSIxq 5sD *24  0  D)gB0DG~`$רP>amSTA\e.A ؜8! 9B"@P<|<  .` w`!5?J4pE* :) Axq9j"KR6‘x# )8 3@G|b@.OP32QB`wB3 1uhbr@'<"%I'qS$acXXmLWS4T(N@@X!ah";iE) BHNTc@B6x H >@_AWRӚS&_ {nP'&at o _Ű;? tt^0B8#87RY$1NY*9-/ {O`At q(RAZ8 L`  0졇Hv! P`pC*.^%&/^G,ŀ&EM1jE8-`p4"BF!@`qCv`G ePZnI|dM/:eLW zx Ҵ- qy X*J `(e7[u4%5f~Mq`9p*d5 >l1Zy @(R]:s `@0|~rmX6Uo/D @%*!f MhA+Ј\:*F8 ^'|<;,,tK`CD=g! P t BEҔJd42'yF)έ՟7wE'@'pyTH PP}8>EY0»B E Ћ^3/?5lqO8wH~m*|* {w6(B j@0 Đ# '1?8&[)! :+ۋ?@p7ГH=6hG:@ȃDB@\U9DHC,AdDA*AH;ۣ02,FMDN\PtRFT@UM(4\[}"UÜJ4L|bH}HǫV$,@<`A:BFDԹ T0II ʇuX\Jlʥԇj9A./scdDPlQ|FS$GA>~{k 8}G]ƒK rZ8:KK LL4JX$LF96!Lɜ$FJJIrLȃx;%ӰMNh0IPX 8@hRXZH}`鶞M NTOTP UQUR%U*WP9 $!RTh1R[U\39;@` VaVb-Vc=b2]>xa߬=CG6VG` H;X>'TJKT0 XUWMҵ{Xd-X=XdUBX|TXX́e5S^DSM>i>C@1E@]P lrVEopו87R+4KJLzW}PWec -[=I5=V9"J[l.@4XfMSxhB0 $"Wbs g HP h5D#0`q `^ܓY,WqUܓQЄ x P |IyڪU @ݓ 0CX @p;PmZ~ uڶ%VI8[ 8-ַF#I %e}[\PT< @EA"ɭt@w 0$0]wH; T30@ e]׍=]] u040$)W(8xFAP)^iߖ(__a_Xg_#Ʉ0ߵ550c>c?? `X8f[h}9$0"KpC I@ \U,PV JH O]X rH]`aSp֠;X؃ rޏ9b 4%N^_ڂ+!pg8 H@ PZ@8 -F??2`܃Bu gcm90c@;VIЇ@hz߅}`e0ii.i3D50"y>(W>DrP~ ,X^(@Tp8\ P[6A4o= fF JwJ HaE%x $U0/D^&FMhp=@ 89@eZ> 6fGpx'>wp9x7t+(PW~XephVmidhmX;ek0gpw(epuȤ@X uIH^h4Ї Yx0\ :j;.AVP8iaNP*hK}\pf6^i z(PPHu>.p= QpF@ 5dv ?AmEh8puo@2`_r.F$h>9%A@#,2`p;78 n@fzl?~ ~(.<0 LppO8P8015-^$nK>N6 4 @Fޓ q6cI&kXW `ng#76gw0l(mi:XV +ru/KiHah ( EN(b b` @S@54 -\2h6wgO聚LyyyOZybg0M7ktc] Nw\ph'h$ %N@eȂ"f; G%g (gNQ` Rrg0*Ov'nvVV,x`*lb|} |"t@mFgP&M 6G ~PyIqb X\cg pPppZNr|S}֏}b՗@Owwb!YoFc A$NwZB!$8q4I#AB̉!#РBuҤJ2m)TrpNԬZf3f(X-!w'ڴjײm6-aҭk *JǞKZ ' J+B >)#Z`D4iӧErm;ԪWok[ ,f9~5#V|q.1âP F$A Y e7 ֓?(QIx[nVa5!['qƙU 5\tI !wprx xX &^{i 5g[ s02"nC H`F!OU[e2ac!A0 TlI r/t?b@=8֋+#AO #":tBL@UD/Ƙ}GLOXF.u`C IariOP$lN W}m"]N8l0D ނ[pt Ѓi[W&؈o8!mf;`jD X >d TCa@TR* X =XXJteLgŢ?1RtŬAr?l?(H1Ġc#-[;Ë*Z- 60708 |A {݈(T>PF[H~)p>YܚT ?O*Ne#.'P?ȸTL&*A?L056"a"=@L34*~@E qx0(cv, ?9J)\$Tw V|zV$~pR890V- Bā  \n-!&!.ktlX& `lZ]$H?2.=0BP5'.HYB{lQC g> '|H*`K(P-4pcs8bԦ@@n| -?`X. Z ,ch' +Pɝ x n[|:ֹ A 0xFRaYX d4ZШƢq˨@&rT?<0CDя@)% B#&D2-`@$JI`'gZEDU愕X 1÷xIM-o*!\ESc XƲPFc?`YdȄ?3X @q^y8Dљ4zj\89 h"_k0VV` m]r9> FP@8H%. EN  E8.0 X"E Q (` `(L ^ i R[jS gxzӫ}/|{4"+F=Y. SlPyX; "Ɇ G "+δ;ShA%@h P 8@5,@ j` q :ЎMj[ζn{\@r\J7-D' @h5h/Dl@/Z8$x{ӶtA41)$%4AY>vjy(ۄYqֳ-iMZղֵ-mm[ַ.q 6}Ik@4}FP5EMNmI@MMG =4Z)Sw!U3( E{C ܠ<ȠD}4f 1IAP ?i`a \ ,}6^`%" _L /""a#A5v؋aZ .nR$aZ A?P@M0ۿ>C$ \C#$B"A-"J?j!!@zȁ-Ph;;#<#F$JrP\ybSt"?(()*?X+¢,-.A/b0c1c2.c3>D4V5b6r78_[\$LƤL !@:c<$<Σ`hĆPPB ,#d }?&T.Zٗύ()*+[CҢ- QZE@r)%]֥]F d [#Xaab b.f14><Dde€e^& ̂fgVgh hf f4f4A)؃$S_ Nn2=%R$N VdW&B9$D؁:T% uVu^'vfvn T e9N_]#Vց A[1reD"/>/01"#q3B4~H^c6n#! `>'R#? 'FgAr%B*W|>XsR أrp0yg_[zg*{B|*,zh}NdE'FFJ3G(5rb*L$fxFEip`zg&'hshcddB~OT1"`"N(yۋ^({'|ꛍ2'EEgF2iG hHVd.?@"4Bz"qj|zi舢$p D8p’DG,B8[K$k\A5ܩ_M(Ҩv)}EF )Ri$&?CDVFiTWU_ONVr"@#(}:g*N`? QgM  C(T4j_-]fƶ^%hBkJj^kGnk)Z溪&VR.Az%,`/@|*Z< Q ~AB,@`3CC3@Ѐ3T 0M@AdX* )zhj*Z+˂$:">CܹbRЊnh!H8("' 2l+F`*F@ A;\CV4;S 38;@ )AH,V,.g:+➬hꏺ,N~^_gnbv-njC ?TA At@:\A?lF?\F,ZQ# t oC4T%Ȁ(NlߞxinlXl//\@Fi誁%km-E-.AT 0@< C ? $Ѐo @4CKD kR "^2M | Aq:Rh/o#i??$A >eζpA,@1Bb(ADE'+N0B~?/!rdDD:  A)p B@o&  ?\K`R,%[\n?ebZ!P p()+qr˲2̺r&A68Cdζ/lφ?hB(+B( ?  E0ewC,S0 d^L *,?wB^/ X@ b>K>a B/젢>nF.RB|A-gb.c!I 'bJ 3"4CA(tA@B1D B6 Fd ?0I ?;xMJrW/'x@TYBr:J+%3#4MrC(Ik0!bb @*I @@r(L>p:6XqA+DM1ruCus3qDkktw488EvۦSbώ&d(?+E<}hcwŶ%c2!l@ T 0k2C4Ưtd?|]8EFF_.nd`0$[D(ԁ.s\b?9tp8Ȟɦ2C쒷r G[:$<+njBo4膸rTqꦃānEA @ d@z  (Z8'[ĹWY#yOt2)DH` w_7pZA P, $;h۝yQr;v|)0B A!۳8B/ L#%D 5 M2RV - I;ɱgXB1ŗHӰ`C6JtIRMR!pgN;yJ x^5ziRpc,Iƍ8EңR6A_<,ǏE2aATgr|tΣ6p(U BuKZؤp$Tb05 D)l0 ɒ,p#~R <ȫ2yAVTq ~DI i6 ӢhMt͑R*bZq9ܵBԈIa=4~49Xc9ُI1?Jt8}!ZȠ$?8qeȕ_y)VCn-tm] .ۥ0^ ZXh 5\! _Bo8D"\ʯ Q@I:P]?pJXEspDBջa;0 xJaT0_K0 |oOaM[$DfQb MВ? ؒ0" m-Q@n/ԡK^8Dg¦rD %qM|b YHUa"=BE>k'4Q>! d$@-$gd ܤ0@bJkĢ9.H,>rJ[bI(т;Ɍ I%f\db6%# `fpe3w`dK@PEC?^YժV~aXZVիZV26{\ZWy^ E쭁.;PKxHsHPK-AOEBPS/img/adque040.gif|pGIF87aC?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU,C H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ J(K> 4xaB 6tȏ?8`A&TП?~'p "Lp!Æϟ?$XA .dС~˧O>~'p "Lp!Æ O|? 4xaB˗/>}П <0… .Ǐ?}˧?$XA .d}ϡC:t谠~ϡC˧?:tСC˗oC:t_}:tСCϡCСC:t߾|:tСC9tСC:/?ϡC:t@~9tСC sСC:tH0_>:$ϡC:t!A9tСC sСC:tH0_>:$C:t!A9tСC sСC:tH0_>:$ϡCr!r  <0…  ϡC:t!|9t`>:tСCСC&ϡC:t!|9t`>:tСCСC&ϡC:t!|9t`>:tСCСC&ϡC9琠>̗ϟC sP>ǯ9/_}/C:t?˷|5'Ás`|:tH0C _ϡ@~? 4x|"D!B"DX?",_'0|| /_| ̧/_?C!C!B!DaA} ̧/>'0߿||ӗO߿|O`>}o>"/_>"D!B!B |/_/}| o@}/|C!BC!B!Da|߿}߾}߾_߾߿| ? 4x@%L0a„ &L8 &} /|˗oO`|'0_A~ۗ0aƒK0a„%L0!?~o`__>G0߿|̗0a„˗0a„ &L0@~&L`>߿|/߿|'P`?}O`|O`(? 4x`|"D|"DH`>߿|/߿|߿߿| ߿|? ? 4x|"D!B"DX?"O}__> '0߾}O`> !B!Ḃ!B߿|//?}'_>۷O>~ W>!D?!D!B"D ?~"D8p_˗/?'0߿||O˗|o`?}"D/_>"D`>"~0߿|/_~ۧo?}/_>~/˗o,hA!D!B"D ?~"Dp`"D!B"̗B"4!BW0B"D!BC!B"DaA~"D|!D!B"D/?"Dh0B"`>"D!Bˇ!B"D!‚!D!B"D!B ̗B"4!B"D!B"DP|"D!B"DX?"D!|"D!B!B C!B"`|8`A~ӗO`>˗?~o}/_~ '0|'_|o`>̧/>/_>~ӗO`>˗?~o/,h „ 2l(?߾}O>~O`>_>~/? ̗ϟC s(߾'P/'0|/?~/?g0_}۷| ߾'05/C:t?70߿|̗o`>o|ϡCСC 7_>}O`>o ?}_ |߿|߿|߿8 A'p "Lp!Æs!|/|O`'p| H/a„ ˗`>O`>/| '0?߿O_> 70߿| /| / /$/_>$XA .dP ?~:$?~o}/|o| _>̗ϟC s(P>߿|O`'0|O ?O>}Ǐ߿|߾}_|O?_|:taB~:tH0_|/_>~˗O|/_~˧O`>̗ϟC s(П|ۗ/?/_|˧/| 'p_|#/|߿_˗߿߾|/_~˧߿| H|8`A&TaC9t`>:t0_>:$ϡCСÅsСCСC:ta|9t`>:th0C˗ϡC:LȏC:tСCs!|:tСC ˗ϡC:LȏC:tСCs!|:tСC ˗ϡC:LȏC:tСCs!|:tСC ˗ϡC:LȏC:tСCs!|:tСC ˗ϡCr(!O@ DPB >T/?"D!B/_>!Bؐ_>!B"DC} B"D˗"D!:ܗO?!BB˗/?˷D!BQ?~  <0… ܗ/_|ϡC:tП~O|8`A&$0@? 4xaB 6t8П?~O|8`A&TaÂ'p A H*\Ȱ@$Xp> H0 'p "Lp!Æ8`8`A&TaCO@ DPB 2Ǐ?$XA  O|,h „ 2l萡>~8`A&TaCO@ DPB'p@$8П? H*\(П? H*\Ȱ!??~ <0… :|1ĉ 'p@$XA .dC%"O8`A&TaC!F8qb? <0… :|1D 8,h „ 2l!Ĉ'N08`A&TaC!F`>O@ DPB >Qĉ8p ,h „ 2\aÆ 6\0'p "Lp!ÆB(q~ 8? 4xaB *엏_Æ 6l`>O@ DPB >Qĉ8p ,h „ 2T/_> 6lذaB? 4xaB 6tbD'O H*\0|kذaÆ 'p~ H*\ȰÇ#J8|O@ DPB'P>$XA .d`>O@ DPB >Qĉ8p ,h „ 2<`>O@ DPB8p`?$XA .dC%N`>'p "Lp!à 8? 4xaB O8`A&TaC!F8qb? <0… O8`A&TA? 4xaB 6tbD'O H*\Ȱ>$O,h „ 2,0'p "Lp!ÆB(q~ 8? 4xaB 0O@ DPB8p`?$XA .dC%N`>'p "Lp!C H ,h „ 2$0'p "Lp!ÆB(q~ 8? 4xaB 0 O@ DPB8p`?$XA .dC%N`>'p "Lp!C8`A8`A&T@? 4xaB 6tbD'O H*\?$X`?$XA .d`>O@ DPB >Qĉ8p ,h „ 20 O@ DPB8p`?$XA .dC%N`>'p "Lp!C 08,h „ 2O8`A&TaC!F8qb? <0… 'p@ H*\ | <0… :|1ĉ'p@$XA .dx`>O@ DPB8p`?$XA .dC%N`>'p "Lp!à 8,h „ 240'p "Lp!ÆB(q~ 8? 4xaB O8`A&TA? 4xaB 6tbD'O H*\ | <0… 'p~ H*\ȰÇ#&O@~ H O H˗/ &40'p "0@8`AO8`A&TaC!FLOD8p ,h B0a„8p?$XA%L0a 8,h „ 2l!Ĉ ̧/_?'0|O`>˗~ 8? 4x|/_>~ӗO`>˗| / 8,h  ӗ}O`>'0| | <0… :|1b|߾}O` _>'08p ,h Bo|/|O`>~ >O8`Ag0_>o|}+0'p "Lp!ÆB`>_߿|߿_OO H#_O`>O߿|7> 8,h  _߿|/߿|_?~(`>O@ DPB >1a>o`>0 `>'p "o|80߿߿| ߿| ?O@ D/|70|Oo@ O8`A&TaC!FL`>_>O?_ `? ~#0'p "`>_>O?_ | <0… :|1bB /߿7߿}o@}˧/߿O~ 8? 4x|7p_|˗/}/_>}ӗO|O8`AO@~?}ۗO_ ߾|O>O8`A&TaC!Fx0ą8p ,h „ )T`>O@ Da> 'p~ H*\ȰÇ#J~0'p "Lp!ÆBT߿|'_|ӗ/_?'_|˧/?~+/_08`Ao@}O8`A&TaC!*'0~>_|'p?_>~g0@ O H ̧o|?}/_~O| /? ' 8,h0|/?~?/}۷|~g`>O@ DPB >0|/߿|ӷ@}/߿|O|08`A ǯ?~O`>~/_}o`>O8`AO}ׯ~ /@~ ˗|8p`?$XA .dC O߿}O|ǯ_7p`>7_'p@$X|O߿| O߾~G_| /@~ o` 8,h0|/?׏_}˷_?} _'p~#(`>O@ DPB >0|/?}󷯟| /@_>}g0A}'p@$X|o߿|8_?~/߾~/߿8߿߿(`>O@ }@~o_?/߾}@~'П> 'p~ H*\ȰÇ/?/_>}˗_|/_}ۗ/_w0~ O Ho'}O`|o?'W`>O@ /?/_>}˗_|/_}˗/}+/_}30'p "Lp!ÆBT_ĈAw|O@ O` 'p_|˗/_~/_}ۗ/_>G`>?8p?$XР?~ 4h`> 3`>O@ DPB >p_D_8p ,h?~O@ DPB >Qĉ8p ,h „ 2<0'p "Lp!C 8,h „ 2l!Ĉ'N08`A&TA? 4xaB O8`A&TaC!F8!@O  <0… 'p@ H*\?8p ?O@ DPB >Qă8`A H*\| <0… 'p 'p "Lp!ÆB(q"B} H A H*\| <0… 'p 'p "Lp!ÆB(qB$Xp ?$XA .d(`>O@ DPB'p 8`A&TaC!F8q?$X0>$XA .d8`>O@ DPB'p 'p "Lp!ÆB(q"} H ,h „ 2$0'p "Lp!Á H>$XA .dC%Nt`>  <0… 'p@ H*\p?$8P,h „ 2l!Ĉ'BO@'p "Lp! 8,h „ 2$`> O@ DPB >QĈ8>$XA .dh`>O@ DPB'p A~ H*\ȰÇ#J(q|O@ DPB8p?$XA .dh`>O@ DPB >QD80_?$XA .dx`>O@ DPB'p`>} H*\ȰÇ#JHQ |O@ DPB8p?$XA .dxp|'p "Lp!ÆB(q"Ł˗O_Ŋ+O8`A&T!B}ǯaÆ 6lذaÆ 6l|5lذaÆ 8p?$XA .d0_|6lذaÆ 6lذaÆ ǯaÆ 6T0'p "Lp!ÄkذaÆ 6lذaÆ 6TaÆ 6\0'p "Lp!C5lذaÆ 6lذaÆ 6lذaÆ 'p@ H*\ȰÇ#JHŋ8`A&TX? 4x @,h |П  <? 4xaB8`A&TaC!F,`> 4xaB'p 0 <0B8`A O@ DP!A} H*\ȰÇ#ODP?%O"D$J8>%J(QDI(q`>'QāI/D'QD%JP?%OC}$J80?(Q@~$J(QD'QāI|D'|%JOD%J(QC}$J80?(Q|$BOD(QD%JtD'>~%JϟDI(q ?}%J(QD(Q|$>OD,hA"D!BO@ DPB >>~%JϟćI(q`>!'QāI(QD%:ODP?%O"D$J8>%J(QDI(q`>'QāI/D'QD%JP?%OC}$J80?(Q@~$J(QD'QāI|D'|%JOD%J(QC}$J80?(Q|$BOD(QD%JtD'>~%J|8`A ˇ!B"O,h „ 2l!Ĉ(Q|$>OD_>%OD%J(ѡ>~%JϟćI(q`>!'QāI(QD%:ODP?%O"D$J8>%J(QDI(q`>'QāI/D'QD%JP?%OC}$J80?(Q@~$J(QD'QāI|D'|%JOD%J(QC}$J80?(Q@ "D?~8`A&TaC!F,D'>~%JϟDI(q ?}%J(QD(Q|$>OD_>%OD%J(ѡ>~%JϟćI(q`>!'QāI(QD%:ODP?%O"D$J8>%J(QD H*,? 4x |,h „ O@ 4`> 4xaB8`A&TaC!F,OD'a>}%JϟDI(q|%J(QD(Q|$>̧OD_>%ܗOD%J(a>}8`A&@'p ̧ @,h „(0?$XAO@ DP  <0… :|1b| 'p "L(?O@ ,O_A$XA 'P`> H+П <0@ ܗ? 4xaB 6tbĂO@ DP  }8`A&@'p  @,h „(p_>$XA .dC W? 4xaB ,h`| 'p "L(?O@ 4/_A$XA 'P| H*\ȰÇ#̧ @,h „(0?$XO@ DP   H+П <0@ ? 4xР|8`A&@'p "Lp!ÆBX0 H O|8`A W? 4xaB ,hA 'p "L(?O@ DPB >`>}%JϟćI(q`>!'QāI(QD%:̧OD0>%O"D$J8p_>%J(QD H*,? 4x |,h „ O@ 4`> 4xaB8`A&TaC!F,OD'a>}%JϟDI(q|%J(QD(Q|$>̧OD_>%ܗOD%J(a>}8`A&@'p ̧ @,h „(0?$XAO@ DP  <0… :|1b| 'p "L(?O@ ,O_A$XA 'P`> H+П <0@ ܗ? 4xaB 6tbĂO@ DP  }8`A&@'p  @,h „(p_>$XA .dC W? 4xaB ,h`| 'p "L(?O@ 4/_A$XA 'P| H*\ȰÇ#̧ @,h „(0?$XO@ DP   H+П <0@ ? 4xР|8`A&@'p "Lp!ÆBX0 H O|8`A W? 4xaB ,hA 'p "L(?O@ DPB >`>}%JϟćI(q`>!'QāI(QD%:̧OD0>%O"D$J8p_>%J(QD H*,? 4x |,h „ O@ 4`> 4xaB8`A&TaC!F,OD'>~%JϟDI(q|%J(QD(Q|$>OD_>%ܗOD%J(a>}8`A&@'p !B"D/?"/_A$XA 'P| H*\ȰÇ#̧ @,h „(0?$X!D!B!B+П <0@ ܗ? 4xaB 6tbĂO@ DP  $XA .dC W? 4xaB ,h`A}"D!BC!BO@ DP  <0… :|1b| 'p "L(?O@ ,B"D_>"D(_ H O}8`A&TaC!F,O_A$XA 'P`> HC!B!BW? 4xaB /,h 2l!Ĉ+П <0@ ? 4x>~"D!!D@ 'p "L(?O@ DPB >`>}%JϟćI(q`>!'QāI(QD%:̧ODP?%O"D$J8p_>%J(QD H*,? 4x>~"D!!D@ H*, <0… :|1b|$J80?(Q|$BOD(QD%JtOD'>~%JϟDI(q ?}%J(QD+П <0@ ? 4x>~"D!!D@"D!BO@ DPB >`>}8`A&@'p !B"D/?"/B"D?} H*\ȰÇ#̧ @,h „(0?$X!D!B!BC!B? 4xaB 6tbĂO@ DP  $XA .dC W? 4xaB ,h`A}"D!BC!B!D!B <0… :|1b| 'p "L(?O@ ,B"D_>"D(_>"D?~8`A&TaC!F,O_A$XA 'P`> HC!B!Bˇ!B"O,h „ 2l!Ĉ(Q|$>OD_>%OD%J(a>}%JϟćI(q`>!'QāI(QD%:O@ DPaA HC!B!Bˇ!B"O,h „ 2l!Ĉ(Q|$>OD_>%OD%J(ѡ>~%JϟćI(q`>!'QāI(QD%:ODP?%O"D$J8>%J(QDI(q`>'QāI/D'QD%JP?%OC}$J80?(Q@~$J(QD'QāI|D'|%JOD%J(QC}$J80?(Q@ "D?~8`A&TaC!F,D'>~%JϟDI(q ?}%J(QD(Q|$>OD_>%OD%J(ѡ>~%JϟćI(q`>!'QāI(QD%:ODP?%O"D$J8>%J(QD'p "LP`> HO@ DP|8`A П <0B'p "Lp!ÆBXP|,h „ O@ ,`> 4xaB'p 0 <0B8`A&TaC!Fp|  <0… :|1D8p ,h „ 2l!Ĉ'N0'p "Lp!ÆB(a? <0… :|1ĉ'p} H*\ȰÇ#JD`>'p "Lp!ÆB(q} (p,h „ 2TO_Æ 6l|O@ DPB >Qĉ8P>$XA .dP_|6lذaC8p ,h „ 2l!Ĉ'N0'p "Lp!C˗aÆ 6T`>'p "Lp!ÆB(q} (p,h „ 2<`>'p "Lp!Ä8p ,h „ 2l!Ĉ'N0'p "Lp!à o,h „ 2D`>'p "Lp!ÆB(q} (p,h „ 24`>O@ DPB'p@$XA .dC%N`>O@ DPB'p A$XA .dx|O@ DPB >Qĉ8P>$XA .dH|̧? 4xaB 08`A&TaC!F8q>? 4xaB O@'p "Lp!Â8p ,h „ 2l!Ĉ'N0'p "Lp!Á8 A H*\Ȑ`? <0… :|1ĉ'p} H*\P>$X0,h „ 2$`>'p "Lp!ÆB(q} (p,h „ 2`> ? 4xaB 08`A&TaC!F8q>? 4xaB O@ O@ DPB'p@$XA .dC%N`>O@ DPB8`8`A&T~ 8? 4xaB 6tbD'O@8`A&T!}'p@} ? 4xaB 08`A&TaC!F8q>? 4xaB O8`A&T~ 8? 4xaB 6tbD'O@8`A&TA? 4xaB 08`A&TaC!F8q>? 4xaB O8`A&T~ 8? 4xaB 6tbD'O@8`A&TA? 4xaB 08`A&TaC!F8q>? 4xaB O8`A&T~ 8? 4xaB 6tbD'O@8`A&TA? 4xaB 08`A&TaC!F8q>? 4xaB O8`A&T~ 8? 4xaB 6tbDOĂ8P>$XA .dh`>O@ DPB'p@$XA .dCD'p} H*\ | ? 4xaB O /_|'p "Lp!ÆB|o?}O| '0@~O`>Wp|  <0… 'p~ ? 4xaB O /@}8`A&TaC!:G0}۷| >'0?~Gp|  <0… 'p~ oo_>}O | '0@~O@ D(|O_|˧/| /?/_>~ H*\ȰC7| '0߿|O`Gp|  <0… 'p~ o˷o?}O` ? 4x~ 8?#>_>o|}O@ DPB &7| _AA } H*\ | ߿| __/߿?} HO /|ӗo`>o ?} /@~8`A&TaC O?_>O?_ >? 4xaB O80 ̗o`>0 HO /@ (߿__'p "Lp!Æ˗/?'P_|˧/}/|˧>? 4xaB O80 ̷o?/?}/߿~'?$XA'p@o>~ o߾ _ _O ? H*\ȰÇ Al`>O@ DPB8p`?O@~/?}ۗO_ ߾|O>$XA'p@/_|˗O@}/|˧O| ܗ/>$XA .dÅ 60'p "Lp!C 8,h_$XA .dC%:0'p "Lp!C 8,h_$XA .dC7_>gp|  <0… 'p~ o| <a~ 08P ? 4x!~&L0a„ _}K0aB gp|  <0… 'p~ o| ~78P>$XA .dh`>O}7p_>ϟ|ӗ/_'p_>}˗ '8p`?O}˗?O_|˗߿}/_>~O ?~ H*\Ȱ`>ǯ_ /_>o߾'0?Wp|  <0… 'p~ o`>~}|߾۷|@ o`>'p|_|_>|o߾O`>~'П>$XA .dX0|/߿|ӷ@}/߿|O|0'p "Lp!C 8߾o ?}o_/| o@ 7p08_>_ӧo_?#_|o ?}˗| H*\Ȱ`>_ |o߿~/߿7P>? 4xaB O80|/?׏_}˷>~߿|߿}_>$X`? O߿}O|ǯ7p O`>$XA .dX0|/?}󷯟| /@_>}g0A}'p} H*\ |o'}O`|o?' o`>'p|㷏߿|߾~'0߿|۷|@~'P,h „ 2,߿|O|/_~|o_|˗O|+`>O@ DPB8p`?O` 'p_|˗/_~/_}ۗ/_>7|׏,h|O_>˗O߿~/_|˗o}'p_|˗/>'p "Lp!Â5l0_Á O@8`A&TA?O@ D!"4`>'p?$H A#H 8`A&T} ԗ/_3`>O@ DPB8p`? A $H|$H`~ $HP`?$H A ˗A  <0… :|Q>? 4xaB O8`A&T~ 8? 4xaB 6tbD'O@8`A&TA? 4xaB 08`A&TaC!F8q>? 4xaB O8`A&T~ 8? 4xaB 6tbD'O@8`A&TA? 4xaB 0  <0… :|1ĉ8`> 'p ,h „ 2O8`A&T@$X`?$XA .dC%N<`> ,? 4xaB 'p~ H*\P?$Xp>$XA .dC%NL`> ? 4xaB O8`A&T} H@$XA .dC%N\0 O@ DPB8p`?$XA .dHP|,? 4xaB 6tbDO@O@ DPB8p`?$XA .dX`>  <0… :|1ĉ 'p A8`A&T@? 4xaB 0O@ DPB >Qć8@} H*\Ȑ | <0… O@8`A&TaC!F81"| <0… 'p~ H*\>? 4xaB 6tbD#O@8`A&TaA? 4xaB "O@8`A&TaC!F8q"?? 4xaB O8`A&T!B ? 4xaB 6tbD)08`A&TA? 4xaB &0@ H*\ȰÇ#JHq |'p "Lp!C 8,h „ 2T/_|6lذaÆ 6lذaÆ ˗/_>~ 6lذ!B? 4xaB .̗o_Æ 6lذaÆ 6lذ}kذaÆ 'p~ H*\p?} 6lذaÆ 6lذaÆ kذaÆ 'p~ H*\ȰÇ#JHŋ3jH`>O@ DPB >QD-^ĘQF 8,h „ 2l!Ĉ'Rh"ƌ7RO8`A&TaC!F8bE/O>$XA .d@}? 4xaBO|,h „ 2lp>} <0… :o_|ϟ>|С?/_|=|`}Ǐ?>|CǏ|Ç2/?>|Ç˗Ç˗_>|˷Ç>L/>|Ã{С|>|ÇÇ"Ç>|Pa>}6Ç>|Pa|>|A}>|ÇC=|Ç*̗Ç>|hP>|C)P|8`A/a„ &L0a„ &$/ &L0a„ 0a„ &L0a„ ̗_„ /a„ &L0a„ &$/ &L0a„ 0a„ &L0a„ ̗_„ /a„ &L0a„ &$/ &L0a„ 0a„ &L0a„ ̗_„ /a„ &L0a„ &$/ &L0a„ 0a„ &L0a„ ̗_„ /a„ &L0a„ &$/ J(J( H?$XAKh0?~ _ƒ/a„0a„K0aB%4a|K0|%L0a„ &LhP &/߾뗐`>'_ ̗_„ /a„ ˷/|%$_ /a„0a„ &L0A}&L~ӗo|_'_|˧_'0| /a„0a„K0aO_}˷O |/_|/_>~ӗO,h`|!D!B"D>"DX0?}o߾۷_/}O`>~/ oB ̗B"ȏBO_?۷_~_>~'p?}߿|̇!B!B"D!B!D!A~'0| /|_>G0߿|O~ H!B!Bo|70߿|o~_>`>"D_|"D!B"DP?"$0@__(>~ '0_'0@ "DP ?~"DH`>߿|/߿|'P`?}_/|/,h`|!D!B"D>"D8?~Ǐ߿|'0߿|O`}/| !B!B !B7p_>_>}O|o>'0_|C!C!B"D!B}"Dp~/_>~O`˗?~ӷ>}/?+/_|"DP`|"D@~"Dp~`|˗/O_|˗o}߾|߿| /_|8`A !B"D!BC!Ḃ!B"Da|"D@~"D|!D!B"D/?"D!B"!BW0B"D!BC!BC!Ḃ!B"Da|"D!B"DP?"D!B!|"D80_>"DP ?~"D!B"D!B!B"D!B!D!B _>C!C!B? 4xaB 6tPa| B"D} ˗?~O_~˗߿| ̧/_?} /?#ϟ|˷O`}O| '0@~/_>~0_>!*"D_|ӗ?/|O_~O`} BD/?!BQ>__>/'0O?۷_>~ o߾ '0?~߾$/ ,X`A,X` | _>~| '0?>ǯ` ,X_|8`A&TaÂ9o|'0?} '0| /@~+O|70߿|̗o`>o||9t?7_>}O`>o ?}9t0_>~:t!C}G0| '|O`>0'P`>7P`o|O`O8`|,X` ǯ` ,Xp`>O`>/| '0?? 4x|%L0a„ &LhPo>'0߿}_| '0?}/_|W0o>_>O>߿| /a„ 0a„o>'0߿}_| '0?}/_„ ̗_„ &L0a„KhП|ۗ/?/_|˧/| 'p_|+/_|#/_>~ ܗ/?'p_>}0_~ _>$X0_> ,X`+X` O_|˗|/_~ӗO`>/_>},X` ̗,h „ 2lXP?:th0CϡC9tСC:$/?:t萡>:t`>.̗ϟCsСC:tH0_>~:t!C}:tСC̗ϟCsСC:tH0_>~:t!C}:tСC̗ϟCsСC:tH0_>~:t!C}:tСC̗ϟCsСC:tH0_>~:t!C}:tСC̗ϟCsСC:tH0_>~:t!C <0… :|0_>!*"D!BQ`| B"D} B"D˗D "D!B/?!B_>~!B"ć"ąA"D˗/?!B|"D!B<菟> O@ D_|K0a„ &L0a„0@8`A&TaÃ8P>~'p "Lp!ÆO| <0?Է~ H*\ȰC~0'p "Lp!Æ O@ DPB >$,h „O@ DPB >$,h „ 2l?~O@ DPB Է?$XA ׏>} H*\Ȱà <0… :lП <0… :O`@ DPB H*\ȰC$XA .dC%NXE5nG!E$YI)UdK1eΤYM9;;PKF3kp|pPK-AOEBPS/img/adque446.gif8/GIF87a?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU, H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXj= П <0… :d <0… :|1ĉ+Z1ƍ8`A&TaC 'p "Lp!ÆB(q"Ŋ/b̨Q#?}7nx07nܸqƍ7nܨ7n<ƍ7nܸqƍ7nOƍ7oƍ7nܸqƍ7joƍqƍ7nܸqƍ5ӷqƍ۸qƍ7nܸqƍ۸qƃmܸqƍ7nܸqFmܸq|6nܸqƍ7nܸqF~6nܸ`>7nܸqƍ7nܸQ#?}7nx07nܸqƍ7nܨ7n<ϟ} %?~O@ǯ` ` <0… :|1ĉ+ZDOŋ/^/a} )쇰| w1axŋ/^x"B~˗|C/_~_>}O |!/_뇐_|˗|ӗ|'_|˧/|ӗ߿|O`>//_~/߾~/_|ӗ?}/O_>}xŋ/^xA~o?_>|/߿|/?~GP }߿|_ _>~}  /߿}'0?/|/'0?'0|> | _>~ >O <0… :|1ĉ+Z_/߿?}'p|~O`>O`>ӷ|/|_|o|'0| |? 4xaB 6tbD)Vx g0|/߿| '0?O|o 7_o?} 짏_| '0|'0|/߾O~>'p_/߿o/߿'p "Lp!ÆB(q"Ŋӧ>~O`>'pӷ߿|߿|?ԷO`0@߾}/߿>}8p`> '0@_>_>o_?O`> '0߿~O ?o>'0|?}o>$XA .dC%NXA~O_| |O_|O`>'0A/|˗}O`>0/>}˗/| /| /_|/@~ӷ>} O|/_~O`>o_|_ŋ/^xŋx!/^dŋ/^xŋxapŋ/.ŋ.袋.袋>$XA .dС|>|Ç>|Ç>|Ç Ç>|0>|Ç>|Ç>|Ç{Ç*Ç>|>|Ç>|@~>|Ç {Ç>|Ç>|Ç>|(>||>|Ç>|Ç>|Ç Ç>|0>|Ç>|Ç>|Ç{Ç*Ç>|Çz衇z衇z衇zH O@ DPB *Ç>|Ç>|Ç>|@~8`A&TaC O@ DPB >QD-^ĘQF H*/߾ .\(? 4xaB 6tbD)VxcF9v/?=zѣG=zѣdžѣG=zѣG=zl/?=zѣG=zѣdžѣG=zѣG=zl/?=zѣG=zѣdžѣG=zѣG=zl/?=zѣG=zѣdžѣG=zѣG=zl/?=zѣG=zѣdžѣG=zѣG=zl/?=zѣG=zѣdž#<#<#7nܸqƍ7nܸQ#?}7nx07nܸqƍ7nܨ7n<ƍ7nܸqƍ7nOƍ7oƍ7nܸqƍ7joƍqƍ7nܸqƍ5ӷ|!|=,_ ,(_+X` ̗/_>}˗/?O`>~/_| ,/_ ? 4xaB 6tbD)&䧯b|b a߾X0|o~ O`}? XP_Ŋ+VXbŊ /_~>~o_|/_>~O | ̧/_/_>~|p_?/?O_>}|˗|˗@~|G0|o`> ܗO`0_~_>}O O_~?~8`A&TaC!F8"B~O}߿|/?o?O`>~O>~O` /?}o|}O>~O>~O>~|/| Ǐ` G0߿|_O?/?~/'0_>'П+VXbŊӗ_}O`>'p o?O`|o|O`>O|O~ oo|///@7|7|/߿7P`_/_߿_?~/߿_O@ DPB >QDS| wP?'>~30߿}__߿(P_7p|7_|o|o|_?}o@߿/߿/߿|_?~߿˷_> '0?߿|O~? 4xaB 6tbD)"oa}'0| O@/|߿|?~߾}/߿O/o~ 80?߾}۷O>~ܷO>~ܷO>~'_ '0>~#`>/@~o'_ O>>~O`>/@} H*\ȰÇ#JH!?} /_~ ̇߾|O |ӧ/_~ۗ/7p_|O>}˧߾ ԧ> Kϟ|O| ԧ| Wp_|/_}ӗ/_?˗O_| ̗/_>~˗o|O |7_|/_~ 'p_|O`ۧo߿~*VXbŊ+VDO_Ŋ+VT_B*VXbE*VXbŊUTQB <0… :Tϟ}>|ÇÇ>|Ç&Ç>|0>|Ç>|Ç>|Ç{Ç*Ç>|Ç>|Ç>|@~>|Ç {Ç>|Ç>|Ç>|(>||>|Ç>|Ç>|Ç Ç>|0>|Ç>|Ç>|Ç{Ç*Ç>|C=C=C=C=CO,h „ 2lPa>>|Ç>|Ç>|ÇП <0… :T,h „ 2l!Ĉ'Rh"ƌ5O@ DPB 2 <0… :|1ĉ+Z1ƍ;cǎ;vرcǎ;vر|:vرcǎ;vرcǎ;cǎ;vرcǎ;vر|:vرcǎ;vرcǎ;cǎ;vرcǎ;vر|:vرcǎ;vرcǎ;cǎ;vرcǎ;vر|:vرcǎ;vرcǎ;cǎ;vرcǎ;v? 4xaBp… 'p "Lp!ÆB(q"Ŋ/b̨q#?$XA .d!C H*\ȰÇ#JHŋ3jOƍ7oƍ7nܸqƍ7joƍqƍ7nܸqƍ5ӷqƍ۸qƍ7nܸqƍ۸qƃmܸqƍ7nܸqFmܸq|6nܸqƍ7nܸqF~6nܸ`>7nܸqƍ7nܸQ#?}7nx07nܸqƍ7nܨ7n<ƍ7nܸqƍ7nOƍ7oƍ7nܸqƍ7joFh1? C`>$X~8`A&TaC!F8bE1N/cF3/_F%췯`>滨/cƌ3f̘1cƌ'ӗ"| ̧/_?'0|˗/#|'p_>}˗?}/_'_|ӗ/_?'3f̘1cƌ3fO_Ɔ_>wp߾ ߾} Է/|o?/|_~|/?~ϟ3f̘1cƌ3fO_F_/߿O/߿/߿,h`|'0|'0@70@ӷ|? 4xaB 6tbD)VxD~2*o`>;o`>Ϡ|0|맏_|맏_| O~o?/,h „ 2l!Ĉ'Rh"Fe\o '0|(p߾?~߿ QD-^( /_~ ̇P_|˗|˸0 ԗ/_ۧo?}˷O>}/_}˗/_?'3f̘1cƌ3fO_ƌ3>/?~+˘1cƌ3f̘1cƉe̘1|H_3f̘1cƌ3fO_ƌ3>/cƌ3f̘1cƌ3f(3f|_ƌ3f̘1cƌ3f̘Q ?}3f03f̘1cƌ3f̘1@~2f(? 4xaB 6tbD)VxcF۸qƃmܸqƍ7nܸqFmܸq|6nܸqƍ7nܸqF~6nܸ`>7nܸqƍ7nܸQ#?}7nx07nܸqƍ7nܨ_>$XA .dС|8`A&TaC!F8bE1fԨ@},h „ ˷p… O@ DPB >QD-^ĘQFױcǎ;vرcǎ;vQ_>;vرcǎ;vرcǎױcǎ;vرcǎ;vQ_>;vرcǎ;vرcǎױcǎ;vرcǎ;vQ_>;vرcǎ;vرcǎױcǎ;vرcǎ;vQ_>;vرcǎ;vرcǎױcǎ;vرcǎ H*\ȰÇ/bĈ#F1!,h „ 2l!Ĉ'6O@ DPB >QD-^? 4xaB 6tbDP <0… :|`|#F1bĈO@ DPB >QĆQH"E"E)R(_>})RH"E)̗"E)R8P_>)RH"EH"E)RHq`|)RH"ŁH"E) OE)RH"EH"E)ԗE)RHQ|(RH"E)R/E)RHq|(RH"EG"E)RH|(RH"EG"E)R/>)RH"EG"E)R/?)RH@'p "Lp!ÆB(qb|(RH"EG"E)R/>)RH"EG"E)R/?)RH@QH"E)R80_>)RH@}QH"E˧"E)RH"ŁQH"E"E)R(_>})RH"E)̗"E)R8P_>)RH"EH"E)RHq`|)RH"ŁH"E) OE)RH"EH"E)ԗE)RHQ|8`A&TaC'p "Lp!|2dȐA$П <0…ǐ!C 'p@$XA ./_> 2dx? 4xaB 'p "Lp!ÆB'p "Lp!ÆB?'p "Lp!ÆB? 4xaB [p… .\pB%o… .\p… g .\p… .… .T… .\p…  /!?} .\p… .\80?-\p… .\p|.\pB}.\p… .\P| [p… .\po… .\p… p… p… .\p…KO… .\p…  ?} .\p… .\80 .\P .\pZh_>O,h „ 2l| "D!Bx0?!BD!BA"D!Bx0?A"D!"D"D!Bh_A"D! ?}!B"D"A"D!/!?}!B"D3OD!B| B>~!B"DKOD!B| "D!Bx0?!Bą|˗|'П|At?8`A;(~"B|b'0@'_>!. ?}!B"D")ܗ/wp_ ̧| ܗ/˗o`70߿}_|_>} /}ӗ߿|'0|ӗ/?%bA~O_~#o߿|˗@~| ߿߿߿_߿|_|8`ϠA 4h |˧/_? 4hРA ϟA 4hРA3/?~/_? W0|/?~/}`/A~'0_?/?~߾'0}|/}38> o?/A ߿}o?O`>~'0@~3_>'0o|g | gРA 2Ƞڧ߾_>$X A}_7p|/_|80| /| /@ ̗o`o_7_7p'0@ '`>O| /߿| ̗o ?} O |_'0߿|O~/O@ D_}_>'P ,HП>} 4hРA3hРA 4h>~70_|@O~+0?}/?}_/߿/߿O|_>ۗo~7p@~8p~ O`7?}맏_| 0||_?}AA/_,X` | W`W` ,H0?$XA *Ǐ`?}} `>?}/߿}߾O__|o߾߿|~?/߾}߿|/?~| 8> 췏?}O`> _>~_}/>~/߿/߿?_|Oo~ H`>W` ,XP`}'0߿| O@'>}8`A&/a„ &L(P?/_> ̇| _|/_>ӗ/?O`|/_|˗ϟ|'0?ϟ|_/|˗>KO_„ӗ/_Ko_| _|/_~ۗ/>o`|o_|/|˧O| ܗ/>%<ϟA~&L0!A˗߿|%`>0a„ (?$XA *o… .\p… ˗ .\p.\0?-\p… .\p|.\pB}.\p… .\P| [p… .\po… .\p… p… p… .\p…KO… .\p…  ?} .\p… .\80 .\P .\p… ./_B~.\p… .\p`>[p… .\p-\pB-\p…ZhZH O'p "Lp!Æ> ?}!B"D"A"D!/!?}!B"D3OD!B| B>~!B"DKOD!B| "D!Bx0?!BD!BA"D!Bx0?A"D!"D"D!Bh_A"D! ?}!B"D"A"D!/!?}!B"D3OD!BDP> H*T/@},h „ 2l| 8_>$XA .dÇ'p | H*\ȰÇO@ DP~ H*\ȰÇ'p@ H*\ȰÇ'p? H*\ȰÇ'p "Lp!ÆB(q"Ŋ/b̨q#ǎ? )r$ɒ&OLr%˖._Œ)s&͚6o̩s'Ϟ> *t(ѢF"Mt)Ӧ; />`>'p A ǯ`A,X` ,8p}W` 'P|O@$8_?$XA &7p_| '0„[80A g_ .\p… >-\0~ [h0~ [pB O`|.\o_| [O… .Do|_>&'0 [(0A} .\p… ~ /?'0|˗@~ӗO߿|O`>}W_|˗?}˗|'_|˗@~.\~#o߿| /@~/߿ϟ|_~ o | ̧/߾˗?}Ǐ,h „ o?˧_>} /?/|˷ | ̧/>˗@~/> .\p…  }߿|}| o@}/_|}>O` ̗?ӷp… g0߿|O`>~ >_> o@}o߾|/_>O… . _>~߾}/_߾߿}߿|/߿_'p "Lp!Æ`>O`>O_/| W0_| /߿| ̗`o |C3_>O߿|7>}g0|70_ӷ|>|(0|'0| _>o`o` /@ӷ|>|Ã#_>O`>'p`> '0_'0@맏_| /|o߿'p "Lh0@}/|8_8_?~_?'0/߿|o| H*~O`>'p|߿߿|߿_ O|˷O`>$XA .d|O߿}/| O?'0߿|'p+`>ӷO`>߿|O ?}Ç ?_|߿|@~oྃ'p/?}O`>>|P`>/>~}?~'p_>}o|O`>>|Ç/_}O |/߿ۗ/>}ۗ/? /_}ӗ/_?˗| ܗ/~'?$XA '߾|o_>}˗O}/_>}˗} ܗ/?/?/_|PB  O}'P/_>}ԗ/_>Wp_|˗|˧?}O_|׏B *TPB PB *TP} *TP?~)TP| SPB PB S> *TPB ܧPB *TP~*TP} *T0!| H~ 4hРA $ϠA 4hР@4hP`~ H*\Ȱô#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjʵׯ`ÊKٳhӪ]˶۷pʝKݻx˷߿ LÈ+^̸ǐ#KL˘3k̹ϠCMӨS^k@;;PKiW88PK-AOEBPS/img/adque039.gif]WGIF87aP?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU,P H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIAP <0… :Է~8`A&TaC!F8A~˧O?~'p "Lp!Æ O_| <0… :|1ĉ˧?)R(_?~G"E)RH"~QH"EG"E)RH@}(RH"ńH"E)RHQ>)RH|QH"E)RO?)RHQa|(RH"E)RE)R0_>)RH"E)"E)RT/?)RH"EG"E)*̗E)RH"EH"E"E)RH"Q|5?Q|P|8`A&TaC!F8q>#˷a/b|(>̗E)RH"EQ_|˷O`>} /?~/_~/?~O_~Ga|(RH"E)Rň'0_߾}o?/|'Pg0?}(:̗E)RH"E 70߿|/_O`>/|oEH"E)RH> H(߿|/߿O ǯ_>7_(`>8`A ? 4xaB 6tbDGa?}?~ӷO`'0| _>7p? G"E)RH?}(>o`?}O`| /?}/_}ӧ_'0|OņH"E)RH>)W0E)"E)RH"Q80_|)R/?)RH"EG"E)*̗E)RH"EH"|)R,/?)RH"(O@ DPa| .\Pa|.\p… .\p… .…  ̧/>/?'0|| ̷… o… .\p… .\p-\p|/?~o?}O`>~[p|-\p… .\p… .\8P .o`#/| /@/… ˗… .\p… .\p…[pB_>'0|'P | <0a|8`A&TaC!F8q>)?~۷O>~O`ӷO`>}/EG"E)RH?}(R4/_>~ ܗ/?'p_>}ӗ/_'0EG"E)RH?}(R4"E"E)RH"Qh0E)̗E)RH"EH"E"E)RH"QH"E G"E)RH?}(RH"EH"E)RH> H*\ȰÇ "D!B"D "D!B/?!B"D!BLO?!B"D}"D!B"D"D!B?}"D!B"D˗/_>}"D!BTϟ?~O|8`A&TaC!F8} H @},h „ 2l8`> ? 4xaB 6tbD)`> 4xaB 6tP~ H*\ȰÇ#JH1?8`A&`>'p "L(П? H*\ȰÇ#JHŋ8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ308`A&TaC!F8bE1f`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD-^Ę? <0… :|1ĉ+Z1? 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ308`A&TaC!F8bE1f`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD-^Ę? <0… :|1ĉ+Z1? 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ308`A&TaC!F8bE1f`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD-^Ę? <0… :|1ĉ+Z1? 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ308`A&TaC!F8bE1f`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD-^Ę? <0… :|1ĉ+Z1? 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ(,h 8p ,h „ 2l!Ĉ'Rhb|)O H*\ȰÇ#JHŋ̧/_?'0|O`>˗A 8? 4xaB 6tbD)Vx`>o߾ '0?~/|@ 8? 4xaB 6tbD)Vx |߿|/߿/߿߿|8p ,h „ 2l!Ĉ'Rhb| /| `>/߿o H*\ȰÇ#JHŋ'0߿}'0߿~'O? 08`A&TaC!F8bE 'P ˧/߿o_>}'P߿8p ,h „ 2l!Ĉ'Rhb| O H*\ȰÇ#JHŋa$`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD-^Ę? <0… :|1ĉ+Z1? 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ)O@ O@ DPB >QD-^P|,Hp,h „ 2l!Ĉ'Rh"F H@} H*\ȰÇ#JHŋ#O@'p "Lp!ÆB(q"Ŋ/b`>  <0… :|1ĉ+Z>$8P,h „ 2l!Ĉ'Rh"F HP>$XA .dC%NXE'p | H*\ȰÇ#JHŋ3O8`A&TaC!F8bE1f`>O@ DPB >QD-^Ęq |O@ DPB >QD-^Ę`?  <0… :|1ĉ+Z1c}QF5jԨQFӧQF5jԨQFӨQF5jԨQF5jԨQF5j0 <0‚ H*\ȰÇ#JHŋ]0ŋ/^xŋ/w|/^xŋ/^ŋ ]xŋ/^xb>/.wŋ/^xŋ]0ŋ/^xŋ/w|/^xŋ/^ŋ ]xŋ/^xb>/.wŋ/^xŋ]0ŋ/^xŋ/w|/^xŋ/^ŋ ]xŋ/^xb>/.wŋ/^xŋ]0ŋ/^xŋ]P> H*? 4xaB 6tbD)Vx1xŋ/^x|.^\ŋ/^xŋxqa/^xŋ/^Ņ.^xŋ/^x1xŋ/^x|.^\ŋ/^xŋxqa/^xŋ/^Ņ.^xŋ/^x1xŋ/^x|.^\ŋ/^xŋxqa/^xŋ/^O@ DPaA$XA .dC%NX|.^T/ŋ/^xŋ/wB.^xŋ/^x1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_wŋ/^xŋ]_/^xŋ/^O@ DPaA$XA .dC%NX|.^T/ŋ/^xŋ/wB.^xŋ/^x1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_wŋ/^xŋ]_/^xŋ/^O@ DPaA$XA .dC%NX|.^T/ŋ/^xŋ/wB.^xŋ/^x1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_ HO@8`A&TaC!F8bE+П <0? ? 4xaB 6tbD)Vx1_wŋ/^xŋ]_/^xŋ/^O@ DPaA$XA .dC%NXE}.^\ŋ/^xŋxqa/^xŋ/^Ņ.^xŋ/^xQxŋ/^xE}.^\ŋ/^xŋxqa/^xŋ/^Ņ.^xŋ/^xQxŋ/^xE}.^\ŋ/^xŋxqa/^xŋ/^Ņ.^xŋ/^xQxŋ/^xE}.^\ŋ/^xŋ.H?$XA   <0… :|1ĉ+Zŋ ]xŋ/^x>/.wŋ/^xŋ]0ŋ/^xŋ/w|/^xŋ/^ŋ ]xŋ/^x>/.wŋ/^xŋ]0ŋ/^xŋ/w|/^xŋ/^ŋ ]xŋ/^x>/.wŋ/^xŋ]0ŋ/^xŋ/'p "L`>$XA .dC%NXEO8@$? 'p@~O@ DPB >QD-^$0'p A HO8`A&TaC!F8bE'p} HP |8p`?$XA .dC%NXŃ 8p0'p A? 4xaB 6tbD)Vx |'p A$`>O@ DPB >QD-^<0'p O8`A&TaC!F8bE'p} H8p`?$XA .dC%NXŃ 8p,h`A? 4xaB 6tbD)Vx | O@ DPB >QD-^<0'p A H? O8`A&TaC!F8bE'p} HP |8p`?$XA .dC%NXŃ 8p0'p A? 4xaB 6tbD)Vx |'p A H`>O@ DPB >QD-^<0'p A HO8`A&TaC!F8bE'p} HP |8p`?$XA .dC%NXŃ 8p,h`A? 4xaB 6tbD)Vx | O@ DPB >QD-^<0'p O8`A&TaC!F8bE'p} H8p`?$XA .dC%NXŃ 8p,h`A? 4xaB 6tbD)Vx |'p A H`>O@ DPB >QD-^<0'p A HO8`A&TaC!F8bE'p} HP |8p`?$XA .dC%NXŃ 8p0'p A? 4xaB 6tbD)Vx |'p A H`>O@ DPB >QD-^<0'p A H? O8`A&TaC!F8bE'p} H8p`?$XA .dC%NXŃ 8p,h`A? 4xaB 6tbD)Vx | O@ DPB >QD-^<0'p O8`A&TaC!F8bE'p} HP @O@8p`?$XA .dC%NXŃ 8p0'p A? 4xaB 6tbD)Vx |'p A H`>O@ DPB >QD-^<0'p A HO8`A&TaC!F8bE'p} HP |8p`?$XA .dC%NXŃ 8p0'p A? 4xaB 6tbD)Vx |'p A$`>O@ DPB >QD-^<0'p O8`A&TaC!F8bE'p} H8p`?$XA .dC%NX`|H`>O@ ,0'p| <0… :|1ĉ_E 8p,h`A?,h „ 2l!Ĉ'Rdo?}O| '0@~O`>g`>O@8 0'p|/_>~ӗO`>˗| /?$XA .dC%BG0}۷| >'0?~W`>O@8?$0'p|O`>~O`>߿|O`>~ H*\ȰÇ#J|`|70|7o ?}8p>$(`> O@ 8 G0߿|70|O߿|7>$XA .dC%>7| _AA 0'p A HO8P`O|_߿| O@ DPB >Q|O ?O`O ?>~+0'p A HO8P`O ?O`'O?'p "Lp!ÆB(a|/_>}˗O| ܗ/>'p_| 'p} HP |8p`?/_|˗O@}/|˧O| ܗ/>$XA .dC%NlB? 4x | $? 4xaB 6tbD)BW1!| O@  <0… :|1ĉ+Z$0'p O8`A&TaC!F8bE'p} H8p`?$XA .dC%NX 0'p ,h`?8p> O@ DPB >QD-N0  H߿$H |8`A&TaC!F8bE8`A8|߿$Hp ?$XA .dC%NX"~ H@0'P>$XP>$XA .dC%NXѢ} H`> (`> O@} H`>$XA .dC%NX8 } 8`> O H?$XA .dC%NXE Hp>$8P`?$8p,h „ 2l!Ĉ'Rh~ HP ,h} H0>$XA .dC%NXł8?$X8 ,h „ 2l!Ĉ'RhA} (p,h`A? 4xaB 6tbD)Vx!| ~ H*\ȰÇ#JHŋ0'p O@ DPB >QD-^|/"| O@ DPB >QD-^Ĩ`> O@ DPB >QD-^Ę? 'p "Lp!ÆB(q?O@ DPB  Ǐ? HǏ@},h „ 2lP>~O@ DPa?~ӧ?~8`A&TaCO_| }'p "L8p_|)TPB *T0?~PB~OB *TPBۗ/> *,O? *TPB *4O> OB *TPB ۗϟB  OB *TPB ˧ ? 'p| H*\ȰÇ bB B"D˷/!|8`A&TaC˗"ĄA"D! ԗO_B$?'p "Lp!Æ*/D "D!B/ HO@ DPB >T/_>"D!B(P_>} 8? <0… :|_|!&"D!BQ|'p A ? 4xaB 6tP!| BLOD{1_|A(P_>}Ѡ>? />˗"ĄAX_}0~ "D部0D0߿~ >A_|!&"ĂO_}˷O`˗?~/˗|+o`>˧|!/|O_}'_|˗?}_|ӗ_A} ~'߾ ԗO_„%L0|߿}o߾o?/|'PW0_„  /_„ /a„ o|70߿|7П@ '0_> |O@ ,/> ̇!Bo|70߿|7П@ '0_>`>"4/_>"Dϟ>"$0@__߿~__@ }'p A ? 4x!|߿_߿/߿߿/o,h`A~!D!!D~/?~O> O`>߿|7>"/>8?  ˗oB /B"OB"`>"D!BӇ|8`AW0_„ &L0!B~%L0aA&L`&L0a„ ˧/!|8`AW0_„ &L0!B~%L0aA&L0a„%$/aBKX_ӗ ? 'p| H*To| '0B-/_ "o… &o| o!A} ˧oB.\pa~ ̷a?Է|.\П| ̧/_O`>ӗ|˗|ϟ| '0|O_|˗߿|/|˗|o|.$o@~/_>~?}O`>/_?'0>~O_|O`>O_|˗߿_>}/?$_| ,X`+Xp }O>~_>O`>_>~/_>߿}/}|o}@ / ,/_/?~/_|o|G0|/|o_>|O`~'0 `+X` O_ `o~߿|/߿80?} O`>ӷ|70߿|O߿|8p@}'p  ;h0@/|70| '0߿|`>O`>ӷ| '0| _>/4OA#_>o| '0@/؏_} '0|˷/@o |߿'p +H? 'p| |'0~O`>|@o߿| 70߿~7p`>0_>$_| ,X`+Xp}'p|O`>O ?߾~ _>o_?_?}/A} ӗO_A H8p o>'0߿}_| '0?}/@'0߿|?~O>O`>'7p@O@ DXП˗߿}O`O| '0|˧O`>˗/_?'P_|˗/_?/|O| 7ӗ`> O|ϟ| ܗ/?/_|˧/| 'p_|(p߾| ԗ/ϟ| '0@}/_>} o  O| H*To… |.\П .\p… &ԗO_B$?'p "Lp!Æ*/D "D!B/ H?O@ DPB >T/_>"D!B(P_>}"D!B/_>"D!B(P_>}"D!B/_>"D!B(P_>}"D!B/_>"D!B(P_>}"D!B/_>"D!B(P_>} 8  <0… :|_|!*"D!B_|'p A o,h „ 2l!~Q|"D!&o_|K0'p?}O@ DPB >؏|'p "<`>ϟ?$XA .dС?ۧ`>O@ H ԗ/_|,h „ 2l?0'p "L`> 4xaB 6t~ H|O@ DPB >,,h „0 <0… :\? H @}`> 4xaB 6tP>~8`A&THП~ H*\ȰaC'p "LXП? H*\Ȱa~O@ DPB >QD-^ĘQF=~RH%MDRJ-]SL5mO@8`A&TaC!F8bE1fO@8`A&TaC!F8qb3菟@˗O?ǯ?8?$XA"?W0_|CH!,!B"D!B!D/߿~ G0~쇰‚"D | /_~ӗO| /?/|| ̧/_C!B H,h|O_~˷O`˗߿|#`>'_|O_}/?O_>}"D!B"~O`~__>O?~o?߿}O`>~O`>",8`A|߿}}_>_o߾߿|!B"D!B '0| /߿| /|(߿|/߿_'߿_'p "Lp!CO`>__ _ӗ߿/߿?~/߿8`A&TaÂO`>_ `O| O`'p`_>$XA .dH0| '0|/_|7_ ? 70?/߿ <0… '0| ?~O>`>'?}O`>O?'0|:ta>O`>_ /߿|O?'0߿|Ǐ߿| _>sСCO`>˗|/_~ ԧo`>˗O?/|߾| '0@}:t| '0|__G0}ϟ|_|߾|߿| <0… :Ç>|? 'p "L(0B ̧PB *TPB)TPa| *T | <0| *TX0,h „ 2l!Ĉ'Rp HP߾}O@ DPB >QD-^P|,X,h „ 2l!Ĉ'Rh"Ƈ H A~ H*\ȰÇ#JHŋ!O@O@ DPB >QD-^(|,? 4xaB 6tbD)Vx#E} H?$XA .dC%NXE8} H*\ȰÇ#JHŋ-O@'p "Lp!ÆB(q"Ŋ/bĸ`> 'p "Lp!ÆB(q"Ŋ/bO|  <0… :|1ĉ+Z1@̷? 4xaB 6tbD)VxcƁ(P,h „ 2l!Ĉ'Rh"ƌ˗/F5jԨQF5Rԗ/?5jԨQF5jO,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РBB׏?}'p "Lp!Æ ӷ? H*\ȰÇ#JH?~ӷ~  <0… O@~˗/>~8`A&TaC!F81b|G"E'/_>~)RH"E)엏E)Rx_>})RH"E)Ǐ"E)RTE)RH"EH"E"E)RH"QH"E G"E)RH?~(RH"EH"E)RH?~)RH|QH"E)R?)RHQa|(RH"E)RǏE)R0_>)RH"E)ǏbD}C/_|'p ̗,h „ 2l!Ĉ'.Ǐ"~='|E7P_? G"E)RH?~(B/|O_} _|˗?}'_|ӗ_|0_>)RH"E)Ǐ"|߿}o߿|_'0|߿|+`> G"E)RH?~(>} ̗o`7П@ '0߿|'0_|Ql/?)RH"EG!@ _ _߿߿|߿_> 7_>$XO@ DPB >QąQtO}|/| ̗O| o>'0_|0_>)RH"E)Ǐ}'0_|˗|ӗ/_?~ӷ>} ܗ/?+/_|(:̗E)RH"EHq`>(RH_|(RH"E)RǏEG"EG"E)RH?~(RH"EH"E)RH?~)RL?~k_~? 4xaB 6tbDG"EA쇰_|E̗E)RH"E/_~_>}/_~ '0|'_|Ǐ~/_>~_>'0?~O_~?H"E)RH?~/?~㗏߿|/| _>~O`>~70?~o?߿}O`>~O`>A̗E)RH"E0߿߿}/߿_?~'p`O_o` _>o˗,h „ 2l!Ĉ'./b'0~O`>|O|O| O`'p`_O@? 4xaB 6tbDQ>'p|O`>'0|O ? >~ӷO`߿| 7P|QH"E)RO|'0߿~'p_>}O`>/}/_>}˗߿|O`'0|׏|QH"E)R?)"ob>E̗E)RH"EHb}Qׯ_|QH"("( ~8`A&TaC"D!B"D"D!B(0_>!B"D!B?!B"D"D!B"ĄA"D! ̗D!B"D!&"D!BQ`| B"D!B1a| B"D˗D!B"D!*/~!B"Ą'P?$XA .dC%Nl`>ϟ?8`A&TaCǏ>} (,h „ 2l!Ĉ'B0 <0… :|XP?$XA .dC%N?} H*\ȰC <0… :|1ĉ'P`?~ H*\Ȱ!A~ 'p "Lp!ÆB(q"Ŋ/b̨q#ǎ? )r$ɒ&OLr%˖._Œ)s&͚6o̩s'Ϟ(`|W@ ǯ`8`A&TaC!F8bEE~7_kŋ/^xŋ?}˷O`˗߿|#`>'_|O_}/?O_>}/^xŋ/^`>߾}߾/_|o|/߿|o߿| _>~ wŋ/^xE |߿|/߿/'P`O_߿|O߿|O@ DPB >QD-g_>~ /߿|/_|0(0|O|߿| H*\ȰÇ#JHE ߿|/߿|_ #>~ӷO`߿| wŋ/^xE ȏ߾߿|O`߿/߿O~7߿߿|O>$XA .dC%NX|-xŋ/^xņ.Z <0… :|1ĉ+Z1ƍ;z2ȑ$K<2ʕ,[| 3̙4kڼ3AΝ<{ 4СD=4ҥL:} 5ԩTZ5֭\z 6رd˚=6ڵlۺ} 7nڀ;;PK?8bW]WPK-AOEBPS/img/adque249.gif<3GIF87an?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU,n H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0='p A H*\ȰÇ#JHŋ3jȱDŽO>$X>} <0… :|1ĉ+Z1ƍ;bo> ԧo?~'p AO> Է?$XA .dC%NXE5na}˧o~:o|ϣG=zѣG=z_|B˗O?=zѣG=zѣC˷G˗/?=zѣG=zQa?}qc}ѣG=zѣG=/_>~=/_~=zѣG=z?~ѣG=zѣG9˗G ϣG=z?$XA .? 4xaB 6tO_}>|p_>}>|C$XA . <0…O@ DPB}8`A&TaCsСCСC:$`> 4xaB O@ DPB1dȐ!Â1dȐ!C "ܗC 2dx_>} 2dȐ!CcȐ!CcȐ!CcȐ!CcȐ!C 2~ 2dȐ!CcȐ!CcȐ!CcȐ!CcȐ!C 2 c0a|2dȐ!C ǐ!C ǐ!C ǐ!C ǐ|0|w0C ǐ?}/_|O`|/@~O@ 엯/>;x?};x _~ ߾?,?~wAw;x<(P_|O | /_~<8_>$`?~O`>O@ ?,o ?_|˗~_/w߿}O`>߿}~+O`||˗_>۷_>o`>OB'_~ _>_>!BB˗O|70| 'П|o`C ?}"D!BC!B"$/B"D?~"DP`>o`>o_>} ̇!ƒ!O`_| '_|"D(_|!'0| '߾|+0߿߿˗/,h?}/?~;x<(P}/_>O`| 70|_|< H*\X_|󗯟?˗C 2L/?!oÁcO`?cȐ!CK~o߿|/߿|O '0}߿|c_|1dȐ!Ä˧_B/> 2d?}ϟ|_|cȐ!C ˗B~o`>} ̧/>/_~|/_>~>~ 2d|o|70??/߿˗߿_>OA'p ,h „ 0@'p?/_>}8`A&T|'p`~8П>  <0…87p|߿}o߾|O`>'P7p?}8`A&TP|(߿|/߿O ǯ_>7_8?}08`A&T | 7| <0B˗@ o O| H*\H`>?~8?~o`O`| /|G0߿|,h „  `?}?~ӷO`'0| _>ӇP|,h „ 2T߿?/_|'p "Lh߾|П?~ H*\P(߿|/߿맏_|/߿|_'p?}8`A&TP|O߿|/_>~O_|˗o}߾| '0A~O@ DPB'P|߾|? 4x~˗o?$80_`> 4xaB "߿'p`?}?~ӷO`|O` _>,h „  |1d ?} 'p ,h „ 08| $菟|Ǐ? $H@˗/_>}'p 8,h „ O} O _| ̗/?/_~ۧo?}/_>~ 7p?}8`A&TP| +!CcO_|1dȐ!Ä˗_B"׏>ԧ?~8~ӧ`>? ,@/_|'p "Lp| ?} +!CcȐ!CcȐ!Cc(П|2dȐaB[/CO>$XР>}߿ HA O@ <0…/!?} +!CcȐ!CcȐ!CcH_> 2d>cȐ!@ 'p 7? ,h „ o!?} 2dȰ>~ 2d| 2dȰ ?} 2dȐ!CcȐ!C8`A <0… ϡCСC sСÄ9tСC СC8`A <0… ϡCСC sСÄ9tСC СC8`A <0… ϡCСC sСÄ9tСC СC8`A <0… ϡCСC sСÄ9tСC СC8`A <0… ϡCСC sСÄ9tСC СC8`A <0… ϡCСC sСÄ9tСC СC8`A <0… ϡCСC O@ DP}8`A&TaÅ9tA$XР|'p "Lp!ÆsСÄ9t!C H*\O,h „ 2l_>:<П @$XA .dذ | H*T,h „ 2l!Ĉ'R_>''p 7? 4xaB 6, ? 4xaB O@ DPB >QDgD$XР|'p "Lp!ÆB(q"Ŋ/bqF8r<П @$XA .dC%NXE5n/G8`A <0… :|1ĉ+Z1ƍcO>"|'p}$H0_ H*\ȰÇ#JHŋ3jܨ_ Է>}!| @_|/_ H*\ȰÇ#JHŋ3jܨ_#/#O߾+Oo_A~'p|'p "Lp!ÆB(q"Ŋ/b̨qF!| a| ۇП}ۧ}8_~8`A&TaC!F8bE1fԸQ|ǐ>c/?[O>[/> o ,h „ 2l!Ĉ'Rh"ƌ7j|˷|˷O`>}˗O`>}ӗ? <0… :|1ĉ+Z1ƍ+ȯ|˧oa?}ϟ} O>%ܧo> o ,h „ 2l!Ĉ'Rh"ƌ7j ~珠?}}׏?}O>W_}ϟ~o?~(0_ H*\ȰÇ#JHŋ3jܨ_ϟ}Ǐ}ϟ?/>~'P?_|O@}/Ǐ?} @$XA .dC%NXE5n/_A~(_|(p'P`?}'P>~O}'p'p|8P@7? 4xaB 6tbD)V`> 4xaB O@ DPB W_? ?o@?O@~П'p ?} @$XA .dذ ?$XA .? 4xaB П <0B'p "Lp!Æ +ȯ@?O}П'p ?}O@8> o ,h „ 2lX>$XA *? 4xaB ǐ!C ǐ!C 2dh_'p`| ?8>?} /@~> ?O|'p "Lp!ÆsСÄ9t!C:t0!?}:tСCo@@/>  ?>}  ?>}(P@~П@ O@ DPB СC sСC9taB~:4/_|3?}s|ϟ~/_?}ۧo_A_>~ӧ@ϟ?}/_?o ,h|_`>"!B"D>~"D!BC!B"OB '> O"Dp|_|Ӈ>}Ǐ>}ϟ|ׯ?ϟ>~П <80~W0?̇!B!D!B!B"D|"D!BC!Bo`O`>˗|!ƒ!O>~p?}ӧB˷/ /_?}8p|'p 70| /_> '_|/_?!B"D>~"D!BC!B"OB '_>߿}O`>߿}"Dx_>~CxП|O@G|'p '_>߿}O`>߿}"DH>"D!!D!B!B"D?}"D(0_| 70߿| '0| 70Bˇ!BP @ G A O@ /_|O`O`}!BC!B"B"D!A"D!BӇ!B70߿| '0@o`>!B"Dx? 4/_ H70|'0@o`>!B"D>~"D!BC!B"OB g0?} 'P| ̇!ƒ!D!B'p 7? 4xp`>O`~O`>o`>!B"D>~"D!BC!B"OB g_>}/_> '_|!BCP|C!П o ,h|/|/|O`"DH>"D!!D!B@}‚@~"!B"D|!Bw0B_>$Xp`~8~'p "Lp|ӗP?Ǐ1<C 2D/_~1_? ?} ˗/C 2L/_>}`} O߿| ̷߾| /_~O | O| H|'p~ <0…/!?}p`>؏A}2dȐ!Bo`>} ̧/>/_~|/_>~ ?} 'P ,h „ /_|!aA70_~O`>~|o|П o /_|'p "Lp@ #HP_|˷O`>} '0?~/_~/@~O_~ <0…K~o߿|/߿|O '0}߿|S`>'p "Lp@~ 7p_~ /_~/| 'П| ϟ| H|'p?} ? 4xaB 'p`~ OO`~߿}߾_>o@}/O@ DPB!} /|˗oO`|'0A~0 <0… O@8p@ _o߾}/߿߿| /_|/@,80_? `> 4xaB "߿'p?~'0| /|_>`#8P?$XA ./B /߿߿|@O`> _>O'p "Lp!C_>$X_|'P_/_?'0|}}8`'p ?$XA .dp߿O _߿Oǯ__/߿8>~ H*\(_ _>?~O>/|'p;O}  ? 4xaB O|8_o_/_~7P_>~70~/_}/@,80?`>O@ DP o7p`?}?~ӷO`|O` _>,h „  ~/_>~O`˗?~ӷ>}ۗ/?;OB(? 4xaB O@~ (_>$XA "O@ ? O@ H*\8`>'p?~ o`?}O`| '0?}/>}/}O`>O@ DPB1`> 䧏?ǐ!C ˗/>1dȐ!Á HA'p A? 4xaB ˗O?1`> "Ǐ!C "|1d ?} ˗!C &oC2dȐ@$X|8 A},_|`_ ̧_,H0_| ,X`O@ DPB1dȐ!Â1,؏!C 2d/C 2П ,`A㧯| ,ϟ>,Xp` <0B-\p…[p… [p… .\8_ ˗/_> _|˗A$X|8`A '0|˗ϟ@~/_>~/|_|<o @,h_> H70|o|/?˗/߿|o߿|;x?~~"D!BC!B"OB"D!B!Bo`>'0|˗O}O@#/?$XAo`o_>}70|˗/_?~߿|o@} @,_|8`A/|/_ '0|/|O߿};x ?}$XO |_|˗~o`>_|!Dh>"D!!D!B!B"D?}"D!B"Dx0?̇!B8ԗ? 4xaB 6LOC&ϡCСC sСCܗϟC:4Пo |8`A&TaÄ9taB}:t萡| H*TO,h „ 2l0> 9th? '~'p "Lp!Æ O@ DPB}8`A&TP?$XA .̧? 4xaB 6l/>:$П_|'p "Lp!Æ 'p "Lpa>~ H*\ȰÇ#JH~h!@O?~O@ DPB >QD-^ĘQFǯ#G 7p <0… :|1ĉ+Z1ƍ˗_G o@? 4xaB 6tbD)VxcF9:/_>~1ϟ /_} H*\ȰÇ#JHŋ3jQb?}ױ?ϟ?~ױcǎ;vرcǎ;Z/_|u?ӗ/_>~;vرcǎ;vرF˗O?o|ױcǎ;vرcǎ;v_}˗o? o_|cǎ;vرcǎ;vhП?ӧ/_|Ǐ?}(P>~8`A&TaC!F8bE1fԸcG ؏߾}8@} Է_? H*\ȰÇ#JHŋ3jȱE$د_?~ Hp ?'p "Lp!ÆB(q"Ŋ/b̨q#ǎ 'p 8`A&TaC!F8bE1fԸcG8P ,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*Wl% ̘2gҬi&Μ:w'РB-j(Ҥ7;;PKWA3<3PK-AOEBPS/img/adque035.gif3C̼GIF87a8?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU,8 H*\ȰÇ#JHŋ3jȱǏ CII'p>$XA .dذ>O@ DPB :o| <0… :O|,h „ 2l |Ç>l?}{Ç̷Ç>|~{ÇÇ>|_~>|C~>|Ç˗Ç>tȏÇ>|B{ÇÇ>|_|>|Æ=|Ç./>|!?~"=CÇ6Ã{?~ @=|X_|>|Æ=|xp|=? ,_> 4X_|8`A&TaC9t0?}˗/__>˗@~/˗Og0?}:4/_>:tСÂ9t |/߿|'AO?'0_A~СAsСCϡC _߿O ӷ_>7_(`>8`A ˗B"D!B!B7p_>O`>}O| ̧o@~|C!!B"D!BC! _| ̗/>/_~˧O߾o_|>~C!!B"D!B !B+!B"D!|?!D!B!B+!B"D!? ܷO},X_>$XA "o… .\p… o|'p_|˗/[p…[p| /߾ .\_|w0߿|O߿| ̷p… pB.$O` .\_|G0߿| H*Dȏ‚_|˗O?'0|߾|/?gp_|˗O߾| '0@>? / '_>@~O`>$XA "oa|/@}˗ϟ| O_?O߿|A}O | /? '0| O?˷p|-$/_}}O`>-\pƒ-,o`#/| /A?O_ o| '߾|O`>0'p A <0… 2ϡ|/@}۷o?/?}O ~O>}O>'0?}| '0?}/CsСCϡ|o| ԗ/>ϟ|ۗ/> ˗/}ӗ/_'0|˗}O`>ۗ/>˗ϟC:t ?~sСC:/_>:tСÂ9ϡC:tP|9tC9PA <0… :|_| B"ăA"D!/?!B ?~!B"D"D!B<ȏD!B@"D"D!B8_| B"ăA"D!/?!B }!B"D"D!BDo?!BC"D!BL/_}A"D`>8`A&TaC'p>} П <0… O@}8>$XA .daA~8`A&TaC  <0… :\?}'p "Lp!Æӧ~8`A&TaC!'p~ H*\ȰÇ#JH"| <0… :|1ĉ)'p~ H*\8_? 2dȐ!C 2d8`>O@ DPcȐ!C 2dȐ!C8p`?$XA ./_| 2dȐ!C 2dP | <0…˗/> 2dȐ!C 2d`>O@ DPB~ ? 4xaB 6tbā 8,h „ O@8`A&TaC!F0'p "LP!|O@ DPB >Q | <0„8>$XA .dC'p~ H*D`>  <0… :|1"| <0ƒ8 A~ H*\ȰÇ!'p~ H*4`> ? 4xaB 6tC? 4xaB8` H*\ȰÇ'p~ H*,`> ? 4xaB 6tC? 4xaB'p 'p "Lp!ÆBl0'p "L }'p AO@ DPB >`>O@ DP} (p,h „ 2l!Ĉ8p`?$XA *0'p "Lp!ÆB(`>O@ DP} (p,h „ 2l!Ĉ8p`?$XA *0'p "Lp!ÆB(`>O@ DP} (p˗/>$XA .dC 8p`?$XA *0'P`'p "Lp!ÆBD0'p "LP>? O|/_| 'p_|'0} <0… :0'p "LP>? >O`>ϟ}>O@ DPB  O8`A&Tp| @`>/߿@$XA .dС@? 4xaB 'p} o>~ȯ߾}|ȯ߿|@~8`A&TaC8p`?$XA *0'P`|o_|˗/}o_|˗/? <0… :0'p "LP>? 4/,h „ 2l!C? 4xaB 'p} H8`A&TaC'p~ H*T`>O@ DPB >Q | <0B8P>$XA .dC'p~ H*T`>O@ DPB >Q | <0B8P>$XA .dC'p~ H*T`>O@ DPB O@~ H 'p~ H*T`>O@ DPB  8,h „ O@8`A&TaC̗/˗O`>˗O/_>}'p~ H*T`>O@ DPB O@/߿|_߿}/?}ۧ߿? 4xaB 'p} H*\ȰÁ_|_'p "LP>? 4xaB 6t80|۷|>~|ȯA? 4xaB 'p} H*\ȰÁ ߿|O o@}>(`>O@ DP} (p,h „ 2la|'p~ H*T`>O@ DPB >,bC? 4xaB 'p} H*\ȰÇ# O8`A&Tp|  <0… :|1@? 4xaB 'p} H*\ȰÇ# O8`A&Tp|  <0… :|1@? 4xaB 'p} H*\ȰÇO@ O@ DP!} (p,h „ 2l!Ć8`A8`A&TXp|  <0… :|!|,H? 4xaB'p} H*\ȰÇO@O@ DP} (p,h „ 2l!ć8`} H*<`>O@ DPB >q|? 4xaB'p} H*\ȰÇ#O@8`A&Tp|  <0… :|1?$,h „ O@8`A&TaC!F`>O@ DP} (p,h „ 2l!Ĉ'p`>} H*\`>O@ DPB >q>  <0…'p} H*\ȰÇ#O@$XA .`>O@ DPB >|(Q} (p,h „ 2l!Ĉ'Qć8P>$XA .dC (Q"} (p,h „ 2l!Ĉ'R`>O@ DPB >L <0‚8 ~ HA H> 4H? 4xaB 6l> 4xaBO@'p "L?$XA .dؐa>:t>9tС|:tСCsС9ܗϡCСC:,ϟC|8`A&@'p "Lp!Æ sС9ܗ @,h „(0?$XA .dؐa>:t>O@ Dp  <0… 2ϡCp_ HO|8`A&TaC9t?~W? 4xa ,h „ 2l0?:O} 'p "L8?O@ DPB СCs/_A$XA 'P`> H*\Ȱ!|:t?}sСC9tСC СCs/C ϡC:tX0?:OC} H*,? 4xaB 6dϟC|:t(0?:ta|:t?}sСC9tСC СCs/_A$XA 'P`> H*\Ȱ!|:t?}+П <0@ ? 4xaB 6dϟC|8`A&@'p "Lp!Æ sС9ܗ @,h „(0?$XA .dؐa>:t>O@ Dp  <0… 2ϡCp_ HO|8`A&TaC9t?~W? 4xa ,h „ 2l0?:O} 'p "L8?O@ DPB СCs/C ϡC:tX0>$XA  ԗ? ܗ ? 4xaBO@ DPB  <0B'p A'p "Lp`> H*\Ȱ!|:t|sСC9tСC W? 4xaB / ? 4xaB[p… .\H0 H O@}8P ?} H*… .\pBO@ DP 7pO@ DP|.\p…  @,h „(P_O,h „ p… .\`>8`A&@ 8p@~8`A&T80 .\p…+П <0@ ԗo <0-\p… .$_A$XA 'P|(>$XA o… .\p!| 'p "L(?8p@'p "Lp`> .\p… p… ˷p ?} .\p`> .\p…  <0B'p A,X` ,Xp`> H*\Ȱ!C$XA O@+X` ,X|8`A&TaC9t?}СCsСCϡC琟>:ϟC:t`>8`A&@ 8p@~8`A&T80 .\p…+П <0@ ԗo <0-\p… .$_A$XA 'P|(>$XA o… .\p!| 'p "L(?8p@'p "Lp`> .\p… W? 4xaB / ? 4xaB[p… .\H0 H O@}8P ?} H*… .\pBO@ DP 7pO@ DP|.\p… o…  ԗo@~.\p|.\p… o…  ԗo@~.\p|.\p… O@ DPA$H ,X` ? 4xaB 6d> 4xaBO@+X` ,X|8`A&TaC9t?}СCsСC @,h „(P_O,h „ p… .\`>8`A&@ 8p@~8`A&T80 .\p…+П <0@ ԗo <0-\p… .$_A$XA 'P|(>$XA o… .\p!| 'p "L(?8p@'p "Lp`> .\p… W? 4xaB / ? 4xaB[p… .\H0 H O@}8P ?} H*… .\pBO@ DP 7pO@ DP|.\p… o…  ԗo@~.\p|.\p… o…  ԗo@~.\p|.\p… O@ DPA$H ,X` ? 4xaB 6dϟC!?}:t(0?:ta|:t?}sСC9tСC СCsOC ϡC:tX0 ? 4xp>Ch> ? 4xa)TPB *T80SP| SH>SPB)TPB *T80'p_|ӗ/_>/_>}˗|ӧ ?} ߾|/_>~˗}/_|ۗ/`> *TPB /!|߿_>ӗO@$HP ?}'P ?}ۧ/??~_/?>} ,h „ 2l0`>/߿/䧏 A#(0@ }߿/߿|߾| O|8`A&TaC%G0?}o?/?}맯|)!?}̧@~O`>ӷO } O_?ȯ_|:tСCK`˧O| ܗ/_˧_|O_B~g0|˧_|/_}˷O`>˗/_?g0?:ta|2С@~pa> СC:,ϟC:OC~.!|:tСC? 4xaB[8 .\80 .\p…[(߾|[paA~o@o…[p… .\H0'П>~ .$O-O?[p!|.\p… o|'0}/|˧B-OB O`>_>˗O[p… .\H0/|O߿|O>} ӷp ?} 3_>'pPO@O@ DPB P_?'0?߿|O@+X ?} ׏?} `>/߿8|8`A&TaC1엏?|ȯ߿|@~琟O~>~|ȯ_|:tСCko_|/_|˗O}o_|琟>˧/_߾| ܗ/_˧a>:tСÂ9,ϡÄ9ϡ~&ϡC:tX0?:OC~:tP`>:tСÂ9t?~СCsСC*|8`A&T(p>$H>$XA ? 4xaB 6d0 <0‚8 A~ H*,? 4xaB 6t`? <0… :|1ĉ)O H*\ȰÇ#JHb? <0…cȐ!C 2dȐ!C'p@$XA .$/C 2dȐ!C 2`>'p "Lp@}cȐ!C 2dȐ!C'p@$XA ./_|1dȐ!C 2dȐ!~ 8? 4xaB O~ H*\ȰÇ# 08`A&T| O@ DPB >Q`? <0… 8P,h „ 2l!Ĉ'p@$XA *0'p "Lp!ÆB`>'p "L0>$(,h „ 2l!D8p ,h „ O@'p "Lp!ÆB|`>'p "L`?$X0,h „ 2l!ć8p ,h „ 'p 'p "Lp!ÆBt`>'p "LР>$Xp>$XA .dC 'p@$XA 0  <0… :|a? <0‚ 08? 4xaB 6t"~ 8? 4xaB 8p>$XA .dCO H*\0'p "Lp!ÆB|O@ DPB? 4xaB 6tb8p ,h „ 'p} H*\ȰÇ#08`A&T`>O@ DPB >_? <0… 8p,h „ 2l!Ĉ'p@$XA .O8`A&TaC!F`>'p "Lp!|@ ? 4xaB 6t~ 8? 4xaB 8p>  <0… :|a? <0… 8p80_|ӗ/_>/_>}O|O@ DPB  08`A&T`>O@ /߿_>/߿>} H*\ȰC8p ,h 'p} o|70|Oo@$XA .dС~ 8? 4xaB 8p> 7p`>_>O?_ ? 4xaB 6t(|O@ DPB?(P߿|O o@}>8`A&TaC'p@$XA .O8`A8`A&TaCO H*\0'p 'p "Lp!Æ208`A&T`>O@ DPB >_? <0… 8p,h „ 2l!Ĉ'p@$XA .O8`A&TaC!F`>'p "Lp!| <0… :|1~ 8? 4xaB 8p>$XA .d|~ 8? 4xaB 8p>$XA .d|{Pa? <0… 8p,h „ 2lp`>˗O?'0|˧߿| ܗ/>'p@$XA .O8`A&TaÇϟ}O`>'pϟ}O H*\0'p "Lp!Æ#0߿|GP|GP#H0,h „ 'p} H*\ȰÁ㧏@~/|@~/?}G|O@ DPB? 4xaB 6t80_|/_>}˗O|/_>}˗}+`>'p "Lp!| <0… :|H0Ć8p ,h „ 'p} H*\ȰÇAl`>'p "Lp!| <0… :|1~ 8? 4xaB 8p>$XA .dCO H*\0'p "Lp!ÆBd>'p@ <0B 8p,h „ 2l!D8`A H*,0'p "Lp!ÆBl`> $? 4xaB8p>$XA .dC'p 'p "L | <0… :|>$Xp,h „ 'p} H*\ȰÇ!'p A8`A&T`>O@ DPB >| <0„ 8p,h „ 2l!Ĉ8`> H*L0'p "Lp!ÆBO| <0B 8p,h „ 2l!Ĉ'p`>} H*\0'p "Lp!ÆB8`>'p "Lp?? 4xaB 6tbā(,h „ O8`A&TaC!F$/_|$J`>O@ DPB >|$J`>O@ DPB >Ѡ>%BO8`A&TaC!F8"E? 4xaB 6tbD)RO8`A&TaC! ?~8`A&T!B$Pϟ?$XA .da~˧O?~'p "Lp!Æ O|? 4xaB 6tXП|{Ç>o|=|ÇÇ>|0!|>|Ç=|Ç.䗯Ç>|P>|{ÇÇ>|_|>|C}>|Ç˗Ç>tÇ>|B=|Ç{=Ç Ç:Ã{?~ |!A=|Ç{>~{/C{  <0… 6ϡÄ'0_|˗/_~ o_|˗O?}o_|/СA9tСC !B~'0| ̧@~O`>}/|(,h`A!D!B"D!B}"D |߿_@O`> _> 7_>$XC!B"D!B!D@/} ̧o| O`>o|7_>"/_>"D!B"DBo`|˷O`| '0?}/_>}ӧ_'0|˗O?"/_>˗B"D!BC!Ḃ!B"D?!}? 4xaB[p… .\pB-,o_|O߿|o>o… o… */߾ [p@-$o`?/߿珠8`A&TXP .\0| ̷p[H0_?'_>~o… o}/_>}˗O?~/|8P߿O O_?̗/_~o_|ӗ/_>/_>~˧߿| 8p@ 8p@~߾| 7_~˗O| H*,B O?'0߿|/| '0?}/}W0'P?'0|O ?}/‚[p… .\XPG0߿| /O`>'p| ߿~ o`/__8_>$X|8`A&TaÆ5ԷO` _>'0߿|O`>'_ 'P_> o߾ _ ̧@~s(_|:tСC5/_~˷O`>˗/_'0|/_>}/_>~̗/>˗o@}/_|˗}ϡ@9tСC СC saC9tСC СC saC9tСC H?$XA .dÅ"D"D!B8_|!B"B} B"D˗"D!BDD!B@A"D"D!B/_>!B>!B"D"D!""D!Bq| B"D"D!B|O_| B"Dǯ?!B"AO@} H*\ȰC80>}'p "Lp!Æ ӧ`>  <0… :,o|,h „ 2l}'p "Lp!ÆǏ?O@ DPB 'p ?~O@ DPB >QD-^ĘQF=~RH%MDRJ-]SL5męSN=} ;;PKt_8C3CPK-AOEBPS/img/adque437.gifGIF89a|@@@𿿿```000 pppᰰPPP;;;___vvv???999ggg///www 888777,,,rrrsssoooXXX***<<<:::666kkkmmmOOOGGGyyyiiiUUUuuuJJJtttnnnqqq˃}}})))+++MMMxxx'''444[[[zzz---Ĝlll̈WWW~~~jjjhhhSSSddd>>>===ZZZFFFɖ555EEE]]]|||NNN(((RRRTTT{{{\\\&&&###KKK...eeebbb ^^^HHHVVVaaaIIIQQQLLLDDDcccBBB$$$YYY333CCCAAAfff %%%"""111!!!222 !,| H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜIy%(Qy@ *]P cyM ʵׯ`Ê]` z өF"4 y8BJtnߌq LÈK怨=+{pT k=Q@4h8R1DѥQ"%2> O̼У7,VxM4\u62+ԧZ1}О8F[-pWV7-pt 6hU5EHނa 0\=Г_@:Fi%M:@ :uA h8RB8dGmЦU]֝Z3UZM1iT5uӌғޭh%T V%^k=eA<.&Ap|=~f}h6D|TVeMIDYFY15mB S|I|UT?)ՍؽT@Y諰DڏiuWN{jehxR TNi!'e-꬘G՗% pȘVC嘀wN49ϓبDcy% aY+=PZ@X.}ڬ~ʥoW`~y6f0VUZ=o8'Yw0Uqb!@GgcqN.@`f-`]=bAX 6@N11}@:@76Ae6J]fI\_aES:}Ϲ:Կ#}a6[(IGG5䤗n5=2 YQ.x$Z9SKUfF5:o`B;u끚b@i}S)TSNohYkn +ɖ8|4_ fe8  ABPƀy ٧ ,JH0h|I O., 50:RKwb*$#2C=`z DZ._fN Y)bԓ\XHG爯@4:PC}f];Ȝhw7MԔqL'+t:ۓw^븻r/7?Leo‹(rN6$].Wd`bCq~piN6-coױ`dODW7 0D_# aMB E7DѠD)?fYյ*aU~8Bn-BNLњ%/rno h-+$$ݍ6$J[~m2ݟa>nt ]SZ+< ӭ h'6]^v+=L+Gxt~UF"$s%\4LY?yvMr*A3 $$x \ꎔiCoF$і 2mYc <ss+ X9Hhoa/%?j?'} A~g~'~AGzw`.G>`B0A ؁B>?#Hk*{w&ʳpGXxwpjT`c@\؅&(<s**=umQ61K`R ^؇~ 0^EbzqwWcqt lFtT\F0{{˧i/X(4eB@ȉ6rRm/9t7.yƊA x=8Dh>'NKq'zc2؍AqyP X+5'sxV)x8DE'!+r%GwQ!tcH 9lRoBrk"r ̑R4DuG\<0{7ѵ)^ ْDeDy4_ $|JSzKxSV|uˆAy'`-BA-)x j:_fWD)2X]q}ק:cА"Ja(.)^:ƕ|Pg Ij8~y;%Gg@b~Dc5B B V9oR)"0h ZTPc~9~*Θr G!Ittjjx#ѪGI0֭&6`М.JTxw):?PʐYe0ҕnp qBAVWrj6ٰRB(xЙ@BŨ$(+F0ȝzţ Q}{cfjq`yyhe3( e#ZQJ1B(3H@b;d;E⵽Mlv9QZ %JҰV$haKk筇9c"X{aC|5\Km{}r şy:{kΑHy ~5ࡖA QPZх!U|* S]ѼF۽ȝ.;ƳgaM#!B@۾+} Iy.0+WU{ɫ뾰yM[*:xRmvv?y=sӠ =  \[+NqN ЯSMu WП/t l2i]UT֬Qg­g!{G(s"2ea:  ,$Lz,8k0MOа,]' Ym=,)ȉ -df-v0u#=v[5> ^~0$hFaw~Ӂ=M+!Pj@ Jxp֍@r0 ޓ} }{CLAs>4^Yџ] `;dQ.Vmf^sP!2VAUˡwx<N!px m#>ȃ"D P'p2N8nSQ|䖃nM.-gort!pxn&03 uӭBz^8¾Z'}0 p`2 ^^P=Ø-lK\@[ A\m̸~n1P-d )^zO8) oN>~N]`BާN,'?jv^3-7p;F( rzqJà*`69[5P" /@^מnmޞ"/%OE1/-O/):6u8;@/@FH//@VZ^_d>#jp|\Q!xx+>A?E(/Y[_cخ>;/w-f av $XA .dC #@^P0a,X bETv% A4(Тō) (^ÇIA 6rHF "RB!V P Faq08p@. LY#&\+>0o^ő pxdɔ`8deΡE&]4iǐE4y=>]mܹuVL"F=I$JM8u gСE&mӨS^ͺ p[lڵmƅ0ݼfu1#op@-Jm4*MAByx(pB aFͲp CqD|(:(J:)%%MYr:` #rJ>Ϫ8< 0@=2 -r . /cH4L4#4BCbҴ( !6tS$sQF 4cѸ[ba` c|g`8d<0 ǰ»`uHyqpL*2-fFu< Z`?U $C4i`n\Lp(- VQpGQn\D.y`SPoT '@ǐN橠yՎydVng $S`ۻ>->0π2絙%\ Н]jp ELpi2pJ+$3vT$`T9Jr 8QyfC9dd"&")3R2p1f'<rDžS,>/K1i{s`3 yy,9M2 "u/}6M\$ 0xpLuٛHER~1W68G0Og~pX ]7\}ELJmyc-MyvR :2<ir6!Oy o`#.[#-yJt:+aK`S2~4 ӖL" A#W^c< @1 Qm8ЊV!8H@,S+dF.^Vԏe3Vb-r$hA zPR1Ub̀2t䱃(B!QR@E*TaRy @Dπ43iMmЅJojD5EњH'(v:)<$%VNt*p2iWU^CY`.zDgT(@A(*GQtSMDUğ?󳀬F aelc;3Q+ ӷF"0$U#kV >SyUcp2@YVE bhLb24uK ( 30'd2@(SU,lD_RBJ 20H,Z0a(C~EpGZyp @Dp2+| /U;7a> GAH#s@o|\;M]'D_M Ho<4 h<0q#T#5hp1Fmmv601iܟ@E` khЃQ\'vy`zFHx'>+= x +D-H_e0 @t؀D  78\3*;2 ,XAٸS`'QhF>J r05xO P7[bc 5_R>\ W) ,,(+X*)B/b*,,ҋvh 2 B)*C=Z ,((!ЮAZR~Jy9PBzx[)C=$(q Q ,lAҬA+ ýB42Bja3L8<++h4E"P% N'+(;Cad-: "; *RpFh@F|Hg1@FpT[ +T?Y%(X"PSDog[ /x:aV +"x)x- RxFCԁH|J3a>$&TxYXǓJ%OPs *2XJE],4K;J {1J8N JHhG҄,H ""x,nD#D͎DH DOРyȀQQLLŏ8h5nx@,4PP  8 (DNJ(h!P+H -Q=&PQ>[R 2]P,p>R s(P-% ÜcJUR-US=UTMUUMEU3/4- 5E49@.:SqQQ E6}ҙlNUEeT!l#JҢsT c >W}UԈLYh;TRU[`1X5S}n8_8y\%%G4 4}Y @72<֟:c %PyҺfOpM eH]b`|4S Ji D(`H[CE>GdQJPtIO 8 fB+i*Ja$HU.6}SVpT?RiKVg-#NFbhSXBA!<+6(-_I1FpeZ58 @b X5XJڻ6~N$V=SNTGv-Āg.C,Ζ2þKbD6Tƌil,_5=P>^\J &ԗmgMnzX/C_A4˶(0FnԶL]H+pqʘM#{Z *6چb>$(Xppzã@Apˊf[j1 pb XCV2r-r.r/SSof\71.o߭FA "@`X &jBvh:9 k L@~sfF>\>sMs_6oyuJ-F<901Tj6`*e(q 864vCLHt X)p)[tkDt@=K:Us $(py(-y.@yh :8HS h1Ђhh ^a_tru Pvz )4_Q ij/&\vSJ8g^svҁ'R(AX-<Xy80 `;kH$9؃y(oְ.]в/yGN0DAB_qq*/6`  ).QJĨ 5^(inGl/7O ,qnPu: {6%N 9ІeKWo sZS(hD?%BVyb.pq^AM ? VJ cWxQ>4D.#97b߯*d$HH]P:$iJ.aʄ@&N\, };61G$yB-B NCڂ#\ Q/`$ &x *8YfX3'3%@T"BHCm 5P<8$@#N8Ds%J-L D"pw J9xW9"5UVTTI P؀T&mIEEA J8O*VPapa 4"Jp +B(:Q (<F'dCY٨<K 00.+nhܐI*زƝ&oWaŚ:,:'=s:;(SYLž` jA 7#0 /x4oCt U@ 5 B J H2@+t+q'oDrO_ಁ $HqÂl|2)KRex·^0n({o6*LQ [0Ib ,bV` 2ه\6Rg 6m -S2PLA 4[!梫.»0k/+ ܴ+,5HuPHMN;onm詫zosqY,,6= B#^+8Cp[1$qIM7 44[?>>OVrݻ< za ؎{|w pg4}|`,rλOY|"q@uXE i6`.|! ٧XGF L]'.!@ | q(2x59btTX ?-#=~c(A!} m9V1^EJxL# r(,jxhdX !85=HiN. @@H<&2y@D!6Pb]%3Cr C+f  SRq?I,+WK[Mc/~Ѕ (Х2E*TJQ \̝y.J$!-Ha7L̐.X(/1\` 8B,PF QN5քۘ*~NQ},d#+ZJ0zU!bS)(R~ 4EDiB 8:KْՆ~|^&2r/ZXu$poALq@@1F)8T<(3dUVer ,. H@6~0;C0CuQ!.G4qI[&򿷌%$RT/@A` Q~$`ArU)GTQ* ,[.d >\ M;1T곷i 3ʎ `YdyD9J J@D')@,iBZ9)(0 g̾<<3xTsN[Oh@#~ :G .)*(>@`xt(s-nUz)a0 Uxyw0C,/Ď;R[X  Y3Rp=yXE z&<-{?eeACA텳|dn$t@myC1䞦o} Ha+u‘ņٱ 1Q$%8TU L4%TvWTW~%YB-XaJԍc4ea@%^*\&ha%XB) \2`E_.Ʋ%c&Y^۶E4y_2[> ]Mae @MfeChFlfg~fQ8[D`6p:Y|]f@^ <H E@f`N\x$U<@$euрt%uU<p}FEqFIb&f$h_]Za` _'gnYÀBq=,}hSPhQgQJQc[ƥjv\(۩Q\ ٕ)R.f%&U,>>Kwhxh(ߒF)>@Z)")^)%Wd&Uډ'.F: Nb&)J=>wY*=]PT}"ie)[ )b@WPzcPfفv(]'@QaJ*~  QF DZ a.+ k`bP(k *Vd9 I&v$[&(a`+@+eH봺{:@Y. )wl+J>Wb:.),=f&lEf.=ebwdg_z&]"3DlB^mf  &j,m>ogDA&&ldF%[tYMm-%!x%s' 4tQ, %&@s!WYFw =b%o^[ٮq+ӢFB|%@-| _Qڕe^ YQ 喾yGeNQ-Ȇ"B꣆bUhiF-ljm_ @ ) d :E+_ebȭi_rRV.f^ś62 a%%N)ez[rir o+RV')Qd@93jY^G)&Y 6p> %h:Qpۇ~Jh퉒n/`p73oƦQ|=dwp.f&*-Z"t0u)Ze]sV< <?l7;Ț%.Gڦ&>os3?tT_srEgN-.&犭>FD?DFI$2>l:ttJrT\&Rn~ ꯋtO0Dq5fbr%Z"SGS?ud5EbJPܒ^b\D%l.fWkXXs\@^ܭ |Fr2%Zֵ5^u7t?XKPb.ww7xsNR pzzw{2흦iit7^7~"eu [v Wx8R$^$q^;xw3dr2Y3?mC/v% /W+qGV˸^8与6ߧxS9Lw%'$7yGy3N9c9Tjs{xsW9۠ySy]9Ϲey湞W:yO١#z㹙O뙢G:s5zTC:Ko:ݥc3KOZ:Bĺ{:  Rz$g_2揁 ;3؏"9KVr.Ua޲BẸ;boe̻ػW6EգqPAȏ<ɗ|ȋ@H;{;3|ؽxHA(=чA{X*oϣm}_=֛<{Ah {Lռͳ:Ϋ|@ֿۣ/Pd@>} X=K{\" ؏cٳ nKgHt=l=ڜO嗾O"IKM.a57#3s_S~Kн=KEXxAh1j.eL(EwnMA{HIMeIncO?< e޼5tbD)V`AB/ vdH#GdYX ü.iִygN=@gPCmqќ!DISV-@ v@cTcɖxR.a\n\4|L*o^HF,éf *"<GÓ)Lܣqö33wA݄@?6]of%y\vlKp=Abbz76^OǙNǼ%A|W㡩Hy-}>KO>swOs;Ыߒ*p8-CP tĠ֛U4 ®tCBH A,u!T&Xk)Ά<*@$H*qxKyD F~T*H$ż1ͤIɡ.K':[یQ<>,3&#S3@(͠h'pG :Dݜ(%*A5Bq*`$QyrTY%-*SNmuHOmZV=|S(Ry5F$V*b*!xVۢ]QW֓YD%t;b`>Džxɧ|/0`PwmicPS0yr> 6d»8 p kHDAl=WP(r^5+(ez<#Њ$΃d;D)`mf\ĉ<:Yӓ2Bc(.`Z q<HS|OR@ pJ1P я~A"HYB hRll$?qAK093r>2/#h uJ%cC˛q:Ҝ$ʰNwvh.PvIr>m4;O p6ͅAt’"gM Gs% F:_VD&PSta  h(G Mvm)M'Da֫Q)` K-l`tG{.VpPXV+3iSA,BxI?,!-ֱbrRХ,  V5'Uu+ ]8؍՜*ڕ%`8!8k Zv-+S ~ h`g@u`ն},45IYN*U,gWmB3HBpzLH'Z>Vm,o܊z'OG˽oR3p\Y^\wD!H ʄ8tD\)oR=yYnv .`t t|u !AqI<7F4 1Yk`^2mD@Xih\5hk9!^0#xM6@0X:BuPʩ7~u6B Ӽf;g,"YLv f0@yB#ġ07aV(Up-f3x`) fCO*|AY E]S5l%^Iӈ1k$W׼5sW4>hlN,p*HfjZr !1c-up9 Q<.k]q&ʑ m\e-{p܀o . (X\QPp5,!U(aNr B/70 V-ͮq; 1_@4`$QJEQ%;`@/@ G#sb/! cq'R/2#RS#]O&. R#%)R] !k27a' #}(,av 8(a@ĀGA\a)3n / @BA^!*! + ,,! / ג !-S'b.2 ~M(j /a  ST A B/v 0E, YHm'en2}^T|`粩(A$ ̒` 0|  ,(!  n,7Y-1*u@8/; !s,93)-5 :w'b;;``U/7~@ <~@'~Eb6 S2sA>r @*B(A&,@~aԌ j@E javraF qRA8I 92HR 2"SUm"#bVP5 tK/2L~@> DtapN@TR@ !1Q1Q `42!O5 PoC2 ! )@>1@ S7u`u *FF{4-XժGs iV3-s p|XOMXѐ'5P ZJR:o ``0WF\ jS@㨍@t7K0A^ ނQ22cJya` VC6={`0ApbWb3]9Tm@QVlgcbU [Q,[VHcvW7'2bgO~!]VZ !(5N@kkU5l_ɖO}_V {*UCPO3RSW06TGTFy5t%,@re,-%Rf+Rx>7Uhtttc!DZZ5,`: >4`Yl|jVx]@7U_Wm2 uBn74̈!DǗ02Uwb7c ^Yc7d7Ȗw,|tV+WT-g )&4Y#8<(A4L{<tD5 F~ׅS bEg8~ĀuAuqz:S+v4 o R3b ` 5.\`4Xa>OוXrQSWl s .z9&qׄ4m/!Q/!+Q)1Qq0/XϩpY"`ròXW a! 鏵ge$/[R;ڣ%5b/&z2Q9:i*{39au" ,[e1  raIyZ/Ыa2:OQϩ <}eϪq%1 4kIѕz ln@r85fa m),.Z|:S @r8ll;)b;e <ڻWL:Yzadz>!,A99  zha:lZ4Ja0 ۰ZGEJ@[Ú`x ```VNaؠF@!lr n5/|`z \!`Vs pDA4/aA`AU'Ý8e 0pOTs! 6xA Lʠ` Obee|<ȇ|< JXL s$jh! @K%6! DAx!cN6zN@ 8@ ` Rv|b"+W.J-~``+l:\!'gq]׻`ajA| L &>!@P'tFvv|W)!(v(! `!N}ơ.(pn@ȝ*!T! ^?aAuyaoUv@QaA\! F `Z!5acACAr~F! aaDf#<E] 8cZ:i@Ab@G"Dpyf&2/*R5h0/TҨhDCy9hrCȼ ;ۄ¥=9Ad+p 0'TѼ>̃# !C99kakp7HP`8@/ܹt}y"3CJ LLeyyQyBv"0re <%rP1IK8ZaE<(scaSfރA%0( Wo  >˛?s,layw,gp2\-qe9ni(s.,s=N\FgұE:"2J_%j۹Rك; Qh F]3t1`Ec a=IE0Bo/ pbx8>8R.v  f 8LbvqlA#؂ fA@Ep . tp@(P8`ZPk 5HCD*p0@2IBfxF0?beBzK\ dGga&pBܳ7R+rע.7osE|F(JQfCP0h0`ZD&4 F4T@R b!PL!RT>4J8`p  !l RB uW^\ЃEw$ۂ2T2fx`X n>1A}sG?-/K(Z@ t<.A Z, =BЄ(T! s*1r&$JdK&؂ #ܲ,EKUmaHCPl7}"T Hfx^/maaX?R`9l (b6ĩ}CrYiy]F~'|lAx"R7+n_`.q},{ _W>ЦS.(3Dum\ V4'nq ԇ=Q KYXo[#Q_anػxE<5V'NdEPY \l~_W 0-w. H0[x\ypB$,. 9\-yIXۀ p{_9c6pgؿ0 4(|!ж6nu8E( humy t5$Yk؀bT<Ϛ}ǭ]1kGX@DFtn˄%́ \X\Xk^W|xPSF(09 xhilc\"Y@2 G d p-O#,].{1 氄c<61.pnh_p{( bw0k `09VѶI1DFvt}YlMD 'PW28UmtpQev&@H0}w :hAsV sZoxZ@O8TȂy G YPD0-)jnE`GP7g XH7?AVIPFglЧddMg!Q`=_8pzMPsIԆ7(hS@萼z= E=zPrV@gXpCk6̘ `G桁5ד>#nٓE`w0X B_Gh F8'N9  0|UxdHlޘwR ^D(4 T)Ii׉٩ɝygXpљ% I[<hW0159!gNa=PFyft%aGkHm H*us`DpYpwCA @hHYY(.PAt d"CEWlϗdt7@  lp}=Y[ʥ]_ڥ%u] IVFО#Z-C0zp 6ymHMIpyo)9zLxxf uqpsPX)J`Y &zH`!z0`,h\@C@`i0ʂ oЩ4G  Qm@qbpL¹VɤZ!dQ`*JjB>7:G`n `Z*wj)Zz|V9硔9CIj h۩ʪ@p ڧکJ{ Ja:.C@7 p*PЛ1 aٍKV h0@ ֗POVJekg{d*]걇 snuک2K7;xʪis M ȫ. ʘj葑 ml*s[zJPAJ;[ C;z&pTWL[OD j`#` M0A`AL4`\9e`)9HN캳E0{ Vв}rjమ[}3 Ph⁥ p W@&:P{1pP { ¸kk A۴̊"Q@#]  R 69ੱÔ˶*,;%|ž{̾ k#l`聥?ꆘ;¬a쩠[@ulG9[뫺E0xµ6p 3B5ËR { J|W@|lФ[tk&ZK\|S|IL\H~kkx#,aŀ|a}<?Gɢ( Jx{/u LȻ̳Ƌ\Zp ax,DtEFJKtlra",TR,΢J ˱˷^ ǬåZ+ySq\vz<|l ̃ЮkGx <lD|ɍWyFP{3rauaЪ\l[ |`}Zpl>r\ X=M0pip  1p+ o d՞G` ȏ6s.ZK*}ߨC]ԕP3j`/ݩ\ u~o pkk nr6 s] lHp\49zS|dCͤ(a(lMoP yg@\paRЮ;ܡfܼC{1P |sژlBd BX> 2P >@CaMSqWP lݝ} _p ވ} ~0!փS |!}WP s @` .9>WX; v9dsiw5<J] `m=f= ) :@ yrkei~lj nv5 G( m2 5 O< &{5 HZ@Z(0 >[\[M{~}^Ob=VЈV <ܒPNL~鳊ɐXNM^w ԍ@m> U4>>~ C v'א 'rr @8b!P#'fIW[ ocӮ.  G [y]RIOn?r Ms-'h S1\9q1_]zu2 eNv!K@:nj? f8{_{~gVn/>hԝ-DoF4Udžm2_ae I ĞiBihF&56wb0kYUsQ@.p(L!yE@# & +Vq 3fĈAC-Zܸ!Oގ0`>4h @@*Tذ#G5j" ʐA 'N`0b6@@ `2 !&:H_… FXbƆ̻cȒ)MysϡGvx:V a˦myoxh[lڵm#TXA \(G"ID˘2iĩϠCESRZŪװcɚE[suad NȣC8#.J:)ɹni~:ϴۮ*"OJkފ=2>oFoı hNZ r β-ʴz8S`1K-1*#0h <.A.cNNBꌴ 6J+HT|. ?0 ;*(@2,8[߄.(S:D@E4=K1Q^4RfXc}?2!5+B[4'Q.xcXr!L$SHP +T5) 6Y@ @DR P,}3A0A$8xE!Dw(° T% EAl .(`+X7^: 3{OX` @"U1hDYK w$I; y J؀8G@a ( Dc[(1`8'"!!H'8 щ0t pEA9\_x.,AABOr]F3I ItCHQ!G đBjK:@H:̣ 3 xa.e# K,`a!*<9&$ <B D4dw(]%/pVK tDh1aC޳42JךBظm{qLhHF检Edi&0dfB䱄%@ ~0 qH~0-P,a8!X@ 4$e)@ i6(2!IB!RLk.0^29xDyBx &c,摂>jjcZ".)`ZܨCw:-(zDhZ$t1MEMHd-˪ mX֙={wVY6 0! ȃ`<>OU 5"h.1]+׹F-pb %6A(potn@9s@Lθ{bw `NC АrV%tyv"HxC@zH7s器*j4>G8X %%Z@!0Z  D"jh!k(] D ,MI\حJ p.|H3y8 >>aG20oc -@:('5, )& p@s9I! 90hOX2H;ATB\33. yUDqDID ؾRcD7yx9œAhYSF5XL- FD+2FQi~ 1\;1yFX9_X& >`y;r2ĊR P s1JG3Zǝ$yzRl:a{ʷiTtHK ı) H5ILFTq I*5:8G~r>Sll: L0*DtɁ{.g|N;ӣ ($6QKQL̟<ɒpPY)l$xM 0 2d:ƙ8h!b=,pLaP0β( ’4@@P5ENs|C,\t?9Ux\?:QF&`&18;01e(,P"(]hnL(Gx@4P?]m 9&%$-iJ2с;@@ yPȂyyPxOjP0TZ&DӯQ#1I G_0FHq⏵bbvT 3ye+2$DVQPpAp24'xn MC){fG P!H3H H|R4)ݴ>>9ߜC6K`oZhI^9Z$)*2Uō>`dA2>0mŃ3 Q/TTa4$W ނHPKg)eM~&<gm:9p_h"|[_6\Iݬ9^hi+p*h>c'FG HHt N2PbȺPxdjY03XеM}hTu>Z0kJd h뿮yQi`.iD,֦Kh.g.:&LMxRi C9X҂m:³RgІnVXh?/>nyh[Mܱ0^?@fARbR}nTonvOhjh~m 'F(0dآYGzERvo> ='IuG.xb2x5IЄ5i $Mq;p(2@)X!N$+ P˴p~W +6N(8!xu ExǮfI5@1'0q.G0C h!@3h)P%P>hӫRElЁ r-: (k_,P4sD81r9*KnPkqҞq.eGL`LJ#a]-)P[`=D/;PX9Z߂`Wzuȃ+󄠄OH@2Ol4Gw^PV9v;Ȅg0qP$:pQ0vrJ4M58po/0A8yW}Up(eXI@؅ZD6UP8W/vz0X;`AWOFseo WPm,Kj;77 ؁(B`,mJ&2 3f<4.xR',&o|Ipl{s-8*GH@0 ? dB&nO0)%N8v?O4HDxu V6 KH7 yH8A(PW%7vg=~g+ɗy/RK5$aÆh" z._Œ)s&͚6o̩s'Ϟ> *t(ѢF"E  0GR5/R r*\!V\ Dij|!ɔ v̘t0jl8 XG=Ա)Bƛ7ӪIB ,)CNz5֮_ÎMt oytqVxKrʯpsȑ%O@"J5xH1o ÔMTa=2dX AC# X+ @ 1^xqz'}s` H ;x"/zwaa/A-CY` . 3^|8rH Ђt )$\p g kTW +_w♧{ d sYs'B-\@gBRZbrکZd=K PM3z@ګʄU$@:L SBQ8 b:C,=ÃȾZK K$K1~, W3 S4 𰸉'K P{<.L%0>< Mp o҉Њ{@-W³߾0#3}.j':TzˊYVUīKiRY*gꯇt W8z qR/Ԋ5%P+ӯm&3\gA=42qՓl*+Uxne-MN06},MÅ7 eeèmsԁy _@VV u!yslY8@:mJ1wR.+l$&Ŋ0 a"qunE8*^1[ߵlI{oR㗘z=_nN=IB"}Cْ"Vdc< z$&S2M[_Rrs`laH;"l5Bu&_D=+/{ Ǯb4^ &!<\+wv™du*NBL2,LX PbVwR%BKڌNaȅ3V8I 8knz]CeM)XE.EӺ֗Khe8fnB9Sm>g6$d3X$XA .dC%NXa?Ǐ_> _>C"D,*0| 䗯`| ܧOb>-ZhѢE-0?~_|˗@~/_~/|˗߿~WP_ۗ/_/_>/?~˗߿}۷ПEO`> G0|O`~/˗?}˷/|˗o| /?-ZhѢE )O_}/_>?}_>~?}(0O`>__|/?'p "D/!| O@~ '0~o_ۗO`> /_|O70| <0… :|1ĉ_O`}o`?~ 70| /| ̗/߿~O`>/~ Ǐ_>W~ '0@~W`>߿|_߿|ϟ@߿|/߿o?$XA .dC%N0߿|/_|ۗO@o| '0|70_|/>~/_|Ǐ_>O}U8_| G0} /|o`/_|'p߾}_ۗO_E*VXbŊ+o>~'P_O`>'P '0|/_A~˗_ 'p@}ϟ|O`|U1 '|'P|O~ ~O~_|O>8`A'p "Lp!ÆB(q"|/߿~/_>~O|/_~o` |O_>~ӗ_| 䗯߿|/?QH1|(߿O|/_} _| /߾ ?~?8`A'p "Lp!ÆB(q"Eoa?XQ`>~ XbŊ+&WbŊ+V_Ŋo!|X_| XbŊ+&WbŊ+V_Ŋ+V_Ŋ+VX1+VXbŇ*VX"D*.WbŊ+VXbŊ+6WbŊ!Wqa+VXbŊ+VXa+VX"~+VXbŊ+VXbC+VXbE*VXbŊ+VXbE'p "Lp!Æ 'p "4>$XA .d!,h „ 2l!Ĉ'*> 4xaB 6dO,h „'p "Lp!Æ O@8`A&TaC!F8'N7qĉĉ'N8qĉM8qDM0'N0?&N8qĉ'Noĉ'"?'oĉ'"a'N8qĉ oĉ'"?'oĉ'"a'N8qĉ oĉ'"?Cĉ'NDĉ'N8qĉ䧯`|˗oĉӇП !`|˗oĉ!7qĉ'h&~ O@Ǐ_>$XA .dؐ>5lh|?~6lذaÆkذaÆ 6lذaÆ 3O_|/?~/_>~O| /|aÆ װaÁG0?~'_|˗@~/_~/?~kذaC5lذaÆ 6lذaÆ 䧯`>_> _>_|?}o_Æ aÆ!`>O`> |/~_>~_} H*… .\p… .\p…+_O`>o'0| ̷p… [paB#_O`>o'0| ̷p… … .\p… .\p/?}˗/_>'߾|/| ̗/_ .\O… `O`| />'0>~_|-\p!p… .\p… -B ?} >}O~ 'P|O>~O~ H&OB `O>'0@} _>ۗ>)TP‚!PB *TPB *TPB~ /_˗o@~/_>~߿~'_|*TPaA~SP_~ />'_|/_|)TPB!PB *TPB *TPB~*Tx)TPBCϟB OB/B )B  <0… :|1D 7Q"|8q"A~7q|&J/>'N$~'N8qĉ3Oĉ'NDOB&60'N0'N8qĉ3Oĉ'NDOB&60'N0'N8qĉ3OA H*\P! 䧏 $H A$A H*\P!?,h „ 2l!Ĉ' g>'p "Lp!Ã'p@~8`A0?'p "Lp!Ã'p|8`A&TaC!F81!?}H"ł!䧏"Eg0?)R,|(RH"E)NϠ|)RX_>Q(| G"ECB)RH"Eg_>)R,/B~(RD߿| G"EC~)RH"Eg_>)R,/B~(RD/_| G"EC~)RH"Eg_>)R,/B~GQ"|O|8`A&TA}_Æ 6lذaÆ 6lϟA~ װaÆ !?}kؐ!|߿|8`A&TA}_Æ 6lذaÆ 6lA~ װaÆ 0 <0…,h „ 2<|kذaÆ 6lذaÆ 3OA6lذaÃ8`A&TP'p "Lp!Ã!aÆ 6lذaÆ 6T ?};}W0_|k_ÆO@'p "L8`>_> H*\>~kذaÆ 6lذaÆ 3OA ˷o`>~G0@~6װ@װaÁ 'p`? 4xaB a> 6lذaÆ 6lذB3/A} Ǐ`}/>~O`>}/?ӗO߾~5T/B~6l8_|g0 6l>~kذaÆ 6lذaÆ Ϡ|_>O߿|'Pۧo|'0߿~P|kذ~ϟ|6lذaÃ!aÆ 6lذaÆ 6lH>}G0_| ߿|O|/ǯ,hP|w'0?;xo>~O~'p>|/|7|ĉ 3ĉ'&a>M8qĉ'NOA7˗/? /_>~߾| 7P>M,/B~珠?'`>'NP?!7qĉ'N8a?ObI7Ѡ|˗/?M80?M8qbB}ĉ'N8qD'p ?} <`0A O~П7߿ ߿_/_?/?$XA .dxP?5lذaÆ 6lذaÆ Ϡ| 6lذAO@׏?G߿? 4xaB a> 6lذaÆ 6lذ~3/_Æ 6lx_8#??G߿O@ DPBC_Æ 6lذaÆ 6lA~ װaÆ >̧OӧOӧOӧOӧOӧOӗOӗ,h „ 2<|6lذaÆ 6lذaC g_ 6l|O@ HCϟ|&L0a„ a> H*\ȰÇ#J>QHbA˗/_>%Cϟ|(RH>~C"E)RHB~ G"ECO_|Qx0?QHbA}E)RH"E"E ˇ>Qx0?QHbA}E)RH"E0 <0… 'p@~? 4xa| 0a„ &L>~C? 4xaB 6tbD3/@,h „ 2 &L0a„ 0?8`A&TaC!FȰA~ 7qĉ COB&Nϟ|&N81>~Coĉ'N8q"~3/ĉ'&!?}ذ| 7qĉ Cĉ'N8qĉϠ|'N_>!ob~3ĉ'&a>'N8qĉ' g>M8qbBӗĆg0'NL|&N8qĉ'N ?}8qĄ!oDg0? ?`>$XA a> .\p… .\p… Ϡ| .\pB!o… !`>w0| .\>~[p… .\p… .\?}[p… "!?} .La>#`'0߿}O_|.\P>~Co… .\p… .\p@~ ˷p… .D/B~.\`>#`>~/߾}?.\P>~Co… .\p…ZhZh O@8`A&TAװaC`|/@~70?}5lذ!A}_Æ 6lذaÆ 6l>5lذaÆCOB6l(0?g`>߿|o,h „ C~ *TPB *TPB g>)TPB !?}SP`>߿|߾~)TPB!a? *TPB *TPB 3OA*TPB ˇ>)Ta}3|ۗ/>˗/߿~PB 0?*TPB *TPB * ?}SPB *,/B~PB ˗/?)TPB )PAO@ DPB >QD g_>)R,/B~Ga ?O@ DPBC_Æ 6laÆ 6lA~ װaÆ ?П < ߿O@ DPBC_Æ 6lذaÆ 6lПA~ װaÆ 0 <0…? 4xaB a> 6lذaÆ 6lذaCaÆ 6<`> 4xaB ,h „ 2<|6lذaÆ 6lذaÆ3/_ 6lx_>/@~,h „80߾ <0… 0?6lذaÆ 6lذaCaÆ 6'P`> H*\>~CدaÆ 6lذaÆ 6DOA6lذaÃ!䧯aÆ ˗|6lذaÃ!a 6lذaÆ 6l!?}kذaÆ ˇ>aC`> 6lذA}_Æ 6lذaÆ 6lA~ װaÆ !?}GП ϟ|6lذaÃ!a 6lذaÆ 6l_?aÆ 6 6lذaÆ 6lذ~3/_Æ 6lx_>8߿ 'p`>,h ~3B"D!BC,h „ 2l!Ĉ' g>/>kCO8`A 0?%L0a„ &$|8`A&TaC!F8Q? ?}X_|G| ߿߿߿߿߿߿߿? 4xaB a> 6lذaÆ 6lذaC~/_?'_|ӗ|O | װ!B OG߿#?  <0… 0?6lذaÆ 6lذaC`>'0'P'0}|5l_>80߿?G߿#?'p "Lp!Ã!a 6lذaÆ 6l!?}+~_>O`| /| "!?}ӧO@7П>} O>}ӧO@7П| / 6l>~CدaÆ 6laÆ 6DOA #>~ '0߿|'0| ǯ_>6D/B~W_Æ g0 6l>~CدaÆ 6lذaÆ 6DOA '|_۷߿}/߿/߿|_>$XA!?"D_>C!B"D>~C? 4xaB 6tbD Ϡ|˷|/|O`>/_~˷O߾&>!?}8q`>8qĄ!a'N8qĉ Ϡ|'N_>!ob~3ĉ'&a>'N8qĉ' g>M8qbBӇП !`>'NP?M8qĉ'N(A~ 7qĉ CO_BCϟ|&N81>~8qĉ'N8Q 'p ?}7P`|8p| H*D/B~.\| p… .D|.\p… .\p… .OA /| .\|[pa~3… .\>~[p… .\p… .\?}+o`>'p_>}'0… ./B~.\| p… .D|[p… .\p… .\8>'߾ o߾_} .\P|[pƒo… -B ~ H*\ȰÇ#JOA 'P`|'߿_?$XA  !?} .\x0?-\p… 0?.\p… .\p… Ϡ| /|_ .\8_>!o…3… .\>~Co… .\p… .\?`'p}'} .\p|C… g0 .\p!B}… .\p… .\p~3/_|'p_|˗/|.\p@Ӈ@ H g`> 4xaB *#H,h „ 2l!Ĉ3OA&7qD!?Cϟ|8`A&TA}8P`> H*\ȰÇ#J(A~ Gq |(R/B~Ga?"E 0?)RH"E Ϡ|)RX_>Q(_A3E)a>)R$/_>}|)RHПA~ G"ECOȨ_>H"ł!"E/?h0E).Ϡ|)RX_>Q(_|g0?b>Q4|(R(p? '0?˧/߾߿|/|ۗO_>$XA .dؐ>5lذaÆCO_Æ 'P ? o|7p  <;/߿}߿| __8`A&TaC~ װaÆ 0 <0…߿߿_~߿}߿|/_>~߿|/߿>$O+8_ ,X`#O| /|O`>o` ,X` W` 䧯?8`A&TA H*\(߿|(?}'0|70߿|/|7o~~8P`?$XA O|/|Ǐ߾}_| o߾)TP‚Pa~3/B *TPaA8P| G A $HP |߿|߿߿|_߿| ߿|O~>8@} ~ ,X` /_>}˧/@}O| ܗO_>/_| ,X` ԗ/_| ,Xp`+_>$XA .dx_>!aC 'P> o|/߿~_>}/|O ? '0߿|O`?}8P <0… :|1B} ,hA~  <0… ˇ>5lh_|g0?˷߿}/_>~O`'0| ܗ/>O|/|0 6lذaÆ'p "LHP?$X`?? 4xaB !?}k``> +aÆ5a> 6l0_|k050 <0A H~3/,h „ 2 6l0@~6LO`8`AO@8` g_>$XA .dx_>5lp`?aÆ 6<|6lpa>| ̧/>'p_>}˗?}_|ӗ_Æ O@~ H3/B"D!BCO߿~!DA3|C?C!BCB"D|?~/__O '0}߿|"D|CA~ ˇ!B"DaA˗/_>"D`>#a> 'B"|C!B ˗/>#__O`>/|"D>'p Ϡ|"D!B?  <0| G0|/'0>~/_?O_>}/?PB}󇰟B *$`>o`~/|/|#_>*T ? Ϡ| *TPB+O|߿߿߿߿߿߿߿߿_?}/?߾߿|߿|O@ |C!B 3O}?~ ߾}O| ̷o}!B"D!B~ ˇ!B"DaAO@׏?G߿߿|߿_߿/߿/߿|O@ |C!B 3o| ̗/ۧo߿}/_}ӧ_'0|"D!B3OA"D!B",/~ HP?G߿#?_߿|__맏_|O߿| HC~"D!B!4!B"D!BϠ|"D!B ?̷ǏǏǏǏǏo߿/߿o߾߿|/߿|_>~? 4xP>~C!B"D0!B"D!B g_>"D!B w|?8`A Cϟ|O`>˗| '0?~ӷ>}ۗ/?CA} <0… :|1ĉϠ|)RX_>˗_ACϟ|(RH>~H"E)RȰA~ G"ECO߿}Qa>H"ł!"E)RHD~ G"ECOE!`>)RXP?QH"E)ROA8`A&TA~8P ?} H Cϟ|8`A&TA}8P`> O@ DPB >QD~ O@ DPB 8P ?} H |,h „ 2T?G`?$XA .dC%Noĉ'"oĆM8qD!7qĉ'N8q"?}'N8!?}8q`>'N8a>M8qĉ'Nd ?}'N8!?}8q`>'N8a>M8qĉ'Nd ?}'N8!?}8q`>'N8a>M1|8qD 7qĉӇП !oĉ'"oĉ!7`'N ?}'N8!?}ذ|&N8q"|&Nh0O`>} /?O_~ӗ? 4xaB 6 ?}:tСÂ9t|:tСCsСÃ/|o@}O`>~۷| ϡC 3OC:t ?}:0?:ta|:t`>o`|'0|70CСC sСCϡCСC:,ϟC'0| ̗`O`sȰ_|sСÅ'p "Lp!Æ O@ D`} H*\Ȱ!|8P`?$XA O`>o>_>o?*$`>߿߿߿߿߿O@ P <0… : <0A$XA .dС>? 4xa„O| ܗ/?'0|˗OB'p A~7߿ ?}O@~',h „ 2l!Ĉ'Rh~1bQ|߿o ߿O@ DPB >HП#F1bĈE1bĈ 'p@}>}>}>}>}>}8`8`A&TaC"D!Ba?!B"~ ? 4xaB-\p… .\П [p… .\p… ./_|-\P-D/_|.\pa~ .\p… .oB.\p… .\p… O… oB~-\p‚.\p… .\… -\p… .\p…  G0߿|/?'_|˧/@~/˗|[… .,o… .\p… .o… .\p… .\P ?}o߾o߾|/}/8`A&T? 2dȐ!C 2\؏!C 2dȐ!C 2T/_|`__>G0߿|1dȐ!C 2dȐ!C 2d? 2dȐ!C cȐ!C `맏_| >~ '0_>? 4xaB 6tbD)VxcFmܘ`> _>'__> '0߾}O`7nܸqƍ7n(ƍ /_>~|o_|˗o}߾| '0ƍ7nܸ񠿍7nXƍ9̷qƇ @   @   @   @ ,hA O@ O@ O@ O@ O@ O@ O@ O@ O@ O@ O@  <0…-ԗ/_? 2dȐ!C O@ O@ O@8?8?8П?O@O@ϟ(?(? 4x @'p @'p? П@ П@ ϟ?'P 'P     R<0… :|1ĉ+Z1ƍ;z2ȑ$K<2ʕ,[| 3̙4kڼ3Ν<{ 4СD=4ҥLG;;PKM@0TsCnCPK-AOEBPS/img/adque430.gif{6GIF89a666lll@@@???櫫yyy999___///rrrggg``` 000pppPPPvvv|||鵵<<XqX^cPᩓpD\&T %Yef9U]N%cI fa*CXZ#&[ZUyw\axeZVEݖnæcaUWcc7ZbSak-7Ljkt밈eu[%+.i)b,nn>eD4X挀T)돴 QXS?)o`wP 9y Q9/'n|\BeXwS@ma؄'dn>dx=> 'K1"I"-砇.褗`GBOf8̫7e;<{戻&<9)S\IH[&g\:T|IL}C dQ,b2=ĒQffjYn~e]j0$`ErH%z܏qB.K|W:=0Fasn^Y’ dQU7 k0  jfŚӕ#\و5BІ: DlbΊZ%'K/a /*ϒ&EĠ5KfAWw#8ͩNwSZk16JԢը: 5ē(TjO*!ufd⦪DJֲhk?¤LPDOJ׺ڕQXD*E~5x`KUX*WB#8d'KZEZ, HhGKҦ5 ;*ZlO1bH(bs~@ pK wK~@tKZntV#jL ٚ-b۝ƍ|{΄?=$ ?֐:#p| GLbGTX0f:qp9a@2OaGWuh a45J0* e~9[(2?X rL\_Ye#7lV0:O͝qu5yΈ2-R1@ z.4L~Ny MjhAWfLWӝ=g_PWk(efb`)i ʚ֞D];{(0`D&n?|ld'Zճ=P Imξ6) $n7pn[snſGp?8~"!3q!s!W5}j& Є^W Mp-X݆w\H37 Q<:>Q|B3Ly#G0.7!AzŒz$ ȇ)u,G c[~B=v/ea.!.*#W2#PYG y=`8BE!σ~#) BOgd+`!/9YE_#UD /iWKB'\k {-}VP7|w~[ws5\` Xg {},Fc H~g|x eVѷi%@f#X} uR%mGrtP[Y`޵vZ:j(Zg$-pPlPO/ue .V { :8t'rz\]egHH-0`zO}x &xXLj xȘʸ،hS@.HeBcqA "zM8M0xt>_d5P3 Oox`S0 t1`؋W 9Yy9HS1TQ&!h ;BP `p  & Lxk'{{0> @E9@k֗(Ȋ9+P 0 ^hO^B I Tp6`h I~G)Yvyɑ>15vRQ":0~*9 eQTpSޤ;w 0p `@ 9y=kl___9o(5@;8 S}NJ x{ R^ QP,jy 閈t AtٞQH -SxiQqHZTAPZ uKT>u0Z:̇xm@]wК@]@P]Yo9IYI*`O0 Q 4D OO.Mp @ x`#0P๖鋉X9b&@5ir?iZ2A`QHz#b1cꁧHf@jn){t:) :**,*q82:P7   Z`PPT|p @($@" RJimǥ9 L` F L ΰh ɐ j ՠ@ w` ` g00] @ 0Xp 0 fڑC4d=j!>I&  .)5;cK4_ё8ђ/3Y7yx8bMO) 3z6=?p'<30+P@40Cp7 2ZSZly@ӚOP'`\_RlZh V@M[P/ nPom0gppf0@qdP/gX3ԨF?)4p311sAcPc!'7q(ߊY )e0wp pPx]ݼ9֝M]b#ޤ}<lj/^=wm:}|bHiSJFrQ.0 *+@!p ) ^{_}pi@@\k^yN߻Ό\!ݞ]=mq\޿ދ 2 ]mWq:[ߒ-1A!Un^uwnY)ʎ_ ͞܌wX׭|. }$-ޥ҈N~ x,s}M㺝1U0HEAMO>Q.`t00Awp!?v 1%Oo^m+o-۞ݜ$݂.)>+<]-} ,dA3bJV%X'Pn?b{Ǝ PQeed?e+Q**H  $ H |(B|x "( h#BB Hh$}(8% Rc6#*vȧO Po/z"XdB$jĂ^gFVji 0E(g=;@ 8@Ol0\z'DB@ğ&uXPT2`6L"xb+`Jkj$KګP&#t 2 2j !eJ;-Z?.dnm~ D{.骻..;/{//H tnc{f@%HZ}b\F~]-@#ݙ-GUGՖ^| `i(;2ak7r}w{]~x47f..aiY(N>Ľ .yPRe:><`TGƌ>"/4NAZԫM:ծ lVmz6, [,aÈA-A@Dw9nŨp+V rVH !t;}u6NA9 D(FщBԁ@xE,fB@baL`r#Ra2;L P f4j܁%!Q"MIH-F*k mZ֫'B GRde+]JXR B4AQgEq@X/e.!/}-$-I3^5yMl?I\  S$g9I!B_]D ^E`bY8&+BEg8%E*7VX|)ڃxq*8L#ɭk 6Jmjv#fK]Rƴ].=B'( &n+sQ gP9!LKͦM%ISjU*&e Mga$8 , VL ʏ.jdEɬIRG I*Г&u( BFVu rS)4)tT֐'J;RYM*T]%z%$ A/Hz:B2₴"x4p[o'E،-`&CNZA.qB| Ţl2K[ ['xuV3@έdQи-g \b#MEZ -Ke. DHESe% &A@NDhY QB:uI5񽜎xi}/G D@f;2A:p#!OUp]+d98M!( ĺDx֐1 %1DqJ1 aA1_pk^/nr IXaxI~s2!OC[D>t%FMmXyՋo/_p\)pmxʼn5WD6X$JxYCW*Ћbn?k _=Cx)x%=%|#NS[W$宏SՎ)1i  DX:9TP` P~PbE#PloFBM FtУc'ˠF"~e]@ˑS G=I?VbKWe{!# "{EP,!XCxd޿W COtr v1L_ӞԓNE=>1TC,Vkb? s,{kK?ۼ 4;Aʳ,R.˿*3*ڃ") .< 2Vc,*A%< \dQ A%:#cA#4l9/-(_A @D;SB3>@$='CB7C*B;'A:ꓲ'2mH ct&G8c/32b8 JP<)eS.,8⋻<$CZZ?\Z DAT0B\3y`K`sf c2e3M>A@2 +?Ro9'2m(E:#HE [!㛻Ey)dчfa\]t^L_l0vژWM X깓/XA5/D!rȂ@EeZFPK`*;{Q|CV8;4BGylH#<,>Â0?tã& Sx#80{J 3ƃb9!F8ȢjDP#Hуo0˃L!N#xIɴsU|{,ŠK>E (,@3@xJ8XM GZŪ|4\.DhF@9AQP x.`8HBTP3<Ȁ#,XFGD4(L1f\Ls;$Bk(ɜL>l D9,Ȃ2, f˂ʃ@<nـ256،&PP׬ͣHlLi4“؇ ІF0`΋BD 84K ` D,d9E*O&̃< <u <Ȃ{3ni2ł M!m(hB-TC Q 9ѷhQѓ' E ҃xؘ LsR1$<)0 l" F@?XN`r@h!@Jwp8H :82Pk(^ ;RZlB,h6E 5e# ȂLӟ %:5BP>ل*E6T9QKEeKCT $Rؐ$EUtR`UoX YYEpU 3u2,x\ ؀MiQʚ<}G}@ð0Q}T8X<)KmQN݌ΘXQXSOT peC=[M[o5ٓ ,((y M @mу$Y۽%7-=U\MI~GMZFԆ$5 bEHjOXR48U[ݵEڶ 4}Pu(=h+;uW1=89,S h\-_=_M|e\ZՃ@: ج!%S]E2D] `% h @?)3l lG ?n<@9ƶɭ-͕_}JĨ@ nݭEU`]Rx $`)J/ @ vB?>Za`XaT]ĨT0(؆9>(UN `dy, P}@Rk%LX@0n `0MIp12]4_5^ٺ\5\܄b=AM`YA6PNRE+F.e!/X!`_`X& /HZ[n,_M]M6.͝abS:X*xfN-`PKkZUP (IdKVV@U@\ \XgXh5 -MW𼀾Ϩ \~jje߅8_b> (>jX摮*f%1(~ b:ϦFΒ"kla]Nh7fb>]fSHh技\`kץCڸ&O@ nme۽92lFVA_Vv =Fl@1+)6k6m5~ P~nnno %ZmYC]o.K`.1~Dmj8fT9BB.䒶68>p p p p p _Coa%j>l>ZFGn:ՕXj&V$ q r!p^Z q(oT`~ߦonGr4O4/#_$J&g=rml,;ɀeXZbqM}/s@8s5tH6os'%8o9ncm=_j:X~Bw>i,fpHu[tJmKsq2؃̸]JNpHwuowwZsrzv7aoI%ZXGxPxT8kx> J0uیX:y`_^sƶy Oy}OxCR=x JCPtzs ?|Ŀ;8 zLz/TRZe߅c6pW:B R(?tY;}ߗ'G~/~?~O~?~ @: }0rȟLɯBM?q}/$mΝdP@h7 :ψ\PnhU"AB FW .ذ# .\dA G\A*U珂2gҬi&Μ'PH-j(ҤJ2m)ԨR(*֬Zr԰R j,ڴ^ K4?4tC0`Ԩ#ǎ8ppE @X #K)1%*fǟ W\R2fB!JhFAVhu?~ʗ3o91C&D ;7|Wœ)ӯo>u\uݕ^}`b-0O$p 3B't@ICDp 2< %PCE4QEeQG?@ H!D$M:ve4K dy%㙇XfX핹&[C]xŗ_ Fa)nCÅ'a9bC"xHL3+pT!!ҹ*.XqGA]9,Ŏ٦Zg:K- Ghgy":z£$0)4l6֖#n<#utB N%#>y0 sJMc0-;1YVL\Y{V1Au{*gK(㼚vm:֣(ʇ`dP4QK=5U[}5P#T>=6qV%Z72^ xz&' 3(CnΕ^3l4|Cgp!uaj:饛~A,0YÝưW@ڹ;|Spp"]8 0A8cR0m ,P(e8@R |%,c l\ 1YQ!0,%@hBd8Pvǝ1z7$8 A8 :DY]2%2X A.%NWdc[P[mky8%BKd@Qt:bF$NQ\x8l=k` E|}: cq"#Aʼn'0#,R )|Zb RCl }Sھ>ke L )?Π Q r<)yGJo p?TC &6SGB0!Qעb`9xγ-qr tR6@cY\'A`QMD5<@$VA \)Uxf  [`')UT13?dԢؓ(6 k  ;BX0[BD(ZàLá=qR؊0[5l !]ވd@ ?Xx8JC<ڂ LEPF HE"d"HNA$ cǀ , Yl0TOB->HhB@ @:3(V #-IVUE3Mk@02ā 92u0' Y4v An 5`{Y@-ӂL(:`ԞKk9Eڙl~g t$R2y;,5}IP_ t ^bn#qXF0aF~@VLzqh'Q"ۥ6xV0}n;۵˂ -@7J!3WYw.{p=p F\""‚`! AHQq]fQn 6.6Zdh@v-%#/ɫPPX<eB6N/Sֿ>O;PK7F{6{6PK-AOEBPS/img/strms021.gifGIF87a?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU, H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@O@ ׯ_~ O@ @ @(`?(~'P ~O@ O@ @ ?(?'P 'P? O@ @ @(`?(~'P ~O@ O@ @ ?(?'P 'P? O@ @ @(`?(~'P ~O@ O@ @ ?(?'P 7p@ _~ @ `?(`?'P ~'P? O@ @ @(?('P O@ O@ @ `?(`?'P ~'P? O@ @ @(?('P O@ O@ @ `?(`?'P ~'P? O@ @ @(?('P O,X?8П?O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@Oׯ,h „ 2l!Ĉ'Rh"ƌ7r<د_;vرcǎ;v`~ ׯcǎ;vرcǎ;FׯDuرcǎ;vرcǎױcǎ;vرcǎ;ׯ_ǎ;vرcǎ;vx_~˷ϟ|;vرcǎ;va|/b;vرcǎ;vP_/}/_>~ /;vرcǎ;vLϟ|˗/߿~'0?_};vرcǎ;v~8`A/'0@ '0,h „ 2l!Ĉ'Rh"ƌ Oc>`} G0|۸qƍ7nܸqƍџ 엯߿|O`>'p@}6nܸqƍ7nܸq#AAׯB~'0A}_|/_}7nܸqƍ7nܸ~ oƍ7nܸqƍ7n܈_~7nܸqƍ7nܸqF۸qƍ7nܸqƍ7&`|Ka7nܸqƍ7nܸa!̇`>$XA .dC%NXE5nto?}_|˗|'p_|˗@~ȑ#G9rȑ#ǂӘ`O`O`>~/?/Ǒ#G9rȑ#G1|O`>'0|O`}#G9rȑ#G Oc ̷_>/| ̷_>'0_|8rȑ#G9rȱ~ ` |/??}/߿߾O@ DPB >QD-^Ę~ `|/|O_>~/_>?~/_}5jԨQF5jԨq? OF5jԨQF5jx_~5jԨQF5jԨQƋӨQF5jԨQF5bc*ӨQF5jԨQF5/_|5jԨQF5jԨQB/_>/߿|W0_|/QF5jԨQF O>~_>߿}o> ߾|O`>$XA .dC%NXE)OcO``O`>5jԨQF5jx_~ '0_|_ _| ̧QF5jԨQF~>O_?} 70߿}OF5jԨQF5ׯD/>˷O`|_|_˗o@}iԨQF5jԨQFӨQF5jԨQF5^ׯ,h „ 2l!Ĉ'Rh"ƌ7r<_;vرcǎ;vرcǎ;vرcǎ;vرcǎ;vرcǎױcǎ;vرcǎ;ׯ_ǎ;vرcǎ;vx_~;vرcǎ;vرAEcǎ;vرcǎ;FׯDuرcǎ;vرcLj_;vرcǎ;v~ 'p "Lp!Æ 'p 8`A&TaÄ8`A&TaC!F8~ П <0… ܧ? ӷ? 4xaB 64/,h „ 2l!Ĉ'`>)RQHbD(RH"E)RE)Fo>~)R_>)RH"EG"Ń(&o>~)R_>)RH"ňQ$E棘QHbD(RH"E!׏"| ˗?~+/_>~O|!̷?~?}g0@~o- | /'0|˧/|o' |'p ? 4xaB 6tbD7`>O> O`>~߾}C?~Ǐ߿|;}-ǯ }O`>~߿|o?o߾O>~oC&N8qĉ'ׯ+_| o`'0߿|!'0|ۗ_[_|O|O`;o`#/@7qĉ'N8 ? ׯ_| #08_߿| (0|Ǐ~/$H?~'p`/߿_>o`#/A $H 'p "Lp!ÆB(Ѡ?W0 ܗ@~@~߾}CO}O?~O>(ܷO>~  _>__> O>&:oĉ'N8qĂ+ϟ}/_>} ܗ/>/_| ܗ/?a_[}/_>} ܗ/>/_|O`ϟ|O@ ,/,h „ 2l!Ĉ'ׯ_|(>G"-Ǐ"|Q_>)RH"E+Ň'p ,(`>8`AӇp>~"DH0? <0A*TPB *TPB *Tp`>˗O /_|˗O?˗/> ̧0!?} g0_|o|a|Pa| ˧PB *TPB *TPB3o ?}/_ O`|Co ?} ̧0!?} g0@~3_~~ˇ0@~*,OaB*TPB *TPB ϟB3` _߿/ G0߿|˗@~/_>~ӗO`>Ǐ_|G@} G0߿|/~#o߿| #_}˗@~/_>~ӗO`>Ǐ_| <0… :|1DH0?/_}O`>Co ?}O>~}۷| '0?~77 O?/|?~o?߾}O`>'0M8qĉ'N43/_|+o`?~g0߿|˗O|̗oӗo`>_ o>~˗O| O_~ / ̗/_>} G0_ /| '0߿|/,h „ 2l!Ĉ ~ g0|o|_> `|80߿߿|GPO@+/_'@#O߿|+/|#0߿|/?/,h „ 2l!Ĉ ~ g0| O|O~!g0߿}o|߾}_|O ?[|70_??}ˇ0|}'}'0߿~@~7qĉ'N8qbA`>˧o@~}_|#`>ϟ| ܗ/>'p_>}/_>}[|˗}/_}ۗ/_|˗/˗?o_|˗/}O| /,h „ 2l!Ĉ'ׯ_|(>G"-Ǐ~)R/E)RH"Ň+E)Fo>~)R_>)RH"EG"E[E)F"E)RH"ŁQHbD~G"EH"E)RE'p "Lp!ÆO@O@ DPB  <0… :|1DH> 4xP_|"D!B'p 8`Aw|Ç>|ÇÇ>$/_>|Ç>|C{AC0@8`A&TaCC0@8`A&TaC!F8bh|!gѢE ˇ0E-ZhѢEgAC`>} ܗO_>/_>~ '_|,Z/_>ӗ߿}O`>'0|ϢE-Zhb~BC`>~۷| >'0?~g|!w0/|O`>~ >YhѢE-RCY\/_>~(߿|߿_O߿|߿'p "L`|'P'߿_O߿|߿'p "Lp!ÆB(qA=ׯņ0|70|Oo@$XA ̗/| ̗o`>0 H*\ȰÇ#JH~*2/? ߾}_|߿|@~*V/_>o߾ _ _O ?+VXbŊ+ׯ_E`>_ o_>}'P߿>8`A&TX0_|(߿Oӗ߿}/|? 4xaB 6tbD)"C80_Ŋ+˗|+VXbŊ+VXQ|UbŊWq`+VXbŊ+V(_|*VX"|UXbŊ+VXa~*VL/_>~(,8ПA 4hРA ̗/A ? $? 4xaB 6tbD) _Ŋ aUXa|80_Ŋ+VXbŊWbBC~ /O_>}ׯbŊˇ0}/_>~|˗_Ŋ+VXbň{_ a}_>_+̗/|o}߿||+VXbŊ#~*2/? _?~߿| <0…ˇ`>~O߿|/?}'p "Lp!ÆB(q"E_|3_> ߿||8`A&T`|;_ /߿_?~'p "Lp!ÆB(q"E_|3o> /|O`+̗/|O?'0|bŊ+VXbE_|'P >/߿? 4xaB ˗!|_~߿|O~'p "Lp!ÆB(q"Ŋ˗ŋ/F̗/ŋ/^xŋ/VO@8`A&TaC8p>$XA .dC%NXq?-0'p "Lp!Æ 8p ,h „ 2l!Ĉ'RȰ_?-O@8`A&TaC80>$XA .dC%NXa~,Z,`>'p "Lp!Æ80,h „ 2l!Ĉ'Rذ_?`>'p "Lp!Æ'P>$XA .dC%NXa~Ϣ~˷ϢE''P ,h „ 2l!Ĉ'R_~gq|Yh"~gѢE-ZhѢŊ_|,Zhb|,ZhѢE-Zh_~gѢEgѢE-ZhѢEؐE-ZϢE-ZhѢE-ZhѢE-ZhѢE-Zxp@},h „ 2l!ĈO@ DPB >Qĉ8P>$XA .dC%? 4xaB 6tbD'׏@}(RH"E#G"E)RHbBQE)RHb|(RH"E)RL_+E)RHb|(RH"E)RL_+E)RHb|(RH"E)RLϟ+C SO?)RH`>)RH"E)R<_1G`>H"E G"E)RH"Ń+A~/_>/|'p_|P߿|O_|_~O@/_> /?} _|O |'p "LPa> .\p… .\p… .\П_> ̗/߿|/߿~'0 _>~ '0߾}a>~o`'0|o… *o… .\p… .\p… `}ϟ| '?~O`>O` _>O`O`o… *o… .\p… .\p… Ϡ}/߿/߿_}߿_߿|@/_| 70|˗/_>/_| H*T… .\p… .\p… p?} O`O`>'P_ '0| 70@~O߿};?~_/ 'P_ .\0 .\p… .\p… o/?o`>/|˗_>O`>/_|!/_|/߿~/˗o… .T… .\p… -B -B _?$XР@}-ZhѢE?},h?,*0łgѢE-Zhq~,b>CϢ|Y,a>-ZhѢE?3/_> ϟ||˗_|˗O`>} ˗O>/|ӗA}ϟG0_|/_~O߿||/߾| /_ _||8P`> H*\ȰÇ#J8_~WP_>_߾__>~o?~o?/߿|?~`> __>~o?_>>'0|(RH"E)RL_+_|'0?} /| '0߿|w0}/} /|_>o?>_/߿_߾߿|/,,h „ 2l!Ĉ'R_W0|˷_O`>'P| `>O߿_8P`>O`>O~O`|ǯ_#0@o߿| H`> H*\ȰÇ#JH1~ WP_ /߿}/|O'p@~O>a>ϟ?}_> ䷏|/@_> >~O`>{_Ŋ+VXbŊ+_Ao_>}˗/_ӗ/?}?}O?}O`O`>珠|/|'0?/_>~ӗO_/_>~ϟ|߿|  <0… :|1ĉ+ϢE w0C}-NϢE-ZhѢŇY,o"|'p 'p߿| /A <0B-\p… .\p… .\? `O`|/_>~˗OO>`|`>O ߿o`~ H| gРA? 4xaB 6tbD'׏@} #/_?7_>}w0@~'P_󧏟| _߿|/@~/_?h0|(RH"E)RL_?3~`|w0| }߾~o?}'0~˗?~?/>'P_>~˗O>/_>O_>~H"E)RH1! ׯ>~#|ӷ/_A㗯`>~ȏ߿|`'0|߾~߾o }ǯ}|? 4xaB 6tbD'~ g0|˗O@~;/_|+Oa|/_|3`˧o`>O?~O`| /߿| 7p@}7p߿| G0?)RH"E_~3~o``7_>_>~o| 70@>~ O|㧏_| 7`>o߿/߿/?$XA .dC%N_~3 |/|/|뗯@}O} __|/||'_>o߾/߿}7P_?~'0|XbŊ+VX1~ g0_|/_>~ ǯ|7pǏ`!7p O o@/_}o`/_}ӗO_O|˗߿| o`> H*\ȰÇ#JHQ?h0_Ŋ+˷P_Ŋ Xb+VX"A}*7`>8`A8? 4xaBOB ? 4xaB 6tbD)V$E-Zh|,ZhѢE-.ׯIg?,*0ł,.ϢE-ZhBY|!CϢ|Y,|,ZhѢE-.ׯ/|˷/@~ ̧ϟA~ OO_~3/}/_|˗ϟ@~?}/@~/߾|O?˗o`>}ӗEEO@ H_> ?ׯ` ,Hp@},h „ 2l_ ׯ>~o|/?~/o?~o?/߿|׏?~o||O`>~o?_>>'0_ ,80 W`+(߿| ׯ` ,80>$XA .da>~ H~ ,_70| /}o>o>|_>o?~ϟ|_#oo>` _#o?~˗ϟ| ܗ/70~˗O| '0@~ '0@~? 4xaB 6DCWP_'P| `>O߿_8P`>O`>O~o`|ǯ_#0@o߿| HC_ϟ}߾/|}O`>߾o?!B"D!BCaAǯ}߾}}O>} /|'0?O߿|oO_>۷|}'p| ̇!BC_|/?__>o| '0?_߿},h „ 2lP?ׯ>~O`>ϟ|wП| 'П| '0?}'0?GP_|˗_>|˗_>ӗ?}O?}O`>9tH0?| /߿|G0@'p߿| ߿| ߿|8`A&TaC9tP?:to`sСC s80_| ϟ>?`O}'0߿~'p߿|}sСCϡÄ9t`>8`A8߿_> O@ DPBkH`>o?}_ /?}70|/|߾|O ? 4xaB 6DC&ϡC:tСCa>s0?:t?}!B}:tСC:t0a>sPa> sСCǏa~"ϡC:tСC`>9_?pa>:tС1ϟϡC:tСC`>s?s0?:t?}ϡ~ СC:tСC sX0_|ϟ0@_?_/|8 |8`A&TaC1ϟCϡC:tСC`>?~o`>>_}O`>o|sϟC:t>~ׯ_A}:tСC:t0a> O>~ /|˗o?O`| '0|:tСCs~ gПC:tСC a| /_|'0| '0߿|ǯ_>/߿߿| H`> ,X`AW? ` $_ ,_A}  <0… :|1b|$ϟ>#o|_> />~'_>۷_?} 0?`?Q?'QD%J(a>˗|7pO_|ϟ|˗_>| '0|˗@~+/_>~O߿|O`/?}ܗO_>'Q>~%OD%J(Q|$"0|%6 }o߿߾ϟ>o߿||?_ A $A#H AO@ DPB >Q|&_|M0?7_} /|O`o` cد8qĉ'Nh0'N<诟| #0GP?߿O oo`>$XA} <0 :|1DM8qACϟ}㧏@~@~߿|/| /|/߿}71>~ _~8qĉ'Nh0'N˗O?~/_|ϟ|'P'P_|&&Ǐa~ׯ>~'N8qĉ 7qĉ'P> ? 4x`>"$!BCHП?WP?$XA .dC%̗> 4xaB O|,h`|O@$ A $A $H~Ǐ@ H*\ȰÇ#FO@ DPB ˗/_>}#(p?7p_| G`|G A #H A$H A׏?}  <0… :|1bD$XA .dp`O/Aϟ> ϟ| OA $ A G A 'p "Lp!ÆB(`>'Nx|߿|8_>#_~#H0|/_>~O |ۗO_>oGP? $H AO@ DPB >Q|&N8|g0/_}O`>Co ?}O>~}_>?~7P8qĉ'Nh0'N'NxП>g0~/>~a>#/_A_߿| ?}8~,X@}8`A&TaC!Fh0'N|70_??} ̇0|}O ?}'0߿~@~ǰ_?7qĉ'N8`>'N81 ˗/}˗o˗/?˧`>˗?'p_|˗/}o|Ǐa~ׯ>~'N8qĉ 7qĉĉ ǰ_?WP'N8qĉ8qĉO@ DPB ?ϡC:tСCСC.ϡC:tO?ׯ>~9tСC:tС|:tСÅ9tСC?`>:tСC:ϟC:t0?:t?}:LC:tСC&ϡC:\ϟC:t>~&ϡC:tСCСC.ϡC:tO?9LC:tСC&ϡC:\|8`A&TaC1ϟC9tСC:ta|:tСÅ9tСCǰ_?СC:tСC sСCСC:~9_A}:tСC:t0a>:t|:tСCcد?+C:tСC&ϡC:\ϟC:t>~ _~sСC:tСÄ9tСC sСCϡ+C:tСCJ|8`A&TaC9tСC?Ϡ?:tСC:ϟC:t0?:t?}:_A} sСC:tСC9tСC sСCϡÄ9tСC:ta|:tСÅ9tСCaB}:tСC:t0a>:t|:tСCcϟ?sСC:tСÄ9tСC O@ DPB ` <0… :|1DM8qD$XA .dp!?$(_? ,(P?$XA .dC%oĉ'N8qĉ_~8qĉ'Nh0'N8qĉ'ϟCoĉ'N8q|&N8qĉ'Nϟ?WP'N8qĉ8qĉ'N8qDϠ'N8qDM8qĉ'N8Q~ g0ĉ'N8q|&N8qĉ'N8џM8qĉ'N4ĉ'N8qĉ'oĉ'N8q|&N8qĉ'N8 @}8`A&TaC!Fh0'N8qĉ'ׯāM8qĉ'N4ĉ'N8qĉo@}&N8qĉ'oĉ'N8qĉ7q>~'N8qĉ 7qĉ'N8qs_M8qĉ'N4ĉ'N8qĉϡ~ 7qĉ'N8`>'N8qĉ'N_M8qĉ'N4ĉ'N8qĉ%ׯ>~M8qĉ'Joĉ'N8qĉׯ7p`>$XA .dC#'QD%J(QD'QD%J(a>%J(QD%J(>~%J(QD'QD%J(QĆI$D%J(QćI(QD%J(~$OD%J(Q|$J(QD%J_~ 'QD%J(a>%J(QD%Jd_OD%J(Q|$J(QD%J_~WP?%J(QD(QD%J(Q"C9ׯ <0… :|1DM8qĉ'N8Q~ 7qĉ'N8`>'N8qĉ'N_7qĉ'N(1'N8qĉ'N篠>~M8qĉ'Joĉ'N8qĉ7qĉ'N8`>'N8qĉ'NxP'N8qĉ8qĉ'N8q?Mĉ'N8qDM8qĉ'N8~&oĉ'N8q|&N8qĉ'N_~7qĉ'N8A <0… :|1ĉ_~H"E)RE)RH"E _~H"E)RE)RH"E _~H"E)RE)RH"Eׯ>~QH"E)*"E)RH"EWP?(RH"EG"E)RH"EǏ"E)RH1b>)RH"E)R|E)RHb|(RH"E)RP?)RH"ňQH"E)R@O@ ? 4xaB 6tbD8qĉ'N8q?Mĉ'N8qDM8qĉ'N8~&oĉ'N8q|&N8qĉ'N_~WP'N8qĉ8qĉ'N8q?9ׯ_A}8`A&TaC!Fh0?$XA .dC%N_~'p P <0… :|?$XA .dC%N_~_Ŋ+VXbŊ+VXbʼn_|*VXbŊ+VXbŊ+V_|*VXbŊ+VXbŊ+V_|*VXbŊ+VXbŊ+bEWbŊ+VXbŊ+VXQ~*VD/_>~+VXbŊ+VXbŊׯbEWbŊ+VXbŊ+VXQ~W|UXbŊ+VXbŊ+V_?_|*VXbŊ***H  ׯ` /_>~ H*\ȰÇ#JHŋ3j_oƍ7nܸqƍ7fׯFqƍ7nܸqƍ5Ѡ|mܸqƍ7nܸqƍ _|qƍ7nܸqƍ7n0'p "Lp!ÆB(q"Ŋ/b̨?)O@8`A&TaC!F8bE1fX_~6RO@ H*\ȰÇ#JHŋ3j4_?)O} H*\ȰÇ#JHŋ3j4_? 뷱> O@ DPB >QD-^ĘQ#~5ׯƂ˗oƍ7nܸqƍ7nDϟCm4/_|7nܸqƍ7nܸ1~6̗ƍ7nܸqƍ7n_۸qƍ7nܸqۈƍ7nܸqƍ7nܸqƍ7nܸqƍ7nܸqƍ7nܸqƍ7ƍ7nܸqƍ7nܸa~(O@ DPB O@ DPB >QD-^د?'p "Lp!ÆO@ DPB >QD-^د#/F)Ӈ#F1bĈ#F _~勨| ˗O?K/_|"+|/>˧_A  g?/A 4H0| '0,h „ 2l萠~_|So ?}./a~{(0_|{(0_A~/~ {0| /Ç _>>|ÇG_70|ӗo| W0|/_>~O |/_~O!?} '_|ӗ}+_?˗|3~G0_|| ̧/_/_~_|7p_>?}O_|˗߿|'P`/_?'p_>}/_>~ <0… "ׯA O_?۷_~߾7'P?~>_|˧'>_`O>~` O_|o}߿||O>~_|_>?/߿}>O_>~۷|o߿ <0… :/C~'0| /߿|+/_|`|7>} ԷC~/_|O`+?~#_> + |O@ /?~_O#o`_o}_O| /|70| /,h „ 2lp|(߿|/߿o| o| /@ |o O|_O|˗o| /_| o} o||_׏_} _ O߿}O_?~ǯ_߿ǯ__/߿'p "Lp!Ã5D/_ _>?~O> o}>~O`}SO_|˧@~߾}+o| _> +o@~#`>@~O` W0߿}70?~O?'0߿}'_>~#`|O`O` /_Æ 6lx_? ߾~/_>~O`>O|/_>~˗}/_|˗7p@~߾| '0@}(0@~˗| /_|˗o|(`>߿/߿ӧ~ O߿}/?/_>}˗߿~/_}ۗ/_>7P`˗o} 'P_|/_>}'p "Lp!Ãkx_ ̇0_Æ  䧯aÆ 6lذaÆ kaÆ 6lذ_? G_ g_~ 6l( 6lذaÆ 6:t!?}:tСC:tСÆСC&ϡÆ:t>:tСC:taCsСCsh_>s!B~:tСC:tСC ϡCϡA*/_'0||O |9lOC:tСC:t谡|9tС~94/C/_߾}_}}sȐ>:tСC9C9PC˗,h „ #/C/| /|3`|cP ?} 2dȐ!C 2dȐ!C /? 2d_? ׏| ǯ_o``> ? 4X>$XA .dC%N_|*VxП? G_ _>?~O߾ O?U,O_Ŋ+VXbŊ ǯbŊ׏|˗o}'0_|}/_>} WbŊ+VXbCXbE#/_E KbEUXbŊ+V_|*VXq?嫈0_|'`>8`A ? 4xaB 6tbD)6/+VL/_Ŋ+"䧯bŊ+VXbņWbŊ O@ DPB  <0… :|1ĉ˗_Ŋb?$XA .dp>$XA .dC%N_|*Vx_?+/+VXbŊ+V_|*Vx_?+/+VXbŊ+V_|*Vx_? W|UXbŊ+VXbņWbŃk_ ǯbŊ+VXbŊ+6/+V_ ǯbŊ+VXbŊ+6/+V_ ǯbŊ+VXbŊ+6/+V_ ǯbŊ+VXbŊ+6/@~ H*\ȰÇ"D!B"D!BC"D!*/?!B"D!B"D"D "D"D!B"D!Bѡ|A~A|A"D!B"D!Bt/_>~!Bh_~!B/_>~ {"D!B"D!B|A~9"㧰_}A"D!B"D!/?!B4د_?O@O_}˷O`}O@ DPB >QD+˗E ׯ~,./?'0_߾}>-ZhѢE-*/?-RׯŅ㗐 70߿|/?~,ZhѢE-Z_|,ZH_~˗_B /߿߿|/,h „ 2l!Ĉ'Rh_|,ZXџ? a?}?~ӷϢE-ZhѢE ϢE-2/? _| ̗/?gѢE-ZhѢŅgѢE˗|!gѢE-ZhѢEgѢEh|AW0A~YhѢE-Zh|Yh~,Z,/_>~ /߾˧A   <0… :|1ĉ#˗_ŊׯbŃ0_A~'0~80_Ŋ+VXbŊǯbŊ_~˗_|O`>3|O`>}ӗO?}XbŊ+VXq|UX~ׯ"CK`G0~o|/|/_Ŋ+VXbŊ ǯbŊ_~˗_|O~7P/߿߿|o_?$XA .dC%N_|*VXQ~*2/ #O`wp|8_߿~O@ DPB >QD ǯbŊׯ"CK }`>۷>~O`>'0_Ŋ+VXbŊ ǯbŊW|%̗/_>}˷o`>'P >_7,h „ 2l!Ĉ'R\/_>~+VX1|UXbŊ+VXbņWbŊ#˗_Ŋ+VXbŊ+Vl/_>~+V<_˗_Ŋ+VXbŊ+Vl/_>~+V<_˗_|'?XbŊ+VXbDXAUx_|~ WbŊ+VXbňWbŃk_ /a />~O |˧_}XbŊ+VX"C˗,h „ ׯc0|%G0|o|/߿|> 2dȐ!C 2dȐ!C 2/_>~ 2dȐ!Cc?ϟ?_>ӗo~ 2dȐ!C 2dȐ!C 2d8_|2dȐ!CǐA$? O`'p`> '0߿}'p "Lp!ÆB(q"Ŋ /_>}gѢE| '0߿|ϟ}'0߿~'p "Lp!ÆB(q"Ŋ 'p@$XA .d!C?˗| ܗ/>} ? 4xaB 6tbD)VT`>O@ DPB 208`A  <0… :|1ĉ+208`A&Tp? 2d`>8`A㗯,h „ 2l!Ĉ'R`>'p "Lp@1dȐ|ǐ!C 2dȐ!C 2dȐ!C 2D`>8`A&Tp~2d|1dȐ!C 2dȐ!C 2dȐ!C ˗/? 2d_~ ǐ|1dȐ!C 2dȐ!C 2dȐ!C ˗/C 2T_?ǐ}2dȐ!C 2dȐ!C 2dȐ!C ǐ!C ׏?1dC 2dȐ!C 2dȐ!C 2dȐa| 2dȐ!ÁO@ DPB >QD-^Ę_ƌׯ @,h „ 2$ <0… :|1ĉ8`A&TaÅ H#`> 4xaB O@ DPB >QD H*\ȰB~ HC!B"Dx_>$XA .dC%N$E)NǏ"D~(R8_>)RH"EH"ʼn9"?})R/E)RH"EQHD}׏"?})R/E)RH"EQHD}׏"?})R/E)RH"EQHD}ׯ~gP|O|O@ D| *TPB *TPB *$ϟB *TP„)_?G+OB OB *TPB *TPBSPB *TP?S8_~Ko| /_> /?PBSPB *TPB *TP!|*TPB &O„#O_|/|/|ϟ|*T_> *TPB *TPB OB *TH!H?$X#O/|'0|!B <0… :|1ĉH"ʼnQTA~o| /|o_>})"E)RH|(RHq>~!ӗ0|?~O~ G?(a>70E)R0?)RE%7P_>~/_> />G?(o| O|)RH"|(RHq>~ G>)NbA} ̧/>'0߾~o>?~/|ۗO_?}O@ DPB СC'0C5ׯC9tСÄ9\~o߿|/_}#`>~ _>o߾O`>~ϡC:t/?`>2ǯ~9,OC:L/CO`_G0| /|70߿|ӷC:tp`>O |̧/_?} /`>} /_?'p_>}_|˷,O?ϟA#OA 4hРA /A 'P_>(0_?}O`0˷? 4xaB 6DϟA~o|/'0|w0/|o?O`>~s8P_~`> 4xaB 'p?$H~/?~o O`>/|۷|߾~'p "Lp!Æ3`|#O`>O}o~_7ϡ#OA$XA .#H AO߿|/_>~ ׏}O`ۧo߿| ܗ/_>_|'p "Lp!Æ3 |߿|/?o'0߿~'0| '`> ϠA ׏ ?} 4hРA 4h| 엏AgP`> 4X0,h „ 2l`>>~O`>@~`>/|۷|'CÇ?}s`>{P|=|Ç wp_|˗O| '0}/_||/|˗O`'0Á=|h6!Cӗ/_|>|Ç>|0>|0>~` =|_8p@,h „ 2l!Ĉ  < |'p "LxP?S/>~_>ӗ/_/_>~O_~O`}˗B0 <0… :|1D8`A&TaC9ϟÂ_| / >/'0| ;`> 4xaB 6tbD'p|_>/_>˧| ˗/> $H`> $A AGp`>#/@ O߾~G0_>o ?} ԷAG?}  ? 4xaB 6tbDO/Aϟ> ϟ| OA $ A G A#H?Gp`>#/؏_}G0_>0|8@ 0@8`A&TaC!Fh0`~ o? ̇0|/_>~O |ۗO_>oGP?c_?'0߿|ӷO`o_?o} '0?}/}c/~7qĉ'N8`> _ϟ| ̇0@~o@}/?~ӷ| '0 o>~_~;O`O_|ۗO_?}˗߿|/߿_˗/_ <0… :|1D̗/_>}7?}3O`>˧O`7߿|O`>o ?}_~8qāA7qĉ'N8`>G_?˧~C`W`>߿|/߿O?$X#OB"D!ƒ'p "Lp!ÆB(q"|3ཱྀ _>~O`> o}>~_>'0@}7P? #OE'G"E)RHa>̗/_>}˗/>˗/_>˗O| ܗ/O|ӗ/_>'0}#EGq`>G"E)RHa>!H@}(B`>Qx_>)RH"EH"ʼn9"?}ӗ߿||o}_|˷?}O@ /,h „ 2l!Ĉ'"E'_?;߿|#o@}o?'0|G"E)RHa>)R8Q?O|W0|70߿|O}(6"E)RH|(RHq>~_~;O` #_0|8`A <0… :|1ĉH"ʼn9C`>߾}߾}@~|G"E)RHa>)R8Q?5ׯA~_˗|˗O| '_|Q\/E)RH"EQHD}(&ׯA~(R8_>)RH"EH"ʼnQL_?QHq|)RH"EG"EП?QHq|)RH"E? 4xaB 6DCsСC sСC:tСC sСCϡC9tСÄ9tСC:tСC9tСC_? СCСC:tСCСC:~9,OC:L/C:tСC:dϟC:t>~ ?}:t0|:tСC:ta>:tС9CϡC&ϡC:tСC2,h „ 2lP?c_?9tСÄ9tСC:tСC9tСC?> 4xaB   <0… :|1ĉ'p "Lp!Æ O@ _?8`A&T!A$XA .dC%N$ <0… . <_~ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cOL2eʔ)a~dʔ)SL2OL2eʔ)a~'SL2eʄٯ?)SL2eCɔ)SL2e6ׯL2eʔ)SfCɔ)SL2e:OL2eʔ)SL2eʔ)SL2eʔ)ӣ?dʔ)SL2ϡ? O@ @ @(?('P O@ O@ @ `?(`?'P ~'P? O@ @ @(?('P O@ O@ @ _~ @(`?(_~(`?'P ~'P~7P ~O@ O@o@ @ @@O ?(?ׯ8$`?(`?'P ~'P? O@ @ @(?('P O@ O@ @ `?(`?'P ~'P? O@ @ @(?('P ׯ_?'P? O@ ׯ_~ O@ @ _~ @(`?(_~(`?'P ~'P~7P ~O@ O@o@ 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'P 'p?$XA .dC%NXE5nG!E$Y3I)UdK1eΤYM9uOA%ZQI.eSQ;;PK:HsYOPK-AOEBPS/img/adque250.gif)nGIF87ap?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU,p H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗03@~ϟ? H*\ȰÇ#JHŋ3jȱGO|,hp}O@ DPB >QD-^ĘQF+O|Ǐ_?'p Ǐ?}(P~ H*\ȰÇ#JHŋ3jȱ#C˗O>~y?}˷G=zѣG=zH߾|ϣ~˗?=zѣG=z象}ϣ~ϣG=zѣG=zL/_|yo_|yѣG=zѣG˧G˧ϟG=zѣG=zO_>}QD-^ĘQFױE}uرcǎ;vرcǎۗ_|Mq`>}:vرcǎ;vرcGe߿~Iq`|uرcǎ;vرcǎ˨~߾| /?˗|رcǎ;vرcǎ˘`>ϟ|߿|o>}uرcǎ;vرceW0|/| '0|_ǎ;vرcǎ;v|8`AO|O`˗/ ϟ?$XA .dC%NXE5nܘ/? 엯|O`>O>eܗo?8rȑ#G9rȑ#dž/_>}/|˗|˷/|#G9rȑ#G9rl_}9^O}ȑ#G9rȑ#G/>+˗}ȑ#G9rȑ#G_|8r/>G9rȑ#G9r0?Ǒ~ϟ}ȑ#G8#8#8j|_|8`A&T_?}ϟ?} <0… :|1ĉ+Z1ƍ+o_|qh_|'p}8`A&TaC!F8bE1fԸqc> /_>~8r/_>}8P}8`A&TaC!F8bE1fԸqc>/_|q菟|O@ <0… :|1ĉ+Z1ƍ+`}˷? ӗ/_>}'p O@ DPB >QD-^ĘQƍ} ? HA/_|П Էo ,h „ 2l!Ĉ'Rh"ƌ7n篢?~'p>}8~ӧ`>ǯ@,hP߾ H*\ȰÇ#JHŋ3jܸ1?Ǐ>}'p AǏ? П o@$XA .dC%NXE5nܘG8`A <0… :|1ĉ+Z1ƍ @,hП}8`A&TaC!F8bE1fԸqc>9O@ ӷo ,h „ 2l!Ĉ'Rh"ƌ7n#G HA O@ DPB >QD-^ĘQƍqh? 4O߾ H*\ȰÇ#JHŋ3jܸ1? 'p 7? 4xaB 6tbD)V <0…8`A&TaC9tСA$XР?}'p "Lp!Æ8`A&T_?$XA .> 4xaB O@ DPB СC8`A <0… > 4xaB O@ DP1dȐ!Â1dȐ!C !C  O@ ӷo ,h „ 2lX_>:LOC6ϡCСC:$ϟCO@ ӷo ,h „ 2lX_>:LOC6ϡC!A  <0„-\pƒ HA O@ O@~ H*߾|o_߿|/߿>$X Ao`>o`;x|O߾ӧO?/_>~ Էo ,h`>o`O`>O`o`/_| /_|~ O>} 'P |㧯 <`_˗/|˗/_?~_>/'P_?~䧯+/WП}O?'p@}'p 3o`>_>O~/߿};x@~篠}o?/>Էo ,h |߿'_߿~/? 4H_,دww|w|4?~~;xA;H_|w`?}ۧOAϟ?@;x(,h B}!/B!<?!B!D!Ba|‚Cp`> ˗/_>"D!B ˗/?+>}˷>`?}?}O|ϟ?}П|C!|"DHP_|!~!<_? @~"D!B P_|˷O`>} /@~/_~/?~O_~C(?} ? 4xaB 'p ?oAO@}ۧ@O@}ۧA~߿}㗏A~o?ϟ?'P ?$XA .`>'p|/|O_}_|˗?}_|ӗO@ DP!O_?۷_~_߾ '0}߿|CO|O@ DPB (7P>뗏߿}(P߿篟>~7'P>}Ǐ?~o}ӧ?~O߾ `>'p "Lp@߿O'0_߾}o?/|'PGp ?} H*\80O`_O~/| ̇08`A&TB} @8p_} ?} />>/@~o_?ԗ ?ϟ?}? H*\pO@O`_ 7_| ̗`#8>$XA .A /߿߿|/߿ǯ_'߿_>A8`A&T!} @8_>?} /@~>O@~o_?ܧ ?ϟ?}߿'p "Lp!Ã_>0@__(>~ '0_'0O@ DPo>~Ǐ߿|/߿|/@o>'0|O@ H*\8`>'p|П'p ?}O@8'p}8P'p>} o?ϟ?08`A&Tp> ?8_?}?~ӷO`'0| _>O,h „ ~/_>~O`ӗ/_?~ӷ>}ۗ/?CC~!C &̗/_} +?O@~П'p |O@'p>O}8p>ӷϟ? (_|O@ DP˗A7'0_|ϟ|/>}/߿}O`1dȐ!Ä1`> "珡}cȐ!C oa>П@(P~?'P|o@Ǐ?~}@'P}8 |'p "Lp@}K/Á cȐA~2dȐa| W0C ǐ> ˗/? 2ܧϟ?o_>~ϟ|ۗA~o>~o?>}ӗ@7? ǯ`Aǯ` ,X`} /_W` ,8>$XA .C 2,C Ǐ!C ?}Ǐ_} _>~󗐟~O_/_?ۗ@ Էo ,h`~8P}8p?}'p O@~/_O | 70?~;x A ߾| '0~_> A;xP`| O@G@}'p #O`> ߾| '0~_>O~/|/_}/߿~;x A/_? *L/B *TX> *T0a> *TPa|*TPa> *T/?˷O`|/|˗|_|˗ϟ~П Էo ,h „)TPaB*TP‚)TPB 8`A&TP?$XA SPBSx_~ ߾|/_~'0_~O`>~O@7? 4xa*T0?$XA .̧? 4xaB 'p "Lp@$XA .dؐa>_~ '0_~/|'П| ϟ| H@}'p "Lp!Æ8`A&TP ,h „ 2l!Ĉ'R0 _o߾}˷_/߿| /_|/@,8P> H*\ȰÇ#JHŋ3j_>'p_O`| _>ϟ|?}П Է? 4xaB 6tbD)VxcF9 |/_~7P_>~70߿~/_}/@,8P>$XA .dC%NXE5n(0 'p O@ DPB >QD-^ĘQFر @,hP?$XA .dC%NXE5n(0 'p O@ DPB >QD-^ĘQFر @,hP?$XA .dC%NXE5n(0O`˗ϟ| /?G? O>~ H*\ȰÇ#JHŋ3jQ`>/|>_}@$Xp?'p "Lp!ÆB(q"Ŋ/b̨q#G]70|'0| '0|O@ 'P?$XA .dC%NXE5n(0o`'0|˗O}O@ 'P?$XA .dC%NXE5n(0O`>O~/}O`> H? <0… :|1ĉ+Z1ƍw_| O߿|˷O |/_}Ǐ @,O?'p "Lp!ÆB(q"Ŋ/b̨q#Gm @,O?'p "Lp!ÆB(q"Ŋ/b̨q#ǁӘA$XO@ DPB >QD-^ĘQF1_G H?O@ DPB >QD-^ĘQFױ@ <0… :|1ĉ+Z1ƍ˷c ? 4xaB 6tbD)VxcF9&/_?8߾|8`A&TaC!F8bE1fԸ#CQ?@˗,h „ 2l!Ĉ'Rh"ƌ7r|/_|:bϟ߾|uرcǎ;vرcǎ˗o_?˗o_ǎ;vرcǎ;vx߾|Q"@ӗ/~ H*\ȰÇ#JHŋ3jq?~˧_ӗ/_>}:vرcǎ;vرcǎo_|_Gۧ/_|رcǎ;vرcǎ;"O@~'P>}П7P`?~0@ <0… :|1ĉ+Z1ƍ;BO~ӧ`> 4O>~O@ DPB >QD-^ĘQF3'p A H?$XA .dC%NXE5nuѣB$XP ,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РB-j(ҤJ2m)ԨRRj*֬Z ;;PKíʖ))PK-AOEBPS/img/adqmg005.gifRDGIF87a?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU, П@ ϟ?'P 'P   7p @'p @'p?'p "Lp!ÆB(q"Eg?8?8П?O@O@ϟ(?(?o@ O@ DР? O@o@ O@ @@ @(?ׯ(?'P ׯ_? H*\ȰÇ#JHQ~W`?(~'P~7P ~'P? O@o@ O@ @@  <0A @@ @(?ׯ(?'P ׯ_?'P O@ ׯ_~8`A&TaC!F8B ~'P? O@o@ O@ @@ @(?ׯ(? 4xaB 6tbD)VxcF9vC ~B 2dH 2$~L_!CBׯ_Ȑ!C _?!Cد 2dH 2dȐ!/dȐ2~B _~!C 2~ b~B&ׯ_Ȑ!!/dȐ!Ctد!CB_H-̗O |:'q_| )П!C ҡ? /_>7_|)/dȂĘOO_D~'p "Lp!ÆB(q"Ŋ>'P_?ۧO?}/^xa>~O|/_?O_|˧/|O`|o>/_|>}o?}ۧ|.^xŋ/^<_~菟}|O |]xŁ__ _>~'0?߿|`>O`|/_?~/?~8`A&TaC!F8bŃ_/߾~o|/?~/E-ZDϟ>O?o`}/| '0| W0| Ǐ_>_ۧ_>/_},ZhѢE-Zϟ>`>˧_>}߿|/|YhѢń_ ߾|/_߿|/߿(0? ̷_>'P/߿O|8`A&TaC!F8bŃ_/@0@/߿/>$XA .dذ~OϟO`'P?O`>W> _>ϟ>o|/_>sСC:tСC |/?~˗O`~/?|O`>:د?oa ϟ|/_?O_}˧/| '_>} ˗_>'P_~'_>/߾|S~ H*\ȰÇ#JHQ`~/|˧/?}O`O |U_?+ׯbE~-'0_Ŋ)ׯ_Ŋ+VXbŊWq+V4دW"|-/ӷ_~+VXbŊ+ _Ŋ+VTدWbŊׯbŊ+VXbEXbŊ W|˗bŊ+VXbŊ+V0_>XbŊ+&̧?}UXbŊUTQEUTQE-P>}? 4xaB 6tbā_>_|˗?}/|OD%J(QD%J(`>~߾| /_?O_|˧/}(QD߾'0?~/|/?~$J(QD%J(QD o||O`>~ۗ}%J(Q|/߿|/>~'?~_>}(Q"$H"$H"$H"(?}˗O?˷߿_?~߿|/,h „ 2l萠? Ǐ߿|(}o_>}߿|7P ,h „ p… .\p… .\p-_>~'p}˷_@ H*Dϟ &ׯ|/?}O| /?/?}ӷp… o… .\p… .\p…0?}˧/?O>/@}/?.\p!~-\0~/|˗?~/_~ۗO`|/_>~ .\~.\p… .\p… .\8_? ۗO`>'_|˗?}/|˗… -B? 4xA%L0A~%L0a„ ? 4xaB 6tbD) _ŊX~U_ǯbŊWbŊ+VX~U/_>~+V4دWbŊWbŊ+VX~UXbEO@ DPB >QD-^ĘQF=~RH%MDRJ-]SL5męSN=}TPEQ;zԨ?ϟJe_G(~ׯ} H*\Ȱ?$_~ H*\ȰÇ#JHQ`~O@ DPB 8~,X` ׯ_'p "Lp!C'p O@ DPB >QDۧB8`A&T!|8~,X` ׯ_O@ DPB [_ 6lذaÆ 6lذaC˗O?5lذaÆ [د oa> 6lذB}װaÆ 6lذaÆ 6lHП?~˷| 6lذ!|װaÆkذaÆ П <0… :|1ĉ%O}? 4xaB 2aÆ aÆ 6\`> 4xaB 6tbD)V<| H*\Ȑa> 6lذ`> 6lذB} H*\ȰÇ#JH"~'p "Lp!C5lذaÂ5lذaÆ O@ DPB >QD'p`>~ <0… װaÆ װaÆ .ǯaÆ 6lذaÆ 6lذA~ ߿O@ DPB kذaC[_#/_} ˗/_ kPkذaÆ 6lذaÆ 6$د߾|3/_Æ 6l0kذ@-?~/+O`?} 0>~ װaÆ 6lذaÆ 6lH_}!aÆ 6d~5lp~_} o`} '0_|˷O`>~/_>˗/_> ̷?}ׯaÆ 6lذaÆ 6l!׏?/,h „ 2d~5lp~_~ W0_|/_۷_>~_}/~ׯ?}ǯaÆ 6lذaÆ 6lؐ`~װaÆ 2oa~6l8_~ k/߿~W0_|'0?o`>ϟ|㗯@}˷aÆ 6lذaÆ 6lؐ`~װaÆ 2oa~6lؐ`> (p߿|۷O80|70|o`7p8p|O@ DPB >QDXbEUX`> 'p_/_ ?~>/|>~˷_>~+VXbŊ+>bŊ WbŃ1ܗo`|˗/_>~7_|/_>˷O`/D} ˗o|*VXbŊ+V|/_Ŋ+bŊHПU>~˧A$XA .dC%N8? 4xaB 2aÆ aÆ 54/_/_>} 'p "Lp!ÆB(q"ň'p "Lp!C5lذaAװaC6l߿~g? 4xaB 6tbD)F? 4xaB 2o?6l8_~ kذaÆ 7_| 'p "Lp!ÆB(q"ʼn H*\Ȑa> װaÁ[_Æ 6lP70߾ 6lذaÆ 6lذaCS/_Æ 6l0kذ@-aÆ 6\A~o_Æ 6lذaÆ 6lذ!~)aÆ 6d~5lp~װaÆ ./|kذaÆ 6lذaÆ 6$د?5lذaÆ [د ׯ|6lذaÅ-ܗo_Æ 6lذaÆ 6lذ!~)aÆ 5C` ,X`O@ DPB c_Æ 6lذaÆ 6lذaC5l/| kذa> 6lذ |,h „ 2lO,h „ 2l!Ĉ'R_>1Yh`} H*\pa} H*\ȰÇ#JHQb? h0|O| O߿|O`~*bŊXbłUXbŊ+V(_}h`>o߿~_>~/~ <WC-bŊ _~+VXbŊ+ o|?8`A/_|/| ̗/_> ׯA~/_|˷O`A;xw`>~ _>kH0C}6lذaÆ 6lذaÆ />kذaÆ װaÆ 70_?ӗ/_?'_|㗏|O| G0|| O_>'0?}kذaÆ 6lذaÆ 6lx@O@'p "Lp!C5lذa W_ _>ӷ_>~ '0_?~_>'P㷏_|o߿? 4xaB 6tbD)VD/E- ϢE`?~ '0|'0| '?~#o`>_?~ '0|'0?1ϢE-ZhѢłYhѢ|,ZH0 _} '0|'0|̷_>O |˷_@>~ H_|8`A&TaC!F8C*VX`>+:ׯ|_>~O`>߾O`> _>O|||o>~˷/߾+VXbŊO|+Vh0X_~ #/_>~ۗO`>˗o| '_|˷/| 'П|ӗo_>ϟ| 7P?_}+VXbŊ+ ϟB*VX`> H_~ ,X`ׯ`'p "Lp!Å/>O@ DPB >QD맰_>$XA .d0kذ@-aÆ 6\@W`> 4xaB 6tbD)NO@ DPB [د ׯ|6lذaÅۗ/ 6lذaÆ 6lذaÆ kذaÆ _? 6lH0 6lp>~˷ @},h „ 2l!Ĉ'R/,h „ 2d_Æ 6,_Æ 6lP?G0>$XA .dC%Np_>$XA .d0 6lX0 6lp>~O`>~ 6lذaÆ 6lذaÆ װaÆ 2aÆ aÆ 6\}ǯaÆ 6lذaÆ 6lذ!A6lذaC5lذaÂ5lذaÆ KO_|6lذaÆ 6lذaÆ aÆ 6d_Æ oa> 6lذB}ӷaÆ 6lذaÆ 6lؐ? kذaÆ П? 6_ H*\Ȱa>} H~8`A&TaC!F8~)bŊ _?+oa>~ H*\p>~ H~8`A&TaC!F8~)bŊ _?+oa>+VXPXbŊ+VXQ`~WbŊ[د0+V,BUXbŊ+V(_? O@ DPB O@W` ,(_~ ? 4xaB .Ǐ? 6lذaÆ 6lذaÆ_>$XA .d0_?$ϟ? ,X` ,h „ 2\_Æ 6lذaÆ 6lذaÆkذaÆ װaÆ װaÆ .ǯaÆ 6lذaÆ 6lذaÂ5lذaÆ kذaÆkذaÆ װaÆ 6lذaÆ 6lذaA6lذaC5lذaÂ5lذaÆ kذaÆ 6lذaÆ 6lذ| 6lذ!|6lذa|6lذaÅ5lذaÆ 6lذaÆ 6lX_ 6lؐa> 6lHП? kذaÆ ~8`A&TaC!F8@)bŊ _?+oa>+VXPXbŊ+VXQ`~WbŊ[د0+V,BUXbŊ+V(_? XbE-_Ŋ[_Ŋ+o~*VXbŊ+Vد?UX|bE-bŊ _~+VXbŊ+ ϟB*VX`> W?WbŊc_Ŋ+VXbŊ? ? 4xaB 2o? 6lX0 6lp>~ 6lذaÆ 6lذaÆ | 6lذ!|6lذa|6lذaÅ5lذaÆ 6lذaÆ 6QD/,h „ 2d_Æ ׯ|6lذaÅ8`A&TaC!F8bEO@ DPB [د ׯ|6lذaÅ'p "Lp!ÆB(q"E (߿'p "Lp!C-_Æ oa> 6lذB}ׯaÆ 6lذaÆ 6lؐ`~(p߿ <0… _? 6_5lذaÆ [_ 6lذaÆ 6lذaC˗/>5lذaÆ [د ׯ|6lذaÅ-ׯ_Æ 6lذaÆ 6lذ!~| 6lذ!|aÆ W_|6O 'P?$(0_O@ DPB >QDK/_Ŋ+bŊ#/@}*_| 䗏a>UXbŊ+VX|+Vh0+珠~o_|/_?70_|'_|˗|'_|˧_ ̷>~+VXbŊ+VD/_Ŋ+bŊ#`|߿}o>ۗ_>ׯ_> W`>߿}o_ <0… :|1ĉ+"ϢEgѢEw?~O`_>؏|7>o`>gP?-ZhѢE'gѢEh? #ϟ@/߿| 70|'0_|`>_ۧoA}gѢE-Zhѡ? 峘`>'p ,X`+X? ,X`ׯ`O>}_>O`>|7_>~/_~W|'p "Lp!ÆB(q"ES/_E0_E-_Ŋ[_A~/| '_| 70߿|O| |ϟ@}/߿'p?}/|8`A&TaC!F8~)| /߾o_>Ud~U_UX1b>~3/_}XbŊ+VXQ`~WQ!|O߿}/_?$X!د?"D(_~!B"DР|G_| <0… :|1ĉ۷O| H O`_>~!D|B"_?C!B"D?}˗O H*\ȰÇ#JH1b| H'0| o>}"DP`>!B"DB"D!Bo_|8`A&TaC!F8bŁYLo |O@}_|,2ϢEhѢ /> H*\ȰÇ#JH1b| H(߿_?'? 4x`>"D!BC!B"D?}˗o|8`A&TaC!F8}8`A&DB PB *OB *T0>~O`>~ H*\ȰÇ#JH|+&/_ŇUX`>+VXP?㗏_Ŋ+VXbŊXbEUП? Xbł)ܗ/߾+VXbŊO|+Vh0X_~ Xbł-o_Ŋ+VXbŊ_+V4~U_UXbA}ׯbŊ+VXbES/_Ŋ+oa~*Vׯ|*VX>~ WbŊ+VX~)bŊP> H_~ ,X`ׯ`'p "Lp!Å-ׯ_Æ 6lذaÆ 6lذ!~)aÆ 6d~5lؐ? kذaÆ П 6lذaÆ 6lذaC-aÆ 6dB6lذ`> 6lذB}6lذaÆ 6lذaÆ 6,/_Æ 6l0 6lX0 6lp>~ 6lذaÆ 6lذaÆ aÆ 6d_Æ 6,_Æ 6lP 6lذaÆ 6laÆ װaÆ 2aÆ P> H*\p>~ 6lذaÆ 6lذaÆ aÆ 6d_Æ 6,_Æ 6lP 6lذaÆ 6lذaÆ װaÆ 2aÆ oa> 6lذB}ׯaÆ 6lذaÆ 6lؐ`~װaÆ 2oa~6l8_~ kذaÆ _~ 6lذaÆ 6lذaÆ_ 6lؐa> װaÁ[_Æ 6lPkذaÆ 6lذaÆ 6$د?$/,h „ 2d~5lp~װaÆ .o~6lذaÆ 6lذaÆ O| 6lذ!|aÆ0 6lp>~ װaÆ 6lذaÆ 6lH_? kذaÆ _? 6lH0 6lp>~ 6lذaÆ 6lذaÆ aÆ 6d_Æ 6,_Æ 6lP 6lذaÆ 6lذaÆ װaÆ 2aÆ aÆ 6\_Æ 6lذaC 5PC 5PC | H*\Ȑa> 6lذ`> 6lذB}6lذaÆ 6lذaÆ 6,/_Æ 6l0 6lX0 6lp>~ 6lذaÆ 6lذaÆ aÆ 6d_Æ oa> 6lذB}װaÆ 6lذaÆ 6lHП5lذaÆ [ϟ ׯ|8`A&T|8?'p "Lp!ÆB(q"ES/@~,h „ 2dׯ ,X`A+X@},h „ 2l_?$XA .dC%N(_? 'p "Lp!Æ8~,X` ׯ,h „ 2lP~>|Ç>|C{Ç*Ç Ç>T_>|Ç>|P`~>|Ç !C=|ÇÇ>|Ç Ç>|P?8`A&TaC!F8bE1fԸcGA9dI'QTeK/aƔ9fM7qԹgO?:hQ%w~5ϟ,_~GYQ;ʲ_?*w~5گ,_~(?(?(?(?(?(?(?(?(?(?ׯ_?$XA .dC%N(_?(?(?(?(?(?(?(?(?(?(?_? H ׯ ~'P? O@ @ @(?('P O@ O@ @ `?8`A&TaC!F8~@ @(`?(~'P ~O@ O@ @ ?(?'P 'p?$XAW`?(~'P ~O@ O@ @ ?(?'P 'P? O@  H*\ȰÇ#JHQ`~'P 'P? O@ @ @(`?(~'P ~O@ O@ @ ? 4xaB 6tbD)VxcF9vdH#I4yeJ+YtfL3iִygN;yhPC5ziRK6ujTSVzkV[vlXcɖ5{mZkٶun\sֵ{o^{p` 6|qbŋ7vrddM 1Ɇ8/+80| ,X`>$XA .dC%NXE5n|> 4x | o߿|˗/|'_|O`~/8`A&TaC!F8bE1fԸ?$XA'p|o`>o>۷_o_ۗ? 4xaB 6tbD)VxcFO@ DhP?| '0| 70߿| 70߿|'p "Lp!ÆB(q"Ŋ/b̨q#D$XA ~O`>o`o`O@ DPB >QD-^ĘQF(O~| ?}O߿|'0|/,h „ 2l!Ĉ'Rh"ƌ7r/_>~˧@~'P_>O|/_|رcǎ;vرcǎ-ױcǎ;vرcǎ;vرcǎ;vرcǎ;vر|1رcǎ;vرcǎ;6' _ǎ;vرcǎ;vرa| /_>O`|/_~/@_|:vرcǎ;vرcǎ'`>o߿۷_>?}_?}_>~O@ DPB >QD-^ĘQF˗|O`/| Ǐ_>o`>رcǎ;vرcǎ;3o`_} 70|O`>o`;vرcǎ;vرc>>_ ߾|O`>>رcǎ;vرcǎ;3o|_|/O|/|˧ϟ|uرcǎ;v쨣:#_>$XA .dC%NXE5nѣ| ˧Ǐ?~Ǐ?~a>$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQ&oԩS6/SNԟ|;a>N:|d><:uԥ70/_O| 70߿|'_>}M:ujR~#`> 4x>O`>~߿}o>߿}o_>$XA .dC%NXE5n/_}8`A  70߿| 70|70|'p "Lp!ÆB(q"Ŋ/b̨qcFg ? 4x>} /|70| 70߿| 70,h „ 2l!Ĉ'Rh"ƌ7n/>O@ $?o`O~?~O~O@ DPB >QD-^ĘQF˧ϟ|:*'0|˗ϟ@'_>}70~ױcǎ;vرcǎ;/߾uرcǎ;vرcǎ;n/_>;vرcǎ;vرcǎױcǎ;vرcǎ;vرc|1رcǎ;vرcǎ;6' _ǎ;vرcǎ;vرa| /_>O`|/_~/@߿| <0… :|1ĉ+Z1ƍ;/|߾}o_|?}_>߿}o_;vرcǎ;vرc|ϟ| 70߿~o`>'0| '0|;vرcǎ;vرc| 70|˷_>o| '0| ױcǎ;vرcǎ;vg0@}'0__>ۗO` '0@}'0|;vQGuQGuQG? />˗?}_| ԗ_>O|o`>$XA .dC%NXE5nQbϣG=zѣG=z1B~ѣG=zѣG=z? 4xaB 6tbD)VxcF9vdH#I4yeJ+YtfL3iִygN;y6hPC5ziRK6ujTSVzkV[vlXcɖ5{mZkٶU;;PKkkWDRDPK-AOEBPS/img/adqmg003.gifS0GIF87a?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU, П@ ϟ?'P 'P   7p @'p @'p?'p "L?8П?O@O@ϟ(?(?o@ O@ O@O@ DP!@'p @'p? П@ П@ ϟ?'P 'P    <0A @@ @(?ׯ(?'P ׯ_?'P O@ ׯ_~8`A&D`?(_~(`?(~'P~7P ~'P? O@o@ O@ @,h „ (?'P ׯ_?'P O@ ׯ_~ O@ @ _~ @ `?8`A&4`?(_~(`?(~'P~7P ~'P? O@o@ O@ @,h „'P ׯ_?'P O@ ׯ_~ O@ @ _~ @ `?(_~O@ D0!~'P? O@o@ O@ @@ @(?ׯ(?'P ,h „ 2l!Ĉ'Rh"ƌ7r#ȇ 2$Ddϟ!CBׯ_Ȇ 2b~B&ׯ_Ȑ!!/$C ~B2ׯ_Ȑ!#/dB ~B2ׯ_Ȑ!!/$C 2b~B&ׯ_Ȑ!!/$C ~B2ׯ_Ȑ!#/dB ~B2ׯ_Ȑ!!/$C 2b~B*a| /A~OFB6oa|џ>ۗ?$X!D!B!|/?C!B!B"D(p_|!D|BC!B"Da>}!BC|C!B"D!B! !"D!B"D!‚'_>}'0_?}_>~O|O_ O`>˗ϟ| '0|˧/B"D!B_>_|˗_|߿|_>}(0_˗߿|ۗ/ӧ}oO@ DPBo`| /? _>~˗~߾|1dȐ!C 2/|/~/?/|/?~/_| '0߿}'0| _>ǐ!C ׏?}ۗ}O`_>'0|_||ۗ}/߿|/|cȐ!C /@}/ #_|_߿|? 4xaB 6thp_ '0|׏| '0@/߿|G0|˧| '0| '0Ç>ϟ>O?o`}/| '0| W0| Ǐ_>_ۧ_>/_}>|pao`3` Ǐ_>/=|Ç 'P`߿}o|/߿o@/|O߿|/߿ <0… Ǐ߿|(}o_>}߿|/߿_'P`>o|O㷏_>~'p "Lpa|70| /_|/߿|O`  <0… ׯ~ ̷> /|O`>O__/|/?/| 'P?ϡC0?}O_'0@}_>'0| _ ԗO` O_ ԗ?}/?~)ׯCoa> } g>70?/|ϡC СC)ܗo|/߿|߿|˗?_>}8p_|/|˗@~O`>˧/ ׯ,h „K(0߿}O_|˗@~/߾|ӗO`>/|/@}/_?}/? ԗo_>%_ &L_ 7_|| 7P_}˗|/a„ _„ ׯ_„ &L  '0_‚K0a„K0aBK(| &Lh0_0a„ 0a„ &L0a„0a„0a„ &L0A˗$_ ,X`+X` /_>~ / ,X`A,_~ ,X` <0… :\دÇ>|_~>ׯÇ>|P~>|_>|~=|pa|Ç>|a|˗Ç>|Ä /Ç>|ÇO|>|Ç&̧?}=|Ç>|0>Ç>||/}/_~| O_>Ç>|X0~'p_|˗@~/_~/߿ <0… :|X0~'p_|˗?~/_~ӗo|A"D߾'0?~/|/?~ B"D O߿|o߿||O`>~ۗ}!B"Ć_O`__>~ ܗ}!B"D__}O`?~ '0߿|"D!Blϟ>/˷߿_?~߿|/,h „ 2la|/߿|'0>~7?~O`>}"D0߿|`>ۗO߿/>~_'p "L0? .\(П_ ߾|/_(? 4xaB [pB-/?~O˧}o|߿8`A&TП *|/?}O| /?/?}ӷp… o… oa|O`>||[p…p…0?}O_ '0?} _'P_-\pB[paB-o_>ӗ/'_|˷/~O_|.\p!B-\p?-o_>ӗ/?~/߾|˧/? <0B[p[߾|/_>~| ԗo_'П|-\pB[paB-\0!?.\p[p[paB~-\p…p…p„[p… o… p„p… ׯ… ׯ… ˗… .\8_~ .\_~ .L/_>~ .\p!~-\0~.\p… .4… ׯ… .\B -d@'p "L_ &L0a„ &D,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РB-jԤ?ׯ_Ke_?mٯ?;_~-w~Zh~ׯ} H*\Ȱ?$_~ ,X`W} H*\Ȱ?$_~ ,X`W~ H*\Ȱ!?$(_? ,X`W| H*\Ȑa>~ H~ ,X` ׯ`8`A&T!|8?,X` ׯ_O@ DPB O@W` ,(_~ ? 4xaB .o~6lh_~ kذaÆ _~ 64_5lذaÆ cد oa> 6lذB}װaÃ-aÆ 6\C6lxП5lذaÆ c_Æ aÆ 6\_Æ 6D_Æ 6lP 6lP 6lp!?} 6l`> 6lذB}6lذ!|6lذaÅ5lذaC5lذaÆ kذaÆkذaÆ װaÆ  <0… װaÆ װaÆ .䧯aÆ aÆ 6\_Æ 6D_Æ 6lP 6lP 6lp!?} 6l`> 6lذB}6lذ!|6lذaÅ5lذaC5lذaÆ kذaÂ[_#/_} ˗/_ kPkذA-?/>˗_Æ5LB5lР~װaÆ .䧏a~6l8_~ k_|߿~'P`>'p ˇA}ׯB",_?Ch_|_| OB CР>~!Bׯ!D!B"D?} !B ׯ!4o_}o_| /?_|˗ϟ|˗߾|ChP?!B |̷/> 췯`| /_>O`~o_>!4C!Bp>~"B!B!@'p A+X` _W@'0_| O`|o߾۷O`> ̗/߿|/_ W?,X` ׯ_+Xp|`'0_|o|/~˗_>_+X~ ,X` ׯ`'p "Lp!Å1_Æ oa> /_ +/_|'0| '0|o`>~5B5lР~p_`O`> '0| '0?/_C-ׯ_Æ o>~ 6lذB~aÆ `>_}'P` 70߿| ̗/_>o}8P?$XA .< _>ۧ? o`_| 70}8p'p "LpA}2dȐ!CcȐ!C c/_?_|g0@}/_ 'P_/_~ ǐ!C a|W0|O|o@}o`|1C 2dO? 2dȐaA~2dȐ|7_~˗/ /_>}/?'0@} ̗!A}2dȐ!1ܗo`|˗/_>~7_| /_>˗o߿/O@gРA 4hРAO@ DPB kذaÆkП 5D_Á5lذaC5d_Cǯ@}6lذ!B}6lذaÅ5lذaC5lPaא>~ 6la> 6\aA5$_Æ 6D_Æ 6l 64|6l0_Æ c_Æ 0 .װ!C}װaÃ-ǯaÆ 6\OC6lH_~ kذaÆ _~ 64_5lذaÆ [_ _~ H>~ H*\p!?} װaÁ[_Æ 6lPkذA-aÆ 6\B5lР~װaÆ .䧏a~6l8_~ kذaÆ _~ 64_5lذaÆ [_ ׯB}6lذaÅ1_Æ oa> 6lذB}ׯa0 6lp>~ װaC[_Æ 6l>kذ@-aÆ 6\C6lh_?8|8`A&TB}װaC[_Æ 6l>5lذa|6lذaÅ5lذaC5lذaÆ kذaÆkذaÆ װaÆ 'p "Lp!Æ'p "LpA$XA .d0>$XA .<C 2dȰ ?} 2dpa} H*\pa} H*\x0>$XA .d0>$XA .<C 2dȰ ?} 2dpa> 2dȐ!Â1dȐ!CcȐ!C Ǐ!C 2C 2dȰ ?} 2dpa> 2dȐ!Â1dȐ!CcȐ!C Ǐ!C 2C 2dȰ ?} 2dП? c!C o~2dП? cȐ!C o~2dП1dȐ!C ǰ_? 24_1dȐ!C _~ 2L_1dȐ!C ~8`A&ׯ_B%L0a„ &DO_K0aBK(0 &L0a„K(_~ &L_~ 0a„ &L>~ /a„ /@}&L0a„ "/~%L0A%_„ &L0aB%_ &L_K0a„ &LP0a„ P>~ &L0a„ ӗp`~&LР~ /a„ &L0!B} ׯ_„ &ׯ_B%L0a„ J!O@W` ,X_~ ? 4xaB .䧏a~6lHП5lذaÆ c_Æ 0 6lp>~ kذAװaÆ .䧏? 6lX0 6lp>~ 6L|6lذaÅ5l0 kذaÆ װaÆ װaÆ .ǯaÆ k0 6lp>~ 6LO kذaÆ װaÆ װaÆ .ǯaÆ ˷!|6lذaÅ5l0|kxP 6lp!?} 6l O@ DPB kذaB  ? 4xaB .ǯaÆ ˗/߾kذaÆ װaÆ װaÆ .ǯ?$XA ,(0?$XA .dP8`A O} H@}8`A&TB~6lذ~װaÆ .o~8`A_~ H_> H*\p>~ 0 < O@O@ DPB cد ׯ|6lذaÅ-׏|,h ƒ? ? 4xaB .o~8`A_~ H>~ H*\p!?} װaÁ[_Æ 6lPO@ 40_~ H_> H*\p>~  ~8?}8`A&TB~aÆ0 6lp>~ װ!B @8p|8`A&TB}ׯaC(߿? ? 4xaB .䧏a~6l8_~ kذaÆ _~ "̗/>0 6lp>~ װ!B}g_~ kذaÆ ǰ_? 6lH0 6lp>~ 6L/ kذaÆ װaÄkP 6lp!?} 6l`> 6lذB}6l_Å5lذaÆ kذa~ װaÆ .䧯aÆ aÆ 6\_Æ5l`> 6lذB}6ׯaÆkذjh!O@ DP‚1dȐ!C ǐa|1d0a> 2dȐ!Â1dO_>~ 2LC 2dȰ ?} 2dpa> 2dȐ!Â1TO_|1d0a> 2dȐ!Â1\/_|2dP? 2dȐaA~2dP? cȐ!C Ǐ?˗|2D|2dȐ!CcA~C[C 2dȰ ?} cȐA-!C 2dXP+/_>~ǐA'p 'p "Lp!Å-ׯ_A~_ÆP 6lp!?} װaÁ[_Æ 6lP/_>~'p ׯ,h „ 2\B /߾ HW`_| ,X` ,O_W` ,(_~ ? 4xaB .o~˗oA$XA <0 _~˧ϟA$XAW`| ,X` ,O_W` ,(_~ ? 4xaB .o~˗O? H? ? 4xaB .o~ӗ/_? H? ǯ`߾~˗ϟ@~/_>~O`|/_> ,H` ,XP~ ,h „ 2\C˗OA H <0… П׏ |,h`A}'p ,X|/|ϟ|/~'0߾ $O_+X` ,X|8`A&TB}/>kذ|6laÅ54/_>}װaC5L_O`>o'0| p!?} 6l`> 6lذB}"/~5l`> 6lذB}"/>5lР>~ ˗/@o_>}O`˗/_Å5lذaC5lذaÆ kp_|5l`> 6lذB}*/_>~ 64_Ä_>?}O߿_/߿} O~ 6lذB}ׯaÆP 6lp!?} װaÁ[_Æ 6lPkA-aÆ 6\B5lР~װaÆ .䧏a~6l8_~ kذaÆ _~ 64_5lذaÆ [_ ׯB}6lذaÅ1,h BK(0 &L0a„K(_~ &L_~ 0a„ &L>~ /a„ /@}&L0a„ "/~%L0A /a„ &L0!B}/a„ /|&L0a„ "/@&L0? /a„ &L0!B~/a„ &_B+/_} ˗/_%L/_ƒ%L0a„  |%LП> #`>'p wG0~w`| },OwA~O`>'p_>/_>O@O@ DPƒ1dȐ!C !C P|`>_>ϟ|߿}_>ۗ!A}2dȐ!W_> ߾|o߿|'0|/?;O`|/ ߾1dȐ!CcȐ!C 䧏!C .珡}O`˗/?'0?~o`>'0| ǐ!C `>'0|'0߿|O`>/| O|O| 'P'p "LpA}2dȐ!CcȐ!Ä[C ߿|۷O߿O|o} 70|o`O ׯ,h „K(0 _} 70|70|̷_>o} '0_|P~&L0~ /a„ &L0!B~_„ ׯ_B%$/_? _|g0?˗|O|?~/@%L0aB%_A~/?O~o`>/'0|O`~O~K(_~ &L~8?}8`A&TB~aÆ0 @~Ǐ`>O`| />߿~p>~ װaC[ϟA~/|O|o`>˗@}/|_|˗oA}ׯaÆP 6lp!?} װaÁ[_ÆkX0 o~6lh_~ kذaÆ!A}ׯaÆP 6lp!?} HP`~ ,X`ׯ`,X` /_ ,X?} _ ,X`+X_> H*L/_>o~.\~p… .\p… p… .\O .\`> .\pa| p… o… .\?} .\pa|.\p… p… o… .\>~ .\pA}.\p… ӷp… o… .\>~ .\p|.\p… p… o… .\?} .\pa|.\p… p… -t@'p "Lp!Å5lذaC5lذaÆ kذaÆkذaÆ װaÆ װaÆ .ǯaÆ "ǯaÆ 6\O_Æ oa> 6lذB}װaÃ-aÆ 6\C6lxП5lذaÆ c_Æ oa> 6lذB}ׯaÆ0 6lp>~ װaC[_Æ 6l>kذ@-aÆ 6\B5lР~װaÆ .>~ H~ ,X` ׯ`'p "Lp!Å1_Æ oa> 6lذB}ׯaÆ0 6lp>~ aC[_Æ 6l>kذ@-aÆ 6\B5lР~װaÆ .o~6lh_~ kذaÆ ǰ_? 6_5lذaÆ c_Æ oa> 6lذB}װaC[_Æ 6l>5lذa|6lذaÅ5lذaC5lذaÆ  <0…cȐ!C 䧏!C .!C 2dXP? 2d_> 2dȐ!Â1dȐ!CcȐ!C 䧏!C .!C 2dXP? 2d_> 2dȐ!Â1dȐ!CcȐ!C 䧏!C .!C 2dXP? 2d_> 2dȐ!Â1dȐ!CcȐ!C 䧏!C .!C 2dXP? 2d_> 2dȐ!Â1dȐ!CcȐ!C 䧏!C ,h „ 2\B5lР?װaÆ .o~6lxП5lذaÆ cد ׯ|6lذaÅ-ׯ_Æ oa> 6lذB}ׯaÆP 6lp!?} װaÁ[_Æ 6lPkذA-aÆ 6\B5lР~װaÆ .䧏a~6l8_~ kذaÆ _~ 64_5lذaÆ [_ `?$O?$XA .d>kذ@-aÆ 6\B5lР~װaÆ .o~6lh_~ kذaÆ ǰ_? 6$|6lذaÅ1aÆ[_Æ 6lP?5l? kذaÆ П 6,_Æ 6lP 6l0 6lp>~ 6l>~ 6lذB~6lذ|6lذaÅ5lذaC5lذaÆ kذaÆkذaÆ װaÆ2|8`A&TB}6lذ!|6lذaÅ5lذaC5lذaÆ kذaÆkذaÆ װaÆ װaÆ .ǯaÆ "ǯaÆ 6\O_Æ 64_Æ 6lP 6l0 6lp>~ 6l>~ 6lذB~6lذ~װaÆ .o~6lh_~ kذaÆ _~ 64_5lذaÆ cد ׯ|6lذaÅ-ׯ_Æ oa> H*\p>~ װaC[_Æ 6l>kذ@-aÆ 6\B5lР~װaÆ .o~6lh_~ kذaÆ ǰ_? 6_5lذaÆ [_ ׯ|6lذaÅ-ׯ_Æ o>~ 6lذB~aÆ0 6lp>~ װaC[_Æ 6lPkذA-ǯaÆ 6\O~5lذ!A'p "Lp!Å5lذaC5lذaÆ kذaÆkذaÆ װaÆ װaÆ .ǯaÆ "aÆ 6\_Æ 6D_Æ 6l 6lh0 6lp>~ 6la> 6lذB}6lذ!B}6lذaÅ5lذaC5lذaÆ kذaÆkذaÆ װaÆ װaÆ .䧯aÆ aÆ 6\_Æ 6D_Æ 6lP 6lP 6lp!?} 6ԐA <0… П oa> 6lذB}װaÃ-ǯaÆ 6\OC6lH_~ O@ DPB O@W` ,X_~ ˷ ? 4xaB .? ׯ_ ,X`A,O>$XA .dP>$(_? ,X`W?$XA .dP_?$_~ ,X`W?$XA .dP_?$_~ ,X`W?~ H*\Ȱ>$(_? ,X` <0… :T_Ç>|_~>ׯÇ>|pa~>d_>|B=|_~>|C{~>|Ç !C=|ÇC=|ÇC=|Ç <0… :|1ĉ+Z1ƍ;z2ȑ$K<2ʕ,[| 3̙4kڼ3Ν<{ 4СD5ϟ,ҟ?GYϥ?G[O~ׯ_Ke_;ڲ_?*w~Z(KׯіS_  @   @   @  ׯ,h „+П@ П@ П@ П@ П@ П@ П@ П@ П@ П@ ϟ~'p "L_   @   @   @ ׯ?$XAW`?(~'P ~O@ O@ @ ?(?'P 'P? O@  Hׯ ~'P? O@ @ @(?('P O@ O@ @ `?8`A&ׯ_A @ @(?('P O@ O@ @ `?(`?'P ~O@ Dh_?(?'P 'P? O@ @ @(`?(~'P ~O@ O@  <0~ 'P O@ O@ @ `?(`?'P ~'P? O@ @ @8? 4xaBO@ @ `?(`?'P ~'P? O@ @ @(?('p?$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[Yiծe[qΥ[]y_&\aĉ/fcȑ%7yd_|O@ DPB >QD-^ĘQƇ8`A_߿}o߾߿}o_>$XA .dC%NXE5n|`> 4xA}8p`>70| '0| '0|  <0… :|1ĉ+Z1ƍ8`A 'p`~ H_>o`>O`O`? 4xaB 6tbD)VxcF9ZO~ Hp ?}/ '0_ ?}/|| H*\ȰÇ#JHŋ3jb|A/~/@}/?|o`뗯cǎ;vرcǎ;v_ǎ;vرcǎ;vرcǎ;vرcǎ;vرcǎ˗_DŽcǎ;vرcǎ;v0~:&ϟ>;vرcǎ;vرcdž_70|ۗ/_?O|˗/|˷o`~رcǎ;vرcǎ;/@߾}o߾~_>~/?_o߿ۗ? 4xaB 6tbD)VxcF9v̗/_>~o`>׏| '?~O`cǎ;vرcǎ;v`o`'0|O`>O`:vرcǎ;vرcǎ ?~'P _>?~cǎ;vرcǎ;v`O`>~/|˗_>| /> ױcǎ;vر:ꨣ$(?8`A&TaC!F8bE1fԸcG-/>?~Ǐ?~G8`A&TaC!F8bE1fԸcGA9dI'QTeK/aƔ9fM7qԹgO?:hQG&UiSOFSNԟ|N:uRd><:uԦ/oԩS˗|N_|/?70|˗~7uԩIǏ?$X8_>ۗ_>~߿}_>~߿}8`A&TaC!F8bE1fԸ1#|O@ $O'0| '0| /|  <0… :|1ĉ+Z1ƍ˗A$XA'p| /| '0| '0| H*\ȰÇ#JHŋ3jܸ_| > 4x ?O`>O`>o`>? 4xaB 6tbD)VxcF9/>0|/_>˧ϟ@~/|/_ǎ;vرcǎ;v8_|ױcǎ;vرcǎ;v츑_|uرcǎ;vرcǎ;vܗ_ǎ;vرcǎ;vرcǎ ˗_DŽcǎ;vرcǎ;v0~:&ϟ>;vرcǎ;vرcdž_70|ۗ/_?O|˗/|p߿˗,h „ 2l!Ĉ'Rh"ƌ7rO|O ߾}O`>~/?O>~߿}:vرcǎ;vرcǎO`> '0|O`/| 70|uرcǎ;vرcǎ70| />~O`} '0| 70_ǎ;vرcǎ;v1|O|/?o_>'0|O|uرcGuQGuQGuP>7_| /_>߿~'P_>~ӗ_>O`8`A&TaC!F8bE1fԸcG_>=zѣG=zc| ˧ϟG=zѣG=zc>$XA .dC%NXE5nG!E$YI)UdK1eΤYM9uOA%ZQI.eSQNZUYnWaŎ%[YiծeVe@;;PKYSSPK-AOEBPS/img/adqmg004.gifP GIF87a?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU, П@ ϟ?'P 'P   7p @'p @'p?'p "Lp!ÆB(q"Eg?8?8П?O@O@ϟ(?(?o@ O@ DР? O@o@ O@ @@ @(?ׯ(?'P ׯ_? H*\ȰÇ#JHQ~W`?(~'P~7P ~'P? O@o@ O@ @@  <0A @@ @(?ׯ(?'P ׯ_?'P O@ ׯ_~8`A&TaC!F8B ~'P? O@o@ O@ @@ @(?ׯ(? 4xaB 6tbD)VxcF9vC ~B 2dH 2$~L_!CBׯ_Ȑ!C _?!Cد 2dH 2dȐ!/dȐ2~B _~!C 2~ b~B&ׯ_Ȑ!!/dȐ!Ctد!CB_H1o|!3/_>~_Ȑ!C П? /_G$˗oB!2| /_A~7џ!C 2$ʧ?}'p ! ԧ`>"D!B̧/_?'p>˗|/_~|O`?} 'p_|O`>'_>}8`A&TaC!F8bE_'_|˗?}/| /?W0_˗_|ۗ/ӧ}oh~'0?_>~'0/߿}/? #O`>>O`>~ ǯ_>-ZhѢE-׏?}>'0?~/|O`>~ ǯ_ _߾/߿||O@ DPBO`>o߿~O`>O?`>_>}O`>O`>2dȐ!C 2dȐ!C 2dp`>/ ̷| Ǐ_>O`>`>؏| ̧|O߿|O`~1dȐ!C _o?}/߿_(_'P`>'0|(߿|/߿_'p "Lp!ÆB(q"Ŋ Ǐ?߾|/_߿|/߿(0? ̷_'P/߿|O|8`A&L_?o?}O_>'0||ϟ|/_>O_ _>O>)$_? *TPB *TPB *T(_? OO@} '0߿|ϟ| '0@}+O@}/߿|O@}ӷ_ /~)TP@)ܗo|ӗ`}ۗO`>˗?_>} ˗O_>˧/?|߿|_>}8 A'p "Lp!ÆB(q"E[߾|ӗ/?'_|˷/~O`>˧/}'P_}ϟ| ϟ|˷/|bEUX _~+VXbŊ+ _Ŋ[O`SدWbŊ ϡ~*VXbŊ+Vدo!|U/X_~+VXQ~*VXbŊ+Vد+V_?+:̗O |8`A&TaC!F8bE1f/@~iԨQF_>5jԨQF5jtOӨQF/߿|| /_'_>}˗ϟF5jԨQF _˗ϟ@~/_~O`| ܗ/?5j/?~/||߾|ӨQF5jԨQ|/߾||㗏_ ǯ_OF%(?}/˷߿_?~߿|/,h „ 2l!Ĉ'Rh"|/_>}o؏| /aĈcC'P?߾|/߿o@$XA &o… .\p… .\p…[/߿|O˧?o|/߿8`A&TП? .L__>_ _o… "ׯ… .\p… .\p… oaO_ '0@}_>O_-\pB[paB-o_>ӗ/'_|˷/~O_|.\p!B-\p… .\p… .\p`~/|O | /_'_>}ӗ/ Zh!,h BK0aBK0a„ ׯ,h „ 2l!Ĉ'Rد WbEX_~+˗_Ŋ ׯbŊ+VXbEX_|*Vh_?+ׯbŊ+.bŊ+VXbEXbŊ  <0… :|1ĉ+Z1ƍ;z2ȑ$K<2ʕ,[| 3̙4kڼ3Ν<{ 4СD-ϟ,wQeٯ?;_~GQS_8`A&TaC H~8`A&TaC!F8~- <0… 'p A+X` _O@ DPB O@ <0… :|1ĉO?'p "Lp!C'p +X` _ <0… _~ 6lذaÆ 6lذaÆۗ/>kذaÆ _? 6$|6lذaÅ1aÆ 6lذaÆ 6lؐ?˗o_A6lذaC-aÆ װaÆ .Է? 4xaB 6tbD)J0/,h „ 2d_Æ 6,_Æ 6lP|,h „ 2l!Ĉ'Rx?8`A&T!|6lذa|6lذaÅ8`A&TaC!F8bEO@ DPB kذaÆkذaÆ  <0… :|1ĉ%O|? 4xaB 2aÆ aÆ 6\_Æ 6lذaÆ 6lذaÃ(߿ <0… װaÆ0G_|̗/_~ 0>~ װaÆ 6lذaÆ 6lH_}g_W_|̗/_~ 0a> װaÁ[_'_>W0~6aB}ׯaÆ 6lذaÆ 6lؐ`~C/_7_>G0~6$a|aÆ0˷O~+o`>/_}˗ϟ@~_~o_>'p A,_~ H*\ȰÇ#JHQ`~%a} o`} '0_|˷O`>~/_>˗/_>}0X_~ k/_}+`> ̗/?}/ >O`|PXbŊ+VXQ`~_~ W0|/_>۷_>~_}/߿~a> W~p_`O`> /@_/߿? ǯ`O@ DPB >QD_뗯|̗/_>~o`O`> '0?~ _?+:!|߿~O|o`/_| 7p>}8p>~ܗ/_>~ H*\ȰÇ#JH| (p߿o70߿| ̗/_>o}8_> H*\H0?/?~˗_| ?}O}o`p>~˷_>~ 2dȐ!C 2dȐ!C &a|'G0|O߿|'p@}O`|1$C 2T}|W0|˧߿|'_|/?1$_A~C 2dȐ!C 2dȐ!C c/~ /_|3|_>/_}| ϠA 4hРA3hР4h`> ϠA />8`A&TaC!F8D$X`ASPBS/? *LOB /_>} 'p "Lp!ÆB(q"ň'p "LX0B ?*TP~OB *T0>~˷ |,h „ 2l!Ĉ'R <0… _? 6_5lذaÆ +/_}kذaÆ 6lذaÆ 6$د?5lذaÆ [د ׯ|6lذaÅ/5lذaÆ 6lذaÆ ϟB6lذaC-_Æ oa> 6lذB}˗/߾ 6lذaÆ 6lذaCS/_Æ 6l0kذ@-aÆ 6\}5lذaÆ 6lذaÆ ϟB6lPC 1P> H? ,X` ,/?$XA .dP?5lذaÆ 6lذaÆ 6$/_Æ 6l0 6lX`> 4xaB 6̧? 4xaB 6tbD)VD`> 4xaB 6? 4xaB  <0…  <0… :|1ĉ+" ? 4xaB 2? 4xaB ǐ!C 2,C 2dȐ!C 2dȐ!C ǐ!C 24C 2TC 2dȰ>~ 2dȐ!C 2dȐ!C 2\/C 2d`> 2dП? cȐ!C o~2dȐ!C 2dȐ!C "ϟB2dȐ!C[د? ׯ|2dȐ!C[_? 2dȐ!C 2dȐ!C_> 2dȐ|!C0? 2dȐaA},h „ 2l!Ĉ'Rد?UX|bE-bŊ _~+VXbŊ+ ϟB*VX`> W~WbŊ[_+VXbŊO|+Vh0X? Xbł1bŊ+VXbE-bŊ ПWbŊXbŊ+VX"B*VX`>+V<_Ŋ+ǯbŊ+VXbŊXbEUX`>+VX>~ H*\ȰÇ#JH"B,ZhQ`>-Z$ϟE-ϢE-ZhѢʼnYhѢ|,ZH0?-ZE-ZhѢEhѢEY_~ hѢ-ׯE-ZhѢES/E- oa~,Rׯ|,Zh>~ gѢE-Zha~gѢE[د?0?-ZBYhѢE-Ztد?YhѢ|"E-ϢE_?8`A&TaC!F8~)bŊ _?+oa>+VXPXbŊ+VXQ`~WbŊ[دWbŊXbŊ+VX"B*VX`>+V<_Ŋ+ǯbŊ+VXbE%bŊ WbŃUXbA}*VXbŊ+V/_>~XbEUX`>+VXP+VXbŊ%˗/_~XbEUX`>+VXP+VXbŊ%|| H*\Ȑa> 6lXП5lذaÆ 'p "Lp!ÆB(q"Ŋ/,h „ 2dB5lp~װaÆ .0 <0… :|1ĉ+"/,h „ 2d~5lp~װaÆ .0 <0… :|1ĉ+| H*\Ȑa> װaÁ[_Æ 6lPK/_> 6lذaÆ ̗/_Æ *o|?8`A&T!|aÆ0 6lp>~ 뗐_|6lذaÆ 6$/_ 6Tد߾|W_ 6lؐa> װaÁ[_Æ 6lP?%/ 8`A&T!B$X | HA ׯA~_|_>~엏߿/_|_|/_~ $/_ ̗/_|߿}/o>ϟ|/?O>~߿}wA;x4د;xO`O`} 70|70@~ԗ|-\pƒS/… .\p|o… [… .\p?}/!|-/_| g0|O`O`>O`O` 70@}/|[8|O|'p "L? [p… .B.\p|/_A~W0_|-o!| p?~[`>_> o`_˗|˧ϟ| '0@}O_> /> '`>@$XA .L/A~cȐ?}#`>'p  w/_/?w` ;xP>~/_} HP |߿|8`A&T!A~8 A̧߿8`A&T0|OC0| !C *|~O|ۗO`} /߾'_>}1$Å8`A? 4xaB 0 @$XA .L/_A}߾| /_~˷O`~O`|ۗ/_?/|/0? 2d0?/|'__|/@}_> ߾| p!?$X~O@ DPB'p 7? 4xaB W0~'0 ߾}/|o_> w0~_>~_}cȐ!C c(p_`>O`?~ Ǐ_>O`?~ 70C1dП 'p`>~? ,0@8`ϠA ? 07? 4xaB W0~o`>o`>_?~ w0|o`CC "ׯ| O}߾}//}O`/| 8p 8P~8`A(7p  $?}~;} 70߿|;/w |엯}_|3|O`>O` | A~/@_|$Ow~ԗ_>O|/|˗_K(_~ ̷/a>  g0|/|/|o|˗0!?} /a„ &L_~ | ԗ_> '_|70||` /_>˷a> /a„ /|&L_„%L0!A} ׯ_„ 0|'0@_߿|/߿߿8`'p "Lp!CS/_Æ 6| _? 6_5lР|6l(PkPa> 3o``>O`䧯aÆ 6dد?5lذaCא`> װakذaÆ װaÅ5<`>o`>_>>kX 6lذ!C6lذ| װaÆ װaÆ .ǯaÆ kx0A~/|O|_|߿8`'p "Lp!Æ sСC СCsСC СC9tСC9tСC СCϡCСCϡCsСC sСCϡC:4ϟC:ϡC:,CСCСC:,/C:th0?:|:tСÂ1ϡC'p "Lp!C'p "Lp!C-aÆ 6dB5lp~װaÆ .o~6TP <0… O@ DPB _ 6lؐa> װaÁ[_Æ 6lPkذaÆ 6lذaÆ 6$د?5lذaÆ [د ׯ|6lذaÅ-ׯ_Æ 6lذaÆ 6lذ!~)aÆ 6d~5lp~װaÆ .o~6lذaÆ 6lذaÆ O| 6lذ!|aÆ0 6lp>~ kذaÆ 6lذa 6$د?'p "Lp!C-_Æ aÆ 6\_Æ 6lذaÆ 6lذaÆkذaÆ װaÆ װaÆ .ǯaÆ 6lذaÆ 6lذaÂ5lذaÆ kذaÆkذaÆ p 6lذaÆ 6lذaÆkذaÆ װaÆ װaÆ .O|5lذaÆ 6lذaÆ 6$/_Æ 6l0 6lX0 6lp>~/ 6lذaÆ 6lذaÆ <0… װaÆ0 6lp>~˷O`} 6lذaÆ 6lذaÆ_ 6lؐa> װaÁ[_Æ 6lP?G0>$XA .dC%N(p߾} O@ DPB [د ׯ|6lذaÅ />8`A&TaC!F8b|8`A&T!|aÆ0 6lp>~ǯaÆ 6lذaÆ 6lذaC6lذaC-_Æ oa> 6lذB}˗OA$(П?$XA .dC1bD'p "Lp!C-_Æ 0 6lp>~˷`>} 80?8`A&TaC_>!2ܷo| H*\Ȑa> kذaÂ5lذaÆ 3/_>~Kϟ| 6lذaÆ | 6l| 6lذ!|6lذa|6lذaÅ!ܗ/|/_C H*\!,h|;x~/'p "Lp!C HA ׯA;x|~ |;x| _'0_| //_>_/_||_|? 4H_ 2dȐ|2dȐ|2dȐ!Cc0?/a> 70>~O} '0| '0|O`_ӧ_| /C 2d_> 2dȐ|2dȐ|2dȐ!Cc0?˗/70|o`>O~o`>| 'P_70@~˗/_>㗏!C 2/C 2d`>8`A&T`> 2dȐ!Â1\ϟ|_>~ 3o`_˗|˧ϟ| '0@}O_> /> '>_>㗏!C 2/C 2d`> 2dPa> 2dȐ!Â1\ϟ|˷o`>~ cȐ!C GП| 䗏|cȐ!C ǐ!C 24C &oa> 2dȐ!Â1/a> /߾ HP?$XA .dH>׏ ?$X| H*,B.\p… П? .L_'p "Lp!Å'p +H0?˗O8|8`A&T!A~˗A$X| H*,د?'p "Lp!C'p +X` _'p "Lp!Æ'p +H0?˗_ H_> H`A  ϟ> 4h?}˷?$X| H*,د?8`A&TaC} HP`~ ,X`? 4xaB 6t_~ ӗo?}#0O@ 3hРϠA o |>  <0‚[p… .\`~.\_~ .\p… ׯ_B~+O_|0 70߿|'_|˗_>70_|-}K„ _>~|O>~߿}|˷p… .… .\p…p… .\p… .\@?G A˗O|70| '0| 70A 䧏  <0… :|1ĉ+Z1ƍ0? _+O`>o`>)/G9rȑ#G9r/a>| '0?'0@}'0|c#G9rȑ#G9r,|/߿| /?'_| 70D~8rȑ#G9rȑ#Gq䨑>9rȑ#GǑ#Ga>9j䧏#GǑ#Gѡ~8rq~8",h „ 2$O_Æ 6lȰ_? 6lذaÆ װaÁkذaÆ 6\_ װaÆ 䧯aÆ 6dد 6lذaÅkذ@O@O@ O@O@O@ O@O@O@ O@O@_~8`A'p "Lp!Ã8`A&T!~O@ O@O@O@ O@O@O@ O@O@O@ ϟ~'p "4_ @(?('P O@ O@ @ `?(`?'P ~'P?O@ DП <0… 'p "Lp!Æ#`?(`?'P ~'P? O@ @ @(?('P O@ O@ H ~'P? O@ @ @(?('P O@ O@ @ `?8`A&TaC!F8~ O@ O@ @ `?(`?'P ~'P? O@ @ @(?8,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РB-j(ҤJ2m)ԨRRj*֬Zr+ذbǒ-k,ڴjײm-ܸrҭk.޼z/.l0Ċ3n1ȒWp`> ,X | H*\ȰÇ#JHŋ3j@},hA? 7߾/_>O| 70|_>}'p "Lp!ÆB(q"Ŋ/b̨qC HO/| ߾}o߿| ߾|/,h „ 2l!Ĉ'Rh"ƌ7>0 <Р> 80O`>o`o`O@ DPB >QD-^ĘQF H80_?$/70| '0| '0|  <0… :|1ĉ+Z1ƍ-'P`?$8>?~?~O`_>$XA .dC%NXE5nh1_| ˗O_?O|˗ϟ@_>} 70߿~ױcǎ;vرcǎ;Zǯcǎ;vرcǎ;vرcǎ;vرcǎ;vرcNjcBױcǎ;vرcǎ;vlO`?}O;vرcǎ;vرc| /?_|˗~'p_|˗_>70_|uرcǎ;vرcǎ O |o߾o_|/ϟ|/߿۷߿| <0… :|1ĉ+Z1ƍ;˗/? 70|Ǐ_>؏| '0| ױcǎ;vرcǎ;vg0| 70߿|o`>'0| '0|;vرcǎ;vرc| ?}O߿|߿}/| ?} ױcǎ;vرcǎ;vg0@'0|ӗ_>/@}O_>˗O?رcǎ;vQGuQG? | H*\ȰÇ#JHŋ3jȱG˗O?~Ǐ?~| H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJMԩSNmO_>SN:u?}w2|M:uj}|y7uԩKo`>' /_~˗ϟ@o`O`|:uԤG|,h`A} /|/ ߾} / ߾| H*\ȰÇ#JHŋ3jܘ_|'p ܧ?o`o`>o`>O@ DPB >QD-^ĘQƌ @~,h A}8_>o`>o`o`>$XA .dC%NXE5n/_>}P 뗯cǎ;vرcǎ;v/_}رcǎ;vرcǎ;v/_|:vرcǎ;vرcǎ;cǎ;vرcǎ;vرcdžׯcBױcǎ;vرcǎ;vlO`?}O;vرcǎ;vرc| /?_|˗~'p_|˗_>߿? 4xaB 6tbD)VxcF9v'_>߿}o߾~'0ϟ| 'P ߾|;vرcǎ;vرc|'0?o`'0|O`>O`:vرcǎ;vرcǎ o`>o| '0>~O`cǎ;vرcǎ;v`O`~|/|O`>O`:vر:ꨣ:ꨣ:(/_>}/_|/|/@'0| H*\ȰÇ#JHŋ3jȱ| /G=zѣG=zcϣG=zѣG=z1,h „ 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РB-j(ҤJ2m)ԨRRj*֬Zr+ذbǒ-k,ڴjײm2 ;;PK:PPPK-AOEBPS/img/adque037.gif5GIF87a@?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU,@ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜM4i|}'P @},h „ 2l`>Ǐ? H*\ȰÇ#J?}ϟ?)RП?~˧?)RH"E"E)R<؏_>})RH"E G"E)6ܗE)RH"EQH"E G"E)RHQ?})RHbC~QH"E)ROE)Rؐ_|)RH"EG"E)6/E)RH"EQH"E G"E)RHQ?})RHbC~QH"E)ROE)Rؐ_|)RH"E ?} H*\ȰÇ "D!B"DAxkO`? | B"D!BhП> ӧa>~AH_|!B"D!B4ODO|/_>}߾| /߾| ̧/?@~A"D!BѠ?}!_}O߿|/| '| ̷}/_A@~A"D!BѠ?8`Aӗ/_| /| ̗}O`|'0_A}˗0aBO@ DPB >QB&J7p_>O`|o`>ӷO ?} W0}&>/ĉ'N8qąM@˗o|O`>_|o߿|˷O`>7_7qĉ'N8q?}'W0ĉ'/ĉ'N8qąMh0_|'Nh_|'N8qĉ7qĉ'N/ĉ'N8qąM8qĉ7qĉ'N8q?}'Nh&_| H*\ȰÇ#J\Oĉ'N8_|'N8qĉ7qĉ'N/ĉ'N8qąM8qĉ7qĉ'N8q?}'N8qD~M8qĉ'N\Oĉ'N8_|'N8qĉ7qĉ'N/ĉ'N8qąM8qĉ7qĉ'N8q|'N8qD}M8qĉ'Nd/߾~'N8qb~˗oĉ'N8qb~ӷ?&N8qbD`>O@ DPB >QC~ H @},h „ 2lx`> ,h „ 2l!Ĉ'o>$XA .d!C} <0… :|1ĉ 8`A&$`>O@ DP ,h „ 2l!Ĉ'Rh1a?? 4xaB 6tbD)Vxc~ 8,h „ 2l!Ĉ'Rh"Ƅ8p?$XA .dC%NXE 'p@ H*\ȰÇ#JHŋO8`A&TaC!F8bE1&0'p "Lp!ÆB(q"Ŋ/bL`>O@ DPB >QD-^Ę| <0… :|1ĉ+Z1a?? 4xaB 6tbD)Vxc~ 8,h „ 2l!Ĉ'Rh"Ƅ8p?$XA .dC%NXE 'p@ H*\ȰÇ#JHŋO8`A&TaC!F8bE1&0'p "Lp!ÆB(q"Ŋ/bL`>O@ DPB >QD-^Ę| <0… :|1ĉ+Z1a?? 4xaB 6tbD)Vxc~ 8,h „ 2l!Ĉ'Rh"Ƅ8p?$XA .dC%NXE 'p@ H*\ȰÇ#JHŋO8`A&TaC!F8bE1&0'p "Lp!ÆB(q"Ŋ/bL`>O@ DPB >QD-^Ę| <0… :|1ĉ+Z1a?? 4xaB 6tbD)Vxc~ 8,h „ 2l!Ĉ'Rh"Ƅ8p?$XA .dC%NXE 'p@ H*\ȰÇ#JHŋO8`A&TaC!F8bE1&0'p "Lp!ÆB(q"Ŋ'P>$XA'p@ H*\ȰÇ#JHE.Z0'p "Lp!ÆB(q"Ŋ3O_>~˧O`>˗O| ܗ/8p?$XA .dC%NXѢB /_>~/߿߾}o8`A&TaC!F8bE '0߿| '0?߿|߿~ <0… :|1ĉ+ZT`>'0|~/߿|G| <0… :|1ĉ+ZT0@/?o ߾?'p@ H*\ȰÇ#JHŋa,`>O@ DPB >QD-^c~ 8,h „ 2l!Ĉ'Rh"Ƅ8p?$XA .dC%NXE 'p@ H*\ȰÇ#JHŋO@ O@ DPB >QD-^0  <0… :|1ĉ+Z`> $ <0… :|1ĉ+Z?$XP ,h „ 2l!Ĉ'Rh"Ɓ8`A H*\ȰÇ#JHŋ O@'p "Lp!ÆB(q"Ŋ/b4`>  <0… :|1ĉ+Z>? 4xaB 6tbD)VxB} O,h „ 2l!Ĉ'Rh"F(P,h „ 2l!Ĉ'Rh"F˧/cƌ3f̘1cƌ!˗/cƌ3f̘1cƌ#/cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1cƌ3f̘1} H*4 <0… :|1ĉ+Z,/~,h „  <0… :|1ĉ+Z,/ŋ x/^xbA}.^d/ŋ/^xŋ w"}.^xŋ/^XP_wŋ/^xł]p_/^xŋ/ԗE]xŋ/^x|/2ܗŋ/^xŋx|/^xŋ/^,/ŋ xŋ/^xbA}8`A&T80_>$XA .dC%NXb|8`A&T80_>$XA .dC%NXbA}.^d/ŋ/^xŋ W? 4xa /,h „ 2l!Ĉ'Rh|8`A&@'p "Lp!ÆB(q"Ŋ W? 4xa /,h „ 2l!Ĉ'Rh|8`A&@'p "Lp!ÆB(q"Ŋ W? 4xa /,h „ 2l!Ĉ'Rh|8`A&@'p "Lp!ÆB(q"Ŋ W? 4xa /,h „ 2l!Ĉ'Rh|/2ܗŋ/^xŋO@ DP|8`A&TaC!F8bEO@ DP|8`A&TaC!F8bEx|/^x/^,/_A$XA 'P| H*\ȰÇ#JHłO@ Dp  <0… :|1ĉ+Z,/_A$XA 'P| H*\ȰÇ#JHłO@ Dp  <0… :|1ĉ+Z,/_A$XA 'P| H*\ȰÇ#JHłO@ Dp  <0… :|1ĉ+Z,/_A$XA 'P| H*\ȰÇ#JHł]p_/^xŋ/ԗE]xŋ/^x>$XA O@ DPB >QD-ԗE]xŋ/^x|/2ܗŋ/^xŋ+П <0@ ܗ? 4xaB 6tbD)VXP_ HO}8`A&TaC!F8bE+П <0@ ܗ? 4xaB 6tbD)VXP_ HO}8`A&TaC!F8bE+П <0@ ܗ? 4xaB 6tbD)VXP_ HO}8`A&TaC!F8bEx|/^xŋ/^,/ŋ xŋ/^xb}8`A&T80_>$XA .dC%NXbA~.^dOŋ/^xŋ w"C~.^xŋ/^X> aCO"?}/^xŋ/^,O|ˇ0߿|!'/^xŋ/Oa}'0|˧_>_א/^xŋ/Oa>O`>O`>_}ǐ/^xŋ/OaO`>O`>08@~8`A&TaC!F8bES?~|'0|/_>~cOŋ/^xŋ ӧ0|/_|ӷ_>'0?}kOŋ/^xŋ wQaxŋ/^xbA~.*w?}/^xŋ/^,O}w?~.^xŋ/^X ]xŋ/^x ?}O| ̧/?/|˷_>~˧O`>}?} H*\ȰÇ#JHłgp?_>O`>_ ܷ_~xŋ/^xbA~ #_>O ?}'0| `>O@~8`A&TaC!F8bE+o@'ϟ|O`>~3Oŋ/^xŋ gp_|/_} _|ۗ/_>?} ?}/^xŋ/^,Oŋ xŋ/^xbA~.^dOŋ/^xŋ ߾|/^xŋ/䧏|C~.^xŋ/^X>O`>˗O| ܗ/>O@ DPB >QD-䧏a>>~O` ܷ!?}/^xŋ/^,O| O` /߿  <0… :|1ĉ+Z,O~o?/?_ !?}/^xŋ/^,O_~˗}O_|˗/?琟/^xŋ/oxŋ/^xbA~.^dOŋ/^xŋ w"C~.^xŋ/^Xwŋ/^xł]Ȑ/^xŋ/> 4xaBO@ DPB >QD-Ǐ} 8 ? 4xР>ȏ~ H*\Ȱ#JHń8p ,h} 8? 4xaB 6tbD)Vذ|O@ 4`>'p "Lp!ÆB(q"ŊO H'p@$XA .dC%NXb~ 8? 4x> <0… :|1ĉ+Zl`>'p 08`A&TaC!F8bE 'p@$XA8p ,h „ 2l!Ĉ'Rha? QD-608`A O H*\ȰÇ#JHņ8p ,h} 8? 4xaB 6tbD)Vذ|O@ 4`>'p "Lp!ÆB(q"ŊO H'p@$XA .dC%NXb~ 8? 4x> <0… :|1ĉ+Zl`>'p 08`A&TaC!F8bE 'p@$XA8p ,h „ 2l!Ĉ'Rha? QD-608`A O H*\ȰÇ#JHņ8p ,h} 8? 4xaB 6tbD)Vذ|O@ 4`>'p "Lp!ÆB(q"ŊO H'p@$XA .dC%NXb~ 8? 4x> <0… :|1ĉ+Zl`>'p 08`A&TaC!F8bE 'p@$XA8p ,h „ 2l!Ĉ'Rha? QD-608`A O H*\ȰÇ#JHņ8p ,h} 8? 4xaB 6tbD)V|O@ 4`>'p "Lp!ÆB(q"ŊO H'p@$XA .dC%NXb~ 8? 4x> <0… :|1ĉ+Zl`>'p 08`A&TaC!F8bE 'p@$XA8p ,h „ 2l!Ĉ'Rha? QD-608`A O H*\ȰÇ#JHņ8p ,h} 8? 4xaB 6tbD)"̗/_>~+08`A O 80_|'p "Lp!ÆB(q|HQ`? /_>}'p@$XA8p G0}/_>} 'p_|O|'p "Lp!ÆB0|o>~ '0߿}/|o_~ 8? 4x>o?'0|O} o?'p "Lp!ÆB0|80߿߿| ߿| O~ 8? 4x>`>/߿@$XA .dCo߿|󧏟|_>~|_~ 8? 4x> ܷ_>~O`>/?_ ? 4xaB 6tbĆ˷O?}O_|˗/?'p_|ӗ/>8p ,h} 8?˗/>˧?}/_|˗O}O_|8`A&TaC!F0ą8p ,h} 8? 4X0,h „ 2l!Ĉ'JGQa? 'p`?$X }'p A <0… :|1ĉ+Z0 O@ 0  <0… :|1ĉ+Z`> $ `> ? 4xaB 6tbD)VH|,(,h>$XP ,h „ 2l!Ĉ'Rh>$X,hР>$X,h „ 2l!Ĉ'Rh>$8,h?} Hp`?$XA .dC%NXbB} H0>$X HP ?$XA .dC%NXB$? 4x?$? 4xaB 6tbD)V`>O@ 4`>O@ DPB >QD-:08`AO@} H*\ȰÇ#JHE(? 4x@~˧? 4xaB 6tbD)V(_|]/_|/^xŋ/^/_wŋ/^xŊ.^xŋ/^xŋ/^xŋ <0… :ϟ? HAO@ DPB ϟ?$XA  O_|@8`A&TaÂ8P>}ǯ?$H?}ӧO@~'p "Lp!Æ8P>}',h „˷? *TPB *>}CO_}SPB *TPB˷ϟB ԧϟB *TPB *䗏A})TPB *TP~)TP| *TPB *Tp`| SPB *TPBӧPB)TPB *TP+OB *TPB /? *̧PB *TPB ˗`> *TPB *T8_|*T0B *TPB *`| ? 4xaB 6t|A0D!BbA"D!BX_| BD"D!B| "D!B,/_>!""D!BX_|A"D!/?"D!B,/_ B"D ˗DA"D!/_|!B"D"D B<|5'"D+"ă='_CA/_>} B/_>!"~A_|A0߿'p /_|"Dh>}a|!DO~"DP|!D!|"Dh0߿|˗OO`˗@~/˗o|3o`>"/_"D` ԗ/>˧߿|ۗ/?O_>}ۗ/>W0"DP|!D!|"DX߾ ?}O|'p@~ '0>~߿|(? 4xР| C!‚O`>?~o?O`>O߿|+!B˗B"̇!B˗/|70|+o߾}/| g0~"D| C!‚˗O`_>o߾| ̗`+`?"D_|"Da>",o>~O߿|'0߿| /| ̧o@~`!D? <__?}O߿|'p߿| '0}O` /a„/a„ K0a}/_|˗o|ӗ/ӧo?}/_} g0_|K0A̗0a„ _| ̗/>/_>~˧O߾o_||K0AK0aB&La&L0a„ /_| &L0_| &L0a„ ˗_„ ? 4x!|%L0a„ &/_&La&L0a„ / &$/a„ &L0a„ &!B"Ă+"D!B|A0D!BbA"D!BX_| BD"D!B| "D!B,/_>!""D!BX_|A"D!/?"D!B,/_ B"D ˗D"D!BO_|"D!BO_| BL/>~ B"D 0@ />~8`A&TaC`>'p "4`>Ǐ?$XA .dС~ۧO| ?O@}? 4xaB 6t(?~O8`A&`> 4xaB 6t~ HP`} H*\ȰÇ <0AۧO>$XA .da>},hП?~ӧ`> 4xaB 6tO>}? 4xaB 6tbD)VxcF9vdH#I4yeJ+YtfL3iִygN;yhPC ;;PKuD55PK-AOEBPS/img/adque448.gif|+GIF87aXL?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU,XL H*\ȰÇ#JHŋ3jȱǏ CI?O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@O@O@ O@$XA .dC%N(П? 'P   7p @'p @'p? П@ П@ ϟ?'P 'P   7p @'p @'p? П@ П@ ϟ?'P 'P   7p @'p @'p? П@ П@ ϟ?'P ,h „ 2l!Ĉ'R? 4xaB 6tbD)VxcF9vdH#I4yeJ+YtfL3iִygN;yhPC5ziRK6ujԠJ| e'П>̇0TRu*?%̗1@EG0|RJOT'0_|˗/_| /߿}/_> />ׯ`>O`>~*U~R`>ۗO`/ ̗/_|o`>p߿|@ /߿߿}8`A&TaC!F8bE1È#F1b| '0|70|/| 70߿|G0߿| 70F1bĈ#F12#F1bĈ`>o`|70|O`_ #_#F1bĈ#F1bĈ#F1J'0| 'P_?}'0|o`>_ #_>?~0bĈ#F1bĈ#F1bĈ|'_>/_}/|/O|O|'P`O`>~O@ DPB >QD-^ĘQF=~ٰ 2dȐ!C 2dȐ!C _| 2dȐ!C 2dȐ!C 2dȐ!C 2~!C 2CB 2dȐ!C i_Ȑ!C П!C 2dȐ!CZ2dȐ!C:/dȐ!C 2dȐ 2dȐ 2dȐ!C 2~!C 2CB 2dȐ!C 2dȐ8`A&TP ,h „ 2l!@,h „ 2T $П <0…8`A&TaC 8`A&TP ,h „8`A&TP ?$XРA} H*<? 4H`> 4xaB * `> 4xaB O@ O@ DP!B$XA~ H*\(? 4xaB)TPBS} H*,,h`>~4~ ,X | ,_ ? 4xaB pa>1/_}2L/B Gp_> ԧ`> !C #/@}O߿|/C C ߿~!W_>ǐa|2|c80?1d0C1\C 2LÅǰ_>ǐ!BcX>/ǐ!Ã1dpa>OcȐ@}p>~o߿|˗/ p߿|߿/? 4H0?/_} /_| /_~/}_|˧_ wAw|;xp ?}O_?/?,| _>@|70|'0|O`o|ۗO`>~O@ gР4hРA 4hp>~ ,ϟo_ o`'0|Ϡ@ g`A~ o?~ >۷ϠA /A 4h`>0@_8`A/?o`O` o`o`>#_„#0@߿|/߿_/߿_?~߿߿| H`| 4XP? 4hРA ϠA3/|W0߿|'0| '0A$Ϡܧo?~O`>3hРAgРA ,|'0@~ 4hР$@~|/|_} 70߿|o`>G0?gp`> O`O`>O`/| 70Ag ?} ϠAdAdAO_O` ߾}_| 70|+8__AO?/_| W` $/_ ,X`AO>}/߿}W` $_˗o_ O`|_> _|_/ 'P_,HP_| `>O`>O>~#| 'P_,X`> `>} O?׏ A $H@G A#Hp |$?~˗߿|o@}_>Gp| $/_|䧏|7p@}> $H AO@ DP`>˷o`_~)T0>~ ˗/_}#/_>}˧_>#/_| O߿|˷O |/_}SHP_|+|/_>}˧_>'0|/A}/|/B)/_|Ǐ`>)TaSxP?˗/?'0|˗/_| O߿|˷| 'P`? o@}7_|/?$XAK0a„K0a„  Է? 0O?$X!D`~ H>߿|8`A | &Lh0_?$(p|>~߿/?/?߿~o~?~o@`>_> HA .\P>$X A~ <0‚ HA 

?}_?}_>~?}_> H*$`> 4XP'p "LP| .\80 .\P|,h>O@ DPaA$X A}O@ DPB8`A߿߿߿|?~߿|/߿_/߿/?$XA 0 4?} H*T/… 篠|ϟ> OO@'p`~? P7p 8P`} H |߿|`>~ HA;xAw|8@} ߿_>70| />~O`} '0| 70'p A~80 'p  ?O@}_>$@̷߿'p|8p|7p /,h „+/_~ O?ϟƒ)o ? @ 8p@}'P@ 7P ?~ӧO8p@(߿8`A;x|w|0@O>_ ߾|O`>>O 0@(0o}(p_ @7p@ ?8_|8p`8po? 4xaB̷/߾_>~O`>'p_|˗_>70_|O?˗A}gP OA}8?G A׏| 70_|O`~/_>~| /߿|뗏}/_>˗o|G0? ˗/?#|˧ϟ|O_>~/_|?}/_>}>~ /_>~G A 'PAG?}'p 7p̗/>7p`} /_>˗߿| /?/_|/_}˗'p "L(0?ۗo`>~߿}O`>~ϟ| 'P ߾|S@~%O!A}wP?}#PF'P`>(P_>~ o|_> ߾|߿|o߿|_>~ ϟ| 'P ߾|7p8P>~8p('p  @~!B O~3ȏA7߿O@ A/_}o>۷_>/_~'0|o߿|G_>$XA Gp_o`O`>؏| '0| GP? >~8p ~8p 8"_ +X0 o`?~ 70߿| 70|O`>/| 70|`A ǯ`+X|+X`+X🿂W?'p N 8> 'p /GP`?G߾|/| /| '?~O`| H |/߿߿|/߿(0>~O`o?}ϟ@ 8`? O@ 8 @}/_O@ `/|/>_o`} '0| 70|<(Pw+П8`'p8|? #H 0@_/߿|//| 70߿| /,h „/_? ?}O| _>~O`>>#B+П8`?$p'p/?$X | ` 70?} 7P_70| _>?~`>8p ~8 @}/߿'p G_~?~ϟ|/| ?} G_/__>~O`>'P_>~ӗ_>O`wA<>> o $ϟ|ԗ_> _|/_>}O`>/'_| 70|<(P oĿ  '_|/O|o`>g? #H A <0… P>~ 6lؐ>~ >gp_? G>8_>$XA~g0<8_ +$ w>3OO@A $/?$XA .dx0 kذaÆk0Oǯ ?~ӧ|  䧏a>6lh_ "a6lxP > ?}O@} 8_> HA 4xaB * 0 <0…'p 'p "L!G A'p "Lp@$XA 'p "Lp~ H? O@ DPA~ H H*\0a?$X@$XA .,? 48? 4xaB'p ~ $(? 4xaB O@ DPB >4D!B"D!B"D!B~!B"D!B? H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8st/_|۹sΝ;w/_>$?۹sΝ;w?}$o`?'_|O?~۹sΝ;wN1~˷O | 㷓>} ߾} _'0?vܹsN0|o@}}ɱ?}70_>_oΝ;GO@ O_~ ̗`o ?}8`A"ϟ  @ @  @ @  @ @  @   @   @   @   @   @   @   @   @ ? 48@/|`>8`A&T!|/'p맏@~6lhП?  7p @'p @'p? П@ П@ ϟ?'P 'P   7p @'p @'p? П@ П@ ϟ?'P 'P   7p @'p @'p? @ П@ ϟ?'P 'P 'P ,hp`~?~߿|O ?~O`ۗ/>$XA .dC%NXE5n"|/_|˗|/_>}=z$ϣG=zѣG=z`>=bѣG=zѣG=zH0,h „` 2l!Ĉ'Rh"ƌ7r#Ȑ"G,i$ʔ*Wl%̘2gҬi&Μ:w'РB-j(ҤJ2m)ԨRRj*֬Zr;;PK&+|+PK-AOEBPS/img/adque041.giffEGIF87aP?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU,P H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8siП?~O@ DPB Ǐ_? H*\ȰÇ#JH`?~˧O@~O@ DPB O@}˧o? H*\ȰÇ#J8q_|H"Eۗ/>)RH"E)o?)RH}QH"E)R8p?)RH1a|(RH"E)RE)R0_>)RH"EG"E)*̗E)RH"EH"E"E)RH"QH"E G"E)RH?}(RH"EH"E)RH>)RH|QH"E)RO?{'Q?$XO@ DPB >QąQ/߾kO`0_>)RH"E)bD} ̧/>'0߿|O |ӗO߿|O`>}/ŇH"E)RH>#|/_/}| o@}/|0_>)RH"E)"D~'0| /߿|_>G0߿|}"E)RH"'p "O/߿|/? O~/o@ O@ 4/?$XA .dC%N\Ň _>?~O>/|'p#O}(6̗E)RH"Ep_˗/?'0߿||O˗|o`?}"E)RH"Q80_|)R/?)RH"EG|QHb|(RH"E)RE)R0_>)RH"E)"EQH`|(RH"E(? 4xaB -\pB[p… .\p… .\p> .\(0|Ǐ_|˧/| /_'0>~ .T/ .\p… .\p… p…o߿|߾}O`>o… p… .\p… .\p@}.\P``| '0߿|O߿| .\/_> .\p… .\p… o… _| /@ /,h „O@ DPB >QąQh0o>_>O>߿|)̗E)RH"EH`| 'p_|˗/}O_|˗O|)̗E)RH"EH`>)R/?)RH"EG|)R80_>)RH"E)"E)RT/?)RH"EG"E)*̗E)RH"EH"E"E)RH"'p "Lp!Æ*̗D!B"D!&"D!BQ`| B"D!B1>}!B"D"D!B"D˷D!Bqa}"D!B"D˗/}"DǏ>̷? 4xaB 6tbDO@8`A&TaÅ H> H*\ȰÇ#J8>} H*\ȰÆO@ DPB >QDO@~ H'p@$XA8? H*\ȰÇ#JHE8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ308`A&TaC!F8bE1f`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD-^Ę? <0… :|1ĉ+Z1? 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ308`A&TaC!F8bE1f`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD-^Ę? <0… :|1ĉ+Z1? 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ308`A&TaC!F8bE1f`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD-^Ę? <0… :|1ĉ+Z1? 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ308`A&TaC!F8bE1f`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD-^Ę? <0… :|1ĉ+Z1? 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ(,h 8p ,h „ 2l!Ĉ'Rhb|)O H*\ȰÇ#JHŋ̧/_?'0|O`>˗A 8? 4xaB 6tbD)Vx`>o߾ '0?~/|@ 8? 4xaB 6tbD)Vx |߿|/߿/߿߿|8p ,h „ 2l!Ĉ'Rhb| /| `>/߿o H*\ȰÇ#JHŋ'0߿}'0߿~'O? 08`A&TaC!F8bE 'P ˧/߿o_>}'P߿8p ,h „ 2l!Ĉ'Rhb| O H*\ȰÇ#JHŋa$`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD-^Ę? <0… :|1ĉ+Z1? 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ)O@ 'p "Lp!ÆB(q"Ŋ/b|`> $? 4xaB 6tbD)Vx#D$X ,h „ 2l!Ĉ'Rh"ƈ8`A8`A&TaC!F8bE1J0 O@ DPB >QD-^H`>  <0… :|1ĉ+Z?$8? 4xaB 6tbD)VxE~ H0?$XA .dC%NXE'p} H*\ȰÇ#JHŋ3O@8`A&TaC!F8bE1f`>'p "Lp!ÆB(q"Ŋ/bHp|O@ DPB >QD-^Ę|ӨQF5jԨQFӨQF5jԨQƊiԨQF5jԨQF5jԨQF5FO@ DPaA$XA .dC%NX|.^\ŋ/^xŋxqa/^xŋ/^Ņ.^xŋ/^x1xŋ/^x|.^\ŋ/^xŋxqa/^xŋ/^Ņ.^xŋ/^x1xŋ/^x|.^\ŋ/^xŋxqa/^xŋ/^Ņ.^xŋ/^x1xŋ/^x|.^\ŋ/^xŋ.(?$XA   <0… :|1ĉ+Zŋ ]xŋ/^xb>/.wŋ/^xŋ]0ŋ/^xŋ/w|/^xŋ/^ŋ ]xŋ/^xb>/.wŋ/^xŋ]0ŋ/^xŋ/w|/^xŋ/^ŋ ]xŋ/^xb>/.wŋ/^xŋ]0ŋ/^xŋ/'p "L ,h? O?$XA .dC%NH1_W1aS/_>~+VXbŊ+ׯbEU̧/>'_|/?}'0}UXbŊ+Vh0_ HO@8p۷_>~O>~O`o~8`A&TaC!F8| 'p "L?8p_>/߿| '0?~ ̗/_?$XA .dC%NX0_ HO@8pO`/| /O@ DPB >QD+П <0ӧ/@},?Ǐ߿|۷O>~ '0~ o@8`A&TaC!F8b| 'p "L?8p˗| ܗ/?O| ̗/>$XA .dC%Nh0_ HO@8p8`A'p "Lp!ÆB(q"EO@ D7p $/_?$XA .dC%N1_ HO@8`A&TaC!F8bExQ|/^xŋ/^ŋ xŋ/^xE$XA O@ DPB >QD-^E]4菟Bxŋ/^x1_w`[/ŋ/^xEO@ D7p̧/>'_|/?}'0O@ DPB >QD+П <0? o߿}/?~/o߿~ <0… :|1ĉW? 4xaB /80| /O`>7p`>$XA .dC%Nx0_ HO@8pO`/| /'p "Lp!ÆB(q"ŃO@ D߿ӗ> @_>'pO`?}? 4xaB 6tbD)ׯ @,h „(_8p`| '0}O`> o8`A&TaC!F8| 'p "L?8pO@  <0… :|1ĉ!W? 4xaB /80,h |8`A&TaC!F8"|*Vt/_Ŋ+VXbŊ+V_ŊXbŊ+VXbŊ8`A&TX? 4xaB 6tbD)Vx1_wѠ?~ ŋ/^x|.^T/Ń/}xŋ/^0_ HO@8p'0>~˗|/}| H*\ȰÇ#JH`~8`A&@ 8po߿|o@}/|o@'p "Lp!ÆB(q"EO@ D7p70߿|7_O` /_?$XA .dC%Nh0_ H~O|'0߿|O`>o}'p "Lp!ÆB(q"ŃO@ D߿ۗ> @_>'pO`?}? 4xaB 6tbD)&ׯ @,h „(_8p`| '0}O`> o? O@ DPB >QD+П <0? o? 4h0,h „ 2l!Ĉ'R_A$XA 'P|8p| HAO@ DPB >QDXѡ|+VXbŊ+VXq`~+:bŊ+VXbŊ+O@ DPaA$XA .dC%NXE}.^\ŋ/^xŋxqa/^xŋ/^Ņ.^xŋ/^xQŋ/^xŋxqa>xŋ/^x"A}.^\|]xŋ/^x>/.P_|]xŋ/^x>/.ǐ|O@ DPB >QD-ŅO~ H*\ȰÇ#JHE]0_B (@,h „8`A&TaC!F8q>)Ḟp|,h „ O@ DPB >QDQ1A} H*$? 4xaB 6tbD%Gb|'p "L>$XA .dC%NE0 <0ƒ8`A&TaC!F8Q>)F7|,h „ O@ DPB >QDQ1~ H*<? 4xaB 6tbD%Gb|'p "L>$XA .dC%NE0 <0B8`A&TaC!F8Q>)Ḟ|,h „ O@ DPB >QDQ1B} ,h 8P>$XA .dC%NE-08`A0'p "Lp!ÆB(qD}(R?  

? 4xaB 6tbD%Gb|˗ʼn8P>$XA .dC%NE=ܗ/_?'p} H*\ȰÇ#J(Q?#/_?'p} H*\ȰÇ#J(> 4xaB'p "Lp>? 4xaB 6tbD%|ПO H|ϟ?$XA 0'p "Lp!ÆB(q"E 8p`>'p  8,h „ O@8`A&TaC!F8@? 08?? 4xaB'p} H*\ȰÇ#JHQ |O H| <0B8P>$XA .dC%N(`>O@'p@$`>O@ DP} (p,h „ 2l!Ĉ'R0'p A8p 0'p "L>? 4xaB 6tbD) O8~ 8? O8`A&Thp|  <0… :|1ĉ'p} HP`?'p~ H*4`>O@ DPB >QD8p>$(|O@8p`?$XA 0'p "Lp!ÆB(q"E 8p`>'p  8,h „ O@8`A&TaC!F8@? 08?? 4xaB'p} H*\ȰÇ#JHQ |O H| <0B8P>$XA .dC%N(`>O@'p@$`>O@ DP} (p,h „ 2l!Ĉ'R0'p A8p 0'p "L>? 4xaB 6tbD) O8~ 8? O8`A&Thp|  <0… :|1ĉ'p} HP`?'p~ H*4`>O@ DPB >QD8p>$(|O@8p`?$XA 0'p "Lp!ÆB(q"E 8p`>'p  8,h „ O@8`A&TaC!F8@? 08?? 4xaB'p} H*\ȰÇ#JHQ |O H| <0B8P> ̗/_>}8O@ DPB >Q"B? 08?? 4xaB'p} o`|'p "Lp!ÆB(!|O H| <0B8P> 7_'p_>}O_|_|? 4xaB 6tbć 8p`>'p  8,h „ O@(0@~߾}_>},h „ 2l!Ĉ8p>$(|O@8p`?$XA 0'P |?~/߿߿?}'p "Lp!ÆB`>O@'p@$`>O@ DP} (p`>/߿/߾/,h „ 2l!Ĉ8p>$(|O@8p`?$XA 0'P`'}'0߿}>~? 4xaB 6tbĈ 8p`>'p  8,h „ O@(0˗O}_|O߿}? 4xaB 6tbĈ 8p`>'p  8,h „ O@8`A8`A&TaC!F8`>O@'p@$`>O@ DP} (p,8P_|8`A&TaC!F8`>O@'p@$`>O@ DP} (p,h „ 2l!Ĉ'R0'p A8p 0'p "L>? 4xaB 6tbD) O8~ 8? O8`A&Thp|  <0… :|1ĉ'p} HP`?'p~ H*4`>O@ DPB >QD8p>$(|O@8p`?$XA 0'p "Lp!ÆB(q"E 8p`>'p  8,h „ O@8`A&TaC!F8@? 08?? 4xaB'p} H*\ȰÇ#JHQ |O H| <0B8P>$XA .dC%N(`>O@'p@$`>O@ DP} (p,h „ 2l!Ĉ'R0'p A8p 0'p "L>? 4xaB 6tbDOD 8p`>'p  8˗/_>~ H0'p "Lp!ÆB0@}$J,0'p A8p 0'p|O@ Dp>? 4xaB 6tbD_|˧/| /?/_>~8p>$(|O@8p`?o?}O| '0@~O`>G 8P>$XA .dC#>_>o|}+0'p A8p 0'p|'0}'0|߿|O`>~ 0'p "Lp!ÆB0|ӗo`>o ?} /@~ 'p} HP`?'p~ /|ӗo`>o ?} /@~$`>O@ DPB >a8P߿| ߿| O@? 08??`>/߿@$(p|  <0… :|1"|O ?O`O ?>~+0'p A8p 0'p|O ?O`O ?>~#H>? 4xaB 6tbDO| ԗ/_>'p_|˧/}30'p A8p 0'p|'p_|˗/}/_>}ӗO|$H>? 4xaB 6tbD M\0'p A8p 0'p ;x'p} H*\ȰÇ#JToB? 08?? 4(0`>O@ DPB >QD8p>$(|O@8p`?$XA 0'p "Lp!ÆB(q"E 8p`>'p  8,h „ O@8`A&TaC!F8"@'p} 8p 'p |П@ H*`>O@ DPB >QD8`8|O@$XР?$XA O@8`A&TaC!F81"|,HP0(|,Hp,h „ O@8`A&TaC!F81b?$Xp  08p|,(P,h „ O@8`A&TaC!F8Q>$X0_?`>'p?} H`>$XA 0'p "Lp!ÆB(qD$Xp08P |,? 4xaB'p} H*\ȰÇ#J8|? O (|? 4xaB'p} H*\ȰÇ#JH|O 8P|̧? 4xaB'p} H*\ȰÇ#JH>$? 08 | <0B8P>$XA .dC%N(`>O@'p@$`>O@ DP} (p,h „ 2l!Ĉ'R`>O@'p@$| <0ƒ8P>$XA .dC%N8|'p A8p `>8`A&Tp|  <0… :|1ĉ ˗/_>~'p@$8`>'p "L>? 4xaB 6tbD)̗/8p /_|8`A&Tp|  <0… :|1ĉ ˗b? ˧? 4xaB 'p} H*\ȰÇ#JH ?'p@$Xp,h „ O@8`A&TaC!F8bŁ8p ,h „ 2$`>O@ DPB >QDO H*\Ȑ>? 4xaB 6D?~'p "Lp!Æ ϟ?$X`? ׏?~ H*408`A Ǐ_? H*珟|ӷ ?8`A&TaÂ(p>}ǯ,`>'p ˗/} ? 4xaB 6,˗O>~8`A&/_})TPB *T~O~ 8?ӗO~8`A&TaC /_>~>ԧÇ>|A~-08|8`A&TaC ӗD "D!Bo~ 8? <0… :|p_>!&"D!BQ|O /,h „ 2lB~AП> 0?~ b|Q|O /A $H A$Hp`>$?$H|$H A /,h ‚%L0~%4_ `>%L|O /A $H #H|$H_>$H>$H A /,h ‚%L0?} ̧/>'0߿||ӗO߿|O`>}70_„ ˧/a?$H A _'0|O |/_| ̧/_? A $H|8`A/a„ |/_/?~o?>_ۗ0aƒK`>'p| $H A|/_/?~o?>_>$H A /_>$XAK0aB~'0| /߿| '_| ̗`+0@8`A ˧~ 8?#H A $ȏ?~__O`>/|#H A $(_| H ӗ0a„ _߿_맏_|O߿| o| HӇ_?$H A O/߿|/߿|_?}/߿/߿|O|O@ ,/_>"Dϟ>"O}_'0_> '0߾}O`Ӈ!BӇ_?$H A o>~Ǐ߿|/߿|/@o>'0 䧏 A $H|8`A/a„O߿|/_>~ϟ|˗o}߾| '0_|ۗ0aƒK`>'p| $H AO߿|/_>~ϟ|˗o}߾| '0AG A $(_| H ӗ0a„̗0a„ &LP_>} 'p@? 4x|%L0a„ "/_„ /a„ +/a„ &L|O /,h ƒ K0a„ &D/_ &,O_„ &L0a„ &LHP_>} 'p@? 4xaB 6tP!| BLOD!B@}%08_>$XA .dC1?}!*/_?'0|˗| ̧/_?} /?1|O /,h ƒ_|ӗ?/|O_~O`}&L |&L?} &LX߾O>~/ '0|/?~/ &4/8p  < }O>~_>O`>_ _>~ &Lh_| &LXП &,oO`>}'0| /@~K0aƒK`>'p| H /| O߾~ '0|7&L |&L?} &LX0_|'0߿~O`>| <|O /,h B#_>o߿| '0|8_>$XA˗0a„K0a‚ o>'0߾~ _>>~/a„ ˧/a?'p "4o| _>'0߿|O`>'&L |&L?} &LXП| ܗ/?/_~ӗO`>/_>}%L0A}%08_>$XA˗߿}O`߾| '0|˧O` &} 'p@? 4xaB 6tP!| BLOD!B@}%08_>$XA .dC1?}!B"Dӗ|O8`A&TaC˗"Ą5ܷ0|惘@kدB}%08_> G| G A G A$HP?~$HP`~ /,h ‚%o_B ̗0| KP`ԗP|O /AG| G A G A$Hp`$8PA ~O |̧/>ϟ|/?GП| '0߿|O_|˗߿|/|˗||O /A/>~ '0?~#(0|˗?'_|˧/A/|˷?}/_~/߿|/_>~?˗? 4xaA70}#߿}/߿|o|/|'0|o_>o?'0߿|o|ϟӗ|O$/|O`>~G_~_}۷|/߿| ߾}߾O`۷>O?} /,h ‚%o`>_70@ӷ|70A}'0߿|o`_ _ӗO_~ 8?#H| '0|G_}O_o`>O߾~ /| ̗o ?}G?~'p ",O_O`>'p>~׏_}/o|70߿~o|7`>߿| HP_>} 08_> '0| O@_>}|߿| ؏_} '0|˷/@o |߿'p@~'p ",O__|O ?Ǐ_>O`>}o?'0|?~}70߿|㧏@~/?}%08_> '0|O??~o_?'}Gp_?/|㷯| /|Ǐ>~>˗? 4xaAO`>'0}+/_>~˷O߾~o_|˗/~'p_>}˗߿~ϟ|70?}/_>} /?}%08_> _'0߿}#(P_|˷O߾~'p_|˗/~o_>}˗߿~O_|| ܗ/>G?~'p ",O_%L0a„ &L྄ӗ|O$?$XA .dذ>s谡?} 9tСC P_>} 'p@ A'p "Lp!Æ S/_>СC:tP |%08_} H*\ȰÇ˗"D"D!B|ۗ|O? 4xaB 6tP?~˗"ą˗O?~A"D o>'p@/_|? 4xaB 6tHП~O|8`A"`> O@ DPB 'p 'p 8p 0'p "Lp!Æ 8`A~ HO|,h „ 2l谡>~8 ~ 8? o|,h „ 2l谡>~'p "L?(> 4xaB 6<@'p 'p@$Xp? p <0… O~'p "Lp!ÆB(qb~ 8? 4xaB 6tbD)Vxc8p ,h „ 2l!Ĉ'Rh"ƌ'p@$XA .dC%NXEO H*\ȰÇ#JHŋ308`A&TaC!F8bE1f`>'p "Lp!ÆB(q"Ŋ/b|O@ DPB >QD ?W~*V4`>'p "L_?~ S? ׏B *TPB O~ O OB "08`A&珟>)_> ?} *TPB *L菟>'0>~˗|˧/}SH0_|ӧPB'p@$XA _>} ̷߿|O`}ӗO߾~)$/_SPB *TPB۷_>~'P /߿~ۧ`> *T8|O@ D`~| _>~߾ԷOa> *TPB *Do`G0߿|'0?~ 'P O@ Da? <0a|70_>_>WП>}SPB *TPBO`|70߿|˧`> *T8|O@ D`/| /}!ԗ`> *TPB *D?~o>70߿|g`>80,h „'p@$XA ۷O>~ /~O_?*TPB *Ta| '0߿}o` O| *Tp`? <0a|o`'0|_}SPB *TPB*4OB *T(|O@ D`> SPB *TPB S |*TPB8`A HK |8`A&TaC!F8bŅ8`A8`A&TaC!F8bE1BO@O@ DPB >QD-^|,(? 4xaB 6tbD)Vx} H?$XA .dC%NXE'p 8`A&TaC!F8bE1ZO@'p "Lp!ÆB(q"Ŋ/b`> O@ DPB >QD-^Ęq| <0… :|1ĉ+Z1?} o,h „ 2l!Ĉ'Rh"ƌ8P,h „ 2l!Ĉ'Rh"ƌ'P ,h „ 2l!Ĉ'Rh"ƌ˗F5jԨQF5RԗoF5jԨQF5Z <0… :|1ĉ+Z1ƍ;z2ȑ$K<2ʕ,[| 3̙4kڼ3Ν<{ 4Сo@},h „ 2lP ?~'p "Lp!ÆB(q"E˗O>~O@ DPB o>}? 4xaB 6tbD%ۗO?)RHQ~׏"E)RH"EH"EǏ"E)RH"ŁQH"E H"E)RHQ ?~)RH|QH"E)R?{?~ /b|0_>)RH"E)Ǐ"~='|E7P_? G"E)RH?~(B/|O_} _|˗?}'_|ӗ_|0_>)RH"(? 4xa ߾}۷_>/߿}O` _>~G0B˗,h „ 2l!Ĉ'.ǏC~70|O`| /|G0߿|G0ņH"E)RH?~'PO맏_|/߿|_'P`'p ̗,h „ 2l!Ĉ'.Ǐ~'0ӷO`|O` _> ņH"E)RH?~7>/_|ϟ|˗o}O| '0_|Ga|(RH"E)RǏEG"EG"E)RH?~(R`>)R/?)RH"EG"E)*̗E)RH"EH"E"E)RH"Eď,h ƒ'_|ӗ?/|O_~O`}&L`|8`A&TaC!F8q!?~) |߿|?O`>~}EG"E)RH?~(RoO`O`>_G|QH"E)R?+`؏_} '0|O8`A̗,h „ 2l!Ĉ'.Ǐ"E o>'0}_| '0?}/EG"E)RH?~(RO_|˗|/_~ӗO`>/_>}Q(0_>)RH"E)Ǐ"E)RT/?)RH"EG"E)*̗E)RH"EH"E"E)RH"5ܷ0| 惘O?~5oa|(RH"E)RǏ~[? 4H0 H*\ȰÇ#J? ̷_>/_>~˷O |/_~O|/_~ '0|ӗ/_'0>~ӗo@~o?~"E)RH"170>߾}_>O`>~`>O`>۷/_>'0_'0Oa|(RH"E)RǏ| '0|W0@/?}߿_ӷ߿߿|˧o_߿_?~_>$/?$XA .dC%N\ȏ| '0@$_맏_|o@/| | O`>'p`? ? 4xaB 6tbD0|O`>}W0/߿}O ?~_>o_?O`>?}/@} G"E)RH?~'0}߾|ԗ/ۧo_|/_>}˗`|/|_|/_~ 'P_|˗O|S/?)RH"E?)RHp|QH"E)R ~8} H*\Ȱ!~ϡC:tСC:,/?:tСCϡC:tСC:4/>~:tСC/_|9tСC:tСC˗/}СC:Dϟ?~O|8`A&TaC!F8} H*\ÇO@ DPB >QĉO@ DPB 2ǯ,h „ 2l!Ĉ'RLϟ?$XA .dС?8`A&TaC!F8bE1fԸcGA9dI'QTeK/aƔ9fM7qԹgϒ[_B?>}菟>o"|OO>}~O|o˗|/}kO`ӧO۷_>~'P'0߿~>>}Do`G0߿| '0?~'P ˗,h „ 2l!Ĉ'Rh|70_>O`>/F1bĈ#F/۷O>~ '0~O?} H*\ȰÇ#JHŋ O`˗| ԧO`~˷#F1bĈ#Fa#F1bĈ#F'_~ H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴӧPJJիXjZ1 ;;PKf&ffPK-AOEBPS/img/adque450.gifzaGIF87aX?**?***UU?UUU????**?*******?*******U*U?*U*U*U**?*****?*****?*****?***UU?UUUU*U*?U*U*U*UUUU?UUUUUUUU?UUUUU?UUUUU?UUUUU?UUU?**?***UU?UUU?????**?***UU?UUU?????**?***UU?UUU?ժժ?ժժժ???**?***UU?UUU?????***UUU,X H*\ȰÇ#JHŋ3jȱǏ CIɓ(S\ɲ˗0cʜI͛8sɳϟ@ JѣH*]ʴ)BO@ O@ O@O@ O@ O@O@ O@ O@O@ O@'p "П@ П П@ П@ П П@ П@ П П@ П@ П ϟ? H(?8?(?(?8?(?(?8?(?(?8?? 4xaB 6tbDg?8?8П?O@O@ϟ(?(?o@ O@O@ DП@ ϟ?'P 'P   7p @'p @'p? ϟ~ H(?o@ O@ O@8?8?8П?O@O@ϟ? 4xaB 6tbD)Vx?1bĈ?1bĈ?1bĈ#F1bĈ#F1bĈ#F1bĈ~1bĈ#~1bĈ#~1bĈ#F1b#F1bd#F1bd#F1bĈ#FaĈ#F aĈ#F aĈ#F1bĈb?1bĈa?1bĈa?1bĈ#F1V짐_|M0߿|/~#B0&0_>ˇ?}$˗O?0>1a(_>  /_|8'0_>_|'p  <0… :|1bB _>9/߾~'0_I(Q?So_П>o_>$JOC WП> '>o_?~$>'QD%J(Q~_'_|/_>Ǐ߿} 7D'Q"|/@~/_>~O| /| /_~/_A}o_|˗?~O߿}߾|ۗ߿|8~ ,X`_|_`˗|˗߾|+(0|/߿|,X`'p "Lp!ÆB(_˗_> _~ >˷ĉ8`>O`> _>_> | ߾|/_|/||O_|/?-7q"|/|/'_O`|/?'0?}/_}&>7qĉ'N8_'?~O`>C_/߿˧? 4xaB[p|/| ̷| Ǐ_>O``׏| '0?O'0?~p… 70|o`O`?~ O`ˇ0|/}[pa .\p… .\p|'0|`>G0|O߿| o… .\p|/|o_>}˧O`} 70| _O|/>~/_|Ǐ_>O} 8p?$XA o`>o`| g0>~o}70|/?SP@ *TPB *TPB '_~ _>_>70o>~ | *TPB  o>~ 'P_O`>'P '0|/_A~˗_ 7p@}ϟ|O`|)TP„O`>_ /| /~?o>~| H*\ȰÇ#JhB~70@}_|/_}˗߿|/@G"E )_~ />_|/O`>/_~ ˗o|?}/>o@}'0_>co`o`|+Ϡ|o|WП| _~/_~)RH"E!H"E)BG~˷QH0?$XA SPB  <0… :|1ĉXbŊ+&W"|[/_>}*V/_ŊU(_|+VXbŊ+2WbŊ+VLدbŊ+V_Ŋ+VXbŊ+VdدbŊ+B"~+VX1b UXbň*VXbŊ+VXB*VXbŊ UXbŊXbŊ+VXbŊ XbŊ+&WbŊ+VLدbŊ+VXbŊ+.bŊ+V_Ŋ+VX1a+VXb8`A&TaC8P? H 'p "Lp!Æ'p~ H 'p "Lp!Æ'p~ H*\ȰÇ#B> 4xaB 6d,h „O@ DPB O@ D| H*\Ȱa| H*\ȰÇ#J ?}'N8>~'g_'N_ 3/ĉ'ND/ĉ'N8q 7qĉ7qb~8qĉ8`?M8qDM8qĉ'N ?}'N8>~'g_'N_ 3/ĉ'ND/ĉ'N8q 7qĉ7qb~8qĉ8`?M8qDM8qĉ'N ?}'N8>~'g_'N_> A $H_?O@ DPB ˗C:tСC3O|/C:tP?9tXA |:tСÃ%a~+/sСC˗C:tСC㧏`}ϡC:DB:d/_|/C:tx_:d/_|/C:tx_:tСC:t?}o_|O | /?'_| /?6?2_> Ǐ߿} /?_|˗~'_|8`A&T/_~ *T/_|/@~/_>~߾| /|OB /a? *TPB *TP„O?} >_>ϟ|/|SPBCϟB W0?}'0~/|/?O_>ۧPB ˗B W0?}'0~//?O_>ۧPB ˗B RH!RH!RH!J ~/߿|_o߿_/߿8`A&TB *T__>o?؏| '0| *T| )TP|/߿| '0>~'?~O`>*TPaASPB *TPB *LO|/|o_>}˧O`} 70|SPBSPB/?} ̗/_>߾|/| ̗/_> *TX_> *T/_|/|o_>}/'0˗/,h „ SPB *TPB *T(A~O?} '0|߿}B *$B g__>O| '0?o_>PB ˧PB`O>'0@}_>ۗO>)TPB)TPB *TPB * ?}㗯߿|˷O | /?_|/_} *T @'p "<Ϡ|㗯߿|˷O |/?_|/_} &L0?&L`?_~ />'_|/O`|%L0a„K0a„ &L0a„ &L0~K0a/a„ &<_„ g_ &?&L0aƒ%L0~K0a/a„ & &PB >~ H3/_„ /> &L0A&L`?%L0?~0a„ /a„ &L0a„ &L0a„/a„ &L0a„C_„ 3/_„ &L0a„ ˗_„ 3/_„ &L0a„ ˗_„ &L0a„ &L0a„ ӗ0a„ &L0aB!/a„/a„ &L0a„K/a„/a„ &L0a„K/a„ &L0a„ &L0aƒ <0… 2?2ϡC:tX_:d/C:t谠| 9tСC:t?~:tСCCϟC sСC/a?СC:,/_~:tСC:t>8`A&TBA$H A $/A8`A&TB _>#H A $H_>'p "Lp!C8|  <0… :|1"D~ П <0… O@ D|O@ DPBO$A $H A/@,h „ 2D 8`A&TaC!FOA~$J(!?}(ѡ|(QDODODw_>%J(QD  ?}%Jؐ>IxA 'QD;/DϠ|%J0I(QD%JT ?}(QĆ!Oă g_>%JtA$J<Ϡ|(QDOD%J(Q~3OD%6>~%g_>I(Q|'Q~ /'p "Lp!CaÆ 6lذaÆ g>5lذaÆC_Æ 3/A6lذaCaÆϠ| 6lذ!|װaÆ 6lذaÆ 3OA~6lذaÃ!? g_>5lذaÆ;/_~ g_>5lذaÆ;/_~ 6lذaÆ 6lؐ>5lذaÆCB6l_>5lذaÆ;/_~ 6/A6lذaCO$,h „ 2l!Ĉ3OD%6>~(|(QD/a? g_>%JtA(QD%Jx>G0_|%JOB}'Q"A W0|I(`>KOD`> (Q"|˗D%J(Qă䧏`>"(Q@~П? g_惘OD;/_~%Ϡ|1D w_$J(QD%?/˗@~/|O`}8`A&OB}*TP|+`'_|˧/@~o? *_|˧/@~o? *O߿}o?_>~O@ DP ?}SP g_ o߿_}/?$XA w_> *Ϡ|+0/}o?_>~O@ Dp`>SPB *TPB *T(A~ G0| O~_˧PBCB g_>G0_ /߿|7*T0a>SP g_o ?}/| _> *LA*TPB *TPB  g>G0?짏_|/߿O@ Dp ?}SP g_'p`~/߿#(_>$XA w_> *Ϡ|+` _|/߿O@ D`>SPB *TPB *T(A~ G0|_>۷|߿| *T>)TP~3/_|'|o?'*T0a>SP g_@~o߾O ?)TPa|˧PB *TPB *TP`?䧏`>˗O?~ӷ| ܗ/>*T!?}SP g_o_|˗o}˗߿}/,h „;/_B *Ϡ|+`>/_}ӗ/_>'0B &| )TPB *TPB  g>)TPB >~SP~3/B *TP|˗B 3/A*TPB w_*TPB *TPB g> *TP‚!? *T/A*TPB w_*T_>)TPB | )TPB )B )B )PB'p "Lp!Ã!? 6/A6lذaC/a Ϡ| 6lذ!|˗_Æ 6lذaÆ 6 ?} 6lذA~П Ϡ| 6lذ!|˗_Æ g_ 6la>KدaÆ 6lذaÆ g 6l ?}CaÆ3/_Æ 6l0%װaaÆ 6DAkذaÆ 6lذaÆ䧯aÆ 6 *T/A*TPB w_> *TPB *TPB ?} *TPBCB g_>)TPB | *T8A ˧PB *Th0)TPB *TPB * ?}SPB *,OB}*Tp`?OB *T`>SP g_> *TPBOB *TPB *TP~ O'p "Lp!Ã!ǯaÆϠ| 6lذ!|װaC g_ 6la>kذaÆ 6lذaÆ| H*\`| (P?$XAϠ| H*\a~ _>$XAϠ| H*\a~ _>$XA .dC%g>'p "Lp!Ã'p@} A $H_?#(_>$XA .d0?/A$H A GP|P <0… #H_?$XA .dC3OA~$J(!?}Cϟć g_>%JtAПA 'QD;/_~%J(QDg>%JlOB}'Q"A 'QD;/_~%Ϡ|%J0%'QD%J( ?}(QĆ!?%Ϡ|%J0%'Q"A 'QD;/_~%J(QDg>%JlOB}'Q"A 'QD(?/A$H A $/A'p "Lp!C/a 6lذaÆ 6lOA~6lذaÃ!ǯaÆ 3/_Æ 6l0%װaaÆ 6DAkذaÆ 6lذaÆ䧯aÆ 65lذaÆ;/_Æ g_ 6la>kذaÆ 6lذaÆ ?} 6lذA~װaC g_ 6la>kذ!~3/_Æ 6l05lذaÆ 6PC 54@8O@ DPBC_Æ 3/A6lذaCaÆϠ| 6lذ!|װaÆ 6lذaÆ 3OA~6lذaÃ!ǯaÆϠ| 6lذ!|װaC g_ 6la>kذaÆ 6lذaÆ ?}˗O ǯaÆC_Æ 3/A ˗/> _Æ w_ g_>̗/_>}6 | 6ljj O ,O`;(,h „ 2l!Ĉ3O| ̷| ̧/>'0߾|'_|ӗ/_?CB$J$/A #_}O`>} /?ӗO߿|?}1%'Q"A W0|/_>~˷O | ̷|/_>~˗D/a?%J(QD3O|}߿}߿|}|Ӈ>~ (П? $H A#(_> _>~ _~O`>~O`>~?$H AGp| G A $H|G_Ǐ>߾} _>~ o|/A $H| 8`A&TaC!FOA~˗/#_ _>o ?}>!OD`|_>/@~O`|ӷD/a? g_˧O`o`|o`> O߾~%w_$J(QD% ?}/| O|߿| ׏_} HCB"D|+`o |߿#8_?~'p |C!B`>#_ _ }󷯟|!w_>%J(QD  ?}'p_|˗}O>} ܗ/OC~'QA3/_| ܗ/?߿}O?}/_>}˗,h|ˇ!B3/A 3O| ̗/?'0@}/_>}˗B | H*\ȰÇ#J ?}(0ĉ ӇP 3/A& 7qăoĂ g_M8`>8qĉ'NA~ 7Q`'>~SϠ|(0ĉw_ KϠ|(0ĉw_'N8qĉ ?}'N>Ml/> g_'NTA&6ԗO g_'NTA&N8qĉ'g>M8qbB'p@}$H A˗A @8`A&T!|˗_Ä˧_~3/_Æ 6l0%װaÆ 6lذaÆ ?} 6lذA~П 8߿O@? 4xaB "| 5L`>_?o@8`A&T!|˗_Æ 6lذaÆ 6 ?} 6lذA~>$XA8p| <0… w_8`AO/,h „ 2DAkذaÆ 6lذaÆ䧯aÆ 6$XA .d0%װaÆ 6lذaÆ 3`> 4xaB *O@$ A O~ H|O@ DPB 'p? A 0@8? 0 <0… O$,h „ 2l!Ĉ3/@~,h „ 2~SϠ|8qDobC~3/A&N8Qa>8qĉ'NA~ 7qĉ CĉϠ|'N0MXA 7qĉ ;/ĉ'N8q g'NLOB}&o~ /'p "Lp!C!} 3/A6lذaCaÆ 6lذaÆ g>5lذaÆCB˧!~3/_Æ 6l0%에_| 3/A6lذaC/a 6lذaÆ 64 ?}kذaÆ ӇP?ܗ/_>} 3/A6lذaC/a˗!B3/_Æ 6l0%װaÆ 6lذaÆ 3O_Æ 6lx>O@`>'p g_Ko`?$߿8p| <0… w_6lذaÆ 6lذ!?}kذaÆ ӇP? O@O@~7@8`A&T!|˗} H0߿O/,h „ 2DAkذaÆ 6lذaÆ䧯aÆ 6Ko ?$߿8p| <0… w_6lذaÆ 6lذ!?}kذaÆ ӇP'P>$XA wA/_|& g_>M8q|_|MϠ|8qDoĉ'N8q~3Oĉ'&>~˧o~3/ĉ'*|7Q`?oĉw_'N8qĉ ?}'N>MoD g_'NTA& 7Q`?oĉw_'N8qĉ ?}'N ~8P>~ H3/A&L0a„ | &LxA ˗0a„ &L`>K0a„ &L0a„ &L0~3O_„ &L0aB!? &4Ϡ|K0a„ &LX0%0aB g_ &L0a„;/_~ &L0a„ &L0a„  ?} &L0a„ ӇP?%L0!A ˗0a„ &L`>K/a„ g_ &L0a„;/_B8`A&TaC!FOA~$J(!?}CϟD3/D%:| IH_>I(Q|˗D%J(QăODӇP?IH_>I(Q|˗D3/D%:| I(QD%JI(Q|˗D%J(QăODӇP?g_>%JtA'p "LX_>)TPB | *TPB *TPB 3OA~*TPB ӇP? *Ϡ|SPB *4A*Tp?OB *T`>SPB *TPB *T(A~ ӧPB *TX>)TP~3/B *TP|˧PBϠ| *TPB;/B *TPB *TPB g> *TP‚!OB ?8_>$XA .d05lؐ`?aÆ 6DA6lذaÆ 6lذ~3O_Æ 6lx>5lؐ`?aÆ 6DA6lHA װaÆ "| 6lذaÆ 6lp`?䧯aÆ 6!aà g_ 6l!|8| G A $A/,h „ 2DAkذaÆ 6lذaÆ䧯aÆ 6~kذ? װaÆ "| 5l|kذaÆ w_6lذaÆ 6lذ!?}#/_|kذaC!? 6/A ˗/_6lؐa>KدaÆ3`> ̗/_~? 4xaB ;/_~ .\p… .\pB䧏`>-̷p… ӇP?.\_>'_.\pa|˗… g_˷0… .LA[p… .\p…  ?} 7_|˧/߿}[p…C… Ϡ| '_|˧/߿}[p…;/… Ϡ| '_|˧/߿}[p…;/… .\pZhZ 'p ?}7_> O>}߾'p "Lp ?}[p~3/_|o@}/߿~۷p… w_ *g_>'߾ o߾_} .\p`>[p… .\p… g>O~_/?~8`A&T8>-\Pa? |߿߿|O@ DP|˷pB g_ /߿ _? 4xaB;/… .\p… .\`?䧏`G0|˷p… ӇP *g_>7_|O>.\p!|˷pB g_˗`| /… .$A.\p… .\p… ?} ߾}_>[p…C… 3/A O߾}۷|۷p… w_ *g_>7}p߾O>$XA | .\p… .\pƒ g>˷o|ӗ/_-\pB!? .g_>̗/_}O| o… | -\A W0_| ܗ/?70_ .\H0%p… .\p… "g>-\(0… .,OB}pB3/…-\p‚/a 3/A.o… | -\p…ZhZh" ~88p?~'p "L ?}C… g_ o… | -\|[|.\pa|˗… .\p… .\ ?}[p… ">~[pA ˷p… .LA[pA ˷p… .LA[p… .\p…  ?} .\pB!? .5lؐ`?aÆ 6DA6lHA װaÆ "| 6lذaÆ 6lp`?䧯aÆ 6kذ!~3/_Æ 6l05lذaÆ 6lذaÁ g 6l ?}kذ!~3/_Æ 6l05lؐ`?aÆ 6DA6lذaÆ 6lذ~3O_Æ 6lx>5lؐ`?aÆ 6DA6lHA װaÆ "| &ܗ/> װa 6lذ~3O_Æ 6lx>!aà g_>$XA .d0%װ~3/_Æ 6l0%pa>~w0| kذaÆ & ?} 6lذA~П Ϡ| 6lذ!|˗_Æ g_ 6la>Kد}/|/|˗| ̧/_?װaÆ 6LOA~6lذaÃ!? 6/A6lذaC/a Ϡ| 6lذ!|˗_C O |/_>~߿|o?8`A&TaÄϡC:OB}!C СC | 9t_>9tСC;/_~3_>o`|'0|70C:tP ?}sСCӇP?9t_>9tСC;/_~2Ϡ|:tС|˗Ä_>o`|'0|70CСCϡC:OB}:t_>9tСC? <0aA ˧PB *Th0)Tp|_ '0'p'0|/B *$/_> *, ?}SPB *,OB}*Tp?OB *T`>SP g_> *TPBOB˗O_?'P'p_|˧/| ԗ/_> *TH_|SP~3OB *TPaA~PBϠ| *TB )d@'p?8`Ag_>%L0a„ &,A&L0a„ &L0aƒ(P,h ~3OB"D!BCB"Ϡ|C!B"D`>C!BϠ|"D!B|"D!B"$P < | <(A~ Ӈ!B"DaA~!B3/A"D!B"4A"D~3/B"D!B;/B"D!B 'p "Lh,h`?~CB !B!B"<`>'p "OA~&L0a„ >~K0aB/a„ &L0a|˗_„ Ϡ| &L0a„ w_&4`/?'_|˧/@~/˗|K0aB˗o_„  ?} &L0a„ ӇP?%L0!A ˗0a„ &L`>K/a„ g_ &L0a„;/_~ 7'P۷߾o?_߾߿| H˗o_„  ?} &L0a„ ӇP?%L0!A ˗0a„ &L`>K/a„ g_ &L0a„;/_~ ̗/_>}G0߿| /߿| /|#_>&L?}&L ?}K0a„ &LH>!0a„3/_„ &L0a‚/ &$/A&L0a„ | %Lh0|/|_ǯ_>/@? 4xaB 2 ?} 6lذA~װaÅaÆ 6DA6l_>5lذaÆ;/_Æo>?~o߾'_>۷O>~ װaÆ g>5lذaÆC_Æ 3/A6lذaCaÆϠ| 6lذ!|װ!| ܗ/?_|/_|˷O߾o_|aÆ 6, ?}kذj O@'p "<Ϡ|K0a„ &LX0%L0~3/_„ &L0a‚/a„ ̗` &L0a„ g>%L0a„ &$OB}&L`?/a„ &L0a|˗0a„Ϡ| &L0a„ w_ &LX0_B0a„ &L0aƒ g &L0a„C_„ g_>%L0a„ &,A&L`?/a„ &L0a|8| H*\ȰÇ#J ?}8qĄ!?3/A&N8Qa>Ko~3/ĉ'*| M8qĉ'*g>M8qbB~ПϠ|'N0%7ѡ?oĉw_&N8qĉ#g'NLOB}7q@ 7qĉ ;/_~' Ϡ|'N0%7qĉ'N>8`A&TaB} (P?#H A $H_>'p "Lp!C8| G A $H|O@ DPB 'p?? 4xaB 6tbDO@ DPBO@$A $H AП <0… O@$A $H AП <0… O@$,h „ 2l!Ĉ(QD (ѡ|%J(| IH_>%J_$J(QD%OD%6ODI(QĆI_>%J_>%J(QD OD%6Oă 'QD'Q~(QD (QD%JA~$J(QbC}$J<Ϡ|%J(|%g_>%J_>!'`>%JȰA~$J(QbC}$J<Ϡ|%J(|%g| H*\Ȱ!C:4a> 9tСC 3OC:t谠>~:Ϡ|:tСÂ9t_?9tСC С|O`>} /?O_~ӗϡÁ9ta~sСC?g_>:taAs`?9tСC ˗C/|o@}_>~۷|/?:th>:taA}!C:tСC/G A $H| H*\Ȱ!Cs0| 70_>_>a~ϡC? 4xaB 6d A $H A8`A&TaC'p~ $H A П <0… 2?#H A '0|#_>_$H 'P?$XA .T`> 4xaB 6t?G A $H?$XA .da>؏ A $H A H*\Ȱ| 8A $O`>}/߿~߾}#H AO@G߿#?'p "Lp!ÆBt_Ĉ#F1bā"F1bĈ#`>/_>~O|'0@}X|??'P,h „ 2l!Ĉ'Rh"ƌ7r#Ȋ8`#??8`A'p "Lp!ÆB8ПD%J(Q"C%J(QD%JT`>'p "Lp~ 2dȐ!C 2dȰC 2dȐ!C 2ǐ!C 2dȐ!C˗O? Ã˗C 2L؏!C 2dȐ!C cȐ!C 2dȐ!C2dȐ!C 2dp`1d0~ ˗C 2L؏!C 2dȐ!C cȐ!C 2dȐ!C2dȐ!C 2dp`>Ǐ_|ӗo@~/||/_>~׏> 2d0a? 2dȐ!C 2@8`A&TaC_?!BBO߿|߿|o?_>'0| _>~A"ā B"D _?!B~!"D!BT"|'0߿|70@70@ '0_>"D!B"D"D!Ba?!B"D AD`o`~/|/|#_> B"D!B? H*\ȰÇ#'QD%JȰD o}|o?/|'p(QD%J(QA$J(QD(QD%JdO| ܗ/?_|/_|˷O߾o_|OD%J(QDI(QD%6'QD%JПD9'QD#ϟA O@ O@8?8?8П?O@O@ϟ(?(? 4x @'p? П@ П@ ϟ?'P 'P   7p @'p O@ϟ(?(?o@ O@ O@8?8?8П?O@$XA%/_~ &L0a„ &<П П@ П@ П П@ П@ П П@ П@ П П@ П@ H8?8?(?(?8?(?(?8?(?(?8?(? 4x @'P @'P @'p @'P @'P @'p @'P @'P @'p @'P @'P @'p "Lp!ÆB(q"Ŋ/b̨q#ǎ? )r$ɒ&OLr%˖._Œ^)s&͚6o̩s'Ϟ> *t(ѢF"Mt)ӦNB*u*ժVbͪu+׮^ +v,ٲfϢMv-۶n+w.ݺvͫw/߾~,d@;;PKNazaPK-AOEBPS/mg_trble.htm Monitoring Oracle Messaging Gateway

21 Monitoring Oracle Messaging Gateway

This chapter discusses means of monitoring the Oracle Messaging Gateway (MGW) agent, abnormal situations you may experience, several sources of information about Messaging Gateway errors and exceptions, and suggested remedies.

This chapter contains these topics:

Oracle Messaging Gateway Log Files

Messaging Gateway agent status, history, and errors are recorded in Messaging Gateway log files. A different log file is created each time the Messaging Gateway agent is started. You should monitor the log file because any errors, configuration information read at startup time, or dynamic configuration information is written to the log.

The format of the log file name for the default agent is:

oramgw-hostname-timestamp-processid.log

The format of the log file name for a named agent is:

oramgw-AGENTNAME-hostname-timestamp-processid.log

By default the Messaging Gateway log file is in ORACLE_HOME/mgw/log. This location can overridden by the parameter log_directory in the Messaging Gateway initialization file used by the agent, usually mgw.ora.

This section contains these topics:

Sample Oracle Messaging Gateway Log File

The following sample log file shows the Messaging Gateway agent starting. The sample log file shows that a messaging link, a registered foreign queue, a propagation job, and a schedule associated with the job have been added. The log file shows that the propagation job has been activated. The last line indicates that the Messaging Gateway is up and running and ready to propagate messages.

Example 21-1 Sample Messaging Gateway Log File

>>2007-01-16 15:04:49 MGW C-Bootstrap 0 LOG process-id=11080
Bootstrap program starting
>>2007-01-16 15:04:50 MGW C-Bootstrap 0 LOG process-id=11080
JVM created -- heapsize = 64
>>2007-01-16 15:04:53 MGW Engine 0 200 main
MGW Agent version: 11.1.0.0
>>2007-01-16 15:04:53 MGW AdminMgr 0 LOG main
Connecting to database using connect string = jdbc:oracle:oci:@INST1
>>2007-01-16 15:05:00 MGW Engine 0 200 main
MGW Component version: 11.1.0.3.0
>>2007-01-16 15:05:01 MGW Engine 0 200 main
MGW agent name: DEFAULT_AGENT, MGW job instance id: 273006EC6ED255F1E040578C6D021A8C, MGW database instance: 1
>>2007-01-16 15:05:09 MGW Engine 0 1 main
Agent is initializing.
>>2007-01-16 15:05:09 MGW Engine 0 23 main
The number of worker threads is set to 1.
>>2007-01-16 15:05:09 MGW Engine 0 22 main
The default polling interval is set to 5000ms.
>>2007-01-16 15:05:09 MGW MQD 0 LOG main
Creating MQSeries messaging link:
link : MQLINK
link type : Base Java interface
queue manager : my.queue.manager
channel : channel1
host : my.machine
port : 1414
user :
ccdt url : 
ssl cipherSuite : 
connections : 1
inbound logQ : logq1
outbound logQ : logq2
>>2007-01-16 15:05:09 MGW Engine 0 4 main
Link MQLINK has been added.
>>2007-01-16 15:05:09 MGW Engine 0 7 main
Queue DESTQ@MQLINK has been registered; provider queue: MGWUSER.MYQUEUE.
>>2007-01-16 15:05:09 MGW Engine 0 9 main
Propagation Schedule JOB_AQ2MQ (MGWUSER.MGW_BASIC_SRC --> DESTQ@MQLINK) has been
added.
>>2007-01-16 15:05:09 MGW AQN 0 LOG main
Creating AQ messaging link:
link : oracleMgwAq
link type : native
database : INST1
user : MGWAGENT
connection type : JDBC OCI
connections : 1
inbound logQ : SYS.MGW_RECV_LOG
outbound logQ : SYS.MGW_SEND_LOG
>>2007-01-16 15:05:10 MGW Engine 0 19 main
MGW propagation job JOB_AQ2MQ has been activated.
>>2007-01-16 15:05:10 MGW Engine 0 14 main
MGW propagation job JOB_AQ2MQ (MGWUSER.MGW_BASIC_SRC --> DESTQ@MQLINK) has been added.
>>2007-01-16 15:05:11 MGW Engine 0 2 main
Agent is up and running.

Interpreting Exception Messages in an Oracle Messaging Gateway Log File

Exception messages logged to the Messaging Gateway log file may include one or more linked exceptions, identified by [Linked-exception] in the log file. These are often the most useful means of determining the cause of a problem. For instance, a linked exception could be a java.sql.SQLException, possibly including an Oracle error message, a PL/SQL stack trace, or both.

The following example shows entries from a Messaging Gateway log file when an invalid value (bad_service_name) was specified for the database parameter of DBMS_MGWADM.CREATE_AGENT or DBMS_MGWADM.ALTER_AGENT. This resulted in the Messaging Gateway agent being unable to establish database connections.

Example 21-2 Sample Exception Message

>>2003-07-22 15:27:26  MGW  AdminMgr  0  LOG  main
Connecting to database using connect string = jdbc:oracle:oci8:@BAD_SERVICE_NAME
>>2003-07-22 15:27:29  MGW  Engine  0  EXCEPTION  main
oracle.mgw.admin.MgwAdminException: [241]  Failed to connect to database. SQL
error: 12154, connect string: jdbc:oracle:oci8:@BAD_SERVICE_NAME
[ …Java stack trace here…]
[Linked-exception]
java.sql.SQLException: ORA-12154: TNS:could not resolve the connect identifier
specified
[ …Java stack trace here…]
>>2003-07-22 15:27:29  MGW  Engine  0  25  main
Agent is shutting down.

Monitoring the Oracle Messaging Gateway Agent Status

This section contains these topics:

MGW_GATEWAY View

The MGW_GATEWAY view monitors the progress of the Messaging Gateway agent. Among the fields that can be used to monitor the agent are:

  • AGENT_NAME

  • AGENT_INSTANCE

  • AGENT_PING

  • AGENT_STATUS

  • LAST_ERROR_MSG

  • SERVICE

The AGENT_STATUS field shows the status of the agent. This column has the following possible values:

NOT_STARTED

Indicates that the agent is neither running nor scheduled to be run.

START_SCHEDULED

Indicates that the agent job is waiting to be run by the job scheduler.

STARTING

Indicates that the agent is in the process of starting.

INITIALIZING

Indicates that the agent has started and is reading configuration data.

RUNNING

Indicates that the agent is ready to propagate any available messages or process dynamic configuration changes.

SHUTTING_DOWN

Indicates that the agent is in the process of shutting down.

BROKEN

Indicates that, while attempting to start an agent process, Messaging Gateway has detected another agent already running. This situation should never occur under normal usage.

Querying the AGENT_PING field pings the Messaging Gateway agent. Its value is either REACHABLE or UNREACHABLE. An agent with status of RUNNING should almost always be REACHABLE.

The columns LAST_ERROR_MSG, LAST_ERROR_DATE, and LAST_ERROR_TIME give valuable information if an error in starting or running the Messaging Gateway agent occurs. AGENT_INSTANCE indicates the Oracle Database instance on which the Messaging Gateway instance was started.


See Also:

"DBMS_MGWADM" in Oracle Database PL/SQL Packages and Types Reference for more information on the MGW_GATEWAY view

Oracle Messaging Gateway Irrecoverable Error Messages

A status of NOT_STARTED in the AGENT_STATUS field of the MGW_GATEWAY view indicates that the Messaging Gateway agent is not running. If the AGENT_STATUS is NOT_STARTED and the LAST_ERROR_MSG field is not NULL, then the Messaging Gateway agent has encountered an irrecoverable error while starting or running. Check if a Messaging Gateway log file has been generated and whether it indicates any errors. If a log file is not present, then the Messaging Gateway agent process was probably not started.

This section describes the causes and solutions for some error messages that may appear in the LAST_ERROR_MSG field of the MGW_GATEWAY view. Unless indicated otherwise, the Messaging Gateway agent will not attempt to restart itself when one of these errors occurs.

ORA-01089: Immediate shutdown in progress - no operations are permitted

The Messaging Gateway agent has shut down because the SHUTDOWN IMMEDIATE command was used to shut down a running Oracle Database instance on which the agent was running. The agent will restart itself on the next available database instance on which it is set up to run.

ORA-06520: PL/SQL: Error loading external library

The Messaging Gateway agent process was unable to start because the shared library was not loaded. This may be because the Java shared library was not in the library path. Verify that the library path in listener.ora has been set correctly.

ORA-28575: Unable to open RPC connection to external procedure agent

The Messaging Gateway agent was unable to start. It will attempt to start again automatically.

Possible causes include:

  • The listener is not running. If you have modified listener.ora, then you must stop and restart the listener before the changes will take effect.

  • Values in tnsnames.ora, listener.ora, or both are not correct.

    In particular, tnsnames.ora must have a net service name entry of MGW_AGENT. This entry is not needed for Messaging Gateway on Windows. The SID value specified for CONNECT_DATA of the MGW_AGENT net service name in tnsnames.ora must match the SID_NAME value of the SID_DESC entry in listener.ora. If the MGW_AGENT net service name is set up for an Inter-process Communication (IPC) connection, then the KEY values for ADDRESS in tnsnames.ora and listener.ora must match. If the names.default_domain parameter for sqlnet.ora has been used to set a default domain, then that domain must be appended to the MGW_AGENT net service name in tnsnames.ora.

ORA-28576: Lost RPC connection to external procedure agent

The Messaging Gateway agent process ended prematurely. This may be because the process was stopped by an outside entity or because an internal error caused a malfunction. The agent will attempt to start again automatically. Check the Messaging Gateway log file to determine if further information is available. If the problem persists, then contact Oracle Support Services for assistance.

ORA-32830: Result code -2 returned by Messaging Gateway agent

An error occurred when the Messaging Gateway agent tried to read its initialization file, usually mgw.ora. Verify that the file is readable.

ORA-32830: Result code -3 returned by Messaging Gateway agent

An error occurred creating the Messaging Gateway log file. Verify that the log directory can be written to. The default location is ORACLE_HOME/mgw/log.

ORA-32830: Result code -8 returned by Messaging Gateway agent

An error occurred starting the Java Virtual Machine (JVM). Verify that:

  • You are using the correct Java version

  • Your operating system version and patch level are sufficient for the JDK version

  • You are using a reasonable value for the JVM heap size

    The heap size is specified by the max_memory parameter of DBMS_MGWADM.ALTER_AGENT

  • On Windows platforms, verify the MGW_PRE_PATH set in mgw.ora contains the path to the correct JVM library (jvm.dll).

ORA-32830: Result code -12 returned by Messaging Gateway agent

An error occurred writing to the Messaging Gateway log file. Check the free disk space or any other issues that might result in file I/O problems.

ORA-32830: Result code -17 returned by Messaging Gateway agent

The JVM was successfully created but an error occurred trying to call the MGW Java agent program. Verify that the CLASSPATH set in mgw.ora is correct.

ORA-32830: Result code -19 returned by Messaging Gateway agent

The Messaging Gateway agent was configured to use a particular initialization file but that file does not exist. The INITFILE field of the MGW_GATEWAY view shows the full pathname of the file specified by the administrator. Either create that initialization file, or use DBMS_MGWADM.ALTER_AGENT to set INITFILE to another file or NULL to use the default initialization file.

ORA-32830: Result code -100 returned by Messaging Gateway agent

The Messaging Gateway agent JVM encountered a runtime exception or error on startup before it could write to the log file.

ORA-32830: Result code -101 returned by Messaging Gateway agent

An irrecoverable error caused the Messaging Gateway agent to shut down. Check the Messaging Gateway log file for further information. Verify that the values specified in mgw.ora are correct. Incorrect values can cause the Messaging Gateway agent to terminate due to unusual error conditions.

ORA-32830: Result code -102 returned by Messaging Gateway agent

The Messaging Gateway agent shut down because the version of file ORACLE_HOME/mgw/jlib/mgw.jar does not match the version of the Messaging Gateway PL/SQL packages. Verify that all Messaging Gateway components are from the same release.

ORA-32830: Result code -103 returned by Messaging Gateway agent

The Messaging Gateway agent shut down because the database instance on which it was running was shutting down. The agent should restart automatically, either on another instance if set up to do so, or when the instance that shut down is restarted.

ORA-32830: Result code -104 returned by Messaging Gateway agent

See previous error.

ORA-32830: Result code -105 returned by Messaging Gateway agent

The Messaging Gateway agent detected that it was running when it should not be. This should not happen. If it does, AGENT_STATUS will be BROKEN and the agent will shut down automatically. If you encounter this error:

  • Terminate any Messaging Gateway agent process that may still be running. The process is usually named extprocmgwextproc.

  • Run DBMS_MGWADM.CLEANUP_GATEWAY(DBMS_MGWADM.CLEAN_STARTUP_STATE).

  • Start the Messaging Gateway agent using DBMS_MGWADM.STARTUP.

ORA-32830: Result code -106 returned by Messaging Gateway agent

See previous error.

Other Oracle Messaging Gateway Error Conditions

This section discusses possible causes for AGENT_STATUS remaining START_SCHEDULED in MGW_GATEWAY view for an extended period.

Database Service Not Started

Messaging Gateway uses an Oracle Scheduler job to start the Messaging Gateway agent. Oracle Scheduler allows you to specify a database service under which a job should be run (service affinity). Messaging Gateway allows an administrator to configure the Messaging Gateway agent with a database service that will be used to configure the Scheduler job class associated with that agent.

When you shutdown a database Oracle stops all services to that database. You may need to manually restart the services when you start the database. If a Scheduler job is associated with a service then the job will not run until the service is started. If AGENT_STATUS for a Messaging Gateway agent remains START_SCHEDULED for an extended period that might indicate that the database service is disabled or no database instances associated with the service are running. Use the MGW_GATEWAY view, Oracle Scheduler views, and service views to determine how the agent was configured and the current state of the Scheduler job and database service.


See Also:

Oracle Messaging Gateway Agent Scheduler Job for information about Oracle Scheduler objects used by Messaging Gateway.

Too Few Job Queue Processes

Messaging Gateway uses Oracle Scheduler to start the Messaging Gateway external process. When AGENT_STATUS is START_SCHEDULED, the Messaging Gateway agent Scheduler job is waiting to be run by the Scheduler. The Messaging Gateway job will not run until there is an available job process. Messaging Gateway holds its Scheduler job process for the lifetime of the Messaging Gateway agent session. If multiple Messaging Gateway agents have been started, each agent uses its own Scheduler job and require its own job process.

If the value of the database initialization parameter JOB_QUEUE_PROCESSES is zero, then no Oracle Scheduler jobs will run. If the value is non-zero, it effectively becomes the maximum number of Scheduler jobs and job queue jobs than can concurrently run.

If Messaging Gateway status remains START_SCHEDULED for an extended period of time, then it may indicate that the database has been started with a value for JOB_QUEUE_PROCESSES that is zero or is too low and that all job slaves are busy. Verify that the value is non-zero and that the database instance has been started with enough job queue processes so that one is available for each Messaging Gateway agent.

Scheduler Job Broken or Disabled

The Messaging Gateway agent status will remain START_SCHEDULED if the Oracle Scheduler job associated with a Messaging Gateway agent has become disabled or broken for some reason. To determine if this is the case, use the DBA_SCHEDULER_JOBS view to look at STATE field for the agent's Scheduler job. Normally the Scheduler job state will be SCHEDULED when the Messaging Gateway agent's Scheduler job is waiting to be run, or RUNNING when the Messaging Gateway agent is running. The agent's Scheduler job should not exist if the Messaging Gateway agent status is NOT_STARTED.

Check other Scheduler views, such as DBA_SCHEDULER_JOB_RUN_DETAILS, for additional information about the Messaging Gateway Scheduler jobs. Also check the MGW_GATEWAY view and the Messaging Gateway log file for any error messages that may indicate a problem.


See Also:

Oracle Messaging Gateway Agent Scheduler Job for information about Oracle Scheduler objects used by Messaging Gateway

Oracle Real Application Clusters (Oracle RAC) Environment

If Messaging Gateway is being used in a Oracle RAC environment and the agent has been configured with a database service but no database instances are running that have the service enabled, then the Messaging Gateway AGENT_STATUS will remain START_SCHEDULED until the service is started on a running database instance.

Monitoring Oracle Messaging Gateway Propagation

Messaging Gateway propagation can be monitored using the MGW_JOBS view and the Messaging Gateway log file. The view provides information on propagated messages and errors that may have occurred during propagation attempts. The log file can be used to determine the cause of the errors.

Besides showing configuration information, the MGW_JOBS view also has dynamic information that can be used to monitor message propagation. Applicable fields include STATUS, ENABLED, PROPAGATED_MSGS, EXCEPTIONQ_MSGS, FAILURES, LAST_ERROR_MSG, LAST_ERROR_DATE, and LAST_ERROR_TIME.

The STATUS field indicates current status of the job. READY means that the job is ready for propagation (but only if the ENABLED field is TRUE). RETRY means that a propagation failure occurred but that propagation will be retried. FAILED means that the agent has stopped propagation for the job due to an unrecoverable error or the maximum number of consecutive propagation failures has been reached. DELETE_PENDING means job removal is pending due to DBMS_MGWADM.REMOVE_JOB being called but certain cleanup tasks pertaining to the job are still outstanding. SUBSCRIBER_DELETE_PENDING means that DBMS_MGWADM.REMOVE_SUBSCRIBER has been called on an old style propagation job but certain cleanup tasks pertaining to the job are still outstanding.

The ENABLED field indicates whether the propagation job is currently enabled. TRUE indicates the job is enabled while FALSE indicates the job is disabled. No propagation will occur unless the job is enabled.

The PROPAGATED_MSGS field of the MGW_JOBS view indicates how many messages have been successfully propagated. This field is reset to zero when the Messaging Gateway agent is started.

If a Messaging Gateway propagation job has been configured with an exception queue, then the Messaging Gateway agent will move messages to that exception queue the first time the Messaging Gateway agent encounters a propagation failure caused by a message conversion failure. A message conversion failure is indicated by oracle.mgw.common.MessageException in the Messaging Gateway log file. The EXCEPTIONQ_MSGS field indicates how many messages have been moved to the exception queue. This field is reset to zero when the Messaging Gateway agent is started.

If an error occurs during message propagation for a propagation job, a count is incremented in the FAILURES field. This field indicates the number of failures encountered since the last successful propagation of messages. Each time a failure occurs, an error message and the time it occurred will be shown by LAST_ERROR_MSG, LAST_ERROR_DATE, and LAST_ERROR_TIME. When the number of failures reaches sixteen, Messaging Gateway halts propagation attempts for this propagation job. To resume propagation attempts you must call DBMS_MGWADM.RESET_JOB for the propagation job.

If an error occurs, then examine the Messaging Gateway log file for further information.

Oracle Messaging Gateway Agent Error Messages

This section lists some of the most commonly occurring errors that are shown in the LAST_ERROR_MSG column of the MGW_JOBS view and logged to the Messaging Gateway agent log file. Also shown are some errors that require special action. When you notice that a failure has occurred, look at the linked exceptions in the log file to determine the root cause of the problem.

Two primary types of errors are logged to the Messaging Gateway agent log file:

  • oracle.mgw.common.MessageException

    This error type is logged when a message conversion failure occurs. The Messaging Gateway agent probably cannot propagate the message causing the failure, and the propagation job will eventually be stopped.

  • oracle.mgw.common.GatewayException

    This error type is logged when some failure other than message conversion occurs. Depending on the cause, the problem may fix itself or require user action.

[221] Failed to access <messaging_system> queue: <queue>

An error occurred while trying to access either an Oracle Streams Advanced Queuing queue or a non-Oracle queue. Check the linked exception error code and message in the log file.

[241] Failed to connect to database. SQL error: <error>, connect string: <connect_string>

This is probably caused by incorrect MGW agent connection information specified for DBMS_MGWADM.CREATE_AGENT or DBMS_MGWADM.ALTER_AGENT. Either the Messaging Gateway agent user or password is incorrect or the database specifier (database parameter) is iJ"ncorrect. Verify that the connection information is correct for the connection type used by the agent, JDBC OCI or JDBC Thin.

If the database parameter is NULL, then check the Messaging Gateway log file for the following Oracle linked errors:

ORA-01034: ORACLE not available
ORA-27101: shared memory realm does not exist

These two errors together indicate that the Messaging Gateway agent is attempting to connect to the database using a local IPC connection, but the ORACLE_SID value is not correct.

A local connection is used when the database parameter is set to NULL. If a local connection is desired, the correct ORACLE_SID value must be set in the Messaging Gateway agent process. This can be done by adding the following line to the MGW initialization file, usually mgw.ora:

set ORACLE_SID = sid_value

ORACLE_SID need not be set in the MGW initialization file if the database parameter is not NULL.

If setting ORACLE_SID in the MGW initialization file does not work, then the database parameter must be set to a value that is not NULL.

If the JDBC Thin connection is used, then the database parameter must be not NULL. If the JDBC Thin connection is used and the database parameter is a TNSNames alias, make sure that the oracle.net.tns_names Java property is set in the MGW initialization file. The property can be set by adding the following line to the MGW initialization file:

setJavaProp oracle.net.tns_admin=<directory containing tnsnames.ora>

See Also:

"oracle.net.tns_admin" for more information

[415] Missing messages from source queue of job <job_name>

Possible causes include:

  • The agent partially processed persistent messages that were dequeued by someone other than the Messaging Gateway agent.

  • The propagation source queue was purged or re-created.

  • A message was moved to the Oracle Streams Advanced Queuing exception queue.

If this error occurs, then call procedure CLEANUP_GATEWAY in the DBMS_MGWADM package:

DBMS_MGWADM.CLEANUP_GATEWAY (
       action => DBMS_MGWADM.RESET_SUB_MISSING_MESSAGE, 
       sarg => <job_name>);

The call takes effect only if the propagation job has encountered the missing message problem and the agent is running. The agent treats the missing messages as nonpersistent messages and continues processing the propagation job.


See Also:

"Propagation Job Overview" for more information on Messaging Gateway exception queues

[416] Missing log records in receiving log queue for job <job_name>

Possible causes include:

  • Log records were dequeued from the log queues by someone other than the Messaging Gateway agent.

  • The log queues were purged or re-created.

If this error occurs, then call procedure CLEANUP_GATEWAY in the DBMS_MGWADM package:

DBMS_MGWADM.CLEANUP_GATEWAY (
       action => DBMS_MGWADM.RESET_SUB_MISSING_LOG_REC,  
       sarg => <job_name>);

The call takes effect only if the propagation job has encountered the missing log records problem and the agent is running.


Note:

Calling procedure DBMS_MGWADM.CLEANUP_GATEWAY may result in duplicated messages if the missing messages have already been propagated to the destination queue. Users should check the source and destination queues for any messages that exist in both places. If such messages exist, then they should be removed from either the source or destination queue before calling this procedure.

[417] Missing log records in sending log queue for job <job_name>

See previous error.

[421] WARNING: Unable to get connections to recover job <job_name>

This message is a warning message indicating that the Messaging Gateway agent failed to get a connection to recover the propagation job, because other propagation jobs are using them all. The agent will keep trying to get a connection until it succeeds.

If this message is repeated many times for a WebSphere MQ link, then increase the maximum number of connections used by the Messaging Gateway link associated with the propagation job.

[434] Failed to access queue <queue>; provider queue <queue>

This message indicates that a messaging system native queue cannot be accessed. The queue may have been registered by DBMS_MGWADM.REGISTER_FOREIGN_QUEUE, or it may be an Oracle Streams Advanced Queuing queue. The linked exceptions should give more information.

Possible causes include:

  • The foreign queue was registered incorrectly, or the Messaging Gateway link was configured incorrectly.

    Verify configuration information. If possible, use the same configuration information to run a sample application of the non-Oracle messaging system.

  • The non-Oracle messaging system is not accessible.

    Check that the non-Oracle messaging system is running and can be accessed using the information supplied in the Messaging Gateway link.

  • The Oracle Streams Advanced Queuing queue does not exist. Perhaps the queue was removed after the Messaging Gateway propagation job was created.

    Check that the Oracle Streams Advanced Queuing queue still exists.

[436] LOW MEMORY WARNING: total memory = < >, free_mem = < >

The Messaging Gateway agent JVM is running low on memory. Java garbage collection will be invoked, but this may represent a JVM heap size that is too small. Use the max_memory parameter of DBMS_MGWADM.ALTER_AGENT to increase the JVM heap size. If the Messaging Gateway agent is running, then it must be restarted for this change to take effect.

[703] Failed to retrieve information for transformation <transformation_id>

The Messaging Gateway agent could not obtain all the information it needs about the transformation. The transformation parameter of DBMS_MGWADM.CREATE_JOB must specify the name of the registered transformation and not the name of the transformation function.

Possible causes include:

  • The transformation does not exist. Verify that the transformation has been created. You can see this from the following query performed as user SYS:

    SELECT TRANSFORMATION_ID, OWNER FROM DBA_TRANSFORMATIONS;
    
  • The wrong transformation is registered with Messaging Gateway. Verify that the transformation registered is the one intended.

  • The Messaging Gateway agent user does not have EXECUTE privilege on the object type used for the from_type or the to_type of the transformation indicated in the exception.

    It is not sufficient to grant EXECUTE to MGW_AGENT_ROLE and then grant MGW_AGENT_ROLE to the agent user. You must grant EXECUTE privilege on the object type directly to the agent user or to PUBLIC.

    Example 21-3 shows such a case for the from_type. It also shows the use of linked exceptions for determining the precise cause of the error.

    Example 21-3 No EXECUTE Privilege on Object Type

    Errors occurred during processing of job JOB_AQ2MQ_2
    oracle.mgw.common.GatewayException: [703] Failed to retrieve information for
    transformation mgwuser.SAMPLEADT_TO_MGW_BASIC_MSG
    […Java stack trace here…]
    [Linked-exception]
    java.sql.SQLException: "from_type" is null
    […Java stack trace here…]
    

[720] AQ payload type <type> not supported; queue: <queue>

The payload type of the Oracle Streams Advanced Queuing queue used by a Messaging Gateway propagation job is not directly supported by Messaging Gateway. For non-JMS propagation, Messaging Gateway directly supports the payload types RAW, SYS.MGW_BASIC_MSG_T and SYS.MGW_TIBRV_MSG_T.

Possible actions include:

  • Configure the Messaging Gateway propagation job to use a transformation that converts the queue payload type to a supported type.

  • Remove the Messaging Gateway propagation job and create a new job that uses an Oracle Streams Advanced Queuing queue with a supported payload type.

    For Java Message Service (JMS) propagation, the Messaging Gateway propagation job must be removed and a new job created whose Oracle Streams Advanced Queuing payload type is supported by Oracle Java Message Service (OJMS). Transformations are not supported for JMS propagation.

[721] Transformation type <type> not supported; queue: <queue_name>, transform: <transformation>

A Messaging Gateway propagation job was configured with a transformation that uses an object type that is not one of the Messaging Gateway canonical types.

For an outbound job, the transformation from_type must be the Oracle Streams Advanced Queuing payload type, and the to_type must be a Messaging Gateway canonical type. For an inbound job, the transformation from_type must be a Messaging Gateway canonical type and the to_type must be the Oracle Streams Advanced Queuing payload type.

[722] Message transformation failed; queue: <queue_name>, transform: <transformation>

An error occurred while attempting execution of the transformation. ORA-25229 is typically thrown by Oracle Streams Advanced Queuing when the transformation function raises a PL/SQL exception or some other Oracle error occurs when attempting to use the transformation.

Possible causes include:

  • The Messaging Gateway agent user does not have EXECUTE privilege on the transformation function. This is illustrated in Example 21-4.

    It is not sufficient to grant EXECUTE to MGW_AGENT_ROLE and then grant MGW_AGENT_ROLE to the Messaging Gateway agent user. You must grant EXECUTE privilege on the transformation function directly to the Messaging Gateway agent user or to PUBLIC.

    Example 21-4 No EXECUTE Privilege on Transformation Function

    Errors occurred during processing of job JOB_MQ2AQ_2
    oracle.mgw.common.GatewayException: [722] Message transformation failed queue:
    MGWUSER.DESTQ_SIMPLEADT, transform: MGWUSER.MGW_BASIC_MSG_TO_SIMPLEADT
    […Java stack trace here…]
    [Linked-exception]
    oracle.mgw.common.MessageException: [722] Message transformation failed;
    queue: MGWUSER.DESTQ_SIMPLEADT, transform: 
    MGWUSER.MGW_BASIC_MSG_TO_SIMPLEADT
    […Java stack trace here…]
    [Linked-exception]
    java.sql.SQLException: ORA-25229: error on transformation of message msgid:
    9749DB80C85B0BD4E03408002086745E
    ORA-00604: error occurred at recursive SQL level 1
    ORA-00904: invalid column name
    […Java stack trace here…]
    
  • The transformation function does not exist, even though the registered transformation does. If the transformation function does not exist, it must be re-created.

  • The Messaging Gateway agent user does not have EXECUTE privilege on the payload object type for the queue indicated in the exception.

    It is not sufficient to grant EXECUTE to MGW_AGENT_ROLE and then grant MGW_AGENT_ROLE to the Messaging Gateway agent user. You must grant EXECUTE privilege on the object type directly to the Messaging Gateway agent user or to PUBLIC.

  • The transformation function raised the error. Verify that the transformation function can handle all messages it receives.

[724] Message conversion not supported; to AQ payload type: <type>, from type: <type>

A Messaging Gateway propagation job is configured for inbound propagation where the canonical message type generated by the non-Oracle messaging system link is not compatible with the Oracle Streams Advanced Queuing queue payload type. For example, propagation from a TIB/Rendezvous messaging system to an Oracle Streams Advanced Queuing queue with a SYS.MGW_BASIC_MSG_T payload type, or propagation from WebSphere MQ to an Oracle Streams Advanced Queuing queue with a SYS.MGW_TIBRV_MSG_T payload type.

Possible actions include:

  • Configure the Messaging Gateway propagation job with a transformation that maps the canonical message type generated by the non-Oracle messaging link to the Oracle Streams Advanced Queuing payload type.

  • Remove the Messaging Gateway propagation job and create a new job whose Oracle Streams Advanced Queuing queue payload type matches the canonical message type generated by the non-Oracle link.

[725] Text message not supported for RAW payload

A Messaging Gateway propagation job is configured for inbound propagation to an Oracle Streams Advanced Queuing destination having a RAW payload type. A text message was received from the source (non-Oracle) queue resulting in a message conversion failure.

If support for text data is required, remove the Messaging Gateway propagation job and create a new job to an Oracle Streams Advanced Queuing destination whose payload type supports text data.

[726] Message size <size> too large for RAW payload; maximum size is <size>

A Messaging Gateway propagation job is configured for inbound propagation to an Oracle Streams Advanced Queuing destination having a RAW payload type. A message conversion failure occurred when a message containing a large RAW value was received from the source (non-Oracle) queue.

If large data support is required, remove the Messaging Gateway propagation job and create a new job to an Oracle Streams Advanced Queuing destination whose payload type supports large data, usually in the form of an object type with a BLOB attribute.

[728] Message contains too many large (BLOB) fields

The source message contains too many fields that must be stored in BLOB types. SYS.MGW_TIBRV_MSG_T is limited to three BLOB fields. Reduce the number of large fields in the message, perhaps by breaking them into smaller fields or combining them into fewer large fields.

[729] Message contains too many large (CLOB) fields

The source message contains too many fields that contain a large text value that must be stored in a CLOB. SYS.MGW_TIBRV_MSG_T is limited to three CLOB fields. Reduce the number of large fields in the message, perhaps by breaking them into smaller fields or combining them into fewer large fields.

[805] MQSeries Message error while enqueuing to queue: <queue>

WebSphere MQ returned an error when an attempt was made to put a message in a WebSphere MQ queue. Check the linked exception error code and message in the log file. Consult WebSphere MQ documentation.

PK%5PK-AOEBPS/mg_start.htm Getting Started with Oracle Messaging Gateway

18 Getting Started with Oracle Messaging Gateway

This chapter describes Oracle Messaging Gateway (MGW) prerequisites and how to load, set up, and unload Messaging Gateway. It also describes how to set up and modify the mgw.ora initialization file.

This chapter contains these topics:

Oracle Messaging Gateway Prerequisites

Messaging Gateway uses one Oracle Scheduler job for each Messaging Gateway agent. If the value of the JOB_QUEUE_PROCESSES database initialization parameter is zero, then no Oracle Scheduler jobs will run. If the value is non-zero, it effectively becomes the maximum number of Scheduler jobs and job queue jobs than can run concurrently.

Verify that a non-zero value is set, and that it is large enough to accommodate a Scheduler job for each Messaging Gateway agent to be started.

Loading and Setting Up Oracle Messaging Gateway

Perform the following procedures before running Messaging Gateway:

Loading Database Objects into the Database

Using SQL*Plus, run ORACLE_HOME/mgw/admin/catmgw.sql as user SYS as SYSDBA. This script loads the database objects necessary for Messaging Gateway, including roles, tables, views, object types, and PL/SQL packages. It creates public synonyms for Messaging Gateway PL/SQL packages. It creates two roles, MGW_ADMINISTRATOR_ROLE and MGW_AGENT_ROLE, with certain privileges granted. All objects are owned by SYS.

Modifying listener.ora for the External Procedure

This procedure is for Linux 32-bit operating systems only. Static service information for the listener is not necessary on the Windows operating system.

You must modify listener.ora so that the Messaging Gateway PL/SQL packages can call the external procedure.

  1. Verify that the default Inter-process Communication (IPC) protocol address for the external procedures is set.

    LISTENER = (ADDRESS_LIST=
    (ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC))
    
  2. Add static service information for the listener in step 1. This involves setting a SID_DESC for the listener. Within the SID_DESC, the parameters described in Table 18-1 are important to Messaging Gateway and must be specified according to your own situation.

Table 18-1 SID_DESC Parameters

ParameterDescription

SID_NAME

The SID that is specified in the net service name in tnsnames.ora. In the following example, the SID_NAME is mgwextproc.

ENVS

Set up the LD_LIBRARY_PATH environment needed for the external procedure to run. The LD_LIBRARY_PATH must contain the following paths:

JRE_HOME/lib/PLATFORM_TYPE
JRE_HOME/lib/PLATFORM_TYPE/server
ORACLE_HOME/lib

It should also contain any additional libraries required by third-party messaging systems. See "Setting Up Non-Oracle Messaging Systems".

ORACLE_HOME

Your Oracle home directory. Using $ORACLE_HOME does not work.

PROGRAM

The name of the external procedure agent, which is extproc



Note:

JRE_HOME represents the root directory of a JRE installation, just as ORACLE_HOME represents the root directory of an Oracle installation. Oracle recommends that you use the JRE installed with Oracle Database.

Example 18-1 adds SID_NAME mgwextproc to a listener.ora file for Linux x86.

Example 18-1 Adding Static Service Information for a Listener

# Add a SID_DESC
SID_LIST_LISTENER= (SID_LIST=
(SID_DESC =
   (SID_NAME= mgwextproc)
   (ENVS=
     "LD_LIBRARY_PATH=JRE_HOME/lib/i386:JRE_HOME/lib/i386/server:ORACLE_HOME/lib")
   (ORACLE_HOME=ORACLE_HOME)
   (PROGRAM = extproc))

Modifying tnsnames.ora for the External Procedure

This procedure is for Linux 32-bit operating systems only. For the external procedure, configure a net service name MGW_AGENT in tnsnames.ora whose connect descriptor matches the information configured in listener.ora, as shown in Example 18-2. The net service name must be MGW_AGENT (this value is fixed). The KEY value must match the KEY value specified for the IPC protocol in listener.ora. The SID value must match the value specified for SID_NAME of the SID_DESC entry in listener.ora.

Example 18-2 Configuring MGW_AGENT

MGW_AGENT = 
(DESCRIPTION= 
   (ADDRESS_LIST= (ADDRESS= (PROTOCOL=IPC)(KEY=EXTPROC))) 
   (CONNECT_DATA= (SID=mgwextproc)))

Note:

If the names.default_domain parameter for sqlnet.ora has been used to set a default domain, then that domain must be appended to the MGW_AGENT net service name in tnsnames.ora. For example, if sqlnet.ora contains the entry names.default_domain=acme.com, then the net service name in tnsnames.ora must be MGW_AGENT.acme.com.

Setting Up a mgw.ora Initialization File

The Messaging Gateway default initialization file ORACLE_HOME/mgw/admin/mgw.ora is a text file. The Messaging Gateway external procedure uses it to get initialization parameters to start the Messaging Gateway agent. Copy ORACLE_HOME/mgw/admin/sample_mgw.ora to mgw.ora and modify it according to your situation.

The following procedure sets environment variables and other parameters required for all applications of Messaging Gateway:

  1. Windows Operating System Only: Set the MGW_PRE_PATH variable. Its value is the path to the jvm.dll library:

    set MGW_PRE_PATH = JRE_HOME\bin\client
    

    This variable is prepended to the path inherited by the Messaging Gateway agent process.

  2. Set CLASSPATH to include at least the following:

    • JRE runtime classes:

      JRE_HOME/lib/rt.jar
      
    • Oracle JDBC classes:

      ORACLE_HOME/jdbc/lib/ojdbc5.jar
      
    • Oracle internationalization classes:

      ORACLE_HOME/jlib/orai18n.jar
      
    • SQLJ runtime:

      ORACLE_HOME/sqlj/lib/runtime12.jar
      
    • Java Message Service (JMS) interface

      ORACLE_HOME/rdbms/jlib/jmscommon.jar
      
    • Oracle JMS implementation classes

      ORACLE_HOME/rdbms/jlib/aqapi.jar
      
    • Java transaction API

      ORACLE_HOME/jlib/jta.jar
      
    • Any additional classes needed for Messaging Gateway to access non-Oracle messaging systems


      Note:

      Replace ORACLE_HOME with the appropriate, spelled-out value. Using $ORACLE_HOME, for example, does not work.

      Users of the Windows operating system must set CLASSPATH using the Windows operating system path syntax.


Creating an Oracle Messaging Gateway Administration User

To perform Messaging Gateway administration work, a database user must be created with MGW_ADMINISTRATOR_ROLE privileges, as shown in Example 18-3.

Example 18-3 Creating a Messaging Gateway Administrator User

CREATE USER admin_user IDENTIFIED BY admin_password;
GRANT CREATE SESSION to admin_user;
GRANT MGW_ADMINISTRATOR_ROLE to admin_user;

Creating an Oracle Messaging Gateway Agent User

To establish the Messaging Gateway agent connection back to the database, a database user with MGW_AGENT_ROLE privileges must be created, as shown in Example 18-4.

Example 18-4 Creating a Messaging Gateway Agent User

CREATE USER agent_user IDENTIFIED BY agent_password;
GRANT CREATE SESSION to agent_user;
GRANT MGW_AGENT_ROLE to agent_user;

Configuring Oracle Messaging Gateway Connection Information

After the Messaging Gateway agent user is created, the administration user uses DBMS_MGWADM.ALTER_AGENT to configure Messaging Gateway with the username, password, and database connect string used by the Messaging Gateway agent to connect back to the database, as shown in Example 18-5. Use the Messaging Gateway username and password that you created in "Creating an Oracle Messaging Gateway Agent User". The database connect string parameter can be set to either a net service name in tnsnames.ora (with IPC protocol for better performance) or NULL. If NULL, then the oracle_sid parameter must be set in mgw.ora.

For this release, always specify a not NULL value for the database connect string parameter when calling DBMS_MGWADM.ALTER_AGENT.

Example 18-5 Configuring Messaging Gateway Connection Information

set echo off
set verify off
connect admin_user
 
ACCEPT password CHAR PROMPT 'Enter the password for AGENT_USER: ' HIDE

EXEC DBMS_MGWADM.ALTER_AGENT(
      agent_name  => 'default_agent', 
      username    => 'agent_user', 
      password    => '&password', 
      database    => 'agent_database');

Configuring Oracle Messaging Gateway in a Oracle RAC Environment

This section contains these topics:

Configuring Connection Information for the MGW Agent Connections

You must make all database connections made by the Messaging Gateway agent to the instance on which the Messaging Gateway agent process is running. This ensures correct failover behavior in a Oracle RAC environment. You can configure connections this way by having the instances use slightly different tnsnames.ora files. Each file contains an entry with the same net service name, but the connect data refers to only the instance associated with that tnsnames.ora file. The common net service name would then be used for the database parameter when DBMS_MGWADM.ALTER_AGENT is used to configure the Messaging Gateway agent database connection information.

For example, in a two-instance Oracle RAC environment with instances OraDB1 and OraDB2, where the net service name AGENT_DB is to be used, the tnsnames.ora for instance OraDB1 would look like this:

AGENT_DB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = myhost1.mycorp.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = OraDB10.mycorp.com)
      (INSTANCE_NAME = OraDB1)
    )
  )

The tnsnames.ora for OraDB2 would look like this:

AGENT_DB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = myhost2.mycorp.com)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = OraDB10.mycorp.com)
      (INSTANCE_NAME = OraDB2)
    )
  )

You would then configure Messaging Gateway agent user connection information by running the following command:

EXEC DBMS_MGWADM.ALTER_AGENT(
   agent_name   => 'default_agent', 
   username     => 'agent_user', 
   password     => 'agent_password', 
   database     => 'agent_db');

Setting the Oracle RAC Instance for the Messaging Gateway Agent

Messaging Gateway provides service affinity for the Messaging Gateway agent external process by leveraging the database service support of the Oracle Scheduler. By default, a Messaging Gateway agent will use the default database service that is mapped to all instances. If you want a Messaging Gateway agent to start on a select group of database instances, you must create a database service for those instances and then assign the database service to the Messaging Gateway agent using the SERVICE parameter of the DBMS_MGWADM.CREATE_AGENT or DBMS_MGWADM.ALTER_AGENT procedures. The DBMS_MGWADM.STARTUP procedure submits an Oracle Scheduler job that starts the Messaging Gateway agent external process when the Scheduler job is executed. The Scheduler job will use the database service configured for the Messaging Gateway agent.

The database service specified by the SERVICE parameter is only used for the service affinity of the Oracle Scheduler job and thus the service affinity for the Messaging Gateway external process. It is not used for the database connections made by the Messaging Gateway agent user. Those JDBC client connections are based on the values specified for the DATABASE and CONNTYPE parameters.

Setting Up Non-Oracle Messaging Systems

This section contains these topics:

Setting Up for TIB/Rendezvous

Running as a TIB/Rendezvous Java client application, the Messaging Gateway agent requires TIB/Rendezvous software to be installed on the computer where the Messaging Gateway agent runs. In this section TIBRV_HOME refers to the installed TIB/Rendezvous software location.

Modifying listener.ora

On the Linux operating system, LD_LIBRARY_PATH in the entry for Messaging Gateway must include TIBRV_HOME/lib for the agent to access TIB/Rendezvous shared library files.

On the Windows operating system, you are not required to modify listener.ora. But the system environment variable PATH must include TIBRV_HOME\bin.

Modifying mgw.ora

MGW_PRE_PATH must include the directory that contains the TIB/Rendezvous license ticket file (tibrv.tkt), which usually is located in TIBRV_HOME/bin.

CLASSPATH must include the TIB/Rendezvous jar file TIBRV_HOME/lib/tibrvj.jar. If you use your own customized TIB/Rendezvous advisory message callback, then the location of the callback class must also be included.

You can set the following Java properties to change the default setting:

Example 18-6 Setting Java Properties

setJavaProp oracle.mgw.tibrv.encoding=ISO8859_1
setJavaProp oracle.mgw.tibrv.intraProcAdvSubjects=_RV.>
setJavaProp oracle.mgw.tibrv.advMsgCallback=MyadvCallback

Setting Up for WebSphere MQ Base Java or JMS

The WebSphere MQ client and WebSphere MQ classes for Java and JMS must be installed on the computer where the Messaging Gateway agent runs. In this section MQ_HOME refers to the location of the installed client. On the Linux operating system, this location is always /opt/mqm. On the Windows operating system, the installed location can vary.

Modifying listener.ora

No extra modification of listener.ora is necessary for Messaging Gateway to access WebSphere MQ.

Modifying mgw.ora

When using WebSphere MQ Base Java (non-JMS) interface, set CLASSPATH to include at least the following (in addition to those in "Setting Up a mgw.ora Initialization File"):

  • MQ_HOME/java/lib/com.ibm.mq.jar

  • MQ_HOME/java/lib/connector.jar

When using WebSphere MQ JMS interface, set CLASSPATH to include at least the following (in addition to those in "Setting Up a mgw.ora Initialization File"):

  • MQ_HOME/java/lib/com.ibm.mqjms.jar

  • MQ_HOME/java/lib/com.ibm.mq.jar

  • MQ_HOME/java/lib/connector.jar

Verifying the Oracle Messaging Gateway Setup

The following procedure verifies the setup and includes a simple startup and shutdown of the Messaging Gateway agent:

  1. Start the database listeners.

    Start the listener for the external procedure and other listeners for the regular database connection.

  2. Test the database connect string for the Messaging Gateway agent user.

    Run sqlplus agent_user/agent_password@agent_database.

    If it is successful, then the Messaging Gateway agent is able to connect to the database.

  3. Linux Operating System Only: Test the net service entry used to call the external procedure.

    Run sqlplus agent_user/agent_password@MGW_AGENT.

    This should fail with "ORA-28547: connection to server failed, probable Oracle Net admin error". Any other error indicates that the tnsnames.ora, listener.ora, or both are not correct.

  4. Connect as admin_user and call DBMS_MGWADM.STARTUP to start the Messaging Gateway agent.

  5. Using the MGW_GATEWAY view, wait for AGENT_STATUS to change to RUNNING and AGENT_PING to change to REACHABLE.

  6. Connect as admin_user and call DBMS_MGWADM.SHUTDOWN to shut down the Messaging Gateway agent.

  7. Using the MGW_GATEWAY view, wait for AGENT_STATUS to change to NOT_STARTED.

Unloading Oracle Messaging Gateway

Use this procedure to unload Messaging Gateway:

  1. Shut down Messaging Gateway.

  2. Remove any user-created queues whose payload is a Messaging Gateway canonical type (for example, SYS.MGW_BASIC_MSG_T).

  3. Using SQL*Plus, run ORACLE_HOME/mgw/admin/catnomgw.sql as user SYS as SYSDBA.

    This drops the database objects used by Messaging Gateway, including roles, tables, views, packages, object types, and synonyms.

  4. Remove entries for Messaging Gateway created in listener.ora and tnsnames.ora.

Understanding the mgw.ora Initialization File

Messaging Gateway reads initialization information from a text file when the Messaging Gateway agent starts. The initialization file contains lines for setting initialization parameters, environment variables, and Java properties. Each entity must be specified on one line. Leading whitespace is trimmed in all cases.

A Messaging Gateway administrator can specify the initialization file to be used for a Messaging Gateway agent via DBMS_MGWADM.CREATE_AGENT and DBMS_MGWADM.ALTER_AGENT. If an initialization file is not specified then a default initialization file will be used.

The default initialization file for the default agent is ORACLE_HOME/mgw/admin/mgw.ora.

The default initialization file for a named agent is ORACLE_HOME/mgw/admin/mgw_AGENTNAME.ora where AGENTNAME is the name in uppercase of the Messaging Gateway agent. For example, if the agent name is my_agent then the name of the agent's default initialization file is ORACLE_HOME/mgw/admin/mgw_MY_AGENT.ora. If the default initialization file for a named agent is not found then ORACLE_HOME/mgw/admin/mgw.ora will be used.

mgw.ora Initialization Parameters

The initialization parameters are typically specified by lines having a "name=value<NL>" format where name represents the parameter name, value represents its value and <NL> represents a new line.

log_directory

Usage:  Specifies the directory where the Messaging Gateway log/trace file is created.

Format:  

log_directory = value

Default: 

ORACLE_HOME/mgw/log

Example:  

log_directory = /private/mgwlog

log_level

Usage:  Specifies the level of logging detail recorded by the Messaging Gateway agent. The logging level can be dynamically changed by changed by calling DBMS_MGWADM.SET_LOG_LEVEL while the Messaging Gateway agent is running. Oracle recommends that log level 0 (the default value) be used at all times.

Format:  

log_level = value

Values:  

0 for basic logging; equivalent to DBMS_MGWADM.BASIC_LOGGING

1 for light tracing; equivalent to DBMS_MGWADM.TRACE_LITE_LOGGING

2 for high tracing; equivalent to DBMS_MGWADM.TRACE_HIGH_LOGGING

3 for debug tracing; equivalent to DBMS_MGWADM.TRACE_DEBUG_LOGGING

Example:  

log_level = 0

mgw.ora Environment Variables

Because the Messaging Gateway process environment is not under the direct control of the user, certain environment variables should be set using the initialization file. The environment variables currently used by the Messaging Gateway agent are CLASSPATH, MGW_PRE_PATH, and ORACLE_SID.

Environment variables such as CLASSPATH and MGW_PRE_PATH are set so the Messaging Gateway agent can find the required shared objects, Java classes, and so on. Environment variables are specified by lines having a "set env_var=value<NL>" or "setenv env_var=value<NL>" format where env_var represents the name of the environment variable to set, value represents the value of the environment variable, and <NL> represents a new line.

CLASSPATH

Usage:  Used by the Java Virtual Machine to find Java classes needed by the Messaging Gateway agent for propagation between Oracle Streams Advanced Queuing and non-Oracle messaging systems.

Format:  

set CLASSPATH=value

Example:  

set CLASSPATH=ORACLE_HOME/jdbc/lib/ojdbc5.jar:JRE_HOME/lib/rt.jar:
ORACLE_HOME/sqlj/lib/runtime12.jar:ORACLE_HOME/jlib/orai18n.jar:ORACLE_HOME/rdbms/
jlib/jmscommon.jar:ORACLE_HOME/rdbms/jlib/aqapi.jar:ORACLE_HOME/jlib/jta.jar:
/opt/mqm/java/lib/com.ibm.mq.jar:/opt/mqm/java/lib/com.ibm.mqjms.jar:/opt/mqm/java
/lib/connector.jar

MGW_PRE_PATH

Usage:  Appended to the front of the path inherited by the Messaging Gateway process. For the Windows operating system, this variable must be set to indicate where the library jvm.dll is found.

Format:  

set MGW_PRE_PATH=value

Example:  

set MGW_PRE_PATH=JRE_HOME\bin\client

ORACLE_SID

Usage:  Can be used when a service name is not specified when configuring Messaging Gateway.

Format:  

set ORACLE_SID=value

Example: 

set ORACLE_SID=my_sid

mgw.ora Java Properties

You must specify Java system properties for the Messaging Gateway JVM when working with TIB/Rendezvous subjects. You can use the setJavaProp parameter of the Messaging Gateway initialization file for this. Java properties are specified by lines having a "setJavaProp prop_name=value<NL>" format, where prop_name represents the name of the Java property to set, value represents the value of the Java property, and <NL> represents a new line character.

oracle.mgw.batch_size

Usage: This Java property represents the maximum number of messages propagated in one transaction. It serves as a default value if the Messaging Gateway job option, MsgBatchSize, is not specified. If altered from the default, then consideration should be given to the expected message size and the Messaging Gateway agent memory (see max_memory parameter of DBMS_MGWADM.ALTER_AGENT). The minimum value of this Java property is 1, the maximum is 100, and the default is 30.

Syntax: 

setJavaProp oracle.mgw.batch_size=value

Example: 

setJavaProp oracle.mgw.batch_size=10

oracle.mgw.polling_interval

Usage: This parameter specifies the time (in milliseconds) that must elapse between polls for available messages of a propagation source queue. The default polling interval used by Messaging Gateway is 5000 milliseconds (5 seconds).

Syntax: 

setJavaProp oracle.mgw.polling_interval=value 

Example: 

setJavaProp oracle.mgw.polling_interval=1000 

oracle.mgw.tibrv.encoding

Usage: This parameter specifies the character encoding to be used by the TIB/Rendezvous messaging system links. Only one character set for all configured TIB/Rendezvous links is allowed due to TIB/Rendezvous restrictions. The default is ISO 8859-1 or the character set specified by the Java system property file.encoding.

Syntax: 

setJavaProp oracle.mgw.tibrv.encoding=value 

Example: 

setJavaProp oracle.mgw.tibrv.encoding=ISO8859_1 

oracle.mgw.tibrv.intraProcAdvSubjects

Usage Used for all TIB/Rendezvous messaging system links, this parameter specifies the names of system advisory subjects that present on the intraprocess transport.

Syntax 

setJavaProp oracle.mgw.tibrv.intraProcAdvSubjects=
advisorySubjectName[:advisorySubjectName]

Example: 

setJavaProp oracle.mgw.tibrv.intraProcAdvSubjects=_RV.>

oracle.mgw.tibrv.advMsgCallback

Usage: Used for all TIB/Rendezvous messaging system links, this parameter specifies the name of the Java class that implements the TibrvMsgCallback interface to handle system advisory messages. If it is not specified, then the default system advisory message handler provided by Messaging Gateway is used, which writes system advisory messages into Messaging Gateway log files. If it is specified, then the directory where the class file is stored must be included in the CLASSPATH in mgw.ora.

Syntax: 

setJavaProp oracle.mgw.tibrv.advMsgCallback=className

Example: 

setJavaProp oracle.mgw.tibrv.advMsgCallback=MyAdvCallback

oracle.net.tns_admin

Usage: This parameter specifies the directory of the tnsnames.ora file. It must be set if the Messaging Gateway agent is configured to use the JDBC Thin driver and the database specifier of the agent connection information is a TNSNames alias. This does not need to be set if the JDBC OCI driver is used or the database specifier is something other than a TNSNames alias.

Syntax: 

setJavaProp oracle.net.tns_admin=value

Example: 

setJavaProp oracle.net.tns_admin=/myoraclehome/network/admin

mgw.ora Comment Lines

Comment lines are designated with a # character as the first character of the line.

PKfR PK-AOEBPS/img_text/adque040.htm( Description of the illustration adque040.eps

Applications at the top and bottom of the illustration are linked by arrows with three unlabeled queues in the middle. At top left Application A, Producer is linked with the leftmost queue by a downward-pointing arrow labeled Enqueue (Message 1). At bottom left, Application B, Consumer and Producer is linked to the leftmost queue with a downward-pointing arrow labeled Dequeue (Message 1) and to the middle queue with an upward-pointing arrow labeled Enqueue (Message 2). At top right, Application C, Producer and Consumer is linked to the middle queue by an upward-pointing arrow labeled Dequeue (Message 2) and to the rightmost queue with a downward-pointing arrow labeled Enqueue (Message 3). At bottom right, Application D, Consumer is linked to the rightmost queue with a downward-pointing arrow labeled Dequeue (Message 3).

PKPK-AOEBPS/img_text/adqmg003.htm Description of the illustration adqmg003.eps

Three messages are linked by arrows to illustrate the conversion process. The Advanced Queuing Message consists of an AQ Property and an AQ Payload. The Messaging Gateway Message consists of an AQ Property and a Canonical Type. The Non-Oracle Message consists of the Message only.

Arrows labeled Outbound Propagation point from the Advanced Queuing Message to the Messaging Gateway Message and from there to the Non-Oracle Message. Arrows labeled Inbound Propagation form the same links, but pointing in the other direction.

PK10PK-AOEBPS/img_text/adque430.htm Description of the illustration adque430.eps

An AQ Client is linked to an AQ Servlet in a Web Server with a double-headed arrow labeled XML Message over HTTP. A second arrow points from the Web Server to an Oracle Server containing an AQ Queue.

PK|,PK-AOEBPS/img_text/adque037.html Description of the illustration adque037.eps

Applications at the top and bottom of the illustration are linked by arrows with a queue labeled Multiple Consumer Queue in the middle. At the top, Application A is linked to the queue with a downward-pointing arrow labeled Enqueue. At the bottom, Application B and Application C are each linked to the queue with downward-pointing arrows labeled Dequeue.

PKjPK-AOEBPS/img_text/adque437.htmN Description of the illustration adque437.eps

An Oracle database server appears as a hub, with messages traveling along spokes linking the hub with applications and users at the edges of the illustration. Inside the database hub are labels for Rules and Transformations and Advanced Queues.

A second Oracle database is linked to the hub with a spoke labeled Internet Propagation. A third Oracle database is linked to the hub with a spoke labeled Internet Propagation (Oracle Net). This third Oracle database is also linked by a double-headed arrow to an array of databases labeled Global Agents, Global Subscriptions, Global Events. The array is linked to the hub, so the array and two Oracle databases form a triangle.

Internet Users are linked to the hub by a spoke labeled XML-Based Internet Transport (HTTP(s)) and Internet Access. OCI, PL/SQL, Java Clients are linked to the hub with an unlabeled spoke, as is a representation of a third-party message system labeled MQ Series.

PK. "SNPK-AOEBPS/img_text/strms021.htm Description of the illustration strms021.eps

This flow diagram shows the environment and calling sequence for the Streams Messaging example. The environment is explained in the text.

PK"PK-AOEBPS/img_text/adque448.htmQ Description of the illustration adque448.eps

A CRM Application at the left of the illustration is linked to a Web Application at the right by right-pointing arrows through an Integration Hub in the middle. Inside the Integration Hub, also linked together by right-pointing arrows, are Out Queue on the left, then Routing and Transformation, Propagation, and finally In Queue.

PKnmyгPK-AOEBPS/img_text/adque447.htmQ Description of the illustration adque447.eps

Two messages are linked by arrows to illustrate the conversion process. The Messaging Gateway Message consists of an AQ Property and a Canonical Body. The TIB/Rendezvous Message consists of Fields and Supplementary Information.

Arrows labeled Outbound Propagation point from the Messaging Gateway Message to the TIB/Rendezvous Message, linking AQ Property to Fields, Canonical Body to Fields, and Canonical Body to Supplementary Information. Arrows labeled Inbound Propagation form the same links, but pointing in the other direction.

PKg-VQPK-AOEBPS/img_text/adque446.htm Description of the illustration adque446.eps

A structure with four levels. The top level, labeled cn=acme, cn=com, is the administrative context. The second level, labeled cn=OracleContext, is the root of the Oracle RDBMS schema. The third level, labeled cn=db1, is the database. The fourth level splits into three nodes. They are Connection Factories, labeled cn=OracleDBConnections, Queues/Topics, labeled cn=OracleDBQueue, and Other DB Objects, labeled cn=...

PKX$PK-AOEBPS/img_text/adqmg004.htm Description of the illustration adqmg004.eps

Two messages are linked by arrows to illustrate the conversion process. The Advanced Queuing Message consists of an AQ Property and an AQ Payload. The Messaging Gateway Message consists of an AQ Property and a Canonical Type.

An arrow labeled Outbound Propagation points from the AQ Property of the Advanced Queuing Message to the AQ Property of the Messaging Gateway Message. Another Outbound Propagation arrow points from the AQ Payload of the Advanced Queuing Message to the Canonical Type of the Messaging Gateway Message. Arrows labeled Inbound Propagation form the same links, but pointing in the other direction.

Optional user-supplied Transformation Functions, to convert between message types, are represented as detours on the two arrows linking message payloads.

PKTPK-AOEBPS/img_text/adque042.htmw Description of the illustration adque042.eps

Three applications, one at the top and two at the bottom, each with a pair of queues labeled Inbox and Outbox, are linked through Oracle Streams AQ Message Propagation Infrastructure in the middle. Each application is labeled Producer and Consumer. Arrows labeled Enqueue point from each application to its Outbox, and arrows labeled Dequeue point to each application from its Inbox. Application A, at the top of the illustration, resides in Database 1. Application B and Application C, at the bottom of the illustration, reside in Database 2.

The Outbox of Application A is linked to the Inbox of Application B by an arrow that passes through the Message Propagation Infrastructure. Similar arrows link the Outbox of Application B to the Inbox of Application C and the Outbox of Application C to the Inbox of Application A.

PK n|wPK-AOEBPS/img_text/adque039.htm; Description of the illustration adque039.eps

Applications at the top and bottom of the illustration are linked by arrows with an unlabeled queue in the middle. At the top, Application A is linked to the queue with a downward-pointing arrow labeled Enqueue. At the bottom are three more applications, each labeled consumer (subscriber). Application B and Application C each carry the additional label Implicit Recipient and are linked to the queue with solid downward-pointing arrows labeled Dequeue. Application D carries the additional label Explicit Recipient and is linked to the queue with a dashed downward-pointing arrow.

PKHǟPK-AOEBPS/img_text/adque249.htmB Description of the illustration adque249.eps

Unlabeled applications, two at the left and two at the right of the illustration, are linked to a database labeled Oracle Advanced Queues in the middle. The two links at the left are double-headed arrows labeled Publish. The two links at the right are double-headed arrows labeled Subscribe and Publish/Subscribe respectively.

PK!ݵGBPK-AOEBPS/img_text/adque445.htmy Description of the illustration adque445.eps

An arrow points from a Job Queue Process on a Source Database to an AQ Queue in the same database. A second arrow from the Job Queue Process points to an AQ Servlet on a Web Server. A third arrow points from the AQ Servlet to an AQ Queue on a Destination Database.

PKPK-AOEBPS/img_text/adque035.htmR Description of the illustration adque035.eps

Applications at the top and bottom of the illustration are linked by arrows with two queues in the middle of the illustration. The application at the top is labeled Application A, Consumer and Producer and Client. It is linked to a queue labeled Request Queue by a downward-pointing arrow labeled Enqueue and to a queue labeled Response Queue by an upward-pointing arrow labeled Dequeue.

The application at the bottom of the illustration is labeled Application B, Producer and Consumer and Server. It is linked to Request Queue by a downward-pointing arrow labeled Dequeue and to Response Queue by an upward-pointing arrow labeled Enqueue.

PKUo=WRPK-AOEBPS/img_text/adqmg005.htmP Description of the illustration adqmg005.eps

Two messages are linked by arrows to illustrate the conversion process. The Messaging Gateway Message consists of an AQ Property, a Canonical Header, and a Canonical Body. The MQSeries Message consists of a Header and a Body.

Arrows labeled Outbound Propagation point from the Messaging Gateway Message to the MQSeries Message, linking AQ Property to Header, Canonical Header to Header, and Canonical Body to Body. Arrows labeled Inbound Propagation form the same links, but pointing in the other direction.

PKUPPK-AOEBPS/img_text/adque041.htmJ Description of the illustration adque041.eps

Applications, one at the top and three at the bottom of the illustration, are linked to an unlabeled queue in the middle. The queue contains three messages labeled priority 3, priority 1, and priority 2 respectively. At the top of the illustration, Application A, Producer is linked to the queue with a downward-pointing arrow labeled Enqueue.

All three applications at the bottom carry the label Consumer (Rule-Based Subscriber). At bottom left, Application B carries the additional label "priority = 1" and is linked to the queue with a downward-pointing arrow labeled Dequeue. Application D carries the additional label "priority = 3" and is also linked to the queue with a downward-pointing arrow. Application C carries the additional label "priority > 1" and is linked to the queue with two arrows. One points downward and is labeled Dequeue. The other arrow points back to the queue and is labeled Register.

PKfnPK-AOEBPS/img_text/adque449.htm` Description of the illustration adque449.eps

Messaging Gateway architecture is represented by four elements connected with arrows. At the upper left is Messaging Gateway Administration PL/SQL Interface, with an arrow pointing to an Oracle Database at lower left. The database contains AQ Queues. The database is connected by a double-headed arrow to Messaging Gateway Agent, which contains the Propagation Engine and three drivers. Each driver is connected by a double-headed arrow labeled Messaging System Link to one of three databases at lower right. MQ Base Java Driver is connected to MQSeries, MQ JMS Driver is connected to another MQSeries, and TIB/Rendezvous Driver is connected to TIB/Rendezvous.

PKR?e`PK-AOEBPS/img_text/adque450.htme Description of the illustration adque450.eps

Three messages linked by arrows illustrate message conversion. The Oracle JMS Message, Messaging Gateway Message, and Third-Party JMS Message each consist of a Header, Properties, and a Body. Arrows labeled Outbound Propagation point from the Oracle JMS Message to the Messaging Gateway Message, and from there to the Third-Party JMS Message. Arrows labeled Inbound Propagation form the same links, but pointing in the other direction.

PKЄCjePK-AOEBPS/img_text/adque250.htmt Description of the illustration adque250.eps

Unlabeled applications at the left and right of the illustration are linked to a database labeled Oracle Advanced Queues in the middle. The links are double-headed arrows labeled Enqueue/Dequeue.

PKPK-AOEBPS/aq_demo.htm Oracle Streams Messaging Examples

23 Oracle Streams Messaging Examples

The examples in this chapter illustrate a messaging environment that can be constructed using Oracle Streams. The examples assume you are in a SQL*Plus testing environment with access to a database named db01.

This chapter contains these topics:

Overview of Messaging Example

This example illustrates using a single ANYDATA queue to create an Oracle Streams messaging environment in which message payloads of different types are stored in the same queue. Specifically, this example illustrates the following messaging features of Oracle Streams:

  • Enqueuing messages containing order payload as ANYDATA payloads

  • Enqueuing messages containing customer payload as ANYDATA payloads

  • Enqueuing messages containing row LCRs as ANYDATA payloads

  • Creating a rule set for applying the events

  • Creating an evaluation context used by the rule set

  • Creating an Oracle Streams apply process to dequeue and process the events based on rules

  • Creating a message handler and associating it with the apply process

  • Explicitly dequeuing and processing events based on rules without using the apply process

Figure 23-1 provides an overview of this environment.

Figure 23-1 Example Oracle Streams Messaging Environment

Description of Figure 23-1 follows
Description of "Figure 23-1 Example Oracle Streams Messaging Environment"

Setting Up Users and Creating an ANYDATA Queue

Because the examples in this chapter use the oe sample schema, the oe user must have privileges to run the subprograms in the DBMS_AQ package. This is accomplished in Example 23-1.


Note:

The oe user is specified as the queue user when the ANYDATA queue is created in Example 23-2. The SET_UP_QUEUE procedure grants the oe user enqueue and dequeue privileges on the queue, but the oe user also needs EXECUTE privilege on the DBMS_AQ package to enqueue and dequeue messages.

Most of the configuration and administration actions illustrated in these examples are performed by the Oracle Streams administrator strmadmin. Example 23-1 also creates this user and grants the necessary privileges. These privileges enable the user to run subprograms in packages related to Oracle Streams, create rule sets, create rules, and monitor the Oracle Streams environment by querying data dictionary views.

In Example 23-1, you connect to database db01 as a user with administrative privileges.

Example 23-1 Setting Up ANYDATA Users

GRANT EXECUTE ON DBMS_AQ TO oe;
CREATE USER strmadmin IDENTIFIED  BY strmadmin DEFAULT TABLESPACE example;
GRANT DBA, SELECT_CATALOG_ROLE    TO strmadmin; 
GRANT EXECUTE ON DBMS_APPLY_ADM   TO strmadmin;
GRANT EXECUTE ON DBMS_AQ          TO strmadmin;
GRANT EXECUTE ON DBMS_AQADM       TO strmadmin;
GRANT EXECUTE ON DBMS_STREAMS_ADM TO strmadmin;
BEGIN 
  DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
    privilege    => DBMS_RULE_ADM.CREATE_RULE_SET_OBJ, 
    grantee      => 'strmadmin', 
    grant_option => FALSE);
  DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
    privilege    => DBMS_RULE_ADM.CREATE_RULE_OBJ, 
    grantee      => 'strmadmin', 
    grant_option => FALSE);
  DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
    privilege    => DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT_OBJ, 
    grantee      => 'strmadmin', 
    grant_option => FALSE);
END;
/

Note:

  • The SELECT_CATALOG_ROLE is not required for the Oracle Streams administrator. It is granted in this example so that the Oracle Streams administrator can monitor the environment easily.

  • If you plan to use the Oracle Streams tool in Oracle Enterprise Manager, then grant the Oracle Streams administrator SELECT ANY DICTIONARY privilege, in addition to the privileges shown in this step.


In Example 23-2, you connect to database db01 as administrator user strmadmin to create ANYDATA queue oe_queue. The SET_UP_QUEUE procedure creates a queue table for the queue and then creates and starts the queue.

Example 23-2 Creating an ANYDATA Queue

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDE
CONNECT strmadmin/&password@db01;
set echo on

BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE( 
    queue_table => 'oe_queue_table', 
    queue_name  => 'oe_queue');
END;
/

In Example 23-3, you connect to database db01 as administrator user strmadmin to grant the oe user privileges on queue oe_queue, create agent explicit_enq that will be used to perform explicit enqueue operations on the queue, and associate the oe user with the agent.

Queue oe_queue is a secure queue because it was created using SET_UP_QUEUE. For a user to perform enqueue and dequeue operations on a secure queue, the user must be configured as a secure queue user of the queue. Associating the oe user with agent explicit_enq enables the oe user to perform enqueue operations on this queue.

Example 23-3 Enabling Enqueue on the ANYDATA Queue

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDE
CONNECT strmadmin/&password@db01;
set echo on

BEGIN
  SYS.DBMS_AQADM.GRANT_QUEUE_PRIVILEGE(
    privilege  => 'ALL',
    queue_name => 'strmadmin.oe_queue',
    grantee    => 'oe');
  SYS.DBMS_AQADM.CREATE_AQ_AGENT(
    agent_name  => 'explicit_enq');
  DBMS_AQADM.ENABLE_DB_ACCESS(
    agent_name  => 'explicit_enq',
    db_username => 'oe');
END;
/

Creating Enqueue Procedures

The examples in this section create two PL/SQL procedures that enqueue messages into the ANYDATA queue oe_queue. One procedure enqueues non-LCR messages, and the other procedure enqueues row LCR messages.

In Example 23-4, you connect to database db01 as sample schema user oe to create a type to represent orders based on the columns in the oe.orders table. This type is used for messages that are enqueued into the ANYDATA queue oe_queue. The type attributes include the columns in the oe.orders table, along with one extra attribute named action. The value of the action attribute for instances of this type is used to determine the correct action to perform on the instance (either apply process dequeue or explicit dequeue).

Example 23-4 Creating an Orders Type

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDE
CONNECT oe/&password@db01;
set echo on

CREATE TYPE order_event_typ AS OBJECT(
  order_id       NUMBER(12),
  order_date     TIMESTAMP(6) WITH LOCAL TIME ZONE,
  order_mode     VARCHAR2(8),
  customer_id    NUMBER(6),
  order_status   NUMBER(2),
  order_total    NUMBER(8,2),
  sales_rep_id   NUMBER(6),
  promotion_id   NUMBER(6),
  action         VARCHAR(7));
/

In Example 23-5, you connect to database db01 as sample schema user oe to create a type to represent customers based on the columns in the oe.customers table. This type is used for messages that are enqueued into the ANYDATA queue oe_queue. The type attributes include the columns in the oe.customers table, along with one extra attribute named action. The value of the action attribute for instances of this type is used to determine the correct action to perform on the instance (either apply process dequeue or explicit dequeue).


Note:

This example assumes you have dropped the cust_geo_location column from the oe.customers table. This column is useful only with Oracle Spatial.

Example 23-5 Creating a Customers Type

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDECONNECT oe/&password@db01;set echo on

CREATE TYPE customer_event_typ AS OBJECT(
  customer_id         NUMBER(6),
  cust_first_name     VARCHAR2(20),
  cust_last_name      VARCHAR2(20),
  cust_address        CUST_ADDRESS_TYP,
  phone_numbers       PHONE_LIST_TYP,
  nls_language        VARCHAR2(3),
  nls_territory       VARCHAR2(30),
  credit_limit        NUMBER(9,2),
  cust_email          VARCHAR2(30),
  account_mgr_id      NUMBER(6),
  date_of_birth       DATE,
  marital_status      VARCHAR2(20),
  gender              VARCHAR2(1),
  income_level        VARCHAR2(20),
  action              VARCHAR(7));
/

In Example 23-6, you connect to database db01 as sample schema user oe to create a PL/SQL procedure called enq_proc to enqueue non-LCR messages into ANYDATA queue oe_queue.


Note:

A single enqueued message can be dequeued by both an apply process and an explicit dequeue, but the examples in this chapter do not illustrate this capability.

Example 23-6 Creating a Procedure to Enqueue Non-LCR Messages

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDECONNECT oe/&password@db01;set echo on

CREATE PROCEDURE oe.enq_proc (event IN ANYDATA) IS
    enqopt       DBMS_AQ.ENQUEUE_OPTIONS_T;
    mprop        DBMS_AQ.MESSAGE_PROPERTIES_T;
    enq_eventid  RAW(16);
  BEGIN
    mprop.SENDER_ID := SYS.AQ$_AGENT('explicit_enq', NULL, NULL);
    DBMS_AQ.ENQUEUE(
      queue_name          =>  'strmadmin.oe_queue',
      enqueue_options     =>  enqopt,
      message_properties  =>  mprop,
      payload             =>  event,
      msgid               =>  enq_eventid);
END;
/

In Example 23-7, you connect to database db01 as sample schema user oe to create a PL/SQL procedure called enq_row_lcr that constructs a row LCR and then enqueues the row LCR into ANYDATA queue oe_queue.


See Also:

Oracle Database PL/SQL Packages and Types Reference for more information about LCR constructors

Example 23-7 Creating a Procedure to Construct and Enqueue Row LCR Events

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDECONNECT oe/&password@db01;set echo on

CREATE PROCEDURE oe.enq_row_lcr(
  source_dbname  VARCHAR2,
  cmd_type       VARCHAR2,
  obj_owner      VARCHAR2,
  obj_name       VARCHAR2,
  old_vals       SYS.LCR$_ROW_LIST,
  new_vals       SYS.LCR$_ROW_LIST) 
AS
  eopt           DBMS_AQ.ENQUEUE_OPTIONS_T;
  mprop          DBMS_AQ.MESSAGE_PROPERTIES_T;
  enq_msgid      RAW(16);
  row_lcr        SYS.LCR$_ROW_RECORD;
BEGIN
  mprop.SENDER_ID := SYS.AQ$_AGENT('explicit_enq', NULL, NULL); 
  row_lcr := SYS.LCR$_ROW_RECORD.CONSTRUCT(
    source_database_name  =>  source_dbname,
    command_type          =>  cmd_type,
    object_owner          =>  obj_owner,
    object_name           =>  obj_name,
    old_values            =>  old_vals,
    new_values            =>  new_vals);
  DBMS_AQ.ENQUEUE(
    queue_name         =>  'strmadmin.oe_queue', 
    enqueue_options    =>  eopt,
    message_properties =>  mprop,
    payload            =>  ANYDATA.ConvertObject(row_lcr),
    msgid              =>  enq_msgid);
END enq_row_lcr;
/

Configuring an Apply Process

The examples in this section configure an apply process to apply the user-enqueued messages in the ANYDATA queue oe_queue.

In Example 23-8, you connect to database db01 as sample schema user oe to create a function called get_oe_action and to grant EXECUTE privilege on the function to administrator user strmadmin.

This function determines the value of the action attribute in the messages in queue oe_queue. It is used in rules later in this chapter to determine the value of the action attribute for an event. Then, the clients of the rules engine perform the appropriate action for the event (either dequeue by apply process or explicit dequeue). In this example, the clients of the rules engine are the apply process and the oe.explicit_dq PL/SQL procedure.

Example 23-8 Creating a Function to Determine the Value of the Action Attribute

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDECONNECT oe/&password@db01;set echo on

CREATE FUNCTION oe.get_oe_action (event IN ANYDATA) 
RETURN VARCHAR2
IS 
  ord         oe.order_event_typ;
  cust        oe.customer_event_typ;
  num         NUMBER;
  type_name   VARCHAR2(61);
BEGIN
  type_name := event.GETTYPENAME; 
  IF type_name = 'OE.ORDER_EVENT_TYP' THEN
    num := event.GETOBJECT(ord);
    RETURN ord.action;  
  ELSIF type_name = 'OE.CUSTOMER_EVENT_TYP' THEN
    num := event.GETOBJECT(cust);
    RETURN cust.action; 
  ELSE
    RETURN NULL;
  END IF;
END;
/
GRANT EXECUTE ON get_oe_action TO strmadmin;

In Example 23-9, you connect to database db01 as sample schema user oe to create a PL/SQL procedure called mes_handler that is used as a message handler by the apply process. You also grant EXECUTE privilege on this procedure to administrator user strmadmin. This procedure takes the payload in a user-enqueued message of type oe.order_event_typ or oe.customer_event_typ and inserts it as a row in the oe.orders table or oe.customers table, respectively.

Example 23-9 Creating a Message Handler

set echo offset verify offACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDECONNECT oe/&password@db01;set echo on

CREATE PROCEDURE oe.mes_handler (event IN ANYDATA) IS
  ord           oe.order_event_typ;
  cust          oe.customer_event_typ;
  num           NUMBER;
  type_name     VARCHAR2(61);
BEGIN
  type_name := event.GETTYPENAME;
  IF type_name = 'OE.ORDER_EVENT_TYP' THEN
    num := event.GETOBJECT(ord);
    INSERT INTO oe.orders VALUES (ord.order_id, ord.order_date, 
      ord.order_mode, ord.customer_id, ord.order_status, ord.order_total, 
      ord.sales_rep_id, ord.promotion_id); 
  ELSIF type_name = 'OE.CUSTOMER_EVENT_TYP' THEN
    num := event.GETOBJECT(cust);
    INSERT INTO oe.customers VALUES (cust.customer_id, cust.cust_first_name, 
      cust.cust_last_name, cust.cust_address, cust.phone_numbers, 
      cust.nls_language, cust.nls_territory, cust.credit_limit, cust.cust_email, 
      cust.account_mgr_id, cust.date_of_birth, cust.marital_status, 
      cust.gender, cust.income_level); 
  END IF;
END;
/
GRANT EXECUTE ON mes_handler TO strmadmin;

In Example 23-10, you connect to database db01 as administrator user strmadmin to create an evaluation context for the rule set.

Example 23-10 Creating an Evaluation Context for the Rule Set

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDE
CONNECT strmadmin/&password@db01;
set echo on

DECLARE
  table_alias     SYS.RE$TABLE_ALIAS_LIST;
BEGIN
  table_alias := SYS.RE$TABLE_ALIAS_LIST(
    SYS.RE$TABLE_ALIAS('tab', 'strmadmin.oe_queue_table'));
  DBMS_RULE_ADM.CREATE_EVALUATION_CONTEXT(
    evaluation_context_name  =>  'oe_eval_context', 
    table_aliases            =>  table_alias);
END;
/

In Example 23-11, you connect to database db01 as administrator user strmadmin to create a rule set for the apply process.

Example 23-11 Creating a Rule Set for the Apply Process

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDE
CONNECT strmadmin/&password@db01;
set echo on

BEGIN
  DBMS_RULE_ADM.CREATE_RULE_SET(
    rule_set_name       =>  'apply_oe_rs',
    evaluation_context  =>  'strmadmin.oe_eval_context');
END;
/

In Example 23-12, you connect to database db01 as administrator user strmadmin to create a rule that evaluates to TRUE if the action value of a message is apply. Notice that tab.user_data is passed to the oe.get_oe_action function. The tab.user_data column holds the event payload in a queue table. The table alias for the queue table was specified as tab in Example 23-10.

Example 23-12 Creating a Rule that Evaluates to TRUE if Action Is Apply

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDE
CONNECT strmadmin/&password@db01; 
set echo on

BEGIN
  DBMS_RULE_ADM.CREATE_RULE(
    rule_name   => 'strmadmin.apply_action',
    condition   => 'oe.get_oe_action(tab.user_data) = ''APPLY'' ');
END;
/

In Example 23-13, you connect to database db01 as administrator user strmadmin to create a rule that evaluates to TRUE if the event in the queue is a row LCR that changes either the oe.orders table or the oe.customers table. This rule enables the apply process to apply user-enqueued changes to the tables directly.

For convenience, this rule uses the Oracle-supplied evaluation context SYS.STREAMS$_EVALUATION_CONTEXT because the rule is used to evaluate LCRs. When this rule is added to the rule set, the Oracle-supplied evaluation context is used for the rule during evaluation instead of evaluation context oe_eval_context created in Example 23-10.

Example 23-13 Creating a Rule that Evaluates to TRUE for Row LCR Events

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDE
CONNECT strmadmin/&password@db01;
set echo on

BEGIN
  DBMS_RULE_ADM.CREATE_RULE(
    rule_name           =>  'apply_lcrs',
    condition           =>  ':dml.GET_OBJECT_OWNER() = ''OE'' AND ' || 
                            ' (:dml.GET_OBJECT_NAME() = ''ORDERS'' OR ' || 
                            ':dml.GET_OBJECT_NAME() = ''CUSTOMERS'') ',
    evaluation_context  =>  'SYS.STREAMS$_EVALUATION_CONTEXT');
END;
/

In Example 23-14, you connect to database db01 as administrator user strmadmin to add the apply_action rule created in Example 23-12 and the apply_lcrs rule created in Example 23-13 to the apply_oe_rs rule set created in Example 23-11.

Example 23-14 Adding Rules to the Rule Set

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDECONNECT strmadmin/&password@db01;set echo on

BEGIN
  DBMS_RULE_ADM.ADD_RULE(
    rule_name          =>  'apply_action',
    rule_set_name      =>  'apply_oe_rs');
  DBMS_RULE_ADM.ADD_RULE(
    rule_name          =>  'apply_lcrs',
    rule_set_name      =>  'apply_oe_rs');
END;
/

In Example 23-15, you connect to database db01 as administrator user strmadmin to create an apply process that is associated with queue oe_queue, that uses the apply_oe_rs rule set, and that uses the mes_handler procedure as a message handler.

Example 23-15 Creating an Apply Process

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDECONNECT strmadmin/&password@db01;set echo on

BEGIN
  DBMS_APPLY_ADM.CREATE_APPLY(
    queue_name       =>  'strmadmin.oe_queue',
    apply_name       =>  'apply_oe',
    rule_set_name    =>  'strmadmin.apply_oe_rs',
    message_handler  =>  'oe.mes_handler',
    apply_user       =>  'oe',
    apply_captured   =>  false);
END;
/

Because oe was specified as the apply user when the apply process was created in Example 23-15, you must grant this user EXECUTE privilege on the strmadmin.apply_oe_rs rule set used by the apply process. You connect to database db01 as administrator user strmadmin to accomplish this in Example 23-16.

Example 23-16 Granting EXECUTE Privilege on the Rule Set To oe User

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDECONNECT strmadmin/&password@db01;set echo on

BEGIN 
  DBMS_RULE_ADM.GRANT_OBJECT_PRIVILEGE(
    privilege    => DBMS_RULE_ADM.EXECUTE_ON_RULE_SET,
    object_name  => 'strmadmin.apply_oe_rs',
    grantee      => 'oe', 
    grant_option => FALSE);
END;
/

In Example 23-17, you connect to database db01 as administrator user strmadmin to start the apply process with the disable_on_error parameter set to n so that the apply process is not disabled if it encounters an error.

Example 23-17 Starting the Apply Process

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDECONNECT strmadmin/&password@db01;set echo on

BEGIN
  DBMS_APPLY_ADM.SET_PARAMETER(
    apply_name  => 'apply_oe', 
    parameter   => 'disable_on_error', 
    value       => 'n');
  DBMS_APPLY_ADM.START_APPLY(
    apply_name  =>  'apply_oe');
END;
/

Configuring Explicit Dequeue

The examples in this section illustrate how to configure explicit dequeue of messages based on message contents.

In Example 23-18, you connect to database db01 as administrator user strmadmin to create agent explicit_dq. This agent is used to perform explicit dequeue operations on the oe_queue queue.

Example 23-18 Creating an Agent for Explicit Dequeue

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDECONNECT strmadmin/&password@db01;set echo on

BEGIN
  SYS.DBMS_AQADM.CREATE_AQ_AGENT(
    agent_name      => 'explicit_dq');
END;
/

The oe_queue queue is a secure queue because it was created using SET_UP_QUEUE in Example 23-2. For a user to perform enqueue and dequeue operations on a secure queue, the user must be configured as a secure queue user of the queue.

In Example 23-19, you connect to database db01 as administrator user strmadmin to associate the oe user with agent explicit_dq. The oe user is able to perform dequeue operations on the oe_queue queue when the agent is used to create a subscriber to the queue in Example 23-20.

Example 23-19 Associating User oe with Agent explicit_dq

set echo offset verify offACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDECONNECT strmadmin/&password@db01;set echo on

BEGIN
  DBMS_AQADM.ENABLE_DB_ACCESS(
    agent_name  => 'explicit_dq',
    db_username => 'oe');
END;
/

In Example 23-20, you connect to database db01 as administrator user strmadmin to add a subscriber to the oe_queue queue. This subscriber will perform explicit dequeues of messages. A subscriber rule is used to dequeue any messages where the action value is not apply. If the action value is apply for a message, then the message is ignored by the subscriber. Such messages are dequeued and processed by the apply process.

Example 23-20 Adding a Subscriber to the oe_queue Queue

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for STRMADMIN: ' HIDECONNECT strmadmin/&password@db01;set echo on

DECLARE
  subscriber SYS.AQ$_AGENT;
BEGIN
  subscriber :=  SYS.AQ$_AGENT('explicit_dq', NULL, NULL);
  SYS.DBMS_AQADM.ADD_SUBSCRIBER(
    queue_name  =>  'strmadmin.oe_queue',
    subscriber  =>  subscriber,
    rule        =>  'oe.get_oe_action(tab.user_data) != ''APPLY''');
END;
/

In Example 23-21, you connect to database db01 as sample schema user oe to create a PL/SQL procedure called explicit_dq to dequeue messages explicitly using the subscriber created in Example 23-20.

The procedure commits after the dequeue of the messages. The commit informs the queue that the dequeued messages have been consumed successfully by this subscriber.

The procedure can process multiple transactions and uses two exception handlers. Exception handler next_trans moves to the next transaction, and exception handler no_messages exits the loop when there are no more messages.

Example 23-21 Creating a Procedure to Dequeue Messages Explicitly

SET ECHO OFFSET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDECONNECT oe/&password@db01;set echo on

CREATE PROCEDURE oe.explicit_dq (consumer IN VARCHAR2) AS
  deqopt       DBMS_AQ.DEQUEUE_OPTIONS_T;
  mprop        DBMS_AQ.MESSAGE_PROPERTIES_T;
  msgid        RAW(16);
  payload      ANYDATA;
  new_messages BOOLEAN := TRUE;
  ord          oe.order_event_typ;
  cust         oe.customer_event_typ;
  tc           pls_integer;
  next_trans   EXCEPTION;
  no_messages  EXCEPTION; 
  pragma exception_init (next_trans, -25235);
  pragma exception_init (no_messages, -25228);
BEGIN
  deqopt.consumer_name := consumer;
  deqopt.wait := 1;
  WHILE (new_messages) LOOP
    BEGIN
    DBMS_AQ.DEQUEUE(
      queue_name          =>  'strmadmin.oe_queue',
      dequeue_options     =>  deqopt,
      message_properties  =>  mprop,
      payload             =>  payload,
      msgid               =>  msgid);
    COMMIT;
    deqopt.navigation := DBMS_AQ.NEXT;
    DBMS_OUTPUT.PUT_LINE('Message Dequeued');
    DBMS_OUTPUT.PUT_LINE('Type Name := ' || payload.GetTypeName);
    IF (payload.GetTypeName = 'OE.ORDER_EVENT_TYP') THEN
      tc := payload.GetObject(ord); 
      DBMS_OUTPUT.PUT_LINE('order_id     - ' || ord.order_id);
      DBMS_OUTPUT.PUT_LINE('order_date   - ' || ord.order_date);
      DBMS_OUTPUT.PUT_LINE('order_mode   - ' || ord.order_mode);
      DBMS_OUTPUT.PUT_LINE('customer_id  - ' || ord.customer_id);
      DBMS_OUTPUT.PUT_LINE('order_status - ' || ord.order_status);
      DBMS_OUTPUT.PUT_LINE('order_total  - ' || ord.order_total);
      DBMS_OUTPUT.PUT_LINE('sales_rep_id - ' || ord.sales_rep_id);
      DBMS_OUTPUT.PUT_LINE('promotion_id - ' || ord.promotion_id);
    END IF;
    IF (payload.GetTypeName = 'OE.CUSTOMER_EVENT_TYP') THEN
      tc := payload.GetObject(cust);
      DBMS_OUTPUT.PUT_LINE('customer_id       - ' || cust.customer_id);
      DBMS_OUTPUT.PUT_LINE('cust_first_name   - ' || cust.cust_first_name);
      DBMS_OUTPUT.PUT_LINE('cust_last_name    - ' || cust.cust_last_name);
      DBMS_OUTPUT.PUT_LINE('street_address    - ' || 
                              cust.cust_address.street_address);
      DBMS_OUTPUT.PUT_LINE('postal_code       - ' || 
                              cust.cust_address.postal_code);
      DBMS_OUTPUT.PUT_LINE('city              - ' || cust.cust_address.city);
      DBMS_OUTPUT.PUT_LINE('state_province    - ' || 
                              cust.cust_address.state_province);
      DBMS_OUTPUT.PUT_LINE('country_id        - ' || 
                              cust.cust_address.country_id);
      DBMS_OUTPUT.PUT_LINE('phone_number1     - ' || cust.phone_numbers(1));
      DBMS_OUTPUT.PUT_LINE('phone_number2     - ' || cust.phone_numbers(2));
      DBMS_OUTPUT.PUT_LINE('phone_number3     - ' || cust.phone_numbers(3));
      DBMS_OUTPUT.PUT_LINE('nls_language      - ' || cust.nls_language);
      DBMS_OUTPUT.PUT_LINE('nls_territory     - ' || cust.nls_territory);
      DBMS_OUTPUT.PUT_LINE('credit_limit      - ' || cust.credit_limit);
      DBMS_OUTPUT.PUT_LINE('cust_email        - ' || cust.cust_email);
      DBMS_OUTPUT.PUT_LINE('account_mgr_id    - ' || cust.account_mgr_id);
      DBMS_OUTPUT.PUT_LINE('date_of_birth     - ' || cust.date_of_birth);
      DBMS_OUTPUT.PUT_LINE('marital_status    - ' || cust.marital_status);
      DBMS_OUTPUT.PUT_LINE('gender            - ' || cust.gender);
      DBMS_OUTPUT.PUT_LINE('income_level      - ' || cust.income_level);
    END IF;
    EXCEPTION
      WHEN next_trans THEN
      deqopt.navigation := DBMS_AQ.NEXT_TRANSACTION;
      WHEN no_messages THEN
        new_messages  := FALSE;
        DBMS_OUTPUT.PUT_LINE('No more messagess');
     END;
  END LOOP; 
END;
/

Enqueuing Messages

The examples in this section illustrate how to enqueue non-LCR messages and row LCR messages into a queue.


Note:

It is possible to dequeue user-enqueued LCRs explicitly, but these examples do not illustrate this capability.

In Example 23-22, you connect to database db01 as sample schema user oe to enqueue two messages with apply for the action value. Based on the apply process rules, the apply process dequeues and processes these messages with the oe.mes_handler message handler procedure created in Example 23-9. The COMMIT after the enqueues makes these two enqueues part of the same transaction. An enqueued message is not visible until the session that enqueued it commits the enqueue.

Example 23-22 Enqueuing Non-LCR Messages to Be Dequeued by an Apply Process

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDECONNECT oe/&password@db01;set echo on

BEGIN
  oe.enq_proc(ANYDATA.convertobject(oe.order_event_typ(
    2500,'05-MAY-01','online',117,3,44699,161,NULL,'APPLY')));
END;
/
BEGIN
  oe.enq_proc(ANYDATA.convertobject(oe.customer_event_typ(
    990,'Hester','Prynne',oe.cust_address_typ('555 Beacon Street',
    '02109','Boston','MA','US'),oe.phone_list_typ('+1 617 123 4104',
    '+1 617 083 4381','+1 617 742 5813'),'i','AMERICA',5000,
    'a@scarlet_letter.com',145,NULL,'SINGLE','F','UNDER 50,000','APPLY')));
END;
/ 
COMMIT;

In Example 23-23, you connect to database db01 as sample schema user oe to enqueue two messages with dequeue for the action value. The oe.explicit_dq procedure created in Example 23-21 dequeues these messages because the action is not apply. Based on the apply process rules, the apply process ignores these messages. The COMMIT after the enqueues makes these two enqueues part of the same transaction.

Example 23-23 Enqueuing Non-LCR Messages to Be Dequeued Explicitly

SET ECHO OFFSET VERIFY OFFACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDECONNECT oe/&password@db01;set echo on

BEGIN
  oe.enq_proc(ANYDATA.convertobject(oe.order_event_typ(
    2501,'22-JAN-00','direct',117,3,22788,161,NULL,'DEQUEUE')));
END;
/
BEGIN
  oe.enq_proc(ANYDATA.convertobject(oe.customer_event_typ(
    991,'Nick','Carraway',oe.cust_address_typ('10th Street',
    '11101','Long Island','NY','US'),oe.phone_list_typ('+1 718 786 2287', 
    '+1 718 511 9114', '+1 718 888 4832'),'i','AMERICA',3000,
    'nick@great_gatsby.com',149,NULL,'MARRIED','M','OVER 150,000','DEQUEUE')));
END;
/
COMMIT;

In Example 23-24, you connect to database db01 as sample schema user oe to create a row LCR that inserts a row into the oe.orders table and another LCR that updates that row. The apply process applies these messages directly.


Note:

Enqueued LCRs should commit at transaction boundaries. In this example, a COMMIT statement is run after each enqueue, making each enqueue a separate transaction. However, you can perform multiple LCR enqueues before a commit if there is more than one LCR in a transaction.

Example 23-24 Enqueuing Row LCRs to Be Dequeued by an Apply Process

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDE
CONNECT oe/&password@db01;
set echo on

DECLARE
  newunit1  SYS.LCR$_ROW_UNIT;
  newunit2  SYS.LCR$_ROW_UNIT;
  newunit3  SYS.LCR$_ROW_UNIT;
  newunit4  SYS.LCR$_ROW_UNIT;
  newunit5  SYS.LCR$_ROW_UNIT;
  newunit6  SYS.LCR$_ROW_UNIT;
  newunit7  SYS.LCR$_ROW_UNIT;
  newunit8  SYS.LCR$_ROW_UNIT;
  newvals   SYS.LCR$_ROW_LIST;
BEGIN
  newunit1 := SYS.LCR$_ROW_UNIT(
    'ORDER_ID',ANYDATA.ConvertNumber(2502),DBMS_LCR.NOT_A_LOB,NULL,NULL);
  newunit2 := SYS.LCR$_ROW_UNIT(
    'ORDER_DATE',ANYDATA.ConvertTimestampLTZ('04-NOV-00'),DBMS_LCR.NOT_A_LOB,
    NULL,NULL);
  newunit3 := SYS.LCR$_ROW_UNIT(
    'ORDER_MODE',ANYDATA.ConvertVarchar2('online'),DBMS_LCR.NOT_A_LOB,NULL,NULL);
  newunit4 := SYS.LCR$_ROW_UNIT(
    'CUSTOMER_ID',ANYDATA.ConvertNumber(145),DBMS_LCR.NOT_A_LOB,NULL,NULL);
  newunit5 := SYS.LCR$_ROW_UNIT(
    'ORDER_STATUS',ANYDATA.ConvertNumber(3),DBMS_LCR.NOT_A_LOB,NULL,NULL);
  newunit6 := SYS.LCR$_ROW_UNIT(
    'ORDER_TOTAL',ANYDATA.ConvertNumber(35199),DBMS_LCR.NOT_A_LOB,NULL,NULL);
  newunit7 := SYS.LCR$_ROW_UNIT(
    'SALES_REP_ID',ANYDATA.ConvertNumber(160),DBMS_LCR.NOT_A_LOB,NULL,NULL);
  newunit8 := SYS.LCR$_ROW_UNIT(
    'PROMOTION_ID',ANYDATA.ConvertNumber(1),DBMS_LCR.NOT_A_LOB,NULL,NULL);
  newvals := SYS.LCR$_ROW_LIST(
    newunit1,newunit2,newunit3,newunit4,newunit5,newunit6,newunit7,newunit8);
  oe.enq_row_lcr('DB01','INSERT','OE','ORDERS',NULL,newvals);
END;
/
COMMIT;
DECLARE
  oldunit1  SYS.LCR$_ROW_UNIT;
  oldunit2  SYS.LCR$_ROW_UNIT;
  oldvals   SYS.LCR$_ROW_LIST;
  newunit1  SYS.LCR$_ROW_UNIT;
  newvals   SYS.LCR$_ROW_LIST;
BEGIN
  oldunit1 := SYS.LCR$_ROW_UNIT(
    'ORDER_ID',ANYDATA.ConvertNumber(2502),DBMS_LCR.NOT_A_LOB,NULL,NULL);
  oldunit2 := SYS.LCR$_ROW_UNIT(
    'ORDER_TOTAL',ANYDATA.ConvertNumber(35199),DBMS_LCR.NOT_A_LOB,NULL,NULL);
  oldvals := SYS.LCR$_ROW_LIST(oldunit1,oldunit2);
  newunit1 := SYS.LCR$_ROW_UNIT(
    'ORDER_TOTAL',ANYDATA.ConvertNumber(5235),DBMS_LCR.NOT_A_LOB,NULL,NULL);
  newvals := SYS.LCR$_ROW_LIST(newunit1);
  oe.enq_row_lcr('DB01','UPDATE','OE','ORDERS',oldvals,newvals);
END;
/
COMMIT;

Dequeuing Messages Explicitly and Querying for Applied Messages

The examples in this section illustrate how to dequeue messages explicitly and query messages that were applied by the apply process. The examples use messages that were enqueued in the previous section.

In Example 23-25, you connect to database db01 as sample schema user oe to run procedure explicit_dq, created in Example 23-21. You specify subscriber explicit_dq, added in Example 23-20, as the consumer of the messages you want to dequeue. In these examples, messages that are not dequeued explicitly by this procedure are dequeued by the apply process.

Example 23-25 Dequeuing Messages Explicitly

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDE
CONNECT oe/&password@db01;
set echo on

CREATE PROCEDURE oe.enq_proc (payload ANYDATA)  IS 
SET SERVEROUTPUT ON SIZE 100000;
EXEC oe.explicit_dq('explicit_dq');

The example returns the payload of the messages enqueued in Example 23-23:

Message Dequeued
Type Name := OE.ORDER_EVENT_TYP
order_id     - 2501
order_date   - 22-JAN-00 12.00.00.000000 AM
order_mode   - direct
customer_id  - 117
order_status - 3
order_total  - 22788
sales_rep_id - 161
promotion_id -
Message Dequeued
Type Name := OE.CUSTOMER_EVENT_TYP
customer_id       - 991
cust_first_name   - Nick
cust_last_name    - Carraway
street_address    - 10th Street
postal_code       - 11101
city              - Long Island
state_province    - NY
country_id        - US
phone_number1     - +1 718 786 2287
phone_number2     - +1 718 511 9114
phone_number3     - +1 718 888 4832
nls_language      - i
nls_territory     - AMERICA
credit_limit      - 3000
cust_email        - nick@great_gatsby.com
account_mgr_id    - 149
date_of_birth     -
marital_status    - MARRIED
gender            - M
income_level      - OVER 150,000
No more messages

Example 23-26, you connect to database db01 as sample schema user oe to query the oe.orders and oe.customers tables to see the rows corresponding to the messages applied by apply process apply_oe, created in Example 23-15.

Example 23-26 Querying for Applied Messages

SET ECHO OFF
SET VERIFY OFF
ACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDE
CONNECT oe/&password@db01; 
set echo on

CREATE PROCEDURE oe.enq_proc (payload ANYDATA)  IS 
SELECT order_id, order_date, customer_id, order_total
  FROM oe.orders WHERE order_id = 2500;
SELECT cust_first_name, cust_last_name, cust_email 
  FROM oe.customers WHERE customer_id = 990;
SELECT order_id, order_date, customer_id, order_total 
  FROM oe.orders WHERE order_id = 2502;

The example returns three rows:

  ORDER_ID ORDER_DATE                     CUSTOMER_ID ORDER_TOTAL
---------- ------------------------------ ----------- -----------
      2500 05-MAY-01 12.00.00.000000 AM           117       44699
 
1 row selected.

CUST_FIRST_NAME      CUST_LAST_NAME       CUST_EMAIL
-------------------- -------------------- ------------------------------
Hester               Prynne               a@scarlet_letter.com
 
1 row selected.

  ORDER_ID ORDER_DATE                     CUSTOMER_ID ORDER_TOTAL
---------- ------------------------------ ----------- -----------
      2502 04-NOV-00 12.00.00.000000 AM           145        5235
 
1 row selected.

Enqueuing and Dequeuing Messages Using JMS

The examples in this section illustrate how to enqueue non-LCR messages and row LCRs into a queue and then dequeue them using Java Message Service (JMS).

Note that the Oracle Database does not support JDK 1.2, JDK 1.3, JDK 1.4, and all classes12*.* files. You need to use the ojdbc5.jar and ojbc6.jar files with JDK 5.n and JDK 6.n, respectively. The following jar and zip files should be in the CLASSPATH based on the release of JDK you are using.

For JDK 1.5.x, the CLASSPATH must contain:

ORACLE_HOME/jdbc/lib/ojdbc5.jar

For JDK 1.6.x, the CLASSPATH must contain:

ORACLE_HOME/jdbc/lib/ojdbc6.jar 

The following files are used for either JDK version:

ORACLE_HOME/lib/jta.jar
ORACLE_HOME/xdk/lib/xmlparserv2.jar
ORACLE_HOME/rdbms/jlib/xdb.jar
ORACLE_HOME/jlib/aqapi.jar 
ORACLE_HOME/rdbms/jlib/jmscommon.jar

Also, make sure LD_LIBRARY_PATH (Linux and Solaris) or PATH (Windows) includes ORACLE_HOME/lib.

These examples show sample schema user oe enqueuing JMS messages into a queue and agent explicit_dq dequeuing them. Agent explicit_dq was created in Example 23-18, associated with sample schema user oe in Example 23-19, and made a subscriber to queue oe_queue in Example 23-20.

Sample schema user oe was granted EXECUTE on DBMS_AQ in Example 23-1. In order for this user to use the Oracle JMS interface, it must have EXECUTE privilege on DBMS_AQIN as well. In Example 23-27, you connect to database db01 as a user with administrative privileges to grant the necessary privilege to oe.

Example 23-27 Granting EXECUTE on DBMS_AQIN to User oe

GRANT EXECUTE on DBMS_AQIN to oe;

Enqueue of JMS types and XML types does not work with Oracle Streams ANYDATA queues unless you call DBMS_AQADM.ENABLE_JMS_TYPES(queue_table_name) after DBMS_STREAMS_ADM.SET_UP_QUEUE(). In Example 23-28, you connect to database db01 as administrator user strmadmin, created in Example 23-1, to run ENABLE_JMS_TYPES on ANYDATA queue table oe_queue_table, created in Example 23-2.

Example 23-28 Enabling JMS Types on an ANYDATA Queue

CONNECT strmadmin;
Enter password: password
BEGIN
  DBMS_AQADM.ENABLE_JMS_TYPES('oe_queue_table');
END;
/

Note:

Enabling an Oracle Streams queue for these types may affect import/export of the queue table.

In Example 23-29, you connect to database db01 as sample schema user oe to create types address and person.

Example 23-29 Creating Oracle Object Types address and person

CONNECT oe;
Enter password: password
CREATE TYPE address AS OBJECT (street VARCHAR (30), num NUMBER)
/ 
CREATE TYPE person AS OBJECT (name VARCHAR (30), home ADDRESS)
/

In Example 23-30, you use JPublisher to generate two Java classes named JPerson and JAddress for the person and address types, respectively. The input to JPublisher is a file called input.typ with the following lines:

SQL PERSON AS JPerson
SQL ADDRESS AS JAddress

Example 23-30 Creating Java Classes That Map to Oracle Object Types

jpub -input=input.typ -user=OE/OE

Example 23-31 is the Java code that you use to publish JMS text messages, LCRs, and non-LCR ADT messages into an Oracle Streams topic. It does the following:

  • Creates a TopicConnectionFactory using the JDBC OCI driver


    Note:

    The JDBC OCI driver is your only choice for accessing Oracle Streams through JMS.

  • Creates a TopicSession

  • Starts the connection

  • Creates method publishUserMessages() to publish an ADT message and a JMS text message to an Oracle Streams topic

  • Creates method publishLcrMessages() to publish an XML LCR message to an Oracle Streams topic

  • Publishes three messages, providing feedback as it proceeds

Method publishUserMessages() does the following:

  • Gets the topic

  • Creates a publisher

  • Specifies agent explicit_enq to access queue oe_queue

  • Creates a PERSON ADT message

  • Sets the payload in the message

  • Specifies explicit_dq as the recipient

  • Publishes the PERSON ADT message

  • Creates a JMS Text message

  • Publishes the JMS Text message

Method publishLcrMessages() does the following:

  • Gets the topic

  • Creates a publisher

  • Gets the JDBC connection

  • Specifies agent explicit_enq to access queue oe_queue

  • Creates an ADT message

  • Creates the LCR representation in XML

  • Creates the XMLType containing the LCR

  • Sets the payload in the message

  • Specifies explicit_dq as the recipient

  • Publishes the LCR

The code is compiled in Example 23-33. For now, just save it as StreamsEnq.java.

Example 23-31 Java Code for Enqueuing Messages

import oracle.AQ.*;
import oracle.jms.*;
import javax.jms.*;
import java.lang.*;
import oracle.xdb.*;
 
public class StreamsEnq
{
  public static void main (String args [])
       throws java.sql.SQLException, ClassNotFoundException, JMSException
  {
     TopicConnectionFactory tc_fact= null;
     TopicConnection        t_conn = null;
     TopicSession           t_sess = null;
 
     try
     {
       if (args.length < 3 )
         System.out.println("Usage:java filename [SID] [HOST] [PORT]");
       else 
       {
         tc_fact = AQjmsFactory.getTopicConnectionFactory(
                      args[1], args[0], Integer.parseInt(args[2]), "oci8");
         t_conn = tc_fact.createTopicConnection( "OE","OE");
         t_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
         t_conn.start() ;
         publishUserMessages(t_sess);
         publishLcrMessages(t_sess);
         t_sess.close() ;
         t_conn.close() ;
         System.out.println("End of StreamsEnq Demo") ;
       }
     }
     catch (Exception ex)
     {
       System.out.println("Exception-1: " + ex);
       ex.printStackTrace();
     }
  }
 
  public static void publishUserMessages(TopicSession t_sess) throws Exception
  {
    Topic           topic     = null;
    TopicPublisher  t_pub     = null;
    JPerson         pers      = null;
    JAddress        addr      = null;
    TextMessage     t_msg     = null;
    AdtMessage      adt_msg   = null;
    AQjmsAgent      agent     = null;
    AQjmsAgent[]    recipList = null;
 
    try
    {
      topic = ((AQjmsSession)t_sess).getTopic("strmadmin", "oe_queue");
      t_pub = t_sess.createPublisher(topic);
      agent = new AQjmsAgent("explicit_enq", null);
      adt_msg = ((AQjmsSession)t_sess).createAdtMessage();
      pers = new JPerson();
      addr = new JAddress();
      addr.setNum(new java.math.BigDecimal(500));
      addr.setStreet("Oracle Pkwy");
      pers.setName("Mark");
      pers.setHome(addr);
      adt_msg.setAdtPayload(pers);
      ((AQjmsMessage)adt_msg).setSenderID(agent);
      System.out.println("Publish message 1 -type  PERSON\n");
      recipList = new AQjmsAgent[1];
      recipList[0] = new AQjmsAgent("explicit_dq", null);
      ((AQjmsTopicPublisher)t_pub).publish(topic, adt_msg, recipList);
      t_sess.commit();
 
      t_msg = t_sess.createTextMessage();
      t_msg.setText("Test message");
      t_msg.setStringProperty("color", "BLUE");
      t_msg.setIntProperty("year", 1999);
      ((AQjmsMessage)t_msg).setSenderID(agent);
      System.out.println("Publish message 2 -type  JMS TextMessage\n");
      ((AQjmsTopicPublisher)t_pub).publish(topic, t_msg, recipList);
      t_sess.commit();
 
    }
    catch (JMSException jms_ex)
    {
      System.out.println("JMS Exception: " + jms_ex);
      if(jms_ex.getLinkedException() != null)
        System.out.println("Linked Exception: " + jms_ex.getLinkedException());
    }
  }
 
  public static void publishLcrMessages(TopicSession t_sess) throws Exception
  {
    Topic                topic     = null;
    TopicPublisher       t_pub     = null;
    XMLType              xml_lcr   = null;
    AdtMessage           adt_msg   = null;
    AQjmsAgent           agent     = null;
    StringBuffer         lcr_data  = null;
    AQjmsAgent[]         recipList = null;
    java.sql.Connection  db_conn   = null;
 
    try
    {
      topic = ((AQjmsSession)t_sess).getTopic("strmadmin", "oe_queue");
      t_pub = t_sess.createPublisher(topic);
      db_conn = ((AQjmsSession)t_sess).getDBConnection();
      agent = new AQjmsAgent("explicit_enq", null);
      adt_msg = ((AQjmsSession)t_sess).createAdtMessage();
      lcr_data = new StringBuffer();
 
      lcr_data.append("<ROW_LCR ");
      lcr_data.append("xmlns='http://xmlns.oracle.com/streams/schemas/lcr' \n");
      lcr_data.append("xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' \n");
      lcr_data.append("xsi:schemaLocation='http://xmlns.oracle.com/streams/schemas/lcr "); 
      lcr_data.append("http://xmlns.oracle.com/streams/schemas/lcr/streamslcr.xsd'");
      lcr_data.append("> \n");
      lcr_data.append("<source_database_name>source_dbname</source_database_name> \n");
      lcr_data.append("<command_type>INSERT</command_type> \n");
      lcr_data.append("<object_owner>Ram</object_owner> \n");
      lcr_data.append("<object_name>Emp</object_name> \n");
      lcr_data.append("<tag>0ABC</tag> \n");
      lcr_data.append("<transaction_id>0.0.0</transaction_id> \n");
      lcr_data.append("<scn>0</scn> \n");
      lcr_data.append("<old_values> \n");
      lcr_data.append("<old_value> \n");
      lcr_data.append("<column_name>C01</column_name> \n");
      lcr_data.append("<data><varchar2>Clob old</varchar2></data> \n");
      lcr_data.append("</old_value> \n");
      lcr_data.append("<old_value> \n");
      lcr_data.append("<column_name>C02</column_name> \n");
      lcr_data.append("<data><varchar2>A123FF</varchar2></data> \n");
      lcr_data.append("</old_value> \n");
      lcr_data.append("<old_value> \n");
      lcr_data.append("<column_name>C03</column_name> \n");
      lcr_data.append("<data> \n");
      lcr_data.append("<date><value>1997-11-24</value><format>SYYYY-MM-DD</format></date> \n");
      lcr_data.append("</data> \n");
      lcr_data.append("</old_value> \n");
      lcr_data.append("<old_value> \n");
      lcr_data.append("<column_name>C04</column_name> \n");
      lcr_data.append("<data> \n");
      lcr_data.append("<timestamp><value>1999-05-31T13:20:00.000</value>");
      lcr_data.append("<format>SYYYY-MM-DD\"T\"HH24:MI:SS.FF</format></timestamp> \n");
      lcr_data.append("</data> \n");
      lcr_data.append("</old_value> \n");
      lcr_data.append("<old_value> \n");
      lcr_data.append("<column_name>C05</column_name> \n");
      lcr_data.append("<data><raw>ABCDE</raw></data> \n");
      lcr_data.append("</old_value> \n");
      lcr_data.append("</old_values> \n");
      lcr_data.append("<new_values> \n");
      lcr_data.append("<new_value> \n");
      lcr_data.append("<column_name>C01</column_name> \n");
      lcr_data.append("<data><varchar2>A123FF</varchar2></data> \n");
      lcr_data.append("</new_value> \n");
      lcr_data.append("<new_value> \n");
      lcr_data.append("<column_name>C02</column_name> \n");
      lcr_data.append("<data><number>35.23</number></data> \n");
      lcr_data.append("</new_value> \n");
      lcr_data.append("<new_value> \n");
      lcr_data.append("<column_name>C03</column_name> \n");
      lcr_data.append("<data><number>-100000</number></data> \n");
      lcr_data.append("</new_value> \n");
      lcr_data.appeU&nd("<new_value> \n");
      lcr_data.append("<column_name>C04</column_name> \n");
      lcr_data.append("<data><varchar2>Hello</varchar2></data> \n");
      lcr_data.append("</new_value> \n");
      lcr_data.append("<new_value> \n");
      lcr_data.append("<column_name>C05</column_name> \n");
      lcr_data.append("<data><char>world</char></data> \n");
      lcr_data.append("</new_value> \n");
      lcr_data.append("</new_values> \n");
      lcr_data.append("</ROW_LCR>");
 
      xml_lcr = oracle.xdb.XMLType.createXML(db_conn, lcr_data.toString());
      adt_msg.setAdtPayload(xml_lcr);
      ((AQjmsMessage)adt_msg).setSenderID(agent);
      System.out.println("Publish message 3 - XMLType containing LCR ROW\n");
      recipList = new AQjmsAgent[1];
      recipList[0] = new AQjmsAgent("explicit_dq", null);
      ((AQjmsTopicPublisher)t_pub).publish(topic, adt_msg, recipList);
      t_sess.commit();
 
    }
    catch (JMSException jms_ex)
    {
      System.out.println("JMS Exception: " + jms_ex);
      if(jms_ex.getLinkedException() != null)
        System.out.println("Linked Exception: " + jms_ex.getLinkedException());
    }
  }
}

Example 23-32 is the Java code you use to receive messages from a Oracle Streams topic. It does the following:

  • Creates a TopicConnectionFactory using the JDBC OCI driver


    Note:

    The JDBC OCI driver is your only choice for accessing Oracle Streams through JMS.

  • Creates a TopicSession

  • Starts the connection

  • Creates method receiveMessages() to receive messages from an Oracle Streams topic

  • Receives three messages, providing feedback as it proceeds

Method receiveMessages() does the following:

  • Gets the topic

  • Creates a TopicReceiver to receive messages for consumer explicit_dq

  • Registers mappings for ADDRESS and PERSON in the JMS typemap

  • Registers a mapping for XMLType in the typemap (required for LCRs)

  • Receives the enqueued messages

The code is compiled in Example 23-33. For now, just save it as StreamsDeq.java.

Example 23-32 Java Code for Dequeuing Messages

import oracle.AQ.*;
import oracle.jms.*;
import javax.jms.*;
import java.lang.*;
import oracle.xdb.*;
import java.sql.SQLException;
 
public class StreamsDeq
{
  public static void main (String args [])
       throws java.sql.SQLException, ClassNotFoundException, JMSException
  {
     TopicConnectionFactory tc_fact= null;
     TopicConnection        t_conn = null;
     TopicSession           t_sess = null;
 
     try
     {
       if (args.length < 3 )
         System.out.println("Usage:java filename [SID] [HOST] [PORT]");
       else 
       {
         tc_fact = AQjmsFactory.getTopicConnectionFactory(
                      args[1], args[0], Integer.parseInt(args[2]), "oci8");
         t_conn = tc_fact.createTopicConnection( "OE","OE");
 
         t_sess = t_conn.createTopicSession(true, Session.CLIENT_ACKNOWLEDGE);
         t_conn.start() ;
 
         receiveMessages(t_sess);
 
         t_sess.close() ;
         t_conn.close() ;
         System.out.println("\nEnd of StreamsDeq Demo") ;
       }
     }
     catch (Exception ex)
     {
       System.out.println("Exception-1: " + ex);
       ex.printStackTrace();
     }
  }
 
  public static void receiveMessages(TopicSession t_sess) throws Exception
  {
    Topic           topic   = null;
    JPerson         pers    = null;
    JAddress        addr    = null;
    XMLType         xtype   = null;
    TextMessage     t_msg   = null;
    AdtMessage      adt_msg = null;
    Message         jms_msg = null;
    TopicReceiver   t_recv  = null;
    int             i       = 0;
    java.util.Map map= null;
 
    try
    {
      topic = ((AQjmsSession)t_sess).getTopic("strmadmin", "oe_queue");
      t_recv = ((AQjmsSession)t_sess).createTopicReceiver(topic, "explicit_dq", null);
      map = ((AQjmsSession)t_sess).getTypeMap();
      map.put("OE.PERSON", Class.forName("JPerson"));
      map.put("OE.ADDRESS", Class.forName("JAddress"));
      map.put("SYS.XMLTYPE", Class.forName("oracle.xdb.XMLTypeFactory"));
      System.out.println("Receive messages ...\n");
      do
      {
        try
        {
          jms_msg = (t_recv.receive(10));
          i++;
 
          ((AQjmsTopicReceiver)t_recv).setNavigationMode(AQjmsConstants.NAVIGATION_NEXT_MESSAGE);
        }
        catch (JMSException jms_ex2)
        {
          if((jms_ex2.getLinkedException() != null) &&
             (jms_ex2.getLinkedException() instanceof SQLException))
          {
            SQLException sql_ex2 =(SQLException)(jms_ex2.getLinkedException());
            if(sql_ex2.getErrorCode() == 25235)
            {
              ((AQjmsTopicReceiver)t_recv).setNavigationMode(
                                                AQjmsConstants.NAVIGATION_NEXT_TRANSACTION);
              continue;
            }
            else
              throw jms_ex2;
          }
          else
            throw jms_ex2;
        }
        if(jms_msg == null)
        {
          System.out.println("\nNo more messages");
        }
        else
        {
          if(jms_msg instanceof AdtMessage)
          {
            adt_msg = (AdtMessage)jms_msg;
 
            System.out.println("Retrieved message " + i + ": " +
                               adt_msg.getAdtPayload());
            if(adt_msg.getAdtPayload() instanceof JPerson)
            {
              pers =(JPerson)( adt_msg.getAdtPayload());
              System.out.println("PERSON: Name: " + pers.getName());
            }
            else if(adt_msg.getAdtPayload() instanceof JAddress)
            {
              addr =(JAddress)( adt_msg.getAdtPayload());
              System.out.println("ADDRESS: Street" + addr.getStreet());
            }
            else if(adt_msg.getAdtPayload() instanceof oracle.xdb.XMLType)
            {
              xtype = (XMLType)adt_msg.getAdtPayload();
              System.out.println("XMLType: Data: \n" + xtype.getStringVal());
            }
            System.out.println("Msg id: " + adt_msg.getJMSMessageID());
            System.out.println();
          }
          else if(jms_msg instanceof TextMessage)
          {
            t_msg = (TextMessage)jms_msg;
 
            System.out.println("Retrieved message " + i + ": " +
                               t_msg.getText());
            System.out.println("Msg id: " + t_msg.getJMSMessageID());
            System.out.println();
          }
          else
            System.out.println("Invalid message type");
        }
      } while (jms_msg != null);
      t_sess.commit();
    }
    catch (JMSException jms_ex)
    {
      System.out.println("JMS Exception: " + jms_ex);
      if(jms_ex.getLinkedException() != null)
        System.out.println("Linked Exception: " + jms_ex.getLinkedException());
      t_sess.rollback();
    }
    catch (java.sql.SQLException sql_ex)
    {
      System.out.println("SQL Exception: " + sql_ex);
      sql_ex.printStackTrace();
      t_sess.rollback();
    }
  }
}

In Example 23-33, you compile the scripts.

Example 23-33 Compiling StreamsEnq.java and StreamsDeq.java

javac StreamsEnq.java StreamsDeq.java JPerson.java JAddress.java

In Example 23-34, you run the enqueue program, specifying values for ORACLE_SID, HOST, and PORT that are appropriate for your testing environment.

Example 23-34 Running StreamsEnq

java StreamsEnq  ORACLE_SID HOST PORT

The example returns:

Publish message 1 -type  PERSON
Publish message 2 -type  JMS TextMessage
Publish message 3 - XMLType containing LCR ROW
End of StreamsEnq Demo

In Example 23-35, you run the dequeue program, specifying values for ORACLE_SID, HOST, and PORT that are appropriate for your testing environment.

Example 23-35 Running StreamsDeq

java StreamsDeq  ORACLE_SID HOST PORT
PK]5d&U&PK-AOEBPS/ap_nonpers.htm1 Nonpersistent Queues

A Nonpersistent Queues

This appendix describes nonpersistent queues, which are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2). Oracle recommends that you use buffered messaging instead.

Oracle Streams Advanced Queuing can deliver nonpersistent messages asynchronously to subscribers. These messages can be event-driven and do not persist beyond the failure of the system (or instance). The messages are stored in a system-created queue table. Oracle Streams Advanced Queuing supports persistent and nonpersistent messages with a common API.

Nonpersistent queues, which can be either single-consumer or multiconsumer, provide a mechanism for notification to all currently connected users. Subscribers can be added to multiconsumer nonpersistent queues, and nonpersistent queues can be destinations for propagation.

You use the enqueue interface to enqueue messages into a nonpersistent queue in the usual way. You can enqueue RAW and Oracle object type messages into a nonpersistent queue. OCI notifications are used to deliver such messages to users that are currently registered for notification.

This appendix contains these topics:

Creating Nonpersistent Queues

DBMS_AQADM.CREATE_NP_QUEUE ( 
   queue_name              IN        VARCHAR2, 
   multiple_consumers      IN        BOOLEAN  DEFAULT FALSE, 
   comment                 IN        VARCHAR2 DEFAULT NULL);

This procedure creates a nonpersistent queue.

Only local recipients are supported for nonpersistent queues. The queue can be either single-consumer or multiconsumer. All queue names must be unique within a schema. The queues are created in an 8.1-compatible system-created queue table (AQ$_MEM_SC or AQ$_MEM_MC) in the same schema as that specified by the queue name. If the queue name does not specify a schema name, then the queue is created in the login user's schema.


Note:

Names of nonpersistent queues must not be longer than 24 characters. If you attempt to create a nonpersistent queue with a longer name, error ORA-24019 results.

Managing Nonpersistent Queues

Once a queue is created with CREATE_NP_QUEUE, it can be enabled by calling START_QUEUE. By default, the queue is created with both enqueue and dequeue disabled.

You can enqueue RAW and Oracle object type messages into a nonpersistent queue. You cannot dequeue from a nonpersistent queue. The only way to retrieve a message from a nonpersistent queue is by using the Oracle Call Interface (OCI) notification mechanism. You cannot invoke the listen call on a nonpersistent queue.

A nonpersistent queue can be dropped only by its owner.

Compatibility of Nonpersistent Queues

For 8.1-style or higher queues, the compatible parameter of init.ora and the compatible parameter of the queue table should be set to 8.1 or higher to use nonpersistent queues.

Nonpersistent Queue Notification

For nonpersistent queues, the message is delivered as part of the notification. Table A-1 shows the actions performed for nonpersistent queues for different notification mechanisms when RAW presentation is specified. Table A-2 shows the actions performed when XML presentation is specified.

Table A-1 Actions Performed for Nonpersistent Queues When RAW Presentation Specified

Queue Payload TypeOCI CallbackE-mailPL/SQL Callback

RAW

OCI callback receives the RAW data in the payload.

Not supported

PL/SQL callback receives the RAW data in the payload.

Oracle object type

Not supported

Not supported

Not supported


Table A-2 Actions Performed for Nonpersistent Queues When XML Presentation Specified

Queue Payload TypeOCI CallbackE-mailPL/SQL Callback

RAW

OCI callback receives the XML data in the payload.

XML data is formatted as a SOAP message and e-mailed to the registered e-mail address.

PL/SQL callback receives the XML data in the payload.

Oracle object type

OCI callback receives the XML data in the payload.

XML data is formatted as a SOAP message and e-mailed to the registered e-mail address.

PL/SQL callback receives the XML data in the payload.


Restrictions on Nonpersistent Queues

You can create nonpersistent queues of RAW and Oracle object type.You are limited to sending messages only to subscribers and explicitly specified recipients who are local. Propagation is not supported from nonpersistent queues. When retrieving messages, you cannot use the dequeue call, but must instead employ the asynchronous notification mechanism, registering for the notification by mean of OCISubscriptionRegister.

The visibility attribute of enqueue_options must be set to IMMEDIATE for nonpersistent messages.


See Also:

"Enqueue Options"

PK11PK-A OEBPS/toc.ncxS Oracle® Streams Advanced Queuing User's Guide, 11g Release 2 (11.2) Cover Table of Contents Oracle Streams Advanced Queuing User's Guide, 11g Release 2 (11.2) Preface What's New in Oracle Streams Advanced Queuing? Introduction to Oracle AQ Basic Components Oracle Streams Advanced Queuing: Programmatic Interfaces Managing Oracle Streams Advanced Queuing Oracle Streams Advanced Queuing Performance and Scalability Internet Access to Oracle Streams Advanced Queuing Troubleshooting Oracle Streams Advanced Queuing Oracle Streams Advanced Queuing Administrative Interface Oracle Streams Advanced Queuing & Messaging Gateway Views Oracle Streams Advanced Queuing Operations Using PL/SQL Introducing Oracle JMS Oracle JMS Basic Operations Oracle JMS Point-to-Point Oracle JMS Publish/Subscribe Oracle JMS Shared Interfaces Oracle JMS Types Examples Introducing Oracle Messaging Gateway Getting Started with Oracle Messaging Gateway Working with Oracle Messaging Gateway Oracle Messaging Gateway Message Conversion Monitoring Oracle Messaging Gateway Using ANYDATA Queues for User Messages Oracle Streams Messaging Examples Nonpersistent Queues JMS and AQ XML Servlet Error Messages Glossary Index Copyright PK'XSPK-AOEBPS/aq_intro.htm Introduction to Oracle AQ

1 Introduction to Oracle AQ

This chapter discusses Oracle Streams Advanced Queuing (AQ) and the requirements for complex information handling in an integrated environment.

This chapter contains the following topics:

What Is Queuing?

When Web-based business applications communicate with each other, producer applications enqueue messages and consumer applications dequeue messages. At the most basic level of queuing, one producer enqueues one or more messages into one queue. Each message is dequeued and processed once by one of the consumers. A message stays in the queue until a consumer dequeues it or the message expires. A producer may stipulate a delay before the message is available to be consumed, and a time after which the message expires. Likewise, a consumer may wait when trying to dequeue a message if no message is available. An agent program or application may act as both a producer and a consumer.

Producers can enqueue messages in any sequence. Messages are not necessarily dequeued in the order in which they are enqueued. Messages can be enqueued without being dequeued.

At a slightly higher level of complexity, many producers enqueue messages into a queue, all of which are processed by one consumer. Or many producers enqueue messages, each message being processed by a different consumer depending on type and correlation identifier.

Enqueued messages are said to be propagated when they are reproduced on another queue, which can be in the same database or in a remote database.

Applications often use data in different formats. A transformation defines a mapping from one data type to another. The transformation is represented by a SQL function that takes the source data type as input and returns an object of the target data type. You can arrange transformations to occur when a message is enqueued, when it is dequeued, or when it is propagated to a remote subscriber.

Oracle Streams Advanced Queuing Leverages Oracle Database

Oracle Streams Advanced Queuing provides database-integrated message queuing functionality. It is built on top of Oracle Streams and leverages the functions of Oracle Database so that messages can be stored persistently, propagated between queues on different computers and databases, and transmitted using Oracle Net Services and HTTP(S).

Because Oracle Streams Advanced Queuing is implemented in database tables, all operational benefits of high availability, scalability, and reliability are also applicable to queue data. Standard database features such as recovery, restart, and security are supported by Oracle Streams Advanced Queuing. You can use database development and management tools such as Oracle Enterprise Manager to monitor queues. Like other database tables, queue tables can be imported and exported.

Messages can be queried using standard SQL. This means that you can use SQL to access the message properties, the message history, and the payload. With SQL access you can also do auditing and tracking. All available SQL technology, such as indexes, can be used to optimize access to messages.


Note:

Oracle Streams Advanced Queuing does not support data manipulation language (DML) operations on a queue table or an associated index-organized table (IOT), if any. The only supported means of modifying queue tables is through the supplied APIs. Queue tables and IOTs can become inconsistent and therefore effectively ruined, if DML operations are performed on them.

System-Level Access Control

Oracle Streams Advanced Queuing supports system-level access control for all queuing operations, allowing an application designer or DBA to designate users as queue administrators. A queue administrator can invoke Oracle Streams Advanced Queuing administrative and operational interfaces on any queue in the database. This simplifies administrative work because all administrative scripts for the queues in a database can be managed under one schema.

Queue-Level Access Control

Oracle Streams Advanced Queuing supports queue-level access control for enqueue and dequeue operations. This feature allows the application designer to protect queues created in one schema from applications running in other schemas. The application designer can grant only minimal access privileges to applications that run outside the queue schema.

Performance

Requests for service must be decoupled from supply of services to increase efficiency and enable complex scheduling. Oracle Streams Advanced Queuing exhibits high performance as measured by:

  • Number of messages enqueued and dequeued each second

  • Time to evaluate a complex query on a message warehouse

  • Time to recover and restart the messaging process after a failure

Scalability

Queuing systems must be scalable. Oracle Streams Advanced Queuing exhibits high performance when the number of programs using the application increases, when the number of messages increases, and when the size of the message warehouse increases.

Persistence for Security

Messages that constitute requests for service must be stored persistently and processed exactly once for deferred execution to work correctly in the presence of network, computer, and application failures. Oracle Streams Advanced Queuing is able to meet requirements in the following situations:

  • Applications do not have the resources to handle multiple unprocessed messages arriving simultaneously from external clients or from programs internal to the application.

  • Communication links between databases are not available all the time or are reserved for other purposes. If the system falls short in its capacity to deal with these messages immediately, then the application must be able to store the messages until they can be processed.

  • External clients or internal programs are not ready to receive messages that have been processed.

Persistence for Scheduling

Queuing systems must deal with priorities, and those priorities can change:

  • Messages arriving later can be of higher priority than messages arriving earlier.

  • Messages may wait for later messages before actions are taken.

  • The same message may be accessed by different processes.

  • Messages in a specific queue can become more important, and so must be processed with less delay or interference from messages in other queues.

  • Messages sent to some destinations can have a higher priority than others.

Persistence for Accessing and Analyzing Metadata

Queuing systems must preserve message metadata, which can be as important as the payload data. For example, the time that a message is received or dispatched can be crucial for business and legal reasons. With the persistence features of Oracle Streams Advanced Queuing, you can analyze periods of greatest demand or evaluate the lag between receiving and completing an order.

Object Type Support

Oracle Streams Advanced Queuing supports enqueue, dequeue, and propagation operations where the queue type is an abstract datatype, ADT. It also supports enqueue and dequeue operations if the types are inherited types of a base ADT. Propagation between two queues where the types are inherited from a base ADT is not supported.

Oracle Streams Advanced Queuing also supports ANYDATA queues, which enable applications to enqueue different message types in a single queue.

If you plan to enqueue, propagate, or dequeue user-defined type messages, then each type used in these messages must exist at every database where the message can be enqueued in a queue. Some environments use directed networks to route messages through intermediate databases before they reach their destination. In such environments, the type must exist at each intermediate database, even if the messages of this type are never enqueued or dequeued at a particular intermediate database.

In addition, the following requirements must be met for such types:

  • Type name must be the same at each database.

  • Type must be in the same schema at each database.

  • Shape of the type must match exactly at each database.

  • Type cannot use inheritance or type evolution at any database.

  • Type cannot contain varrays, nested tables, LOBs, rowids, or urowids.

The object identifier need not match at each database.

Structured and XMLType Payloads

You can use object types to structure and manage message payloads. Relational database systems in general have a richer typing system than messaging systems. Because Oracle Database is an object-relational database system, it supports traditional relational and user-defined types. Many powerful features are enabled as a result of having strongly typed content, such as content whose format is defined by an external type system. These include:

  • Content-based routing

    Oracle Streams Advanced Queuing can examine the content and automatically route the message to another queue based on the content.

  • Content-based subscription

    A publish and subscribe system is built on top of a messaging system so that you can create subscriptions based on content.

  • Querying

    The ability to run queries on the content of the message enables message warehousing.

You can create queues that use the new opaque type, XMLType. These queues can be used to transmit and store messages that are XML documents. Using XMLType, you can do the following:

  • Store any type of message in a queue

  • Store documents internally as CLOB objects

  • Store more than one type of payload in a queue

  • Query XMLType columns using the operator ExistsNode()

  • Specify the operators in subscriber rules or dequeue conditions

Integration with Oracle Internet Directory

You can register system events, user events, and notifications on queues 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 also create aliases for Oracle Streams Advanced Queuing agents in Oracle Internet Directory. These aliases can be specified while performing Oracle Streams Advanced Queuing enqueue, dequeue, and notification operations. This is useful when you do not want to expose an internal agent name.

Support for Oracle Real Application Clusters(Oracle RAC)

Oracle Real Application Clusters can be used to improve Oracle Streams Advanced Queuing performance by allowing different queues to be managed by different instances. You do this by specifying different instance affinities (preferences) for the queue tables that store the queues. This allows queue operations (enqueue and dequeue) on different queues to occur in parallel.

If compatibility is set to Oracle8i release 8.1.5 or higher, then an application can specify the instance affinity for a queue table. When Oracle Streams Advanced Queuing is used with Oracle RAC and multiple instances, this information is used to partition the queue tables between instances for queue-monitor scheduling as well as for propagation. The queue table is monitored by the queue monitors of the instance specified by the user. If the owner of the queue table is terminated, then the secondary instance or some available instance takes over the ownership for the queue table.

If an instance affinity is not specified, then the queue tables are arbitrarily partitioned among the available instances. This can result in pinging between the application accessing the queue table and the queue monitor monitoring it. Specifying the instance affinity prevents this, but does not prevent the application from accessing the queue table and its queues from other instances.

Oracle Streams Advanced Queuing in Integrated Application Environments

Oracle Streams Advanced Queuing provides the message management and communication needed for application integration. In an integrated environment, messages travel between the Oracle Database server, applications, and users, as shown in Figure 1-1.

Messages are exchanged between a client and the Oracle Database server or between two Oracle Database servers using Oracle Net Services. Oracle Net Services also propagates messages from one Oracle Database queue to another. Or, as shown in Figure 1-1, you can perform Oracle Streams Advanced Queuing operations over the Internet using HTTP(S). In this case, the client, a user or Internet application, produces structured XML messages. During propagation over the Internet, Oracle Database servers communicate using structured XML also.

Application integration also involves the integration of heterogeneous messaging systems. Oracle Streams Advanced Queuing seamlessly integrates with existing non-Oracle Database messaging systems like IBM WebSphere MQ through Messaging Gateway, thus allowing existing WebSphere MQ-based applications to be integrated into an Oracle Streams Advanced Queuing environment.

This section contains these topics:

Figure 1-1 Integrated Application Environment Using Oracle Streams Advanced Queuing

Description of Figure 1-1 follows
Description of "Figure 1-1 Integrated Application Environment Using Oracle Streams Advanced Queuing"

Oracle Streams Advanced Queuing Client/Server Communication

Client/Server applications usually run in a synchronous manner. Figure 1-2 demonstrates the asynchronous alternative using Oracle Streams Advanced Queuing. In this example Application B (a server) provides service to Application A (a client) using a request/response queue.

Application A enqueues a request into the request queue. In a different transaction, Application B dequeues and processes the request. Application B enqueues the result in the response queue, and in yet another transaction, Application A dequeues it.

The client need not wait to establish a connection with the server, and the server dequeues the message at its own pace. When the server is finished processing the message, there is no need for the client to be waiting to receive the result. A process of double-deferral frees both client and server.

Figure 1-2 Client/Server Communication Using Oracle Streams Advanced Queuing

Description of Figure 1-2 follows
Description of "Figure 1-2 Client/Server Communication Using Oracle Streams Advanced Queuing"

Multiconsumer Dequeuing of the Same Message

A message can only be enqueued into one queue at a time. If a producer had to insert the same message into several queues in order to reach different consumers, then this would require management of a very large number of queues. To allow multiple consumers to dequeue the same message, Oracle Streams Advanced Queuing provides for queue subscribers and message recipients.

To allow for subscriber and recipient lists, the queue must reside in a queue table that is created with the multiple consumer option. Each message remains in the queue until it is consumed by all its intended consumers.

Queue Subscribers

Multiple consumers, which can be either applications or other queues, can be associated with a queue as subscribers. This causes all messages enqueued in the queue to be made available to be consumed by each of the queue subscribers. The subscribers to the queue can be changed dynamically without any change to the messages or message producers.

You cannot add subscriptions to single-consumer queues or exception queues. A consumer that is added as a subscriber to a queue is only able to dequeue messages that are enqueued after the subscriber is added. No two subscribers can have the same values for name, address, and protocol. At least one of these attributes must be different for two subscribers.

It cannot be known which subscriber will dequeue which message first, second, and so on, because there is no priority among subscribers. More formally, the order of dequeuing by subscribers is indeterminate.

Subscribers can also be rule-based. Similar in syntax to the WHERE clause of a SQL query, rules are expressed in terms of attributes that represent message properties or message content. These subscriber rules are evaluated against incoming messages, and those rules that match are used to determine message recipients.

In Figure 1-3, Application B and Application C each need messages produced by Application A, so a multiconsumer queue is specially configured with Application B and Application C as queue subscribers. Each receives every message placed in the queue.

Figure 1-3 Communication Using a Multiconsumer Queue

Description of Figure 1-3 follows
Description of "Figure 1-3 Communication Using a Multiconsumer Queue"

Message Recipients

A message producer can submit a list of recipients at the time a message is enqueued. This allows for a unique set of recipients for each message in the queue. The recipient list associated with the message overrides the subscriber list associated with the queue, if there is one. The recipients need not be in the subscriber list. However, recipients can be selected from among the subscribers.

A recipient can be specified only by its name, in which case the recipient must dequeue the message from the queue in which the message was enqueued. It can be specified by its name and an address with a protocol value of 0. The address should be the name of another queue in the same database or another installation of Oracle Database (identified by the database link), in which case the message is propagated to the specified queue and can be dequeued by a consumer with the specified name. If the recipient's name is NULL, then the message is propagated to the specified queue in the address and can be dequeued by the subscribers of the queue specified in the address. If the protocol field is nonzero, then the name and address are not interpreted by the system and the message can be dequeued by a special consumer.

Subscribing to a queue is like subscribing to a magazine: each subscriber is able to dequeue all the messages placed into a specific queue, just as each magazine subscriber has access to all its articles. Being a recipient, on the other hand, is like getting a letter: each recipient is a designated target of a particular message.

Figure 1-4 shows how Oracle Streams Advanced Queuing can accommodate both kinds of consumers. Application A enqueues messages. Application B and Application C are subscribers. But messages can also be explicitly directed toward recipients like Application D, which may or may not be subscribers to the queue. The list of such recipients for a given message is specified in the enqueue call for that message. It overrides the list of subscribers for that queue.

Figure 1-4 Explicit and Implicit Recipients of Messages

Description of Figure 1-4 follows
Description of "Figure 1-4 Explicit and Implicit Recipients of Messages"


Note:

Multiple producers can simultaneously enqueue messages aimed at different targeted recipients.

Oracle Streams Advanced Queuing Implementation of Workflows

Figure 1-5 illustrates the use of Oracle Streams Advanced Queuing for implementing a workflow, also known as a chained application transaction:

  1. Application A begins a workflow by enqueuing Message 1.

  2. Application B dequeues it, performs whatever activity is required, and enqueues Message 2.

  3. Application C dequeues Message 2 and generates Message 3.

  4. Application D, the final step in the workflow, dequeues it.

Figure 1-5 Implementing a Workflow using Oracle Streams Advanced Queuing

Description of Figure 1-5 follows
Description of "Figure 1-5 Implementing a Workflow using Oracle Streams Advanced Queuing"


Note:

The contents of the messages 1, 2 and 3 can be the same or different. Even when they are different, messages can contain parts of the contents of previous messages.

The queues are used to buffer the flow of information between different processing stages of the business process. By specifying delay interval and expiration time for a message, a window of execution can be provided for each of the applications.

From a workflow perspective, knowledge of the volume and timing of message flows is a business asset quite apart from the value of the payload data. Oracle Streams Advanced Queuing helps you gain this knowledge by supporting the optional retention of messages for analysis of historical patterns and prediction of future trends.

Oracle Streams Advanced Queuing Implementation of Publish/Subscribe

A point-to-point message is aimed at a specific target. Senders and receivers decide on a common queue in which to exchange messages. Each message is consumed by only one receiver. Figure 1-6 shows that each application has its own message queue, known as a single-consumer queue.

Figure 1-6 Point-to-Point Messaging

Description of Figure 1-6 follows
Description of "Figure 1-6 Point-to-Point Messaging"

A publish/subscribe message can be consumed by multiple receivers, as shown in Figure 1-7. Publish/subscribe messaging has a wide dissemination mode called broadcast and a more narrowly aimed mode called multicast.

Broadcasting is like a radio station not knowing exactly who the audience is for a given program. The dequeuers are subscribers to multiconsumer queues. In contrast, multicast is like a magazine publisher who knows who the subscribers are. Multicast is also referred to as point-to-multipoint, because a single publisher sends messages to multiple receivers, called recipients, who may or may not be subscribers to the queues that serve as exchange mechanisms.

Figure 1-7 Publish/Subscribe Mode

Description of Figure 1-7 follows
Description of "Figure 1-7 Publish/Subscribe Mode"

Publish/subscribe describes a situation in which a publisher application enqueues messages to a queue anonymously (no recipients specified). The messages are then delivered to subscriber applications based on rules specified by each application. The rules can be defined on message properties, message data content, or both.

You can implement a publish/subscribe model of communication using Oracle Streams Advanced Queuing as follows:

  1. Set up one or more queues to hold messages. These queues should represent an area or subject of interest. For example, a queue can be used to represent billed orders.

  2. Set up a set of rule-based subscribers. Each subscriber can specify a rule which represents a specification for the messages that the subscriber wishes to receive. A null rule indicates that the subscriber wishes to receive all messages.

  3. Publisher applications publish messages to the queue by invoking an enqueue call.

  4. Subscriber applications can receive messages with a dequeue call. This retrieves messages that match the subscription criteria.

  5. Subscriber applications can also use a listen call to monitor multiple queues for subscriptions on different queues. This is a more scalable solution in cases where a subscriber application has subscribed to many queues and wishes to receive messages that arrive in any of the queues.

  6. Subscriber applications can also use the Oracle Call Interface (OCI) notification mechanism. This allows a push mode of message delivery. The subscriber application registers the queues (and subscriptions specified as subscribing agent) from which to receive messages. This registers a callback to be invoked when messages matching the subscriptions arrive.

Figure 1-8 illustrates the use of Oracle Streams Advanced Queuing for implementing a publish/subscribe relationship between publisher Application A and subscriber Applications B, C, and D:

  • Application B subscribes with rule "priority = 1".

  • Application C subscribes with rule "priority > 1".

  • Application D subscribes with rule "priority = 3".

Figure 1-8 Implementing Publish/Subscribe using Oracle Streams Advanced Queuing

Description of Figure 1-8 follows
Description of "Figure 1-8 Implementing Publish/Subscribe using Oracle Streams Advanced Queuing"

If Application A enqueues three messages with priorities 1, 2, and 3 respectively, then the messages will be delivered as follows:

  • Application B receives a single message (priority 1).

  • Application C receives two messages (priority 2, 3).

  • Application D receives a single message (priority 3).

Buffered Messaging

Buffered messaging, a new feature in Oracle Streams Advanced Queuing 10g Release 2 (10.2), combines the rich functionality that this product has always offered with a much faster queuing implementation. Buffered messaging is ideal for applications that do not require the reliability and transaction support of Oracle Streams Advanced Queuing persistent messaging.

Buffered messaging is faster than persistent messaging, because its messages reside in shared memory. They are usually written to disk only when the total memory consumption of buffered messages approaches the available shared memory limit.


Note:

The portion of a queue that stores buffered messages in memory is sometimes referred to as a buffered queue.

Message retention is not supported for buffered messaging.

When using buffered messaging, Oracle recommends that you do one of the following:

  • Set parameter streams_pool_size

    This parameter controls the size of shared memory available to Oracle Streams Advanced Queuing. If unspecified, up to 10% of the shared pool size may be allocated for the Oracle Streams Advanced Queuing pool from the database cache.

  • Turn on SGA autotuning

    Oracle will automatically allocate the appropriate amount of memory from the SGA for Oracle Streams Advanced Queuing, based on Oracle Streams Advanced Queuing usage as well as usage of other components that use the SGA. Examples of such other components are buffer cache and library cache. If streams_pool_size is specified, it is used as the lower bound.


See Also:

"Setting Initialization Parameters Relevant to Streams" in Oracle Streams Concepts and Administration

This section contains the following topics:

Enqueuing Buffered Messages

Buffered and persistent messages use the same single-consumer or multiconsumer queues and the same administrative and operational interfaces. They are distinguished from each other by a delivery mode parameter, set by the application when enqueuing the message to an Oracle Streams Advanced Queuing queue.

Recipient lists are supported for buffered messaging enqueue.

Buffered messaging is supported in all queue tables created with compatibility 8.1 or higher. Transaction grouping queues and array enqueues are not supported for buffered messages in this release. You can still use the array enqueue procedure to enqueue buffered messages, but the array size must be set to one.

Buffered messages can be queried using the AQ$Queue_Table_Name view. They appear with states IN-MEMORY or SPILLED.

The queue type for buffered messaging can be ADT, XML, ANYDATA, or RAW. For ADT types with LOB attributes, only buffered messages with null LOB attributes can be enqueued.

All ordering schemes available for persistent messages are also available for buffered messages, but only within each message class. Ordering among persistent and buffered messages enqueued in the same session is not currently supported.

Both enqueue and dequeue buffered messaging operations must be with IMMEDIATE visibility mode. Thus they cannot be part of another transaction. You cannot specify delay when enqueuing buffered messages.

Dequeuing Buffered Messages

Rule-based subscriptions are supported with buffered messaging. The procedure for adding subscribers is enhanced to allow an application to express interest in persistent messages only, buffered messages only, or both.

Array dequeue is not supported for buffered messaging, but you can still use the array dequeue procedure by setting array size to one message.

Dequeuing applications can choose to dequeue persistent messages only, buffered messages only, or both types. Visibility must be set to IMMEDIATE for dequeuing buffered messages. All of the following dequeue options are supported:

  • Dequeue modes BROWSE, LOCK, REMOVE, and REMOVE_NO_DATA

  • Navigation modes FIRST_MESSAGE and NEXT_MESSAGE

  • Correlation identifier

  • Dequeue condition

  • Message identifier


See Also:

"Dequeue Options"

Propagating Buffered Messages

Propagation of buffered messages is supported. A single propagation schedule serves both persistent and buffered messages. The DBA_QUEUE_SCHEDULES view displays statistics and error information.

Oracle Streams AQ deletes buffered messages once they are propagated to the remote sites. If the receiving site fails before these messages are consumed, then these messages will be lost. The source site will not be able to re-send them. Duplicate delivery of messages is also possible.

Flow Control

Oracle Streams Advanced Queuing implements a flow control system that prevents applications from flooding the shared memory with messages. If the number of outstanding messages per sender exceeds a system-defined threshold, the enqueue call will block and timeout with an error message. A message sender is identified by sender_id.name in the enqueue options. A sender blocked due to flow control on a queue does not affect other message senders. The resolution is to dequeue messages, thereby resolving flow control, after which new messages can be enqueued.

Flow control threshold varies with memory pressure and could come down to the system-defined limit if streams pool usage becomes significant. Message senders will block on event Streams AQ: enqueue blocked due to flow control and time out with error ORA-25307 if flow control is not resolved. Applications are expected to handle this error, and re-enqueue the failed message.

Even with flow control, slow consumers of a multiconsumer queue can cause the number of messages stored in memory to grow without limit. Provided there is at least one subscriber who is keeping pace, older messages are spilled to disk and removed from the pool to free up memory. This ensures that the cost of disk access is paid by the slower consumers, and faster subscribers can proceed unhindered.

Buffered Messaging with Oracle Real Application Clusters (Oracle RAC)

An application can enqueue and dequeue buffered messages from any Oracle RAC instance as long as it uses password-based authentication to connect to the database. The structures required for buffered messaging are implemented on one Oracle RAC instance. The instance where the buffered messaging structures are implemented is the OWNER_INSTANCE of the queue table containing the queue. Enqueue and dequeue requests received at other instances are forwarded to the OWNER_INSTANCE over the interconnect. The REMOTE_LISTENER parameter in listener.ora must also be set to enable forwarding of buffered messaging requests to correct instance.


See Also:


A service name is associated with each queue in Oracle RAC and displayed in the DBA_QUEUES and USER_QUEUES views. This service name always points to the instance with the most efficient access for buffered messaging, minimizing pinging between instances. OCI clients can use the service name for buffered messaging operations.

Oracle recommends that you use buffered messaging with queue-to-queue propagation. This results in transparent failover when propagating messages to a destination Oracle RAC system. You do not need to re-point your database links if the primary Oracle Streams Advanced Queuing RAC instance fails.

Buffered Messaging Restrictions

The following Oracle Streams Advanced Queuing features are not currently supported for buffered messaging:

  • Message retention

  • Message delay

  • Transaction grouping

  • Array enqueue

  • Array dequeue

  • Message export and import

  • Posting for subscriber notification

  • Messaging Gateway

Error Handling

Retry count and retry delay are not supported for buffered messages. Message expiration is supported. When a buffered message has been in the queue beyond its expiration period, it is moved into the exception queue as a persistent message.

Asynchronous Notifications

Asynchronous notification allows clients to receive notifications of messages of interest. The client can use these notifications to monitor multiple subscriptions. The client need not be connected to the database to receive notifications regarding its subscriptions. Asynchronous notification is supported for buffered messages. The delivery mode of the message is available in the message descriptor of the notification descriptor.


Note:

In releases before Oracle Database 10g Release 2 (10.2), the Oracle Streams Advanced Queuing notification feature was not supported for queues with names longer than 30 characters. This restriction no longer applies. The 24-character limit on names of user-generated queues still applies. See "Creating a Queue".

The client specifies a callback function which is run for each message. Asynchronous notification cannot be used to invoke an executable, but it is possible for the callback function to invoke a stored procedure.

Clients can receive notifications procedurally using PL/SQL, Java Message Service (JMS), or OCI callback functions, or clients can receive notifications through e-mail or HTTP post. Clients can also specify the presentation for notifications as either RAW or XML.

For JMS queues, the dequeue is accomplished as part of the notification; explicit dequeue is not required. For RAW queues, clients can specify payload delivery; but they still must dequeue the message in REMOVE_NO_DATA mode. For all other persistent queues, the notification contains only the message properties; clients explicitly dequeue to receive the message.

Payload Delivery for RAW Queues

For RAW queues, Oracle Streams Advanced Queuing clients can now specify that the message payload be delivered along with its notification.

Reliable Notification

In earlier releases of Oracle Streams Advanced Queuing, message notifications were stored in shared memory and were lost if the instance failed. Clients can now specify persistent message notification. If a Oracle RAC instance fails, its notifications are delivered by another Oracle RAC node. If a standalone instance fails, its notifications are delivered when the instance restarts.


Note:

Notification reliability refers only to server failures. If Oracle Streams Advanced Queuing is unable to deliver client notifications for any other reason, then the notifications are purged along with the client registration.

Designated Port Notification

Oracle Streams Advanced Queuing clients can now use the OCI subscription handle attribute OCI_ATTR_SUBSCR_PORTNO to designate the port at which notifications are delivered. This is especially useful for clients on a computer behind a firewall. The port for the listener thread can be designated before the first registration, using an attribute in the environment handle. The thread is started the first time an OCISubscriptionRegister is called. If the client attempts to start another thread on a different port using a different environment handle, then Oracle Streams Advanced Queuing returns an error.


Note:

Designated port notification and IP address notification apply only to OCI clients.


See Also:

"Publish-Subscribe Registration Functions in OCI" in Oracle Call Interface Programmer's Guide

IPv6 Compliance and Designated IP Support

Oracle Streams AQ supports IPv6 and Oracle Streams AQ clients can use the OCI subscription handle attribute OCI_ATTR_SUBSCR_IPADDR to designate the IP address at which notifications are delivered. This is especially useful for clients on a computer that has multiple network interface cards or IP addresses. The IP address for the listener thread can be designated before the first registration using an attribute in the environment handle. The thread is started the first time an OCISubscriptionRegister is called. If the client attempts to start another thread on a different IP address using a different environment handle, Oracle Streams AQ returns an error. If no IP address is specified, Oracle Streams AQ will deliver notifications on all IP addresses of the computer the client is on.

Registration Timeout

In earlier releases of Oracle Streams Advanced Queuing, registrations for notification persisted until explicitly removed by the client or purged in case of extended client failure. In Oracle Streams Advanced Queuing 10g Release 2 (10.2) clients can register for a specified time, after which the registration is automatically purged.

When the registration is purged, Oracle Streams Advanced Queuing sends a notification to the client, so the client can invoke its callback and take any necessary action.


See Also:

"AQ Registration Information Type" for information on the timeout parameter

Purge on Notification

Clients can also register to receive only the first notification, after which the registration is automatically purged.

An example where purge on notification is useful is a client waiting for enqueues to start. In this case, only the first notification is useful; subsequent notifications provide no additional information. Previously, this client would be required to unregister once enqueuing started; now the registration can be configured to go away automatically.

Buffered Message Notification

Clients can register for notification of buffered messages. The registration requests apply to both buffered and persistent messages. The message properties delivered with the PL/SQL or OCI notification specify whether the message is buffered or persistent.


See Also:

  • "Registering for Notification" for more information on PL/SQL notification

  • Appendix C, "OCI Examples", which appears only in the HTML version of this guide, for an example of OCI notification


Reliable notification is not supported.

Views on Registration

The dictionary views DBA_SUBSCR_REGISTRATIONS and USER_SUBSCR_REGISTRATIONS display the various registrations in the system. The diagnostic view GV$SUBSCR_REGISTRATION_STATS may be used to monitor notification statistics and performance.

Event-Based Notification

Event-based notifications are processed by a set of coordinator (EMNC) and subordinate processes (EXXX). The event notification load is distributed amongst these processes. These processes work on the system notifications in parallel, offering a capability to process a larger volume of notifications, a faster response time and lower shared memory use for staging notifications.

Notification Grouping by Time

Notification applications may register to receive a single notification for all events that occur within a specified time interval. Notification Clients may specify a start time for the notifications. Additionally, they must specify a time as the grouping class and the time interval as the grouping value. A repeat count may be used to limit the number of notifications delivered.Clients can receive two types of grouping events, Summary or Last. A summary notification is a list of Message Identifiers of all the messages for the subscription. If last was specified as a grouping type, notification would have information about the last message in the notification interval. A count of the number of messages in the interval is also sent.The registration interfaces in PLSQL and OCI allow for specification of the START_TIME, REPEAT_COUNT, GROUPING CLASS, GROUPING VALUE, GROUPING TYPE in the AQ$_REGISTRATION_INFO and the OCI subscription Handle.

The notification descriptor received by the AQ notification client provides information about the group of message identifiers and the number of notifications in the group.

Enqueue Features

The following features apply to enqueuing messages:

Enqueue an Array of Messages

When enqueuing messages into a queue, you can operate on an array of messages simultaneously, instead of one message at a time. This can improve the performance of enqueue operations. When enqueuing an array of messages into a queue, each message shares the same enqueue options, but each message can have different message properties. You can perform array enqueue operations using PL/SQL or OCI.

Array enqueuing is not supported for buffered messages in this release.

Correlation Identifiers

You can assign an identifier to each message, thus providing a means to retrieve specific messages at a later time.

Priority and Ordering of Messages in Enqueuing

You can specify the priority of an enqueued message and its exact position in the queue. This means that users can specify the order in which messages are consumed in three ways:

  • A priority can be assigned to each message.

  • A sort order specifies which properties are used to order all messages in a queue. This is set when the queue table is created and cannot be changed. You can choose to sort messages by priority, enqueue time, or commit time. The commit-time option, a new feature in Oracle Streams Advanced Queuing 10g Release 2 (10.2), orders messages by an approximate CSCN calculated for each transaction.

    Commit-time ordering is useful when transactions are interdependent or when browsing the messages in a queue must yield consistent results.


    See Also:


  • A sequence deviation positions a message in relation to other messages.


Note:

The sequence deviation feature is deprecated in 10g Release 2 (10.2).

If several consumers act on the same queue, then each consumer gets the first message that is available for immediate consumption. A message that is in the process of being consumed by another consumer is skipped.

Priority ordering of messages is achieved by specifying priority, enqueue time as the sort order. If priority ordering is chosen, then each message is assigned a priority at enqueue time by the enqueuing agent. At dequeue time, the messages are dequeued in the order of the priorities assigned. If two messages have the same priority, then the order in which they are dequeued is determined by the enqueue time. A first-in, first-out (FIFO) priority queue can also be created by specifying enqueue time, priority as the sort order of the messages.

Message Grouping

Messages belonging to one queue can be grouped to form a set that can only be consumed by one user at a time. This requires that the queue be created in a queue table that is enabled for message grouping. All messages belonging to a group must be created in the same transaction, and all messages created in one transaction belong to the same group.

This feature allows users to segment complex messages into simple messages. For example, messages directed to a queue containing invoices can be constructed as a group of messages starting with a header message, followed by messages representing details, followed by a trailer message.

Message grouping is also useful if the message payload contains complex large objects such as images and video that can be segmented into smaller objects.

Group message properties priority, delay, and expiration are determined solely by the message properties specified for the first message in a group, irrespective of which properties are specified for subsequent messages in the group.

The message grouping property is preserved across propagation. However, the destination queue where messages are propagated must also be enabled for transactional grouping. There are also some restrictions you must keep in mind if the message grouping property is to be preserved while dequeuing messages from a queue enabled for transactional grouping.

Sender Identification

Applications can mark the messages they send with a custom identification. Oracle Streams Advanced Queuing also automatically identifies the queue from which a message was dequeued. This allows applications to track the pathway of a propagated message or a string message within the same database.

Time Specification and Scheduling

Messages can be enqueued with an expiration that specifies the interval of time the message is available for dequeuing. The default for expiration is never. When a message expires, it is moved to an exception queue. Expiration processing requires that the queue monitor be running.

Dequeue Features

The following features apply to dequeuing messages:

Concurrent Dequeues

When there are multiple processes dequeuing from a single-consumer queue or dequeuing for a single consumer on the multiconsumer queue, different processes skip the messages that are being worked on by a concurrent process. This allows multiple processes to work concurrently on different messages for the same consumer.

Dequeue Methods

A message can be dequeued using one of the following dequeue methods:

  • Specifying a correlation identifier

    A correlation identifier is a user-defined message property. Multiple messages with the same correlation identifier can be present in a queue, which means that the ordering (enqueue order) between messages might not be preserved on dequeue calls.

  • Specifying a message identifier

    A message identifier is a system-assigned value (of RAW datatype). Only one message with a given message identifier can be present in the queue.

  • Specifying a dequeue condition

    A dequeue condition is expressed in terms of message properties or message content and is similar in syntax to the WHERE clause of a SQL query. Messages in the queue are evaluated against the condition, and messages that satisfy the given condition are returned. When a dequeue condition is used, the order of the messages dequeued is indeterminate, and the sort order of the queue is not honored.

  • Default dequeue

    A default dequeue retrieves the first available message.


Note:

Dequeuing with correlation identifier, message identifier, or dequeue condition does not preserve the message grouping property.

Dequeue Modes

A dequeue request can browse a message, remove it, or remove it with no data. If a message is browsed, then it remains available for further processing. If a message is removed or removed with no data, then it is no longer available for dequeue requests. Depending on the queue properties, a removed message can be retained in the queue table. A message is retained in the queue table after it has been consumed only if a retention time is specified for its queue.

The browse mode has three risks. First, there is no guarantee that the message can be dequeued again after it is browsed, because a dequeue call from a concurrent user might have removed the message. To prevent a viewed message from being dequeued by a concurrent user, you should view the message in the locked mode.

Second, your dequeue position in browse mode is automatically changed to the beginning of the queue if a nonzero wait time is specified and the navigating position reaches the end of the queue. If you repeat a dequeue call in the browse mode with the NEXT_MESSAGE navigation option and a nonzero wait time, then you can end up dequeuing the same message over and over again. Oracle recommends that you use a nonzero wait time for the first dequeue call on a queue in a session, and then use a zero wait time with the NEXT_MESSAGE navigation option for subsequent dequeue calls. If a dequeue call gets an "end of queue" error message, then the dequeue position can be explicitly set by the dequeue call to the beginning of the queue using the FIRST_MESSAGE navigation option, following which the messages in the queue can be browsed again.

Third, if the sort order of the queue is ENQ_TIME, PRIORITY, or a combination of these two, then results may not be repeatable from one browse to the next. If you must have consistent browse results, then you should use a commit-time queue.

When a message is dequeued using REMOVE_NODATA mode, the payload of the message is not retrieved. This mode can be useful when the user has already examined the message payload, possibly by means of a previous BROWSE dequeue.

Dequeue an Array of Messages

When dequeuing messages from a queue, you can operate on an array of messages simultaneously, instead of one message at a time. This can improve the performance of dequeue operations. If you are dequeuing from a transactional queue, you can dequeue all the messages for a transaction with a single call, which makes application programming easier.

When dequeuing an array of messages from a queue, each message shares the same dequeue options, but each message can have different message properties. You can perform array enqueue and array dequeue operations using PL/SQL or OCI.

Array dequeuing is not supported for buffered messages in this release.

Message States

Multiple processes or operating system threads can use the same consumer name to dequeue concurrently from a queue. In that case Oracle Streams Advanced Queuing provides the first unlocked message that is at the head of the queue and is intended for the consumer. Unless the message identifier of a specific message is specified during dequeue, consumers can dequeue messages that are in the READY state.

A message is considered PROCESSED only when all intended consumers have successfully dequeued the message. A message is considered EXPIRED if one or more consumers did not dequeue the message before the EXPIRATION time. When a message has expired, it is moved to an exception queue.

Expired messages from multiconsumer queues cannot be dequeued by the intended recipients of the message. However, they can be dequeued in the REMOVE mode exactly once by specifying a NULL consumer name in the dequeue options.


Note:

If the multiconsumer exception queue was created in a queue table with the compatible parameter set to 8.0, then expired messages can be dequeued only by specifying a message identifier.

Queues created in a queue table with compatible set to 8.0 (referred to in this guide as 8.0-style queues) are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2). Oracle recommends that any new queues you create be 8.1-style or newer and that you migrate existing 8.0-style queues at your earliest convenience.


Beginning with Oracle Streams Advanced Queuing release 8.1.6, only the queue monitor removes messages from multiconsumer queues. This allows dequeuers to complete the dequeue operation by not locking the message in the queue table. Because the queue monitor removes messages that have been processed by all consumers from multiconsumer queues approximately once every minute, users can see a delay between when the messages have been completely processed and when they are physically removed from the queue.

Navigation of Messages in Dequeuing

You have several options for selecting a message from a queue. You can select the first message with the FIRST_MESSAGE navigation option. Alternatively, once you have selected a message and established its position in the queue, you can then retrieve the next message with the NEXT_MESSAGE navigation option.

The FIRST_MESSAGE navigation option performs a SELECT on the queue. The NEXT_MESSAGE navigation option fetches from the results of the SELECT run in the FIRST_MESSAGE navigation. Thus performance is optimized because subsequent dequeues need not run the entire SELECT again.

If the queue is enabled for transactional grouping, then the navigation options work in a slightly different way. If FIRST_MESSAGE is requested, then the dequeue position is still reset to the beginning of the queue. But if NEXT_MESSAGE is requested, then the position is set to the next message in the same transaction. Transactional grouping also offers a NEXT_TRANSACTION option. It sets the dequeue position to the first message of the next transaction.

Transaction grouping has no effect if you dequeue by specifying a correlation identifier or message identifier, or if you dequeue some of the messages of a transaction and then commit.

If you reach the end of the queue while using the NEXT_MESSAGE or NEXT_TRANSACTION option, and you have specified a nonzero wait time, then the navigating position is automatically changed to the beginning of the queue. If a zero wait time is specified, then you can get an exception when the end of the queue is reached.

Waiting for Messages

Oracle Streams Advanced Queuing allows applications to block on one or more queues waiting for the arrival of either a newly enqueued message or a message that becomes ready. You can use the DEQUEUE operation to wait for the arrival of a message in a single queue or the LISTEN operation to wait for the arrival of a message in more than one queue.


Note:

Applications can also perform a blocking dequeue on exception queues to wait for arrival of EXPIRED messages.

When the blocking DEQUEUE call returns, it returns the message properties and the message payload. When the blocking LISTEN call returns, it discloses only the name of the queue where a message has arrived. A subsequent DEQUEUE operation is needed to dequeue the message.

When there are messages for multiple agents in the agent list, LISTEN returns with the first agent for whom there is a message. To prevent one agent from starving other agents for messages, the application can change the order of the agents in the agent list.


Note:

This feature is not currently supported in Visual Basic (OO4O).

Applications can optionally specify a timeout of zero or more seconds to indicate the time that Oracle Streams Advanced Queuing must wait for the arrival of a message. The default is to wait forever until a message arrives in the queue. This removes the burden of continually polling for messages from the application, and it saves CPU and network resources because the application remains blocked until a new message is enqueued or becomes READY after its DELAY time.

An application that is blocked on a dequeue is either awakened directly by the enqueuer if the new message has no DELAY or is awakened by the queue monitor process when the DELAY or EXPIRATION time has passed. If an application is waiting for the arrival of a message in a remote queue, then the Oracle Streams Advanced Queuing propagator wakes up the blocked dequeuer after a message has been propagated.

Retries with Delays

If the transaction dequeuing a message from a queue fails, then it is regarded as an unsuccessful attempt to consume the message. Oracle Streams Advanced Queuing records the number of failed attempts to consume the message in the message history. Applications can query the RETRY_COUNT column of the queue table view to find out the number of unsuccessful attempts on a message. In addition, Oracle Streams Advanced Queuing allows the application to specify, at the queue level, the maximum number of retries for messages in the queue. The default value for maximum retries is 5. If the number of failed attempts to remove a message exceeds this number, then the message is moved to the exception queue and is no longer available to applications.


Note:

If a dequeue transaction fails because the server process dies (including ALTER SYSTEM KILL SESSION) or SHUTDOWN ABORT on the instance, then RETRY_COUNT is not incremented.

A bad condition can cause the transaction receiving a message to end. Oracle Streams Advanced Queuing allows users to hide the bad message for a specified retry delay interval, during which it is in the WAITING state. After the retry delay, the failed message is again available for dequeue. The Oracle Streams Advanced Queuing time manager enforces the retry delay property. The default value for retry delay is 0.

If multiple sessions are dequeuing messages from a queue simultaneously, then RETRY_COUNT information might not always be updated correctly. If session one dequeues a message and rolls back the transaction, then Oracle Streams AQ notes that the RETRY_COUNT information for this message must be updated. However RETRY_COUNT cannot be incremented until session one completes the rollback. If session two attempts to dequeue the same message after session one has completed the rollback but before it has incremented RETRY_COUNT, then the dequeue by session two succeeds. When session one attempts to increment RETRY_COUNT, it finds that the message is locked by session two and RETRY_COUNT is not incremented. A trace file is then generated in the USER_DUMP_DESTINATION for the instance with the following message:

Error on rollback: ORA-25263: no message in queue schema.qname with message ID ...

Note:

Maximum retries and retry delay are not available with 8.0-style multiconsumer queues.

Queues created in a queue table with compatible set to 8.0 (referred to in this guide as 8.0-style queues) are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2). Oracle recommends that any new queues you create be 8.1-style or newer and that you migrate existing 8.0-style queues at your earliest convenience.


Optional Transaction Protection

Enqueue and dequeue requests are usually part of a transaction that contains the requests, thereby providing the wanted transactional action. You can, however, specify that a specific request is a transaction by itself, making the result of that request immediately visible to other transactions. This means that messages can be made visible to the external world when the enqueue or dequeue statement is applied or after the transaction is committed.


Note:

Transaction protection is not supported for buffered messaging.

Exception Queues

An exception queue is a repository for expired or unserviceable messages. Applications cannot directly enqueue into exception queues. Also, a multiconsumer exception queue cannot have subscribers associated with it. However, an application that intends to handle these expired or unserviceable messages can dequeue them exactly once from the exception queue using remove mode. The consumer name specified while dequeuing should be null. Messages can also be dequeued from the exception queue by specifying the message identifier.


Note:

Expired or unserviceable buffered messages are moved to an exception queue as persistent messages.

Messages intended for single-consumer queues, or for 8.0-style multiconsumer queues, can only be dequeued by their message identifiers once the messages have been moved to an exception queue.

Queues created in a queue table with compatible set to 8.0 (referred to in this guide as 8.0-style queues) are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2). Oracle recommends that any new queues you create be 8.1-style or newer and that you migrate existing 8.0-style queues at your earliest convenience.


After a message has been moved to an exception queue, there is no way to identify which queue the message resided in before moving to the exception queue. If this information is important, then the application must save this information in the message itself.

The exception queue is a message property that can be specified during enqueue time. If an exception queue is not specified, then a default exception queue is used. The default exception queue is automatically created when the queue table is created.

A message is moved to an exception queue under the following conditions:

  • It was not dequeued within the specified expiration interval.

    For a message intended for multiple recipients, the message is moved to the exception queue if one or more of the intended recipients was not able to dequeue the message within the specified expiration interval. The default expiration interval is never, meaning the messages does not expire.

  • The message was dequeued successfully, but the application that dequeued it rolled back the transaction because of an error that arose while processing the message. If the message has been dequeued but rolled back more than the number of times specified by the retry limit, then the message is moved to the exception queue.

    For a message intended for multiple recipients, a separate retry count is kept for each recipient. The message is moved to the exception queue only when retry counts for all recipients of the message have exceeded the specified retry limit.

    The default retry limit is five for single-consumer queues and 8.1-style multiconsumer queues. No retry limit is supported for 8.0-style multiconsumer queues, which are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2).


    Note:

    If a dequeue transaction fails because the server process dies (including ALTER SYSTEM KILL SESSION) or SHUTDOWN ABORT on the instance, then RETRY_COUNT is not incremented.

  • The statement processed by the client contains a dequeue that succeeded but the statement itself was undone later due to an exception.

    If the dequeue procedure succeeds but the PL/SQL procedure raises an exception, then Oracle Streams Advanced Queuing increments the retry count of the message returned by the dequeue procedure.

  • The client program successfully dequeued a message but terminated before committing the transaction.

Propagation Features

Messages can be propagated from one queue to another, allowing applications to communicate with each other without being connected to the same database or to the same queue. The destination queue can be located in the same database or in a remote database.

Propagation enables you to fan out messages to a large number of recipients without requiring them all to dequeue messages from a single queue. You can also use propagation to combine messages from different queues into a single queue. This is known as compositing or funneling messages.


Note:

You can propagate messages from a multiconsumer queue to a single-consumer queue. Propagation from a single-consumer queue to a multiconsumer queue is not possible.

A message is marked as processed in the source queue immediately after the message has been propagated, even if the consumer has not dequeued the message at the remote queue. Similarly, when a propagated message expires at the remote queue, the message is moved to the exception queue of the remote queue, and not to the exception queue of the local queue. Oracle Streams Advanced Queuing does not currently propagate the exceptions to the source queue.

To enable propagation, one or more subscribers are defined for the queue from which messages are to be propagated and a schedule is defined for each destination where messages are to be propagated from the queue.

Oracle Streams Advanced Queuing automatically checks if the type of the remote queue is structurally equivalent to the type of the local queue within the context of the character sets in which they are created. Messages enqueued in the source queue are then propagated and automatically available for dequeuing at the destination queue or queues.

When messages arrive at the destination queues, sessions based on the source queue schema name are used for enqueuing the newly arrived messages into the destination queues. This means that you must grant schemas of the source queues enqueue privileges to the destination queues.

Propagation runs as an Oracle Scheduler job. A background process, the JOB_QUEUE_PROCESS will run the job. Propagation scheduling may be a dedicated process, running continuously and without end, or it may be event driven, in which case it runs only if there is a message to be propagated.

Oracle Streams Advanced Queuing offers two kinds of propagation:

  • Queue-to-dblink propagation

  • Queue-to-queue propagation

Queue-to-dblink propagation delivers messages or events from the source queue to all subscribing queues at the destination database identified by the dblink.

A single propagation schedule is used to propagate messages to all subscribing queues. Hence any changes made to this schedule will affect message delivery to all the subscribing queues.

Queue-to-queue propagation delivers messages or events from the source queue to a specific destination queue identified on the dblink. This allows the user to have fine-grained control on the propagation schedule for message delivery.

This new propagation mode also supports transparent failover when propagating to a destination Oracle RAC system. With queue-to-queue propagation, you are no longer required to re-point a database link if the owner instance of the queue fails on Oracle RAC.

Oracle Streams Advanced Queuing provides detailed statistics about the messages propagated and the schedule itself. This information can be used to tune propagation schedules for best performance.

Remote Consumers

Consumers of a message in multiconsumer queues can be local or remote. Local consumers dequeue messages from the same queues into which the producer enqueued the messages. Local consumers have a name but no address or protocol in their agent descriptions.

Remote consumers dequeue from queues that are different from the queues where the messages were enqueued. Remote consumers fall into three categories:

  • The address refers to a queue in the same database.

    In this case the consumer dequeues the message from a different queue in the same database. These addresses are of the form [schema].queue_name. If the schema is not specified, then the schema of the current user is used.

  • The address refers to a queue in a different database.

    In this case the database must be reachable using database links and the protocol must be either NULL or 0. These addresses are of the form [schema].queue_name@dblink. If the schema is not specified, then the schema of the current user is used. If the database link does not have a domain name specified, then the default domain as specified by the DB_DOMAIN init.ora parameter is used.

  • The address refers to a destination that can be reached by a third party protocol.

    You must refer to the documentation of the third party software to determine how to specify the address and the protocol database link and schedule propagation.

Propagation to Remote Subscribers

Oracle Streams Advanced Queuing validates the database link specified in a propagation schedule when the schedule runs, but not when the schedule is created. It is possible, therefore, to create a queue-to-dblink or queue-to-queue propagation before creating its associated database link. Also, the propagation schedule is not disabled if you remove the database link.

Oracle Streams AQ offers two kinds of propagation:

A) Queue-to-dblink propagation - specified by providing a (source) queue and (destination) databaselink. Messages from the source queue for any queues at the destination specified by the dblink will be handled by this propagation.

In this scenario, we cannot have multiple propagations from a source queue, with dblinks connecting to the same database. Thus(q1, dblink1) and (q1, dblink2) cannot co-exist if both dblinks connect to the same database. On the other hand (q1, dblink1) and (q2, dblink1) OR (q1, dblink1) and (q2, dblink2) can co-exist as source queues are different.

B) Queue-to-queue propagation - specified by providing a (source) queue, (destination) dblink and (destination) queue. Messages from the source queue for the indicated queue at the destination dblink will be handled by this propagation. Here, either (q1, dblink1, dq1), (q1, dblink1, dq2) OR (q1, dblink1, dq1), (q1, dblink2, dq2) succeeds. This strategy works because the destination queues are different even though source queue is the same and dblink connects to the same database.

In this scenario, we cannot have multiple propagations between a source queue, destination queue, even if using different dblinks: (q1, dblink1, q2) and (q1, dblink2, q2) cannot co-exist, if dblink1 and dblink2 are pointing to the same database.

Priority and Ordering of Messages in Propagation

The delay, expiration, and priority parameters apply identically to both local and remote consumers in both queue-to-dblink and queue-to-queue propagation. Oracle Streams Advanced Queuing accounts for any delay in propagation by adjusting the delay and expiration parameters accordingly. For example, if expiration is set to one hour, and the message is propagated after 15 minutes, then the expiration at the remote queue is set to 45 minutes.

Inboxes and Outboxes

Figure 1-9 illustrates applications on different databases communicating using Oracle Streams Advanced Queuing. Each application has an inbox for handling incoming messages and an outbox for handling outgoing messages. Whenever an application enqueues a message, it goes into its outbox regardless of the message destination. Similarly, an application dequeues messages from its inbox no matter where the message originates.

Figure 1-9 Message Propagation in Oracle Streams Advanced Queuing

Description of Figure 1-9 follows
Description of "Figure 1-9 Message Propagation in Oracle Streams Advanced Queuing"

Propagation Scheduling

A queue-to-dblink propagation schedule is defined for a pair of source and destination database links. A queue-to-queue propagation schedule is defined for a pair of source and destination queues. If a queue has messages to be propagated to several queues, then a schedule must be defined for each of the destination queues. With queue-to-dblink propagation, all schedules for a particular remote database have the same frequency. With queue-to-queue propagation, the frequency of each schedule can be adjusted independently of the others

A schedule indicates the time frame during which messages can be propagated from the source queue. This time frame can depend on a number of factors such as network traffic, load at the source database, and load at the destination database. If the duration is unspecified, then the time frame is an infinite single window. If a window must be repeated periodically, then a finite duration is specified along with a NEXT_TIME function that defines the periodic interval between successive windows.

When a schedule is created, a job is automatically submitted to the job queue facility to handle propagation.

The propagation schedules defined for a queue can be changed or dropped at any time during the life of the queue. You can also temporarily disable a schedule instead of dropping it. All administrative calls can be made irrespective of whether the schedule is active or not. If a schedule is active, then it takes a few seconds for the calls to be processed.

Propagation of Messages with LOBs

Large Objects can be propagated using Oracle Streams Advanced Queuing using two methods:

  • Propagation from RAW queues

    In RAW queues the message payload is stored as a BLOB. This allows users to store up to 32KB of data when using the PL/SQL interface and as much data as can be contiguously allocated by the client when using OCI. This method is supported by all releases after 8.0.4 inclusive.

  • Propagation from object queues with LOB attributes

    The user can populate the LOB and read from the LOB using Oracle Database LOB handling routines. The LOB attributes can be BLOBs or CLOBs (not NCLOBs). If the attribute is a CLOB, then Oracle Streams Advanced Queuing automatically performs any necessary character set conversion between the source queue and the destination queue. This method is supported by all releases from 8.1.3 inclusive.


    Note:

    Payloads containing LOBs require users to grant explicit Select, Insert and Update privileges on the queue table for doing enqueues and dequeues.

Propagation Statistics

Detailed runtime information about propagation is gathered and stored in the DBA_QUEUE_SCHEDULES view for each propagation schedule. This information can be used by queue designers and administrators to fix problems or tune performance. Similarly, errors reported by the view can be used to diagnose and fix problems. The view also describes additional information such as the session ID of the session handling the propagation and the process name of the job queue process handling the propagation.

For each schedule, detailed propagation statistics are maintained:

  • Total number of messages propagated in a schedule

  • Total number of bytes propagated in a schedule

  • Maximum number of messages propagated in a window

  • Maximum number of bytes propagated in a window

  • Average number of messages propagated in a window

  • Average size of propagated messages

  • Average time to propagated a message

Propagation Error Handling

Propagation has built-in support for handling failures and reporting errors. For example, if the specified database link is invalid, if the remote database is unavailable, or if the remote queue is not enabled for enqueuing, then the appropriate error message is reported. Propagation uses a linear backoff scheme for retrying propagation from a schedule that encountered a failure.

If a schedule continuously encounters failures, then the first retry happens after 30 seconds, the second after 60 seconds, the third after 120 seconds and so forth. If the retry time is beyond the expiration time of the current window, then the next retry is attempted at the start time of the next window. A maximum of 16 retry attempts is made, after which the schedule is automatically disabled.


Note:

Once a retry attempt slips to the next propagation window, it will always do so; the exponential backoff scheme no longer governs retry scheduling. If the date function specified in the next_time parameter of DBMS_AQADM.SCHEDULE_PROPAGATION results in a short interval between windows, then the number of unsuccessful retry attempts can quickly reach 16, disabling the schedule.

When a schedule is disabled automatically due to failures, the relevant information is written into the alert log. A check for scheduling failures indicates:

  • How many successive failures were encountered

  • The error message indicating the cause for the failure

  • The time at which the last failure was encountered

By examining this information, a queue administrator can fix the failure and enable the schedule. If propagation is successful during a retry, then the number of failures is reset to 0.

In some situations that indicate application errors in queue-to-dblink propagations, Oracle Streams Advanced Queuing marks messages as UNDELIVERABLE and logs a message in alert.log. Examples of such errors are when the remote queue does not exist or when there is a type mismatch between the source queue and the remote queue. The trace files in the background_dump_dest directory can provide additional information about the error.

When a new job queue process starts, it clears the mismatched type errors so the types can be reverified. If you have capped the number of job queue processes and propagation remains busy, then you might not want to wait for the job queue process to terminate and restart. Queue types can be reverified at any time using DBMS_AQADM.VERIFY_QUEUE_TYPES.


Note:

When a type mismatch is detected in queue-to-queue propagation, propagation stops and throws an error. In such situations you must query the DBA_SCHEDULES view to determine the last error that occurred during propagation to a particular destination. The message is not marked as UNDELIVERABLE.

Propagation with Oracle Real Application Clusters

Propagation has support built-in for Oracle Real Application Clusters. It is transparent to the user and the queue administrator. The job that handles propagation is submitted to the same instance as the owner of the queue table where the queue resides.

If there is a failure at an instance and the queue table that stores the source queue is migrated to a different instance, then the propagation job is also migrated to the new instance. This minimizes pinging between instances and thus offers better performance.

The destination can be identified by a database link or by destination queue name. Specifying the destination database results in queue-to-dblink propagation. If you propagate messages to several queues in another database, then all queue-to-dblink propagations to that database have the same frequency. Specifying the destination queue name results in queue-to-queue propagation, a new feature in Oracle Streams Advanced Queuing 10g Release 2 (10.2). If you propagate messages to several queues in another database, then queue-to-queue propagation enables you to adjust the frequency of each schedule independently of the others. You can even enable or disable individual propagations.

This new queue-to-queue propagation mode also supports transparent failover when propagating to a destination Oracle RAC system. With queue-to-queue propagation, you are no longer required to re-point a database link if the owner instance of the queue fails on Oracle RAC.


See Also:

"Scheduling a Queue Propagation" for more information on queue-to-queue propagation

Propagation has been designed to handle any number of concurrent schedules. The number of job queue processes is limited to a maximum of 1000, and some of these can be used to handle jobs unrelated to propagation. Hence, propagation has built-in support for multitasking and load balancing.

The propagation algorithms are designed such that multiple schedules can be handled by a single job queue process. The propagation load on a job queue process can be skewed based on the arrival rate of messages in the different source queues.

If one process is overburdened with several active schedules while another is less loaded with many passive schedules, then propagation automatically redistributes the schedules so they are loaded uniformly.

Third-Party Support

If the protocol number for a recipient is in the range 128 - 255, then the address of the recipient is not interpreted by Oracle Streams Advanced Queuing and the message is not propagated by the Oracle Streams Advanced Queuing system. Instead, a third-party propagator can dequeue the message by specifying a reserved consumer name in the dequeue operation. The reserved consumer names are of the form AQ$_Pprotocol_number. For example, the consumer name AQ$_P128 can be used to dequeue messages for recipients with protocol number 128. The list of recipients for a message with the specific protocol number is returned in the recipient_list message property on dequeue.

Another way for Oracle Streams Advanced Queuing to propagate messages to and from third-party messaging systems is through Messaging Gateway. Messaging Gateway dequeues messages from an Oracle Streams Advanced Queuing queue and guarantees delivery to supported third-party messaging systems. Messaging Gateway can also dequeue messages from these systems and enqueue them to an Oracle Streams Advanced Queuing queue.

Propagation Using HTTP

In Oracle Database 10g you can set up Oracle Streams Advanced Queuing propagation over HTTP and HTTPS (HTTP over SSL). HTTP propagation uses the Internet access infrastructure and requires that the Oracle Streams Advanced Queuing servlet that connects to the destination database be deployed. The database link must be created with the connect string indicating the Web server address and port and indicating HTTP as the protocol. The source database must be created for running Java and XML. Otherwise, the setup for HTTP propagation is more or less the same as Oracle Net Services propagation.

Message Format Transformation

Applications often use data in different formats. A transformation defines a mapping from one Oracle data type to another. The transformation is represented by a SQL function that takes the source data type as input and returns an object of the target data type. Only one-to-one message transformations are supported.

To transform a message during enqueue, specify a mapping in the enqueue options. To transform a message during dequeue, specify a mapping either in the dequeue options or when you add a subscriber. A dequeue mapping overrides a subscriber mapping. To transform a message during propagation, specify a mapping when you add a subscriber.

You can create transformations by creating a single PL/SQL function or by creating an expression for each target type attribute. The PL/SQL function returns an object of the target type or the constructor of the target type. This representation is preferable for simple transformations or those not easily broken down into independent transformations for each attribute.

Creating a separate expression specified for each attribute of the target type simplifies transformation mapping creation and management for individual attributes of the destination type. It is useful when the destination type has many attributes.

As Figure 1-10 shows, queuing, routing, and transformation are essential building blocks to an integrated application architecture. The figure shows how data from the Out queue of a CRM application is routed and transformed in the integration hub and then propagated to the In queue of the Web application. The transformation engine maps the message from the format of the Out queue to the format of the In queue.

Figure 1-10 Transformations in Application Integration

Description of Figure 1-10 follows
Description of "Figure 1-10 Transformations in Application Integration"

XML Data Transformation

You can transform XML data using the extract() method supported on XMLType to return an object of XMLType after applying the supplied XPath expression. You can also create a PL/SQL function that transforms the XMLType object by applying an XSLT transformation to it, using the package XSLPROCESSOR.

Other Oracle Streams Advanced Queuing Features

This section contains these topics:

Queue Monitor Coordinator

Before 10g Release 1 (10.1), the Oracle Streams Advanced Queuing time manager process was called queue monitor (QMNn), a background process controlled by setting the dynamic init.ora parameter AQ_TM_PROCESSES. Beginning with 10g Release 1 (10.1), time management and many other background processes are automatically controlled by a coordinator-slave architecture called Queue Monitor Coordinator (QMNC). QMNC dynamically spawns slaves named qXXX depending on the system load. The slaves provide mechanisms for:

  • Message delay

  • Message expiration

  • Retry delay

  • Garbage collection for the queue table

  • Memory management tasks for buffered messages

Because the number of processes is determined automatically and tuned constantly, you are saved the trouble of setting it with AQ_TM_PROCESSES.

Although it is no longer necessary to set init.ora parameter AQ_TM_PROCESSES, it is still supported. If you do set it (up to a maximum of 40), then QMNC still autotunes the number of processes. But you are guaranteed at least the set number of processes for persistent queues. Processes for a buffered queue and other Oracle Streams tasks, however, are not affected by this parameter.


Note:

If you want to disable the Queue Monitor Coordinator, then you must set AQ_TM_PROCESSES = 0 in your pfile or spfile. Oracle strongly recommends that you do NOT set AQ_TM_PROCESSES = 0. If you are using Oracle Streams, setting this parameter to zero (which Oracle Database respects no matter what) can cause serious problems.

Integration with Oracle Internet Directory

Oracle Internet Directory is a native LDAPv3 directory service built on Oracle Database that centralizes a wide variety of information, including e-mail addresses, telephone numbers, passwords, security certificates, and configuration data for many types of networked devices. You can look up enterprise-wide queuing information—queues, subscriptions, and events—from one location, the Oracle Internet Directory. Refer to the Oracle Fusion Middleware Administrator's Guide for Oracle Internet Directory for more information.

Integration with Oracle Enterprise Manager

You can use Oracle Enterprise Manager to:

  • Create and manage queues, queue tables, propagation schedules, and transformations

  • Monitor your Oracle Streams Advanced Queuing environment using its topology at the database and queue levels, and by viewing queue errors and queue and session statistics

Retention and Message History

The systems administrator specifies the retention duration to retain messages after consumption. Oracle Streams Advanced Queuing stores information about the history of each message, preserving the queue and message properties of delay, expiration, and retention for messages destined for local or remote receivers. The information contains the enqueue and dequeue times and the identification of the transaction that executed each request. This allows users to keep a history of relevant messages. The history can be used for tracking, data warehouse, and data mining operations, as well as specific auditing functions.

Message retention is not supported for buffered messaging.

Cleaning Up Message Queues

The Oracle Streams Advanced Queuing retention feature can be used to automatically clean up messages after the user-specified duration after consumption.

If messages are accidentally inserted into a queue for the wrong subscriber, you can dequeue them with the subscriber name or by message identifier. This consumes the messages, which are cleaned up after their retention time expires.

To clean up messages for a particular subscriber, you can remove the subscriber and add the subscriber again. Removing the subscriber removes all the messages for that subscriber.

Tracking and Event Journals

Retained messages can be related to each other to form sequences. These sequences represent event journals, which are often constructed by applications. Oracle Streams Advanced Queuing is designed to let applications create event journals automatically.

Non-repudiation

Oracle Streams Advanced Queuing maintains the entire history of information about a message along with the message itself. This information serves as proof of sending and receiving of messages and can be used for non-repudiation of the sender and non-repudiation of the receiver.

The following information is kept at enqueue for non-repudiation of the enqueuer:

  • Oracle Streams Advanced Queuing agent doing the enqueue

  • Database user doing the enqueue

  • Enqueue time

  • Transaction ID of the transaction doing enqueue

The following information is kept at dequeue for non-repudiation of the dequeuer:

  • Oracle Streams Advanced Queuing agent doing dequeue

  • Database user doing dequeue

  • Dequeue time

  • Transaction ID of the transaction doing dequeue

After propagation, the ORIGINAL_MSGID field in the destination queue of the propagation corresponds to the message ID of the source message. This field can be used to correlate the propagated messages. This is useful for non-repudiation of the dequeuer of propagated messages.

Stronger non-repudiation can be achieved by enqueuing the digital signature of the sender at the time of enqueue with the message and by storing the digital signature of the dequeuer at the time of dequeue.

Internet Integration

You can access Oracle Streams Advanced Queuing over the Internet by using Simple Object Access Protocol (SOAP). Internet Data Access Presentation (IDAP) is the SOAP specification for Oracle Streams Advanced Queuing operations. IDAP defines the XML message structure for the body of the SOAP request.

An IDAP message encapsulates the Oracle Streams Advanced Queuing request and response in XML. IDAP is used to perform Oracle Streams Advanced Queuing 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.

You can create an alias to an Oracle Streams Advanced Queuing agent in Oracle Internet Directory and then use the alias in IDAP documents sent over the Internet to perform Oracle Streams Advanced Queuing operations. Using aliases prevents exposing the internal name of the Oracle Streams Advanced Queuing agent.

Figure 1-11 shows the architecture for performing Oracle Streams Advanced Queuing operations over HTTP. The major components are:

  • Oracle Streams Advanced Queuing client program

  • Web server/servlet runner hosting the Oracle Streams Advanced Queuing servlet

  • Oracle Database server

The Oracle Streams Advanced Queuing client program sends XML messages (conforming to IDAP) to the Oracle Streams Advanced Queuing servlet, which understands the XML message and performs Oracle Streams Advanced Queuing operations. Any HTTP client, a Web browser for example, can be used. The Web server/servlet runner hosting the Oracle Streams Advanced Queuing servlet, Apache/Jserv or Tomcat for example, interprets the incoming XML messages. The Oracle SiWtreams Advanced Queuing servlet connects to the Oracle Database server and performs operations on user queues.


Note:

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.

Figure 1-11 Architecture for Performing Oracle Streams Advanced Queuing Operations Using HTTP

Description of Figure 1-11 follows
Description of "Figure 1-11 Architecture for Performing Oracle Streams Advanced Queuing Operations Using HTTP"

Interfaces to Oracle Streams Advanced Queuing

You can access Oracle Streams Advanced Queuing functionality through the following interfaces:

  • PL/SQL using DBMS_AQ, DBMS_AQADM, and DBMS_AQELM

  • Visual Basic using Oracle Objects for OLE

  • Java Message Service (JMS) using the oracle.jms Java package

  • Internet access using HTTP(S)


    Note:

    The oracle.AQ Java package was deprecated in Oracle Streams Advanced Queuing 10g Release 1 (10.1). Oracle recommends that you migrate existing Java AQ applications to Oracle JMS and use Oracle JMS to design your future Java AQ applications.


    See Also:


Oracle Streams Advanced Queuing Demonstrations

Oracle Streams Advanced Queuing demos can be installed from the Oracle Database Companion CD. Once they are installed, you can find them in the $ORACLE_HOME/rdbms/demo directory. Refer to aqxmlREADME.txt and aqjmsREADME.txt in the demo directory for more information.

Table 1-1 lists and briefly describes the PL/SQL and OCI demos. Table 1-2 lists and briefly describes the JMS demos. Table 1-3 lists and briefly describes the XML demos.

Table 1-1 Oracle Streams Advanced Queuing Demonstrations

Demo and LocationsTopic

aqdemo00.sql

Create users, message types, and tables

aqdemo01.sql

Create queue tables, queues, subscribers, and propagation schedule

aqdemo02.sql

Enqueue messages into input queue

aqdemo03.sql

Install dequeue procedures

aqdemo04.sql

Perform blocking dequeues

aqdemo05.sql

Perform listen for multiple agents

aqdemo06.sql

Clean up users, queue tables, queues, and subscribers in aqdemo00.sql to aqdemo05.sql

aqdemo07.sql

Enqueue and dequeue to XMLType queue using XPATH expressions

aqdemo08.sql

Demonstrates server-to-server email notifications with default XML presentation

aqdemo09.sql

Set up queues and subscribers for array enqueue and dequeue (for OCI array demos also)

aqdemo10.sql

Array enqueue 10 messages

aqdemo11.sql

Array dequeue 10 messages

aqdemo12.sql

Clean up queues and subscribers for array enqueue and dequeue (for OCI array demos also)

ociaqdemo00.c

Enqueue messages

ociaqdemo01.c

Perform blocking dequeues

ociaqdemo02.c

Perform listen for multiple agents

ociaqarrayenq.c

Array enqueue 10 messages

ociaqarraydeq.c

Array dequeue 10 messages


Table 1-2 Oracle Streams Advanced Queuing JMS Demonstrations

Demo and LocationsTopic

aqjmsREADME.txt

Describes the Oracle Streams Advanced Queuing Java API and JMS demos

aqjmsdmo.sql

Set up Oracle Streams Advanced Queuing JMS demos

aqjmsdemo01.java

Enqueue text messages and dequeue based on message properties

aqjmsdemo02.java

Message listener demo (enqueue messages)

aqjmsdemo03.java

Message listener demo (set up listener and dequeue messages)

aqjmsdemo04.java

Oracle type payload: dequeue on payload content

aqjmsdemo05.java

Queue browser example

aqjmsdemo06.java

Schedule propagation between queues in the database

aqjmsdemo07.java

Send and receive an ADT message containing XML data

aqjmsdemo08.java

JMS 1.1 domain unification demo

aqjmsdemo09.java

JMS bulk array enqueue and dequeue

aqjmsdemo10.java

ANYDATA messaging with JMS message types and ADT messages

aqjmsdrp.sql

Clean up AQ JMS demos

aqoradmo.sql

Set up Oracle Streams Advanced Queuing Java API demos

aqorademo01.java

Enqueue and dequeue RAW messages

aqorademo02.java

Enqueue and dequeue object type messages using ORAData interface

aqoradrp.sql

Clean up AQ Java API demos

aqjmskprb01.java

Enqueues and dequeues a message within the database

aqjmskprb01a.sql

Set up kprb driver demo

aqjmskprb01b.sql

Defines Java program aqjmskprb01.java as stored procedure

aqjmskprb01c.sql

Runs aqjmskprb01.java as stored procedure

aqjmskprb01d.sql

Clean up AQ kprb driver demo


Table 1-3 Oracle Streams Advanced Queuing XML Demonstrations

Demo and LocationsTopic

aqxmlREADME.txt

Describes the Internet access demos

aqxmldmo.sql

Create users, queue tables, and queues

aqxml01.xml

AQXmlSend: Enqueue three messages to an ADT single- consumer queue with piggyback commit

aqxml02.xml

AQXmlReceive: Dequeue messages from ADT single-consumer queue with piggyback commit

aqxml03.xml

AQXmlPublish: Enqueue two messages to an ADT multiconsumer queue

aqxml04.xml

AQXmlReceive: Dequeue messages from an ADT (with LOB) multiconsumer queue

aqxml05.xml

AQXmlCommit: Commit previous operation

aqxml06.xml

AQXmlSend: Enqueue a message to a JMS TEXT single-consumer queue with piggyback commit

aqxml07.xml

AQXmlReceive: Dequeue messages from a JMS TEXT single-consumer queue with piggyback commit

aqxml08.xml

AQXmlPublish: Enqueue a JMS MAP message with recipient into multiconsumer queue

aqxml09.xml

AQXmlReceive: Dequeue JMS MAP messages from a multiconsumer queue

aqxml10.xml

AQXmlRollback: Roll back previous operation

aqxmlhtp.sql

HTTP propagation

AQDemoServlet.java

Servlet to post Oracle Streams Advanced Queuing XML files (for Jserv)

AQPropServlet.java

Servlet for Oracle Streams Advanced Queuing HTTP propagation

aqxmldrp.sql

Clean up AQ XML demo


PK2WiWPK-AOEBPS/content.opfk6 Oracle® Streams Advanced Queuing User's Guide, 11g Release 2 (11.2) en-US E11013-04 Oracle Corporation Oracle Corporation Oracle® Streams Advanced Queuing User's Guide, 11g Release 2 (11.2) 2011-07-22T07:06:56Z Describes features of application development and integration using Oracle Streams Advanced Queuing (AQ). This information applies to versions of the Oracle Database server that run on all platforms, unless otherwise specified. PK p6k6PK-AOEBPS/manage.htm Managing Oracle Streams Advanced Queuing

4 Managing Oracle Streams Advanced Queuing

This chapter discusses topics related to managing Oracle Streams Advanced Queuing (AQ).

This chapter contains these topics:

Oracle Streams Advanced Queuing Compatibility Parameters

The queues in which buffered messages are stored must be created with compatibility set to 8.1 or higher.

The compatible parameter of init.ora and the compatible parameter of the queue table should be set to 8.1 or higher to use the following features:

  • Queue-level access control

  • Support for Oracle Real Application Clusters environments

  • Rule-based subscribers for publish/subscribe

  • Asynchronous notification

  • Sender identification

  • Separate storage of history management information

  • Secure queues


    See Also:

    Oracle Streams Concepts and Administration for more information on secure queues

Mixed case (upper and lower case together) queue names, queue table names, and subscriber names are supported if database compatibility is 10.0, but the names must be enclosed in double quote marks. So abc.efg means the schema is ABC and the name is EFG, but "abc"."efg" means the schema is abc and the name is efg.

Queue Security and Access Control

This section contains these topics:

Oracle Streams Advanced Queuing Security

Configuration information can be managed through procedures in the DBMS_AQADM package. Initially, only SYS and SYSTEM have execution privilege for the procedures in DBMS_AQADM and DBMS_AQ. Users who have been granted EXECUTE rights to these two packages are able to create, manage, and use queues in their own schemas. The MANAGE_ANY AQ system privilege is used to create and manage queues in other schemas.


See Also:

"Granting Oracle Streams Advanced Queuing System Privileges" for more information on AQ system privileges

Users of the Java Message Service (JMS) API need EXECUTE privileges on DBMS_AQJMS and DBMS_AQIN.

This section contains these topics:

Administrator Role

The AQ_ADMINISTRATOR_ROLE has all the required privileges to administer queues. The privileges granted to the role let the grantee:

  • Perform any queue administrative operation, including create queues and queue tables on any schema in the database

  • Perform enqueue and dequeue operations on any queues in the database

  • Access statistics views used for monitoring the queue workload

  • Create transformations using DBMS_TRANSFORM

  • Run all procedures in DBMS_AQELM

  • Run all procedures in DBMS_AQJMS

User Role

You should avoid granting AQ_USER_ROLE, because this role does not provide sufficient privileges for enqueuing or dequeuing.

Your database administrator has the option of granting the system privileges ENQUEUE_ANY and DEQUEUE_ANY, exercising DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE and DBMS_AQADM.REVOKE_SYSTEM_PRIVILEGE directly to a database user, if you want the user to have this level of control.

You as the application developer give rights to a queue by granting and revoking privileges at the object level by exercising DBMS_AQADM.GRANT_QUEUE_PRIVILEGE and DBMS_AQADM.REVOKE_QUEUE_PRIVILEGE.

As a database user, you do not need any explicit object-level or system-level privileges to enqueue or dequeue to queues in your own schema other than the EXECUTE right on DBMS_AQ.

Access to Oracle Streams Advanced Queuing Object Types

All internal Oracle Streams Advanced Queuing objects are now accessible to PUBLIC.

Queue Security

Oracle Streams Advanced Queuing administrators of Oracle Database can create queues. When you create queues, the default value of the compatible parameter in DBMS_AQADM.CREATE_QUEUE_TABLE is that of the compatible parameter.

To enqueue or dequeue, users need EXECUTE rights on DBMS_AQ and either enqueue or dequeue privileges on target queues, or ENQUEUE_ANY/DEQUEUE_ANY system privileges.

Queue Privileges and Access Control

You can grant or revoke privileges at the object level on queues. You can also grant or revoke various system-level privileges. Table 4-1 lists all common Oracle Streams Advanced Queuing operations and the privileges needed to perform these operations.

Table 4-1 Operations and Required Privileges

Operation(s)Privileges Required

CREATE/DROP/MONITOR own queues

Must be granted EXECUTE rights on DBMS_AQADM. No other privileges needed.

CREATE/DROP/MONITOR any queues

Must be granted EXECUTE rights on DBMS_AQADM and be granted AQ_ADMINISTRATOR_ROLE by another user who has been granted this role (SYS and SYSTEM are the first granters of AQ_ADMINISTRATOR_ROLE)

ENQUEUE/ DEQUEUE to own queues

Must be granted EXECUTE rights on DBMS_AQ. No other privileges needed.

ENQUEUE/ DEQUEUE to another's queues

Must be granted EXECUTE rights on DBMS_AQ and be granted privileges by the owner using DBMS_AQADM.GRANT_QUEUE_PRIVILEGE.

ENQUEUE/ DEQUEUE to any queues

Must be granted EXECUTE rights on DBMS_AQ and be granted ENQUEUE ANY QUEUE or DEQUEUE ANY QUEUE system privileges by an Oracle Streams Advanced Queuing administrator using DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE.


OCI Applications and Queue Access

For an Oracle Call Interface (OCI) application to access a queue, the session user must be granted either the object privilege of the queue he intends to access or the ENQUEUE ANY QUEUE or DEQUEUE ANY QUEUE system privileges. The EXECUTE right of DBMS_AQ is not checked against the session user's rights.

Security Required for Propagation

Oracle Streams Advanced Queuing propagates messages through database links. The propagation driver dequeues from the source queue as owner of the source queue; hence, no explicit access rights need be granted on the source queue. At the destination, the login user in the database link should either be granted ENQUEUE ANY QUEUE privilege or be granted the right to enqueue to the destination queue. However, if the login user in the database link also owns the queue tables at the destination, then no explicit Oracle Streams Advanced Queuing privileges must be granted.

Queue Table Export-Import

When a queue table is exported, the queue table data and anonymous blocks of PL/SQL code are written to the export dump file. When a queue table is imported, the import utility executes these PL/SQL anonymous blocks to write the metadata to the data dictionary.

Oracle AQ does not export registrations with a user export. All applications that make use of client registrations should take this into account as the client may not be present in the imported database.


Note:

You cannot export or import buffered messages.

If there exists a queue table with the same name in the same schema in the database as in the export dump, then ensure that the database queue table is empty before importing a queue table with queues. Failing to do so has a possibility of ruining the metadata for the imported queue.


This section contains these topics:

Exporting Queue Table Data

The export of queues entails the export of the underlying queue tables and related dictionary tables. Export of queues can also be accomplished at queue-table granularity.

Exporting Queue Tables with Multiple Recipients

A queue table that supports multiple recipients is associated with the following tables:

  • Dequeue index-organized table (IOT)

  • Time-management index-organized table

  • Subscriber table

  • A history IOT

These tables are exported automatically during full database mode, user mode and table mode exports. See "Export Modes".

Because the metadata tables contain ROWIDs of some rows in the queue table, the import process generates a note about the ROWIDs being made obsolete when importing the metadata tables. This message can be ignored, because the queuing system automatically corrects the obsolete ROWIDs as a part of the import operation. However, if another problem is encountered while doing the import (such as running out of rollback segment space), then you should correct the problem and repeat the import.

Export Modes

Exporting operates in full database mode, user mode, and table mode. Incremental exports on queue tables are not supported.

In full database mode, queue tables, all related tables, system-level grants, and primary and secondary object grants are exported automatically.

In user mode, queue tables, all related tables, and primary object grants are exported automatically. However, doing a user-level export from one schema to another using the FROMUSER TOUSER clause is not supported.

In table mode, queue tables, all related tables, and primary object grants are exported automatically. For example, when exporting a multiconsumer queue table, the following tables are automatically exported:

  • AQ$_queue_table_I (the dequeue IOT)

  • AQ$_queue_table_T (the time-management IOT)

  • AQ$_queue_table_S (the subscriber table)

  • AQ$_queue_table_H (the history IOT)

Importing Queue Table Data

Similar to exporting queues, importing queues entails importing the underlying queue tables and related dictionary data. After the queue table data is imported, the import utility executes the PL/SQL anonymous blocks in the dump file to write the metadata to the data dictionary.

Importing Queue Tables with Multiple Recipients

A queue table that supports multiple recipients is associated with the following tables:

  • A dequeue IOT

  • A time-management IOT

  • A subscriber table

  • A history IOT

These tables must be imported as well as the queue table itself.

Import IGNORE Parameter

You must not import queue data into a queue table that already contains data. The IGNORE parameter of the import utility must always be set to NO when importing queue tables. If the IGNORE parameter is set to YES, and the queue table that already exists is compatible with the table definition in the dump file, then the rows are loaded from the dump file into the existing table. At the same time, the old queue table definition is lost and re-created. Queue table definition prior to the import is lost and duplicate rows appear in the queue table.

Data Pump Export and Import

The Data Pump replace and skip modes are supported for queue tables. In the replace mode an existing queue table is dropped and replaced by the new queue table from the export dump file. In the skip mode, a queue table that already exists is not imported.

The truncate and append modes are not supported for queue tables. The behavior in this case is the same as the replace mode.


See Also:

Oracle Database Utilities for more information on Data Pump Export and Data Pump Import

Oracle Enterprise Manager Support

Oracle Enterprise Manager supports most of the administrative functions of Oracle Streams Advanced Queuing. Oracle Streams Advanced Queuing functions are found under the Distributed node in the navigation tree of the Enterprise Manager console. Functions available through Oracle Enterprise Manager include:

  • Using queues as part of the schema manager to view properties

  • Creating, starting, stopping, and dropping queues

  • Scheduling and unscheduling propagation

  • Adding and removing subscribers

  • Viewing propagation schedules for all queues in the database

  • Viewing errors for all queues in the database

  • Viewing the message queue

  • Granting and revoking privileges

  • Creating, modifying, or removing transformations

Using Oracle Streams Advanced Queuing with XA

You must specify "Objects=T" in the xa_open string if you want to use the Oracle Streams Advanced Queuing OCI interface. This forces XA to initialize the client-side cache in Objects mode. You are not required to do this if you plan to use Oracle Streams Advanced Queuing through PL/SQL wrappers from OCI or Pro*C.

The large object (LOB) memory management concepts from the Pro* documentation are not relevant for Oracle Streams Advanced Queuing raw messages because Oracle Streams Advanced Queuing provides a simple RAW buffer abstraction (although they are stored as LOBs).

When using the Oracle Streams Advanced Queuing navigation option, you must reset the dequeue position by using the FIRST_MESSAGE option if you want to continue dequeuing between services (such as xa_start and xa_end boundaries). This is because XA cancels the cursor fetch state after an xa_end. If you do not reset, then you get an error message stating that the navigation is used out of sequence (ORA-25237).


See Also:


Restrictions on Queue Management

This section discusses restrictions on queue management.

This section contains these topics:


Note:

Mixed case (upper and lower case together) queue names, queue table names, and subscriber names are supported if database compatibility is 10.0, but the names must be enclosed in double quote marks. So abc.efg means the schema is ABC and the name is EFG, but "abc"."efg" means the schema is abc and the name is efg.

Subscribers

You cannot have more than 1,000 local subscribers for each queue. Also, only 32 remote subscribers are allowed for each remote destination database.

DML Not Supported on Queue Tables or Associated IOTs

Oracle Streams Advanced Queuing does not support data manipulation language (DML) operations on queue tables or associated index-organized tables (IOTs), if any. The only supported means of modifying queue tables is through the supplied APIs. Queue tables and IOTs can become inconsistent and therefore effectively ruined, if DML operations are performed on them.

Propagation from Object Queues with REF Payload Attributes

Oracle Streams Advanced Queuing does not support propagation from object queues that have REF attributes in the payload.

Collection Types in Message Payloads

You cannot construct a message payload using a VARRAY that is not itself contained within an object. You also cannot currently use a NESTED Table even as an embedded object within a message payload. However, you can create an object type that contains one or more VARRAYs, and create a queue table that is founded on this object type, as shown in Example 4-1.

Example 4-1 Creating Objects Containing VARRAYs

CREATE TYPE number_varray AS VARRAY(32) OF NUMBER; 
CREATE TYPE embedded_varray AS OBJECT (col1 number_varray);
EXECUTE DBMS_AQADM.CREATE_QUEUE_TABLE( 
  queue_table           =>     'QT', 
  queue_payload_type    =>     'embedded_varray'); 

Synonyms on Queue Tables and Queues

No Oracle Streams Advanced Queuing PL/SQL calls resolve synonyms on queues and queue tables. Although you can create synonyms, you should not apply them to the Oracle Streams Advanced Queuing interface.

Synonyms on Object Types

If you have created synonyms on object types, you cannot use them in DBMS_AQADM.CREATE_QUEUE_TABLE. Error ORA-24015 results.

Tablespace Point-in-Time Recovery

Oracle Streams Advanced Queuing currently does not support tablespace point-in-time recovery. Creating a queue table in a tablespace disables that particular tablespace for point-in-time recovery. Oracle Streams Advanced Queuing does support regular point-in-time recovery.

Virtual Private Database

You can use Oracle Streams Advanced Queuing with Virtual Private Database by specifying a security policy with Oracle Streams Advanced Queuing queue tables. While dequeuing, use the dequeue condition (deq_cond) or the correlation identifier for the policy to be applied. You can use "1=1" as the dequeue condition. If you do not use a dequeue condition or correlation ID, then the dequeue results in an error.


Note:

When a dequeue condition or correlation identifier is used, the order of the messages dequeued is indeterminate, and the sort order of the queue is not honored.

Managing Propagation

This section contains these topics:


Caution:

For propagation to work correctly, the queue aq$_prop_notify_X should never be stopped or dropped and the table aq$_prop_table_X should never be dropped.

EXECUTE Privileges Required for Propagation

Propagation jobs are owned by SYS, but the propagation occurs in the security context of the queue table owner. Previously propagation jobs were owned by the user scheduling propagation, and propagation occurred in the security context of the user setting up the propagation schedule. The queue table owner must be granted EXECUTE privileges on the DBMS_AQADM package. Otherwise, the Oracle Database snapshot processes do not propagate and generate trace files with the error identifier SYS.DBMS_AQADM not defined. Private database links owned by the queue table owner can be used for propagation. The username specified in the connection string must have EXECUTE access on the DBMS_AQ and DBMS_AQADM packages on the remote database.

Propagation from Object Queues

Propagation from object queues with BFILE objects is supported. To be able to propagate object queues with BFILE objects, the source queue owner must have read privileges on the directory object corresponding to the directory in which the BFILE is stored. The database link user must have write privileges on the directory object corresponding to the directory of the BFILE at the destination database.

AQ propagation does not support non-final types. Propagation of BFILE objects from object queues without specifying a database link is not supported.


See Also:

"CREATE DIRECTORY" in Oracle Database SQL Language Reference for more information on directory objects

Optimizing Propagation

AQ propagation jobs are run by the Oracle Scheduler. Propagation may be scheduled in the following ways:

  • A dedicated schedule in which the propagation runs forever or for a specified duration. This mode provides the lowest propagation latencies.

  • A periodic schedule in which the propagation runs periodically for a specified interval. This may be used when propagation can be run in a batched mode.

  • An event based system in which propagation is started when there are messages to be propagated. This mode makes more efficient use of available resources, while still providing a fast response time.

The administrator may choose a schedule that best meets the application performance requirements.

Oracle Scheduler will start the required number of job queue processes for the propagation schedules. Since the scheduler optimizes for throughput, if the system is heavily loaded, it may not run some propagation jobs. The resource manager may be used to have better control over the scheduling decisions. In particular, associating propagation jobs with different resource groups can allow for fairness in scheduling which may be important in heavy load situations.

In setting the number of JOB_QUEUE_PROCESSES, DBAs should be aware that this number is determined by the number of queues from which the messages must be propagated and the number of destinations (rather than queues) to which messages must be propagated.

A scheduling algorithm handles propagation. The algorithm optimizes available job queue processes and minimizes the time it takes for a message to show up at a destination after it has been enqueued into the source queue, thereby providing near-OLTP action. The algorithm can handle an unlimited number of schedules and various types of failures. While propagation tries to make the optimal use of the available job queue processes, the number of job queue processes to be started also depends on the existence of jobs unrelated to propagation, such as replication jobs. Hence, it is important to use the following guidelines to get the best results from the scheduling algorithm.

The scheduling algorithm uses the job queue processes as follows (for this discussion, an active schedule is one that has a valid current window):

  • If the number of active schedules is fewer than half the number of job queue processes, then the number of job queue processes acquired corresponds to the number of active schedules.

  • If the number of active schedules is more than half the number of job queue processes, after acquiring half the number of job queue processes, then multiple active schedules are assigned to an acquired job queue process.

  • If the system is overloaded (all schedules are busy propagating), depending on availability, then additional job queue processes are acquired up to one fewer than the total number of job queue processes.

  • If none of the active schedules handled by a process has messages to be propagated, then that job queue process is released.

  • The algorithm performs automatic load balancing by transferring schedules from a heavily loaded process to a lightly load process such that no process is excessively loaded.

Handling Failures in Propagation

The scheduling algorithm has robust support for handling failures. Common failures that prevent message propagation include the following:

  • Database link failed

  • Remote database is not available

  • Remote queue does not exist

  • Remote queue was not started

  • Security violation while trying to enqueue messages into remote queue

Under all these circumstances the appropriate error messages are reported in the DBA_QUEUE_SCHEDULES view.

When an error occurs in a schedule, propagation of messages in that schedule is attempted again after a retry period of 30*(number of failures) seconds, with an upper bound of ten minutes. After sixteen consecutive retries, the schedule is disabled.

If the problem causing the error is fixed and the schedule is enabled, then the error fields that indicate the last error date, time, and message continue to show the error information. These fields are reset only when messages are successfully propagated in that schedule.

PK][QPK-AOEBPS/dcommon/prodbig.gif GIF87a!!!)))111BBBZZZsss{{ZRRcZZ!!1!91)JB9B9)kkcJJB991ssc絽Zcc!!{祽BZc!9B!c{!)c{9{Z{{cZB1)sJk{{Z{kBsZJ91)Z{!{BcsRsBc{9ZZk甽kBkR!BZ9c)JJc{!))BZks{BcR{JsBk9k)Zck!!BZ1k!ZcRBZcZJkBk1Z9c!R!c9kZRZRBZ9{99!R1{99R{1!1)c1J)1B!BJRkk{ƽ絵ތkk絵RRs{{{{JJsssBBkkk!!9ss{{ZZssccJJZZRRccRRZZ))cBBJJ99JJ!!c11991199Z11!c!!))Z!!!1BRck{)!cJBkZRZ,HP)XRÇEZ֬4jJ0 @ "8pYҴESY3CƊ@*U:lY0_0#  5tX1E: C_xޘeKTV%ȣOΏ9??:a"\fSrğjAsKJ:nOzO=}E1-I)3(QEQEQEQEQEQEQE֝Hza<["2"pO#f8M[RL(,?g93QSZ uy"lx4h`O!LŏʨXZvq& c՚]+: ǵ@+J]tQ]~[[eϸ (]6A&>ܫ~+כzmZ^(<57KsHf妬Ϧmnẁ&F!:-`b\/(tF*Bֳ ~V{WxxfCnMvF=;5_,6%S>}cQQjsOO5=)Ot [W9 /{^tyNg#ЄGsֿ1-4ooTZ?K Gc+oyڙoNuh^iSo5{\ܹ3Yos}$.nQ-~n,-zr~-|K4R"8a{]^;I<ȤL5"EԤP7_j>OoK;*U.at*K[fym3ii^#wcC'IIkIp$󿉵|CtĈpW¹l{9>⪦׺*ͯj.LfGߍԁw] |WW18>w.ӯ! VӃ :#1~ +މ=;5c__b@W@ +^]ևՃ7 n&g2I8Lw7uҭ$"&"b eZ":8)D'%{}5{; w]iu;_dLʳ4R-,2H6>½HLKܹR ~foZKZ࿷1[oZ7׫Z7R¢?«'y?A}C_iG5s_~^ J5?œ tp]X/c'r%eܺA|4ծ-Ե+ْe1M38Ǯ `|Kյ OVڅu;"d56, X5kYR<̭CiطXԮ];Oy)OcWj֩}=܅s۸QZ*<~%뺃ȶp f~Bðzb\ݳzW*y{=[ C/Ak oXCkt_s}{'y?AmCjޓ{ WRV7r. g~Q"7&͹+c<=,dJ1V߁=T)TR՜*N4 ^Bڥ%B+=@fE5ka}ędܤFH^i1k\Sgdk> ֤aOM\_\T)8靠㡮3ģR: jj,pk/K!t,=ϯZ6(((((((49 xn_kLk&f9sK`zx{{y8H 8b4>ÇНE|7v(z/]k7IxM}8!ycZRQ pKVr(RPEr?^}'ðh{x+ՀLW154cK@Ng C)rr9+c:׹b Жf*s^ fKS7^} *{zq_@8# pF~ [VPe(nw0MW=3#kȵz晨cy PpG#W:%drMh]3HH<\]ԁ|_W HHҡb}P>k {ZErxMX@8C&qskLۙOnO^sCk7ql2XCw5VG.S~H8=(s1~cV5z %v|U2QF=NoW]ո?<`~׮}=ӬfԵ,=;"~Iy7K#g{ñJ?5$y` zz@-~m7mG宝Gٱ>G&K#]؃y1$$t>wqjstX.b̐{Wej)Dxfc:8)=$y|L`xV8ߙ~E)HkwW$J0uʟk>6Sgp~;4֌W+חc"=|ř9bc5> *rg {~cj1rnI#G|8v4wĿhFb><^ pJLm[Dl1;Vx5IZ:1*p)إ1ZbAK(1ׅ|S&5{^ KG^5r>;X׻K^? s fk^8O/"J)3K]N)iL?5!ƾq:G_=X- i,vi2N3 |03Qas ! 7}kZU781M,->e;@Qz T(GK(ah(((((((Y[×j2F}o־oYYq $+]%$ v^rϭ`nax,ZEuWSܽ,g%~"MrsrY~Ҿ"Fت;8{ѰxYEfP^;WPwqbB:c?zp<7;SBfZ)dϛ; 7s^>}⍱x?Bix^#hf,*P9S{w[]GF?1Z_nG~]kk)9Sc5Ո<<6J-ϛ}xUi>ux#ţc'{ᛲq?Oo?x&mѱ'#^t)ϲbb0 F«kIVmVsv@}kҡ!ˍUTtxO̧]ORb|2yԵk܊{sPIc_?ħ:Ig)=Z~' "\M2VSSMyLsl⺿U~"C7\hz_ Rs$~? TAi<lO*>U}+'f>7_K N s8g1^CeКÿE ;{+Y\ O5|Y{/o+ LVcO;7Zx-Ek&dpzbӱ+TaB0gNy׭ 3^c T\$⫫?F33?t._Q~Nln:U/Ceb1-im WʸQM+VpafR3d׫é|Aү-q*I P7:y&]hX^Fbtpܩ?|Wu󭏤ʫxJ3ߴm"(uqA}j.+?S wV ~ [B&<^U?rϜ_OH\'.;|.%pw/ZZG'1j(#0UT` Wzw}>_*9m>󑓀F?EL3"zpubzΕ$+0܉&3zڶ+jyr1QE ( ( ( ( ( ( ( (UIdC0EZm+]Y6^![ ԯsmܶ捆?+me+ZE29)B[;я*wGxsK7;5w)}gH~.Ɣx?X\ߚ}A@tQ(:ͧ|Iq(CT?v[sKG+*רqҍck <#Ljα5݈`8cXP6T5i.K!xX*p&ќZǓϘ7 *oƽ:wlຈ:Q5yIEA/2*2jAҐe}k%K$N9R2?7ýKMV!{W9\PA+c4w` Wx=Ze\X{}yXI Ү!aOÎ{]Qx)#D@9E:*NJ}b|Z>_k7:d$z >&Vv󃏽WlR:RqJfGإd9Tm(ҝEtO}1O[xxEYt8,3v bFF )ǙrPNE8=O#V*Cc𹾾&l&cmCh<.P{ʦ&ۣY+Gxs~k5$> ӥPquŽўZt~Tl>Q.g> %k#ú:Kn'&{[yWQGqF}AЅ׮/}<;VYZa$wQg!$;_ $NKS}“_{MY|w7G!"\JtRy+贾d|o/;5jz_6fHwk<ѰJ#]kAȎ J =YNu%dxRwwbEQEQEQEQEQEQEQEQEQE'fLQZ(1F)hQ@X1KEQE-Q@ 1KE3h=iPb(((1GjZ(-ʹRPbR@ 1KE7`bڒyS0(-&)P+ ڎԴP11F)h&:LRmQ@Q@Š(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((Z5/t bS($ `Dǂ7Tg4*-ƫ8@$x =qh(o^4[7zծ-;UR!PNW|N_w}4x^+%{7iX;e-'N=rnn^i}FeC`qU.66 nč ?2Oq@U=7Vuv K4,$g{xAѮTwWI8#>ƀ5(7zwp]ɝA GRO<6\K0DF dOhJ+Ş#wu&vCr;`p ؠϋ]wClg>g?&6\}Q%u6uBJrHRN2@ϸ J+?St}ll<kH3XvqX]wk&vMDlppAX_r^_ik7<4\X2Hgzvv Ү`GlNO@QEWvԦ>Ŋ.o,,VU;~QM}ai$] `{V~'ypo3g=EIjnnic8EeK` cW+h=O᎙yawݬl ؎`pÃ+/5m7O--}2L ր.QESմ>P[G4ʍ3d ',r`zZEW,伿5(.66 nč ?2Oq@V~ߛ8>pq8=} hPEe^%tk56v@DrF@b2ϱ7zwp]ɝA G@(zepZZǍO $< T:[zޛ}:v%`$)' gPV^]F[}S[lgd]$LW$d yi}ŭim=춎if@NXroxeż䍃+܂9{%QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEyמ"tsR6wcI*nnJ %V}ck%\u y8c{w/ xo1hخ9byco-ûNK`A\I?[;F)anI,}$ "it汆{kMa ry"Fw[>!V"OIDc6۩b_|] /BxnИ[,1Ll$78 Vßοsǧ鈖~9xdeHz-xGNC%<ד.@=~Ui3nu-~I4K.cc0#  @^iͻ\iz KYU pJ3=y_$P**Ɲs"_cGKL3.w葜u=/YJ{\Ҫ %ufyf$g +{>69&Kķ74C+(sqv /a7zZ\Mii݄S=4F69Y{ u6Vvrc=I| 99 ?xsXӯ|[Ic$l&\)P{ 7i/C7oMD e5ӤF0f pcW_ɴ<^$M,v&961@N@25[_w]Ž&v鈮+ MpCz(OԤk+{sL++;\/9'nIɬ;MR|YCm#;Aڼrǧ C²訨sO"UYma)M9PPH!&*|+ %O_i 1O#U c#c?6Huw҈ 4(UXЌJ!٤HU *KAǾÏ@ѧ:>HFP~b< $_ K^: *O9_/ۿ!ٻݱ7ϗ'෌A+~Uq'pۜc=Ư>{/]ZG::j0"AeV9Aܼϊ ltw<3}cmQ,r2 wːO9>'PG|ӻ<`b__ x;U֙knҟ5!yr^y'_M t DY0;F_Pm |@U;lo2LibgR/~ ş/5(gL, qsZ~!mGFn<k/ 4Y]Fd)yRsݲh5mJF.FK0 E,@8OË/0]GjZG,rwv䀠u$m>^/YKL  ѱ$0xG4< 4OFh"/X;w+1rr vqZx2SAH4{ˈNi]L:N9R Gl&a[ Zx9 qm4El<7n漂@)H$99 ]s~ѵZF{pyPYXc8+7xuAi L[yM{d~d9c@IΐF̑UTw> f\ qϥ# l7ImK&a*&G?6q' m5RGaoo[ifU>v?/:I=Yo25Cy;a;zx_S:"dJ5qdweKuluZKKK$6K BY,dwp+? x*Rү4x$cP̀uSp'⿃Go浴wf6%H9<7R;A?I9֗ oj+]e&w,Q|q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@z9eִ{K(d*m,Q}Ms|}mqIs3 g!Q@l,8- ;!1.I' 8$ƱI x:ܑ,hg m1;s5Q@:K 얲Jfd^L$QQ hӤk$fO5ː9rOElQ@q:t.$;$a(f$aEa煑WE-!O9St6]q'c_-j;B1*UB=FA:ZP|,N@I4Me3`@Glxo7t,4;?Z)y2N\G[P>mAuK2Ⱥ%v_,s$]cXM;zml5㻗Ζ{U *(::汢A=233!8(=x%5ѿ [LU$]o Z@Gq8QEr$w_j1WBcHFκ( ??@klwdd$`ᔃFpp=e <Ew}&Gy$20Wf,W`v ( DӼ96gw}'O&o7t,4;?Z)y2N\G[P?<-xN\]r<׏=uE? </=$$YlrǓ[K3kYF|%$nsln88EcºŮA{$sggxE?|e,iiuQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@_C Ŋ;BVvvE8Tdn<?iæt u1f;])d`+~> o?{cmhEv<ݑy#q([?\jqVd$yU;2rFXgW}q, \V 09g6sayku2n#r0!G# Y!Mj*_+g'dQQG<+=#x| ]c[u)7my[8@d+>]? xRէ@|yfb0# US +k]SĭïOy]o|Vrw6@ nx`[$+J o@E?Nѷi [Ɵ>g}Ǘݿw?m{۞¼t>,T g}\c|{xpnMmռOkR! {#)Vla F c8j O]GR^żS [`0'T| ?J wVԡ|1Ũ]6-'mgzx|'`? wVԡ|1Ũ]6-'mgzx|'`?:ƍgYj3:nvcۨ(FNFAv0ͳp Ex^[ᖳp_nT.6Ұ\ H|3Ygfbwkvs9r2YS'8Ҁ; +Zx|QvcC=d-nRەAQ@$vEW4; -/]wעoXC)TyaNA+h'cRp|$Tujt"$jqfBŽCFcKPM>m1[ENn9d W;JJǸwOgWǚb?}J!4k=QIu n^AB0r2 цm+߂ [w}:vQ N2@ϸ\yrLէծ߾|.3c u=(b-fv e~!w @L ?n+mZkewl!]b#?/^N@#Ou+{]X @<-K4?X#|7;ya´1b6Σ;sxĖ~޹Zސ(.w:$;}𮳬v~GoI AC;Bqh(iEK^@q~CIhc3dJ7oޛO?kG|'`? +/xE"1PH ?2U#~~Zg?}MTxwQn ,ew;lg<='CGװW uZ.>ѫAyRͼ?w|S5x\Ysm7/TH#eݲg ë"m.1Rkx'+yc P4Wvr\=#:[iՌwvbTYH*z8$t&,MiX'-"+V"y89(u|@-E+@w8$g֥K]V5`B>AEn:GON+𧀴:g_YVY!b8\UFP:*?֏PTz,QSݝB[:A@eFkԞX 1YWn0Xz/$:D2&}N C:SEwaw+2 VVNT $䚓|{oa |n/ec8¨T RA< sw?±k+񯂴hzp+Z ˃Xc{zWI@aUͪExM gX)Dl) =C/[x9xvFBFH8TGLڼhkE oNI˃ul7Jz0l`EzXz][Gmgn":(dII4r>UOJPf׉"CL$ ,~RKo/S&Rz=³KdAV8a3 7zwp]ɝA G^?fwë8nUh$%]9\Fzg_q,w(#*7FNNI>Y>^t6g:&.' W 9?* sjE#:O+*|-72:旨qvIng>о^fvoێ>w4=f_W?j{D-, Z!n_W5}2(' mݸ`X'W/|xNݍBEHeЎ65VI.ja,Y`Gl~Ize:zݭi]ځw'q &X]ƙGsgp%0`> O>oO/9ٝ㏽a<|QCxXFL+.ۦu$gdd|B%ͼmiylBJ푝H9q [_W5}2(' mݸ`X'[4mV1R:e 2К?g[qo3A*Haeu# #s>S~Wš3K7*+Yģ8'ӂ8?g_qwΈ).# vN>Wh<-ih%1YǠ'@(z66h)[ELrɜ/$wrz%şPnt?4gDڭ A`G9ldzeQEQEQEQEQEQEQEQEQEQEQEW7[2P ¬]0Uml˧;o4o'S_A{o%å*#h-<@EO0MVT bT)' Vx:^%FK>EvˆJFRA(:ݫ(((Xx&5%ݼcd BGۭ\ԼIS᭺'cj<8!r rUXd(mg'kuM #r0N# b (?O5|Cqo,rdaA9I x:ܑ,hg m1;s5|,N@I4Me3`@GWAy-ѯ/绺4!ҥh`Gq?)(3sxm4~FpحX vnRJ'nB?1mg'kuM #r0N# b(((((((((((((?t>T {x|'`? (<?6ryᵷX$/$0UE$xs^GJ q^O兜~e֟q ) ѰQ#x~.7ŷ7tQ0U_ŷ<|[w%$^V)w ᙲv {仰yR/+z<9CU_ 9AV[[TKA3l(xþPڵVs$>︧ܽ}j_zGF_ 5 QU"1"m}Ix $EIB'U>_]|p8OAW>+xK^ Jմw'"cI87P֛6]#Kh{+(mh*Y)# dz G\i~ ֟/ueÌ98*T7=C¾!_rvGwr'ppvas+珆~ 5mǷ[*ع0L j(|3Մ$|owh/RG{8BK0(UAנj>#1k0ya/4)( lamɸu*SqUռ5 I++ >#W@> i6zhjeYI3 aIKIoQ%r>!>_5ˇ1:rpT+ ou_W|3^kh=ݺVq2e%Uom$gW'@^ៈ$&{v Dwiz>c޹pF2YB&R_׼A:y<?w^w?][oqSY PȒ38lNDǩ=6o@>pB{f2W@?5oַ$8vc$nx3~#/Py-+Q^7JZR{+Ԗ ؙ#"x\J(^:5p G$K0 :0 v\%OrGyZ:&({2r_1a`<ۉ0Wn{Ϣ/l$P^?#&W{ۙ>ǰW^ _iZy'1G6y ;IaXTw?±h(OR7U!n(yᵷX$/$0UE$xs@ko-ıH^I$`I$d) 2ZHUXNBƇ#9}}|q$Ҵ'-]0B? ~;{&Xz][Gmgn":(dII4m{S|'֒ywlޅwc#8q^S-/>km۳dwc9蚶_j #Aeo%ċ dQ^o>X2e/e)9 ņT(((((((((((((/hi~!ЧKmCnu apKG| צ!%> lʋ v@{Z(/ }[ŷ|/aqvqGۇL}֩5otjZ n5};dQ9;?Zquqe'R L'.Dc''תx[G|9i_P{>w˗f1:EyY.x?Wz=Ǩ}_4 IVt:3+ ?^oWzߍ;cl劓. s !3L I3O@@` w x&Os~7;Ƭ!@GC7|3(_E#z>lݴTs^Egz^ǢZAEMPp`s99sNs^_7%=W@-ϒ 7+*`G<װQ@oi [^un';Ɏ |Iaf,GE~;un7]3dW}ac%ſv3Š'gfvyrm lʬ C^R(׿|a ~%E1 iEnbs^ESլtk+{,縷(cYst+/ZnĝJpջʡF@i 5P[lj4jw]Zl(3XpH=J$,㳰Zǝ p| O]g x_YTƥ]ڌYNFHG(/Ŭ\Y:%>s?36ӹT'i_J FeX&[H$:`Xq$օQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEPK{ooPK-AOEBPS/dcommon/contbig.gif`GIF87a!!!111999BBBJJJRRRccckkksss{{{skk{{ZRRRJJƽ{sZRJRJB91)kcZB9)sskZRJ1޽ƽ{{ssskkkcƵZZRccZRRJJJB{BB9991ssckkZccR))!RRB!!JJ1))99!11ƌ)1R)k֔)s1RZJR{BJs9R1J!11J1J9k{csZk!1J!)cBR9J1B)91B!cRs{!)s!){1B!k!s!{ksksckckZc9B)1!)!)BJ9B1919έƌ!!)JJcZZ{!!!1RR{JJsBBkJJ{!!9BB{1!!J9)!!Z!!c1!!kR!!s9Z!BckJs)19!!c!!ZRZ,H rrxB(Kh" DժuICiи@S z$G3TTʖ&7!f b`D 0!A  k,>SO[!\ *_t  Exr%*_}!#U #4 & ֩3|b]L ]t b+Da&R_2lEٱZ`aC)/яmvUkS r(-iPE Vv_{z GLt\2s!F A#葡JY r|AA,hB}q|B`du }00(䡆<pb,G+oB C0p/x$…– ]7 @2HFc ) @AD \0 LHG',(A` `@SC)_" PH`}Y+_|1.K8pAKMA @?3҄$[JPA)+NH I ,@8G0/@R T,`pF8Ѓ)$^$ DDTDlA@ s;PKPK-AOEBPS/dcommon/darbbook.cssPKPK-A!OEBPS/dcommon/O_signature_clr.JPG"(JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (?O '~MQ$Vz;OlJi8L%\]UFjޙ%ԯS;rA]5ފ<׈]j7Ouyq$z'TQuw7Ŀ KX߁M2=S'TQt?.5w'97;~pq=" ~k?`'9q6 E|yayM^Om'fkC&<5x' ?A?Zx'jß={=SßM gVC.5+Hd֪xc^)Җufz{Cީ|D Vkznq|+Xa+{50rx{|OG.OϞ~f/ xxX[2H )c+#jpUOZYX\=SG ߨC|K@;_߆'e?LT?]:?>w ڔ`D^So~xo[Ӡ3i7B:Q8 Vc-ďoi:FM292~y_*_闱YN\Fr=xZ3鳎OwW_QEzW~c]REeaSM}}Hӏ4&.E]u=gMѠ+mF`rNn$w9gMa꺢nTuhf2Xv>އ a(Û6߭?<=>z'TQuw7Ŀ KX߁M2=S'TQt?.5Kko\.8S$TOX߀Gw?Zx汴X)C7~.i6(Щ=+4{mGӭ¸-]&'t_kV*I<1)4thtIsqpQJ+> \m^[aJ5)ny:4o&QEnyAEPEEss 72,PDۢ׃K W{Wjr+wگ iM/;pd?~&?@;7E4gv8 $l'z'TQuw7Ŀ Gֱ=ɿ&G?. iR(5W*$|?w᫼gkmIbHe/_t>tg%y.l}N5[]+Mk0ĠeHdPrsst'UiC,y8`V%9ZIia|ܪvi מYG,o}+kk{YbyIeb*sAtի82zWoEK5z*o-eo;n(P u-I)4Š(HQEQEQEQEhz(X/Đ?}Bk˩ ݏrk0]4>8XzV? }6$}d^F>nU K ?Bտk_9׾x~w'ߞ  uDŽtL ؈5c-E/"|_Oo.IH쐍=i*Iw5(ںw?t5s.)+tQ2dUt5Vĺ.jZ"@IRrZƅY4ߡ_;}ų(KyQf1Aǵt?sZg+?F5_oQR&Dg߿]6FuRD u>ڿxl7?IT8'shj^=.=J1rj1Wl$얲cPx;E,p$֟ˏkw qg"45(ǛkV/=+ũ)bYl~K#˝J_כ5&\F'I#8/|wʾ_Xj Q:os^T1.M_|TO.;?_  jF?g N 8nA2F%i =qW,G=5OU u8]Rq?wr'˻S+۾.ܼ 87Q^elo/T*?L|ۚ<%<,/v_OKs B5f/29n0=zqQq(ª=VX@*J(э(f5qJN_EVǞQEOuoѕOuoa5}gO?:߂8Wא|cڽ~]N&O( (<]>͠@VQ=^~U ̴m&\խ5i:}|}r~9՝f}_>'vVֲ$~^f30^in{\_.O F8to}?${φ|#x^#^n~w=~k~?'KRtO.㌡h![3Zu*ٷճ(ԟ]z_/W1(ԟ]v~g|Yq<ז0 ; b8֮s,w9\?uEyStKaª@\,)) (!EPEPEPEPEPzѧts{v>C/"N6`d*J2gGӧWqBq_1ZuΓ\X]r?=Ey88Mp&pKtO-"wR2 K^-Z< \c>V0^@O7x2WFjs<׻kZ(<Т(OFw/6$1[:ޯԯ#q~4|,LVPem=@=YLUxӃV}AUbcUB.Ds5*kٸAeG>PJxt͝ b88?*$~@ׯD VkraiJs}Q.20x&mXξ,Z]“A-J#`+-E/"<]\a'tZGy.(|lދ~gMK OZdxDŽU9T6ϯ^<Ϡt5CZ]].t۫S=s`ڳ%8iVK:nqe+#<.T6U>zWoy3^I {F?J~=G}k)K$$;$de8*G Uӟ4Ocºw}|]4=ݣ\x$ʠms?q^ipw\"ȿPs^Z Q_0GڼU.t}ROM[G#]8wٞ ӫ87}Cgw vHȩBM55vof =A_٭`Ygx[6 P,5}>蚊(0(+?>+?> k|TuXq6_ +szk :u_ Z߶Ak_U}Jc2u/1[_»ݸG41-bሬ۴}}Eȹפ_c?5gi @cL\L<68hF_Ih>X4K7UТ sMj =J7CKo>Օ5s:߀t ~ηaٿ?|gdL8+gG%o?x`دOqȱwc¨&TW_V_aI=dpG!wu۞սZ1yL50$(l3(:~'ַo A}a3N*[0ǭ HKQV}G@֜$ 9of$ArNqUOgË05#m?D)^_h//5_/<?4}Jį+GkpG4"$ r| >S4Ђ"S 1%R:ȝ 8;PKPz PK-AOEBPS/dcommon/feedback.gif7GIF89a'%(hp|fdx?AN5:dfeDGHɾTdQc`g*6DC\?ؘ||{;=E6JUՄfeA= >@,4`H.|`a (Q 9:&[|ځ,4p Y&BDb,!2@, $wPA'ܠǃ@CO~/d.`I @8ArHx9H75j L 3B/` P#qD*s 3A:3,H70P,R@ p!(F oԥ D;"0 ,6QBRɄHhI@@VDLCk8@NBBL2&pClA?DAk%$`I2 #Q+l7 "=&dL&PRSLIP)PɼirqМ'N8[_}w;PK-PK-AOEBPS/dcommon/booklist.gifGIF89a1޵֥΄kZ{Jk1Rs!BZ)B),@I9Z͓Ca % Dz8Ȁ0FZЌ0P !x8!eL8aWȠFD(~@p+rMS|ӛR$ v "Z:]ZJJEc{*=AP  BiA ']j4$*   & 9q sMiO?jQ = , YFg4.778c&$c%9;PKː5PK-AOEBPS/dcommon/cpyr.htm1 Oracle Legal Notices

Oracle Legal Notices

Copyright Notice

Copyright © 1994-2012, Oracle and/or its affiliates. All rights reserved.

Trademark Notice

Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Intel and Intel Xeon are trademarks or registered trademarks of Intel Corporation. All SPARC trademarks are used under license and are trademarks or registered trademarks of SPARC International, Inc. AMD, Opteron, the AMD logo, and the AMD Opteron logo are trademarks or registered trademarks of Advanced Micro Devices. UNIX is a registered trademark of The Open Group.

License Restrictions Warranty/Consequential Damages Disclaimer

This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.

Warranty Disclaimer

The information contained herein is subject to change without notice and is not warranted to be error-free. If you find any errors, please report them to us in writing.

Restricted Rights Notice

If this is software or related documentation that is delivered to the U.S. Government or anyone licensing it on behalf of the U.S. Government, the following notice is applicable:

U.S. GOVERNMENT RIGHTS Programs, software, databases, and related documentation and technical data delivered to U.S. Government customers are "commercial computer software" or "commercial technical data" pursuant to the applicable Federal Acquisition Regulation and agency-specific supplemental regulations. As such, the use, duplication, disclosure, modification, and adaptation shall be subject to the restrictions and license terms set forth in the applicable Government contract, and, to the extent applicable by the terms of the Government contract, the additional rights set forth in FAR 52.227-19, Commercial Computer Software License (December 2007). Oracle America, Inc., 500 Oracle Parkway, Redwood City, CA 94065.

Hazardous Applications Notice

This software or hardware is developed for general use in a variety of information management applications. It is not developed or intended for use in any inherently dangerous applications, including applications that may create a risk of personal injury. If you use this software or hardware in dangerous applications, then you shall be responsible to take all appropriate fail-safe, backup, redundancy, and other measures to ensure its safe use. Oracle Corporation and its affiliates disclaim any liability for any damages caused by use of this software or hardware in dangerous applications.

Third-Party Content, Products, and Services Disclaimer

This software or hardware and documentation may provide access to or information on content, products, and services from third parties. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to third-party content, products, and services. Oracle Corporation and its affiliates will not be responsible for any loss, costs, or damages incurred due to your access to or use of third-party content, products, or services.

Alpha and Beta Draft Documentation Notice

If this document is in prerelease status:

This documentation is in prerelease status and is intended for demonstration and preliminary use only. It may not be specific to the hardware on which you are using the software. Oracle Corporation and its affiliates are not responsible for and expressly disclaim all warranties of any kind with respect to this documentation and will not be responsible for any loss, costs, or damages incurred due to the use of this documentation.

Oracle Logo

PKN61PK-AOEBPS/dcommon/masterix.gif.GIF89a1ޜΌscJk1Rs!Bc1J),@IS@0"1 Ѿb$b08PbL,acr B@(fDn Jx11+\%1 p { display: none; } /* Class Selectors */ .ProductTitle { font-family: sans-serif; } .BookTitle { font-family: sans-serif; } .VersionNumber { font-family: sans-serif; } .PrintDate { font-family: sans-serif; font-size: small; } .PartNumber { font-family: sans-serif; font-size: small; } PKeӺ1,PK-AOEBPS/dcommon/larrow.gif#GIF87a絵ƌֵƽ{{ss֜ƔZZ{{{{ZZssZZccJJJJRRBBJJJJ991111))!!{,@pH,Ȥrl:ШtpHc`  өb[.64ꑈ53=Z]'yuLG*)g^!8C?-6(29K"Ĩ0Яl;U+K9^u2,@@ (\Ȱ Ë $P`lj 8x I$4H *(@͉0dа8tA  DсSP v"TUH PhP"Y1bxDǕ̧_=$I /& .)+ 60D)bB~=0#'& *D+l1MG CL1&+D`.1qVG ( "D2QL,p.;u. |r$p+5qBNl<TzB"\9e0u )@D,¹ 2@C~KU 'L6a9 /;<`P!D#Tal6XTYhn[p]݅ 7}B a&AƮe{EɲƮiEp#G}D#xTIzGFǂEc^q}) Y# (tۮNeGL*@/%UB:&k0{ &SdDnBQ^("@q #` @1B4i@ aNȅ@[\B >e007V[N(vpyFe Gb/&|aHZj@""~ӎ)t ? $ EQ.սJ$C,l]A `8A o B C?8cyA @Nz|`:`~7-G|yQ AqA6OzPbZ`>~#8=./edGA2nrBYR@ W h'j4p'!k 00 MT RNF6̙ m` (7%ꑀ;PKl-OJPK-AOEBPS/dcommon/index.gifGIF89a1޵ΥΥ{sc{BZs,@IM" AD B0 3.R~[D"0, ]ШpRNC  /& H&[%7TM/`vS+-+ q D go@" 4o'Uxcxcc&k/ qp zUm(UHDDJBGMԃ;PK(PK-AOEBPS/dcommon/bookbig.gif +GIF89a$!!!)))111999BBBJJJRRRZZZccckkksss{{{skkB991)))!!B11))1!JB9B9!!cZ9ƭƽssk{ZZRccZRRJJJBBB9c!!ν)1)k{s絽ƌkssֽZccJRRBJJ{9BB)11)99!!))11!!k!JZ!)RcJccBcs)1c)JZ!BR!)BZ)99J!Rk9!c11B)Z{)9Bkc1kB9BZ!Z{9Rs)Jkksk9kB1s1Jk9Rƥc{k9s)Z{1k91)s1Rk)Jc1J!))BZ!1k{csc{)19B!)Bcsc{ksc{kZs!RkJkJkքc{9Zks{ck9R)Bks9R9R1J!)Z1B!)c)9)99BR19kksBBJcc{ccBBZ))9kk!!199c11ZBB{9!!R!!Z!!c))!!kR!!s!!BcksRZ1c9B)R91c1)Z!R9B9k1)RcZ{)!1B9JB9B)!)J9B!& Imported from GIF image: bookbig.gif,$!!!)))111999BBBJJJRRRZZZccckkksss{{{skkB991)))!!B11))1!JB9B9!!cZ9ƭƽssk{ZZRccZRRJJJBBB9c!!ν)1)k{s絽ƌkssֽZccJRRBJJ{9BB)11)99!!))11!!k!JZ!)RcJccBcs)1c)JZ!BR!)BZ)99J!Rk9!c11B)Z{)9Bkc1kB9BZ!Z{9Rs)Jkksk9kB1s1Jk9Rƥc{k9s)Z{1k91)s1Rk)Jc1J!))BZ!1k{csc{)19B!)Bcsc{ksc{kZs!RkJkJkքc{9Zks{ck9R)Bks9R9R1J!)Z1B!)c)9)99BR19kksBBJcc{ccBBZ))9kk!!199c11ZBB{9!!R!!Z!!c))!!kR!!s!!BcksRZ1c9B)R91c1)Z!R9B9k1)RcZ{)!1B9JB9B)!)J9BH`\Ȑ:pظа"A6DBH,V@Dڹ'G"v Æ ܥ;n;!;>xAܽ[G.\rQC wr}BŊQ A9ᾑ#5Y0VȒj0l-GqF>ZpM rb ;=.ސW-WѻWo ha!}~ْ ; t 53 :\ 4PcD,0 4*_l0K3-`l.j!c Aa|2L4/1C`@@md;(H*80L0L(h*҇҆o#N84pC (xO@ A)J6rVlF r  fry†$r_pl5xhA+@A=F rGU a 1х4s&H Bdzt x#H%Rr (Ѐ7P`#Rщ'x" #0`@~i `HA'Tk?3!$`-A@1l"P LhʖRG&8A`0DcBH sq@AXB4@&yQhPAppxCQ(rBW00@DP1E?@lP1%T` 0 WB~nQ@;PKGC PK-AOEBPS/dcommon/rarrow.gif/GIF87a絵ƌֵƽ{{ss֜ƔZZ{{{{ZZssZZccJJJJRRBBJJJJ991111))!!{,@pH,Ȥrl:ШLlԸ NCqWEd)#34vwwpN|0yhX!'+-[F 'n5 H $/14w3% C .90" qF 7&E "D mnB|,c96) I @0BW{ᢦdN p!5"D`0 T 0-]ʜ$;PKJV^PK-AOEBPS/dcommon/mix.gifkGIF89aZZZBBBJJJkkk999sss!!!111cccֽ{{{RRR)))猌ƭ{s{sks!,@@pH,B$ 8 t:<8 *'ntPP DQ@rIBJLNPTVEMOQUWfj^!  hhG H  kCúk_a Ǥ^ h`B BeH mm  #F` I lpǎ,p B J\Y!T\(dǏ!Gdˆ R53ټ R;iʲ)G=@-xn.4Y BuU(*BL0PX v`[D! | >!/;xP` (Jj"M6 ;PK枰pkPK-AOEBPS/dcommon/doccd_epub.jsM /* Copyright 2006, 2012, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2012.3.17 */ function addLoadEvent(func) { var oldOnload = window.onload; if (typeof(window.onload) != "function") window.onload = func; else window.onload = function() { oldOnload(); func(); } } function compactLists() { var lists = []; var ul = document.getElementsByTagName("ul"); for (var i = 0; i < ul.length; i++) lists.push(ul[i]); var ol = document.getElementsByTagName("ol"); for (var i = 0; i < ol.length; i++) lists.push(ol[i]); for (var i = 0; i < lists.length; i++) { var collapsible = true, c = []; var li = lists[i].getElementsByTagName("li"); for (var j = 0; j < li.length; j++) { var p = li[j].getElementsByTagName("p"); if (p.length > 1) collapsible = false; for (var k = 0; k < p.length; k++) { if ( getTextContent(p[k]).split(" ").length > 12 ) collapsible = false; c.push(p[k]); } } if (collapsible) { for (var j = 0; j < c.length; j++) { c[j].style.margin = "0"; } } } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(compactLists); function processIndex() { try { if (!/\/index.htm(?:|#.*)$/.test(window.location.href)) return false; } catch(e) {} var shortcut = []; lastPrefix = ""; var dd = document.getElementsByTagName("dd"); for (var i = 0; i < dd.length; i++) { if (dd[i].className != 'l1ix') continue; var prefix = getTextContent(dd[i]).substring(0, 2).toUpperCase(); if (!prefix.match(/^([A-Z0-9]{2})/)) continue; if (prefix == lastPrefix) continue; dd[i].id = prefix; var s = document.createElement("a"); s.href = "#" + prefix; s.appendChild(document.createTextNode(prefix)); shortcut.push(s); lastPrefix = prefix; } var h2 = document.getElementsByTagName("h2"); for (var i = 0; i < h2.length; i++) { var nav = document.createElement("div"); nav.style.position = "relative"; nav.style.top = "-1.5ex"; nav.style.left = "1.5em"; nav.style.width = "90%"; while (shortcut[0] && shortcut[0].toString().charAt(shortcut[0].toString().length - 2) == getTextContent(h2[i])) { nav.appendChild(shortcut.shift()); nav.appendChild(document.createTextNode("\u00A0 ")); } h2[i].parentNode.insertBefore(nav, h2[i].nextSibling); } function getTextContent(e) { if (e.textContent) return e.textContent; if (e.innerText) return e.innerText; } } addLoadEvent(processIndex); PKo"nR M PK-AOEBPS/dcommon/toc.gifGIF89a1ΥΥ{c{Z{JkJk1Rk,@IK% 0| eJB,K-1i']Bt9dz0&pZ1o'q(؟dQ=3S SZC8db f&3v2@VPsuk2Gsiw`"IzE%< C !.hC IQ 3o?39T ҍ;PKv I PK-AOEBPS/dcommon/topnav.gifGIF89a1ֽ筽ޭƔkZZk{Bc{,@ ) l)-'KR$&84 SI) XF P8te NRtHPp;Q%Q@'#rR4P fSQ o0MX[) v + `i9gda/&L9i*1$#"%+ ( E' n7Ȇ(,҅(L@(Q$\x 8=6 'נ9tJ&"[Epljt p#ѣHb :f F`A =l|;&9lDP2ncH R `qtp!dȐYH›+?$4mBA9 i@@ ]@ꃤFxAD*^Ŵ#,(ε  $H}F.xf,BD Z;PK1FAPK-AOEBPS/dcommon/bp_layout.css# @charset "utf-8"; /* bp_layout.css Copyright 2007, Oracle and/or its affiliates. All rights reserved. */ body { margin: 0ex; padding: 0ex; } h1 { display: none; } #FOOTER { border-top: #0d4988 solid 10px; background-color: inherit; color: #e4edf3; clear: both; } #FOOTER p { font-size: 80%; margin-top: 0em; margin-left: 1em; } #FOOTER a { background-color: inherit; color: gray; } #LEFTCOLUMN { float: left; width: 50%; } #RIGHTCOLUMN { float: right; width: 50%; clear: right; /* IE hack */ } #LEFTCOLUMN div.portlet { margin-left: 2ex; margin-right: 1ex; } #RIGHTCOLUMN div.portlet { margin-left: 1ex; margin-right: 2ex; } div.portlet { margin: 2ex 1ex; padding-left: 0.5em; padding-right: 0.5em; border: 1px #bcc solid; background-color: #f6f6ff; color: black; } div.portlet h2 { margin-top: 0.5ex; margin-bottom: 0ex; font-size: 110%; } div.portlet p { margin-top: 0ex; } div.portlet ul { list-style-type: none; padding-left: 0em; margin-left: 0em; /* IE Hack */ } div.portlet li { text-align: right; } div.portlet li cite { font-style: normal; float: left; } div.portlet li a { margin: 0px 0.2ex; padding: 0px 0.2ex; font-size: 95%; } #NAME { margin: 0em; padding: 0em; position: relative; top: 0.6ex; left: 10px; width: 80%; } #PRODUCT { font-size: 180%; } #LIBRARY { color: #0b3d73; background: inherit; font-size: 180%; font-family: serif; } #RELEASE { position: absolute; top: 28px; font-size: 80%; font-weight: bold; } #TOOLS { list-style-type: none; position: absolute; top: 1ex; right: 2em; margin: 0em; padding: 0em; background: inherit; color: black; } #TOOLS a { background: inherit; color: black; } #NAV { float: left; width: 96%; margin: 3ex 0em 0ex 0em; padding: 2ex 0em 0ex 4%; /* Avoiding horizontal scroll bars. */ list-style-type: none; background: transparent url(../gifs/nav_bg.gif) repeat-x bottom; } #NAV li { float: left; margin: 0ex 0.1em 0ex 0em; padding: 0ex 0em 0ex 0em; } #NAV li a { display: block; margin: 0em; padding: 3px 0.7em; border-top: 1px solid gray; border-right: 1px solid gray; border-bottom: none; border-left: 1px solid gray; background-color: #a6b3c8; color: #333; } #SUBNAV { float: right; width: 96%; margin: 0ex 0em 0ex 0em; padding: 0.1ex 4% 0.2ex 0em; /* Avoiding horizontal scroll bars. */ list-style-type: none; background-color: #0d4988; color: #e4edf3; } #SUBNAV li { float: right; } #SUBNAV li a { display: block; margin: 0em; padding: 0ex 0.5em; background-color: inherit; color: #e4edf3; } #SIMPLESEARCH { position: absolute; top: 5ex; right: 1em; } #CONTENT { clear: both; } #NAV a:hover, #PORTAL_1 #OVERVIEW a, #PORTAL_2 #OVERVIEW a, #PORTAL_3 #OVERVIEW a, #PORTAL_4 #ADMINISTRATION a, #PORTAL_5 #DEVELOPMENT a, #PORTAL_6 #DEVELOPMENT a, #PORTAL_7 #DEVELOPMENT a, #PORTAL_11 #INSTALLATION a, #PORTAL_15 #ADMINISTRATION a, #PORTAL_16 #ADMINISTRATION a { background-color: #0d4988; color: #e4edf3; padding-bottom: 4px; border-color: gray; } #SUBNAV a:hover, #PORTAL_2 #SEARCH a, #PORTAL_3 #BOOKS a, #PORTAL_6 #WAREHOUSING a, #PORTAL_7 #UNSTRUCTURED a, #PORTAL_15 #INTEGRATION a, #PORTAL_16 #GRID a { position: relative; top: 2px; background-color: white; color: #0a4e89; } PK3( # PK-AOEBPS/dcommon/bookicon.gif:GIF87a!!!)))111999BBBJJJRRRZZZccckkksss{{{ޭ{{ZRRcZZRJJJBB)!!skRB9{sν{skskcZRJ1)!֭ƽ{ZZRccZJJBBB999111)JJ9BB1ZZB!!ﭵBJJ9BB!!))Jk{)1!)BRZJ{BsR!RRJsJ!J{s!JsBkks{RsB{J{c1RBs1ZB{9BJ9JZ!1BJRRs!9R!!9Z9!1)J19JJRk19R1Z)!1B9R1RB!)J!J1R)J119!9J91!9BkksBBJ119BBR!))9!!!JB1JJ!)19BJRZckތ1)1J9B,H*\hp >"p`ƒFF "a"E|ժOC&xCRz OBtX>XE*O>tdqAJ +,WxP!CYpQ HQzDHP)T njJM2ꔀJ2T0d#+I:<жk 'ꤱF AB @@nh Wz' H|-7f\A#yNR5 /PM09u UjćT|q~Yq@&0YZAPa`EzI /$AD Al!AAal 2H@$ PVAB&c*ؠ p @% p-`@b`uBa l&`3Ap8槖X~ vX$Eh`.JhAepA\"Bl, :Hk;PKx[?:PK-AOEBPS/dcommon/conticon.gif^GIF87a!!!)))111999BBBJJJRRRZZZccckkksss{{{ZRR޽{{ssskkkcccZ991ccRZZBBJJZck)19ZcsBJZ19J!k{k)Z1RZs1!B)!J91{k{)J!B!B911)k{cs!1s!9)s!9!B!k)k1c!)Z!R{9BJcckZZcBBJ99B119{{!!)BBRBBZ!))999R99Z!!999c1!9!)19B1)!B9R,  oua\h2SYPa aowwxYi 9SwyyxxyYSd $'^qYȵYvh ч,/?g{н.J5fe{ڶyY#%/}‚e,Z|pAܠ `KYx,ĉ&@iX9|`p ]lR1khٜ'E 6ÅB0J;t X b RP(*MÄ!2cLhPC <0Ⴁ  $4!B 6lHC%<1e H 4p" L`P!/,m*1F`#D0D^!AO@..(``_؅QWK>_*OY0J@pw'tVh;PKp*c^PK-AOEBPS/dcommon/blafdoc.cssL@charset "utf-8"; /* Copyright 2002, 2011, Oracle and/or its affiliates. All rights reserved. Author: Robert Crews Version: 2011.10.7 */ body { font-family: Tahoma, sans-serif; /* line-height: 125%; */ color: black; background-color: white; font-size: small; } * html body { /* http://www.info.com.ph/~etan/w3pantheon/style/modifiedsbmh.html */ font-size: x-small; /* for IE5.x/win */ f\ont-size: small; /* for other IE versions */ } h1 { font-size: 165%; font-weight: bold; border-bottom: 1px solid #ddd; width: 100%; } h2 { font-size: 152%; font-weight: bold; } h3 { font-size: 139%; font-weight: bold; } h4 { font-size: 126%; font-weight: bold; } h5 { font-size: 113%; font-weight: bold; display: inline; } h6 { font-size: 100%; font-weight: bold; font-style: italic; display: inline; } a:link { color: #039; background: inherit; } a:visited { color: #72007C; background: inherit; } a:hover { text-decoration: underline; } a img, img[usemap] { border-style: none; } code, pre, samp, tt { font-family: monospace; font-size: 110%; } caption { text-align: center; font-weight: bold; width: auto; } dt { font-weight: bold; } table { font-size: small; /* for ICEBrowser */ } td { vertical-align: top; } th { font-weight: bold; text-align: left; vertical-align: bottom; } ol ol { list-style-type: lower-alpha; } ol ol ol { list-style-type: lower-roman; } td p:first-child, td pre:first-child { margin-top: 0px; margin-bottom: 0px; } table.table-border { border-collapse: collapse; border-top: 1px solid #ccc; border-left: 1px solid #ccc; } table.table-border th { padding: 0.5ex 0.25em; color: black; background-color: #f7f7ea; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } table.table-border td { padding: 0.5ex 0.25em; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; } span.gui-object, span.gui-object-action { font-weight: bold; } span.gui-object-title { } p.horizontal-rule { width: 100%; border: solid #cc9; border-width: 0px 0px 1px 0px; margin-bottom: 4ex; } div.zz-skip-header { display: none; } td.zz-nav-header-cell { text-align: left; font-size: 95%; width: 99%; color: black; background: inherit; font-weight: normal; vertical-align: top; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-header-link { font-size: 95%; } td.zz-nav-button-cell { white-space: nowrap; text-align: center; width: 1%; vertical-align: top; padding-left: 4px; padding-right: 4px; margin-top: 0ex; padding-top: 0ex; } a.zz-nav-button-link { font-size: 90%; } div.zz-nav-footer-menu { width: 100%; text-align: center; margin-top: 2ex; margin-bottom: 4ex; } p.zz-legal-notice, a.zz-legal-notice-link { font-size: 85%; /* display: none; */ /* Uncomment to hide legal notice */ } /*************************************/ /* Begin DARB Formats */ /*************************************/ .bold, .codeinlinebold, .syntaxinlinebold, .term, .glossterm, .seghead, .glossaryterm, .keyword, .msg, .msgexplankw, .msgactionkw, .notep1, .xreftitlebold { font-weight: bold; } .italic, .codeinlineitalic, .syntaxinlineitalic, .variable, .xreftitleitalic { font-style: italic; } .bolditalic, .codeinlineboldital, .syntaxinlineboldital, .titleinfigure, .titleinexample, .titleintable, .titleinequation, .xreftitleboldital { font-weight: bold; font-style: italic; } .itemizedlisttitle, .orderedlisttitle, .segmentedlisttitle, .variablelisttitle { font-weight: bold; } .bridgehead, .titleinrefsubsect3 { font-weight: bold; } .titleinrefsubsect { font-size: 126%; font-weight: bold; } .titleinrefsubsect2 { font-size: 113%; font-weight: bold; } .subhead1 { display: block; font-size: 139%; font-weight: bold; } .subhead2 { display: block; font-weight: bold; } .subhead3 { font-weight: bold; } .underline { text-decoration: underline; } .superscript { vertical-align: super; } .subscript { vertical-align: sub; } .listofeft { border: none; } .betadraft, .alphabetanotice, .revenuerecognitionnotice { color: #e00; background: inherit; } .betadraftsubtitle { text-align: center; font-weight: bold; color: #e00; background: inherit; } .comment { color: #080; background: inherit; font-weight: bold; } .copyrightlogo { text-align: center; font-size: 85%; } .tocsubheader { list-style-type: none; } table.icons td { padding-left: 6px; padding-right: 6px; } .l1ix dd, dd dl.l2ix, dd dl.l3ix { margin-top: 0ex; margin-bottom: 0ex; } div.infoboxnote, div.infoboxnotewarn, div.infoboxnotealso { margin-top: 4ex; margin-right: 10%; margin-left: 10%; margin-bottom: 4ex; padding: 0.25em; border-top: 1pt solid gray; border-bottom: 1pt solid gray; } p.notep1 { margin-top: 0px; margin-bottom: 0px; } .tahiti-highlight-example { background: #ff9; text-decoration: inherit; } .tahiti-highlight-search { background: #9cf; text-decoration: inherit; } .tahiti-sidebar-heading { font-size: 110%; margin-bottom: 0px; padding-bottom: 0px; } /*************************************/ /* End DARB Formats */ /*************************************/ @media all { /* * * { line-height: 120%; } */ dd { margin-bottom: 2ex; } dl:first-child { margin-top: 2ex; } } @media print { body { font-size: 11pt; padding: 0px !important; } a:link, a:visited { color: black; background: inherit; } code, pre, samp, tt { font-size: 10pt; } #nav, #search_this_book, #comment_form, #comment_announcement, #flipNav, .noprint { display: none !important; } body#left-nav-present { overflow: visible !important; } } PKʍPK-AOEBPS/dcommon/rightnav.gif&GIF89a1ֽ筽ޭƔkZZk{Bc{,@ ) l)- $CҠҀ ! D1 #:aS( c4B0 AC8 ְ9!%MLj Z * ctypJBa H t>#Sb(clhUԂ̗4DztSԙ9ZQҀEPEPEPEPEPEPEPM=iԍP Gii c*yF 1׆@\&o!QY00_rlgV;)DGhCq7~..p&1c:u֫{fI>fJL$}BBP?JRWc<^j+χ5b[hֿ- 5_j?POkeQ^hֿ1L^ H ?Qi?z?+_xɔŪ\썽O]χ>)xxV/s)e6MI7*ߊޛv֗2J,;~E4yi3[nI`Ѱe9@zXF*W +]7QJ$$=&`a۾?]N T䏟'X)Ɣkf:j |>NBWzYx0t!* _KkoTZ?K Gc+UyڹgNuh^iSo5{\ܹ3Yos}.>if FqR5\/TӮ#]HS0DKu{($"2xִ{SBJ8=}Y=.|Tsц2UЫ%.InaegKo z ݎ3ֹxxwM&2S%';+I',kW&-"_¿_ Vq^ܫ6pfT2RV A^6RKetto^[{w\jPZ@ޢN4/XN#\42j\(z'j =~-I#:q[Eh|X:sp* bifp$TspZ-}NM*B-bb&*xUr#*$M|QWY ~p~- fTED6O.#$m+t$˙H"Gk=t9r娮Y? CzE[/*-{c*[w~o_?%ƔxZ:/5𨴟q}/]22p qD\H"K]ZMKR&\C3zĽ[PJm]AS)Ia^km M@dК)fT[ijW*hnu Ͳiw/bkExG£@f?Zu.s0(<`0ֹoxOaDx\zT-^ѧʧ_1+CP/p[w 9~U^[U<[tĽwPv[yzD1W='u$Oeak[^ |Gk2xv#2?¹TkSݕ| rݞ[Vi _Kz*{\c(Ck_܏|?u jVڔ6f t?3nmZ6f%QAjJf9Rq _j7Z-y.pG$Xb]0')[_k;$̭?&"0FOew7 z-cIX岛;$u=\an$ zmrILu uٞ% _1xcUW%dtÀx885Y^gn;}ӭ)場QEQ@Q@Q@Q@Q@Q@!4xPm3w*]b`F_931˜[ן+(> E ly;<;MF-qst+}DH @YKlLmؤciN<|]IU)Lw(8t9FS(=>og<\Z~u_+X1ylsj'eՃ*U3`C!N9Q_WܱhKc93^ua>H ƕGk=8~e#_?{ǀe-[2ٔ7;=&K挑5zsLdx(e8#{1wS+ΝVkXq9>&yஏh$zq^0~/j@:/«Vnce$$uoPp}MC{$-akH@ɫ1O !8R9s5ԦYmϧ'OUṡ5T,!Ԛ+s#1Veo=[)g>#< s)ƽُA^䠮ωFUj(ǩ|N3Jڷ睁ϱuږZYGOTsI<&drav?A^_f׻B$,O__ԿC`it{6>G׈C~&$y؎v1q9Sc1fH[ѽ>,gG'0'@Vw,BO [#>ﱺg5ΒFVD%Yr:O5 Tu+O멃]ی38Ze}R&ѝ_xzc1DXgس;<,_,{ƽY'AS#oF.M#~cBuEx7G+Y)(5q+GCV;qF+CLQ)qEC&6z𿊘z}?&w=+)??&\g{;V??׻xGœdٿ׼-Nc')3K]N)iLTӿCdb7Q^a N sd>Fz[0S^s'Zi 77D}kWus ab~~H(>.fif9,~|Jk;YN3H8Y(t6Q݉k͇_÷Z+2߄&[ +Tr^藺97~c܎=[f1RrBǓ^kEMhxYVm<[џ6| kqbѱ| YA{G8p?\UM7Z66 g1U1igU69 u5Pƪ:VVZC=[@ҹ¨$kSmɳО\vFz~i3^a Osŧυ9Q}_3 όO{/wgoet39 vO2ea;Ύ7$U#?k+Ek&dpzbӱ+TaB0gN{[N7Gי}U7&@?>Fz~E!a@s ?'67XxO*!?qi]֏TQN@tI+\^s8l0)2k!!iW8F$(yOּT.k,/#1:}8uT˾+5=O/`IW G֯b.-<= HOm;~so~hW5+kS8s.zwE| ?4ӿw/K N 9?j(#0UT` Wzw}:_*9m>󑓀F?ELzv=8q:=WgJ`nDr Zе<ֹ](Q@Q@Q@Q@Q@Q@Q@Q@ 'IdC0EYJVcMty_~u+Sw-aO n<[YJgL#6i g5ЖDZ14cʝ!!\/M}/_AYR__>oC? _?7_G#RERW쏞KB}JxGSkǕA pƱơP m]hwB7U$Zq M95"3q1ioATߚ{g.t uu2k=;h#YB= fgS :TdLԃ!44mFK{Hrd^7oz|BVr<{)6AXգV»|>*/hS܏z͆OM=Εq (s|s׊LKQI :9NJ)P+!ʣoAF>+=@I}"x/}۠1aנc¹4emC:>p_xWKX` >R3_S½èųp3޺u3N e یbmͺ<_ mnݮ1Op?Gm)Qb%N585'%Ahs\6yw!"&Ɨ._wk)}GP;Z!#\"< *oƾ\)}N>"լ/~]Lg}pBG X?<zZ#x69S=6) jzx=y9O&>+e!!? ?s~k5Gʏ)?*ce7Ox~k5􇔾Q/e7/Ԑ#3OgNC0] ;_FiRl>Q.g>!%k#ú:Kn'&}?U@\pџPtp)v<{_i}Oվֲ3XIYIx~b<D?(=_JXH=bbi=Oh?_ C_O)}oW쏜? %Ƶ;-RYFi`wۭ{ϖZMtQ$"c_+ԃx1*0b;ԕ݋ESQEQEQEQEQEQEQEQEQEQZ(1F)h1K@XLRE&9P (bf{RӨ&)PEPEPbԴPGKZ(iإbn(:A%S0(-&)P+ ڎԴP11F)h&:LRmQ@Q@Š(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((PKje88PK-AOEBPS/dcommon/help.gif!GIF89a1εֵ֜֜{kZsBc{,@ )sƠTQ$8(4ʔ%ŌCK$A HP`$h8ŒSd+ɡ\ H@%' 6M HO3SJM /:Zi[7 \( R9r ERI%  N=aq   qƦs *q-n/Sqj D XZ;PKއ{&!PK-A OEBPS/toc.htm Table of Contents

Contents

Title and Copyright Information

Preface

What's New in Oracle Streams Advanced Queuing?

1 Introduction to Oracle AQ

2 Basic Components

3 Oracle Streams Advanced Queuing: Programmatic Interfaces

4 Managing Oracle Streams Advanced Queuing

5 Oracle Streams Advanced Queuing Performance and Scalability

6 Internet Access to Oracle Streams Advanced Queuing

7 Troubleshooting Oracle Streams Advanced Queuing

8 Oracle Streams Advanced Queuing Administrative Interface

9 Oracle Streams Advanced Queuing & Messaging Gateway Views

10 Oracle Streams Advanced Queuing Operations Using PL/SQL

11 Introducing Oracle JMS

12 Oracle JMS Basic Operations

13 Oracle JMS Point-to-Point

14 Oracle JMS Publish/Subscribe

15 Oracle JMS Shared Interfaces

16 Oracle JMS Types Examples

17 Introducing Oracle Messaging Gateway

18 Getting Started with Oracle Messaging Gateway

19 Working with Oracle Messaging Gateway

20 Oracle Messaging Gateway Message Conversion

21 Monitoring Oracle Messaging Gateway

22 Using ANYDATA Queues for User Messages

23 Oracle Streams Messaging Examples

A Nonpersistent Queues

B JMS and AQ XML Servlet Error Messages

Glossary

Index

PKhsPK-AOEBPS/jm_exmpl.htm Oracle JMS Types Examples

16 Oracle JMS Types Examples

This chapter provides examples that illustrate how to use Oracle JMS Types to dequeue and enqueue Oracle Streams Advanced Queuing (AQ) messages.

The chapter contains the following topics:

How to Run the Oracle Streams Advanced Queuing JMS Type Examples

To run Example 16-2 through Example 16-7 follow these steps:

  1. Copy and save Example 16-1 as setup.sql.

  2. Run setup.sql as follows:

    sqlplus /NOLOG @setup.sql
    
  3. Log in to SQL*Plus as jmsuser/jmsuser.

  4. Run the corresponding pair of SQL scripts for each type of message.

    For JMS BytesMessage, for example, run Example 16-2 and Example 16-3.

  5. Ensure that your database parameter java_pool-size is large enough. For example, you can use java_pool_size=20M.

Setting Up the Examples

Example 16-1 performs the necessary setup for the JMS types examples. Copy and save it as setup.sql.

Example 16-1 Setting Up Environment for Running JMS Types Examples

connect sys;
enter password: password

Rem 
Rem Create the JMS user: jmsuser
Rem

DROP USER jmsuser CASCADE;
CREATE USER jmsuser IDENTIFIED BY jmsuser;
GRANT DBA, AQ_ADMINISTRATOR_ROLE, AQ_USER_ROLE to jmsuser;
GRANT EXECUTE ON DBMS_AQADM TO jmsuser;
GRANT EXECUTE ON DBMS_AQ TO jmsuser;
GRANT EXECUTE ON DBMS_LOB TO jmsuser;
GRANT EXECUTE ON DBMS_JMS_PLSQL TO jmsuser;


set echo offset verify offconnect sysDROP USER jmsuser CASCADE;ACCEPT password CHAR PROMPT 'Enter the password for JMSUSER: ' HIDECREATE USER jmsuser IDENTIFIED BY &password;GRANT DBA, AQ_ADMINISTRATOR_ROLE, AQ_USER_ROLE to jmsuser;GRANT EXECUTE ON DBMS_AQADM TO jmsuser;GRANT EXECUTE ON DBMS_AQ TO jmsuser;GRANT EXECUTE ON DBMS_LOB TO jmsuser;GRANT EXECUTE ON DBMS_JMS_PLSQL TO jmsuser;connect jmsuser/&password

Rem
Rem Creating five AQ queue tables and five queues for five payloads: 
Rem SYS.AQ$_JMS_TEXT_MESSAGE
Rem SYS.AQ$_JMS_BYTES_MESSAGE
Rem SYS.AQ$_JMS_STREAM_MESSAG
Rem SYS.AQ$_JMS_MAP_MESSAGE
Rem SYS.AQ$_JMS_MESSAGE
Rem

EXECUTE DBMS_AQADM.CREATE_QUEUE_TABLE (Queue_table => 'jmsuser.jms_qtt_text', 
    Queue_payload_type => 'SYS.AQ$_JMS_TEXT_MESSAGE', compatible => '8.1.0');
EXECUTE DBMS_AQADM.CREATE_QUEUE_TABLE (Queue_table => 'jmsuser.jms_qtt_bytes', 
    Queue_payload_type => 'SYS.AQ$_JMS_BYTES_MESSAGE', compatible => '8.1.0');
EXECUTE DBMS_AQADM.CREATE_QUEUE_TABLE (Queue_table => 'jmsuser.jms_qtt_stream', 
    Queue_payload_type => 'SYS.AQ$_JMS_STREAM_MESSAGE', compatible => '8.1.0');
EXECUTE DBMS_AQADM.CREATE_QUEUE_TABLE (Queue_table => 'jmsuser.jms_qtt_map', 
    Queue_payload_type => 'SYS.AQ$_JMS_MAP_MESSAGE', compatible => '8.1.0');
EXECUTE DBMS_AQADM.CREATE_QUEUE_TABLE (Queue_table => 'jmsuser.jms_qtt_general', 
    Queue_payload_type => 'SYS.AQ$_JMS_MESSAGE', compatible => '8.1.0');
EXECUTE DBMS_AQADM.CREATE_QUEUE (Queue_name => 'jmsuser.jms_text_que', 
    Queue_table => 'jmsuser.jms_qtt_text');
EXECUTE DBMS_AQADM.CREATE_QUEUE (Queue_name => 'jmsuser.jms_bytes_que', 
    Queue_table => 'jmsuser.jms_qtt_bytes');
EXECUTE DBMS_AQADM.CREATE_QUEUE (Queue_name => 'jmsuser.jms_stream_que', 
    Queue_table => 'jmsuser.jms_qtt_stream');
EXECUTE DBMS_AQADM.CREATE_QUEUE (Queue_name => 'jmsuser.jms_map_que', 
    Queue_table => 'jmsuser.jms_qtt_map');
EXECUTE DBMS_AQADM.CREATE_QUEUE (Queue_name => 'jmsuser.jms_general_que', 
    Queue_table => 'jmsuser.jms_qtt_general');

Rem
Rem Starting the queues and enable both enqueue and dequeue 
Rem
EXECUTE DBMS_AQADM.START_QUEUE (Queue_name => 'jmsuser.jms_text_que');
EXECUTE DBMS_AQADM.START_QUEUE (Queue_name => 'jmsuser.jms_bytes_que');
EXECUTE DBMS_AQADM.START_QUEUE (Queue_name => 'jmsuser.jms_stream_que');
EXECUTE DBMS_AQADM.START_QUEUE (Queue_name => 'jmsuser.jms_map_que');
EXECUTE DBMS_AQADM.START_QUEUE (Queue_name => 'jmsuser.jms_general_que');

Rem The supporting utility used in the example to help display results in SQLPLUS enviroment

Rem
Rem Display a RAW data in SQLPLUS
Rem
create or replace procedure display_raw(rdata raw)
IS
    pos                 pls_integer;
    length              pls_integer;
BEGIN
    pos := 1;
    length := UTL_RAW.LENGTH(rdata);

    WHILE pos <= length LOOP
      IF pos+20 > length+1 THEN
        dbms_output.put_line(UTL_RAW.SUBSTR(rdata, pos, length-pos+1));
      ELSE
        dbms_output.put_line(UTL_RAW.SUBSTR(rdata, pos, 20));
      END IF;
      pos := pos+20;
    END LOOP;

END display_raw;
/

show errors;

Rem
Rem Display a BLOB data in SQLPLUS
Rem
create or replace procedure display_blob(bdata blob)
IS
    pos                 pls_integer;
    length              pls_integer;
BEGIN
    length :=  dbms_lob.getlength(bdata);
    pos := 1;
    WHILE pos <= length LOOP
      display_raw(DBMS_LOB.SUBSTR(bdata, 2000, pos));
      pos := pos+2000;
    END LOOP;
END display_blob;
/

show errors;

Rem
Rem Display a VARCHAR data in SQLPLUS
Rem
create or replace procedure display_varchar(vdata varchar)
IS
    pos                 pls_integer;
    text_len            pls_integer;
BEGIN
    text_len :=  length(vdata);
    pos := 1;

    WHILE pos <= text_len LOOP
      IF pos+20 > text_len+1 THEN
        dbms_output.put_line(SUBSTR(vdata, pos, text_len-pos+1));
      ELSE
        dbms_output.put_line(SUBSTR(vdata, pos, 20));
      END IF;
      pos := pos+20;
    END LOOP;

END display_varchar;
/

show errors;

Rem
Rem Display a CLOB data in SQLPLUS
Rem
create or replace procedure display_clob(cdata clob)
IS
    pos                 pls_integer;
    length              pls_integer;
BEGIN
    length :=  dbms_lob.getlength(cdata);
    pos := 1;
    WHILE pos <= length LOOP
      display_varchar(DBMS_LOB.SUBSTR(cdata, 2000, pos));
      pos := pos+2000;
    END LOOP;
END display_clob;
/

show errors;

Rem 
Rem Display a SYS.AQ$_JMS_EXCEPTION data in SQLPLUS
Rem
Rem When application receives an ORA-24197 error, It means the JAVA stored
Rem procedures has thrown some exceptions that could not be catergorized. The
Rem user can use GET_EXCEPTION procedure of SYS.AQ$_JMS_BYTES_MESSAGE, 
Rem SYS.AQ$_JMS_STREAM_MESSAG or SYS.AQ$_JMS_MAP_MESSAGE 
Rem to retrieve a SYS.AQ$_JMS_EXCEPTION object which contains more detailed
Rem information on this JAVA exception including the exception name, JAVA error
Rem message and stack trace.
Rem
Rem This utility function is to help display the SYS.AQ$_JMS_EXCEPTION object in
Rem SQLPLUS
Rem
create or replace procedure display_exp(exp SYS.AQ$_JMS_EXCEPTION)
IS
    pos1                pls_integer;
    pos2                pls_integer;
    text_data           varchar(2000);
BEGIN
    dbms_output.put_line('exception:'||exp.exp_name);
    dbms_output.put_line('err_msg:'||exp.err_msg);
    dbms_output.put_line('stack:'||length(exp.stack));
    pos1 := 1;
    LOOP
      pos2 := INSTR(exp.stack, chr(10), pos1);
      IF pos2 = 0 THEN
        pos2 := length(exp.stack)+1;
      END IF;

      dbms_output.put_line(SUBSTR(exp.stack, pos1, pos2-pos1));

      IF pos2 > length(exp.stack) THEN
        EXIT;
      END IF;

      pos1 := pos2+1;
    END LOOP;

END display_exp;
/

show errors;

EXIT;

JMS BytesMessage Examples

This section includes examples that illustrate enqueuing and dequeuing of a JMS BytesMessage.

Example 16-2 shows how to use JMS type member functions with DBMS_AQ functions to populate and enqueue a JMS BytesMessage represented as sys.aq$_jms_bytes_message type in the database. This message later can be dequeued by a JAVA Oracle Java Message Service (OJMS) client.

Example 16-2 Populating and Enqueuing a BytesMessage

set echo offset verify offconnect sysDROP USER jmsuser CASCADE;ACCEPT password CHAR PROMPT 'Enter the password for JMSUSER: ' HIDECREATE USER jmsuser IDENTIFIED BY &password;GRANT DBA, AQ_ADMINISTRATOR_ROLE, AQ_USER_ROLE to jmsuser;GRANT EXECUTE ON DBMS_AQADM TO jmsuser;GRANT EXECUTE ON DBMS_AQ TO jmsuser;GRANT EXECUTE ON DBMS_LOB TO jmsuser;GRANT EXECUTE ON DBMS_JMS_PLSQL TO jmsuser;connect jmsuser/&password

SET ECHO ON
set serveroutput on

DECLARE

    id                 pls_integer;
    agent              sys.aq$_agent := sys.aq$_agent(' ', null, 0);
    message            sys.aq$_jms_bytes_message;
    enqueue_options    dbms_aq.enqueue_options_t;
    message_properties dbms_aq.message_properties_t;
    msgid raw(16);

    java_exp           exception;
    pragma EXCEPTION_INIT(java_exp, -24197);
BEGIN

    -- Consturct a empty BytesMessage object
    message := sys.aq$_jms_bytes_message.construct;

    -- Shows how to set the JMS header 
    message.set_replyto(agent);
    message.set_type('tkaqpet1');
    message.set_userid('jmsuser');
    message.set_appid('plsql_enq');
    message.set_groupid('st');
    message.set_groupseq(1);

    -- Shows how to set JMS user properties
    message.set_string_property('color', 'RED');
    message.set_int_property('year', 1999);
    message.set_float_property('price', 16999.99);
    message.set_long_property('mileage', 300000);
    message.set_boolean_property('import', True);
    message.set_byte_property('password', -127);

    -- Shows how to populate the message payload of aq$_jms_bytes_message 

    -- Passing -1 reserve a new slot within the message store of sys.aq$_jms_bytes_message.
    -- The maximum number of sys.aq$_jms_bytes_message type of messges to be operated at
    -- the same time within a session is 20. Calling clean_body function with parameter -1 
    -- might result a ORA-24199 error if the messages currently operated is already 20. 
    -- The user is responsible to call clean or clean_all function to clean up message store.
    id := message.clear_body(-1);

    -- Write data into the BytesMessage paylaod. These functions are analogy of JMS JAVA api's.
    -- See the document for detail.

    -- Write a byte to the BytesMessage payload
    message.write_byte(id, 10);

    -- Write a RAW data as byte array to the BytesMessage payload
    message.write_bytes(id, UTL_RAW.XRANGE(HEXTORAW('00'), HEXTORAW('FF')));

    -- Write a portion of the RAW data as byte array to BytesMessage payload
    -- Note the offset follows JAVA convention, starting from 0
    message.write_bytes(id, UTL_RAW.XRANGE(HEXTORAW('00'), HEXTORAW('FF')), 0, 16);

    -- Write a char to the BytesMessage payload
    message.write_char(id, 'A');

    -- Write a double to the BytesMessage payload
    message.write_double(id, 9999.99);

    -- Write a float to the BytesMessage payload
    message.write_float(id, 99.99);

    -- Write a int to the BytesMessage payload
    message.write_int(id, 12345);

    -- Write a long to the BytesMessage payload
    message.write_long(id, 1234567);

    -- Write a short to the BytesMessage payload
    message.write_short(id, 123);

    -- Write a String to the BytesMessage payload, 
    -- the String is encoded in UTF8 in the message payload
    message.write_utf(id, 'Hello World!');

    -- Flush the data from JAVA stored procedure (JServ) to PL/SQL side 
    -- Without doing this, the PL/SQL message is still empty. 
    message.flush(id);

    -- Use either clean_all or clean to clean up the message store when the user 
    -- do not plan to do paylaod population on this message anymore
    sys.aq$_jms_bytes_message.clean_all();
    --message.clean(id);

    -- Enqueue this message into AQ queue using DBMS_AQ package
    dbms_aq.enqueue(queue_name => 'jmsuser.jms_bytes_que',
                    enqueue_options => enqueue_options,
                    message_properties => message_properties,
                    payload => message,
                    msgid => msgid);


    EXCEPTION 
    WHEN java_exp THEN
      dbms_output.put_line('exception information:');
      display_exp(sys.aq$_jms_stream_message.get_exception());

END;
/

commit;

Example 16-3 illustrates how to use JMS type member functions with DBMS_AQ functions to dequeue and retrieve data from a JMS BytesMessage represented as sys.aq$_jms_bytes_message type in the database. This message might be enqueued by a Java OJMS client.

Example 16-3 Dequeuing and Retrieving JMS BytesMessage Data

set echo off
set verify off
 
connect sys
 
DROP USER jmsuser CASCADE;
 
ACCEPT password CHAR PROMPT 'Enter the password for JMSUSER: ' HIDE
 
CREATE USER jmsuser IDENTIFIED BY &password;
GRANT DBA, AQ_ADMINISTRATOR_ROLE, AQ_USER_ROLE to jmsuser;
GRANT EXECUTE ON DBMS_AQADM TO jmsuser;
GRANT EXECUTE ON DBMS_AQ TO jmsuser;
GRANT EXECUTE ON DBMS_LOB TO jmsuser;
GRANT EXECUTE ON DBMS_JMS_PLSQL TO jmsuser;
connect jmsuser/&password
set echo on
set serveroutput on size 20000

DECLARE

    id                 pls_integer;
    blob_data          blob;
    clob_data          clob;
    blob_len           pls_integer;
    message            sys.aq$_jms_bytes_message;
    agent              sys.aq$_agent;
    dequeue_options    dbms_aq.dequeue_options_t;
    message_properties dbms_aq.message_properties_t;
    msgid raw(16);
    gdata              sys.aq$_jms_value;

    java_exp           exception;
    pragma EXCEPTION_INIT(java_exp, -24197);
BEGIN
    DBMS_OUTPUT.ENABLE (20000);

    -- Dequeue this message from AQ queue using DBMS_AQ package
    dbms_aq.dequeue(queue_name => 'jmsuser.jms_bytes_que',
                    dequeue_options => dequeue_options,
                    message_properties => message_properties,
                    payload => message,
                    msgid => msgid);

    -- Retrieve the header 
    agent := message.get_replyto;

    dbms_output.put_line('Type: ' || message.get_type || 
                         ' UserId: ' || message.get_userid || 
                         ' AppId: ' || message.get_appid || 
                         ' GroupId: ' || message.get_groupid || 
                         ' GroupSeq: ' || message.get_groupseq);

    -- Retrieve the user properties
    dbms_output.put_line('price: ' || message.get_float_property('price'));
    dbms_output.put_line('color: ' || message.get_string_property('color'));
    IF message.get_boolean_property('import') = TRUE THEN
       dbms_output.put_line('import: Yes' );
    ELSIF message.get_boolean_property('import') = FALSE THEN
       dbms_output.put_line('import: No' );
    END IF;
    dbms_output.put_line('year: ' || message.get_int_property('year'));
    dbms_output.put_line('mileage: ' || message.get_long_property('mileage'));
    dbms_output.put_line('password: ' || message.get_byte_property('password'));

-- Shows how to retrieve the message payload of aq$_jms_bytes_message

-- Prepare call, send the content in the PL/SQL aq$_jms_bytes_message object to 
   -- Java stored procedure(Jserv) in the form of a byte array. 
   -- Passing -1 reserves a new slot in msg store of sys.aq$_jms_bytes_message.
   -- Max number of sys.aq$_jms_bytes_message type of messges to be operated at
   -- the same time in a session is 20. Call clean_body fn. with parameter -1 
   -- might result in ORA-24199 error if messages operated on are already 20. 
   -- You must call clean or clean_all function to clean up message store.
    id := message.prepare(-1);

-- Read data from BytesMessage paylaod. These fns. are analogy of JMS Java
-- API's. See the JMS Types chapter for detail.
    dbms_output.put_line('Payload:');

    -- read a byte from the BytesMessage payload
    dbms_output.put_line('read_byte:' || message.read_byte(id));

    -- read a byte array into a blob object from the BytesMessage payload
    dbms_output.put_line('read_bytes:');
    blob_len := message.read_bytes(id, blob_data, 272);
    display_blob(blob_data);

    -- read a char from the BytesMessage payload
    dbms_output.put_line('read_char:'|| message.read_char(id));

    -- read a double from the BytesMessage payload
    dbms_output.put_line('read_double:'|| message.read_double(id));

    -- read a float from the BytesMessage payload
    dbms_output.put_line('read_float:'|| message.read_float(id));

    -- read a int from the BytesMessage payload
    dbms_output.put_line('read_int:'|| message.read_int(id));

    -- read a long from the BytesMessage payload
    dbms_output.put_line('read_long:'|| message.read_long(id));

    -- read a short from the BytesMessage payload
    dbms_output.put_line('read_short:'|| message.read_short(id));

    -- read a String from the BytesMessage payload. 
    -- the String is in UTF8 encoding in the message payload
    dbms_output.put_line('read_utf:');
    message.read_utf(id, clob_data);
    display_clob(clob_data);

    -- Use either clean_all or clean to clean up the message store when the user 
    -- do not plan to do paylaod retrieving on this message anymore
    message.clean(id);
    -- sys.aq$_jms_bytes_message.clean_all();

    EXCEPTION 
    WHEN java_exp THEN
      dbms_output.put_line('exception information:');
      display_exp(sys.aq$_jms_bytes_message.get_exception());

END;
/

commit;

JMS StreamMessage Examples

This section includes examples that illustrate enqueuing and dequeuing of a JMS StreamMessage.

Example 16-4 shows how to use JMS type member functions with DBMS_AQ functions to populate and enqueue a JMS StreamMessage represented as sys.aq$_jms_stream_message type in the database. This message later can be dequeued by a JAVA OJMS client.

Example 16-4 Populating and Enqueuing a JMS StreamMessage

set echo off
set verify off
 
connect sys
 
DROP USER jmsuser CASCADE;
 
ACCEPT password CHAR PROMPT 'Enter the password for JMSUSER: ' HIDE
 
CREATE USER jmsuser IDENTIFIED BY &password;
GRANT DBA, AQ_ADMINISTRATOR_ROLE, AQ_USER_ROLE to jmsuser;
GRANT EXECUTE ON DBMS_AQADM TO jmsuser;
GRANT EXECUTE ON DBMS_AQ TO jmsuser;
GRANT EXECUTE ON DBMS_LOB TO jmsuser;
GRANT EXECUTE ON DBMS_JMS_PLSQL TO jmsuser;
connect jmsuser/&password
SET ECHO ON
set serveroutput on

DECLARE

    id                 pls_integer;
    agent              sys.aq$_agent := sys.aq$_agent(' ', null, 0);
    message            sys.aq$_jms_stream_message;
    enqueue_options    dbms_aq.enqueue_options_t;
    message_properties dbms_aq.message_properties_t;
    msgid raw(16);

    java_exp           exception;
    pragma EXCEPTION_INIT(java_exp, -24197);
BEGIN

    -- Consturct a empty StreamMessage object
    message := sys.aq$_jms_stream_message.construct;

    -- Shows how to set the JMS header 
    message.set_replyto(agent);
    message.set_type('tkaqpet1');
    message.set_userid('jmsuser');
    message.set_appid('plsql_enq');
    message.set_groupid('st');
    message.set_groupseq(1);

    -- Shows how to set JMS user properties
    message.set_string_property('color', 'RED');
    message.set_int_property('year', 1999);
    message.set_float_property('price', 16999.99);
    message.set_long_property('mileage', 300000);
    message.set_boolean_property('import', True);
    message.set_byte_property('password', -127);

    -- Shows how to populate the message payload of aq$_jms_stream_message 

    -- Passing -1 reserve a new slot within the message store of sys.aq$_jms_stream_message.
    -- The maximum number of sys.aq$_jms_stream_message type of messges to be operated at
    -- the same time within a session is 20. Calling clean_body function with parameter -1 
    -- might result a ORA-24199 error if the messages currently operated is already 20. 
    -- The user is responsible to call clean or clean_all function to clean up message store. 
    id := message.clear_body(-1);

    -- Write data into the message paylaod. These functions are analogy of JMS JAVA api's.
    -- See the document for detail.

    -- Write a byte to the StreamMessage payload
    message.write_byte(id, 10);

    -- Write a RAW data as byte array to the StreamMessage payload
    message.write_bytes(id, UTL_RAW.XRANGE(HEXTORAW('00'), HEXTORAW('FF')));

    -- Write a portion of the RAW data as byte array to the StreamMessage payload
    -- Note the offset follows JAVA convention, starting from 0
    message.write_bytes(id, UTL_RAW.XRANGE(HEXTORAW('00'), HEXTORAW('FF')), 0, 16);

    -- Write a char to the StreamMessage payload
    message.write_char(id, 'A');

    -- Write a double to the StreamMessage payload
    message.write_double(id, 9999.99);

    -- Write a float to the StreamMessage payload
    message.write_float(id, 99.99);

    -- Write a int to the StreamMessage payload
    message.write_int(id, 12345);

    -- Write a long to the StreamMessage payload
    message.write_long(id, 1234567);

    -- Write a short to the StreamMessage payload
    message.write_short(id, 123);

    -- Write a String to the StreamMessage payload
    message.write_string(id, 'Hello World!');

    -- Flush the data from JAVA stored procedure (JServ) to PL/SQL side 
    -- Without doing this, the PL/SQL message is still empty. 
    message.flush(id);

    -- Use either clean_all or clean to clean up the message store when the user 
    -- do not plan to do paylaod population on this message anymore
    sys.aq$_jms_stream_message.clean_all();
    --message.clean(id);

    -- Enqueue this message into AQ queue using DBMS_AQ package
    dbms_aq.enqueue(queue_name => 'jmsuser.jms_stream_que',
                    enqueue_options => enqueue_options,
                    message_properties => message_properties,
                    payload => message,
                    msgid => msgid);


    EXCEPTION 
    WHEN java_exp THEN
      dbms_output.put_line('exception information:');
      display_exp(sys.aq$_jms_stream_message.get_exception());

END;
/

commit;

Example 16-5 shows how to use JMS type member functions with DBMS_AQ functions to dequeue and retrieve data from a JMS StreamMessage represented as sys.aq$_jms_stream_message type in the database. This message might be enqueued by a JAVA OJMS client.

Example 16-5 Dequeuing and Retrieving Data From a JMS StreamMessage

set echo off
set verify off
 
connect sys
 
DROP USER jmsuser CASCADE;
 
ACCEPT password CHAR PROMPT 'Enter the password for JMSUSER: ' HIDE
 
CREATE USER jmsuser IDENTIFIED BY &password;
GRANT DBA, AQ_ADMINISTRATOR_ROLE, AQ_USER_ROLE to jmsuser;
GRANT EXECUTE ON DBMS_AQADM TO jmsuser;
GRANT EXECUTE ON DBMS_AQ TO jmsuser;
GRANT EXECUTE ON DBMS_LOB TO jmsuser;
GRANT EXECUTE ON DBMS_JMS_PLSQL TO jmsuser;
connect jmsuser/&password
set echo on
set serveroutput on 

DECLARE

    id                 pls_integer;
    blob_data          blob;
    clob_data          clob;
    message            sys.aq$_jms_stream_message;
    agent              sys.aq$_agent;
    dequeue_options    dbms_aq.dequeue_options_t;
    message_properties dbms_aq.message_properties_t;
    msgid raw(16);
    gdata              sys.aq$_jms_value;

    java_exp           exception;
    pragma EXCEPTION_INIT(java_exp, -24197);
BEGIN
    DBMS_OUTPUT.ENABLE (20000);

    -- Dequeue this message from AQ queue using DBMS_AQ package
    dbms_aq.dequeue(queue_name => 'jmsuser.jms_stream_que',
                    dequeue_options => dequeue_options,
                    message_properties => message_properties,
                    payload => message,
                    msgid => msgid);

    -- Retrieve the header 
    agent := message.get_replyto;

    dbms_output.put_line('Type: ' || message.get_type || 
                         ' UserId: ' || message.get_userid || 
                         ' AppId: ' || message.get_appid || 
                         ' GroupId: ' || message.get_groupid || 
                         ' GroupSeq: ' || message.get_groupseq);

    -- Retrieve the user properties
    dbms_output.put_line('price: ' || message.get_float_property('price'));
    dbms_output.put_line('color: ' || message.get_string_property('color'));
    IF message.get_boolean_property('import') = TRUE THEN
       dbms_output.put_line('import: Yes' );
    ELSIF message.get_boolean_property('import') = FALSE THEN
       dbms_output.put_line('import: No' );
    END IF;
    dbms_output.put_line('year: ' || message.get_int_property('year'));
    dbms_output.put_line('mileage: ' || message.get_long_property('mileage'));
    dbms_output.put_line('password: ' || message.get_byte_property('password'));

    -- Shows how to retrieve the message payload of aq$_jms_stream_message

    -- The prepare call send the content in the PL/SQL aq$_jms_stream_message object to 
    -- JAVA stored procedure(Jserv) in the form of byte array. 
    -- Passing -1 reserve a new slot within the message store of sys.aq$_jms_stream_message.
    -- The maximum number of sys.aq$_jms_stream_message type of messges to be operated at
    -- the same time within a session is 20. Calling clean_body function with parameter -1 
    -- might result a ORA-24199 error if the messages currently operated is already 20. 
    -- The user is responsible to call clean or clean_all function to clean up message store.
    id := message.prepare(-1);


    -- Assume the users know the types of data in the StreamMessage payload. 
    -- The user can use the specific read function corresponding with the data type.
    -- These functions are analogy of JMS JAVA api's. See the document for detail.
    dbms_output.put_line('Retrieve payload by Type:');

    -- Read a byte from the StreamMessage payload
    dbms_output.put_line('read_byte:' || message.read_byte(id));

    -- Read a byte array into a blob object from the StreamMessage payload
    dbms_output.put_line('read_bytes:');
    message.read_bytes(id, blob_data);
    display_blob(blob_data);

    -- Read another byte array into a blob object from the StreamMessage payload
    dbms_output.put_line('read_bytes:');
    message.read_bytes(id, blob_data);
    display_blob(blob_data);

    -- Read a char from the StreamMessage payload
    dbms_output.put_line('read_char:'|| message.read_char(id));

    -- Read a double from the StreamMessage payload
    dbms_output.put_line('read_double:'|| message.read_double(id));

    -- Read a float from the StreamMessage payload
    dbms_output.put_line('read_float:'|| message.read_float(id));

    -- Read a int from the StreamMessage payload
    dbms_output.put_line('read_int:'|| message.read_int(id));

    -- Read a long from the StreamMessage payload
    dbms_output.put_line('read_long:'|| message.read_long(id));

    -- Read a short from the StreamMessage payload
    dbms_output.put_line('read_short:'|| message.read_short(id));

    -- Read a String into a clob data from the StreamMessage payload
    dbms_output.put_line('read_string:');
    message.read_string(id, clob_data);
    display_clob(clob_data);


    -- Assume the users do not know the types of data in the StreamMessage payload. 
    -- The user can use read_object method to read the data into a sys.aq$_jms_value object
    -- These functions are analogy of JMS JAVA api's. See the document for detail.

    -- Reset the stream pointer to the begining of the message so that we can read throught 
    -- the message payload again. 
    message.reset(id);

    LOOP
      message.read_object(id, gdata);
      IF gdata IS NULL THEN
        EXIT;
      END IF;

      CASE gdata.type
        WHEN sys.dbms_jms_plsql.DATA_TYPE_BYTE      THEN 
                 dbms_output.put_line('read_object/byte:' || gdata.num_val);
        WHEN sys.dbms_jms_plsql.DATA_TYPE_SHORT     THEN 
                 dbms_output.put_line('read_object/short:' || gdata.num_val); 
        WHEN sys.dbms_jms_plsql.DATA_TYPE_INTEGER   THEN 
                 dbms_output.put_line('read_object/int:' || gdata.num_val); 
        WHEN sys.dbms_jms_plsql.DATA_TYPE_LONG      THEN 
                 dbms_output.put_line('read_object/long:' || gdata.num_val); 
        WHEN sys.dbms_jms_plsql.DATA_TYPE_FLOAT     THEN 
                 dbms_output.put_line('read_object/float:' || gdata.num_val); 
        WHEN sys.dbms_jms_plsql.DATA_TYPE_DOUBLE    THEN 
                 dbms_output.put_line('read_object/double:' || gdata.num_val); 
        WHEN sys.dbms_jms_plsql.DATA_TYPE_BOOLEAN   THEN 
                 dbms_output.put_line('read_object/boolean:' || gdata.num_val); 
        WHEN sys.dbms_jms_plsql.DATA_TYPE_CHARACTER THEN 
                 dbms_output.put_line('read_object/char:' || gdata.char_val);
        WHEN sys.dbms_jms_plsql.DATA_TYPE_STRING    THEN 
                 dbms_output.put_line('read_object/string:'); 
                 display_clob(gdata.text_val);
        WHEN sys.dbms_jms_plsql.DATA_TYPE_BYTES     THEN 
                 dbms_output.put_line('read_object/bytes:'); 
                 display_blob(gdata.bytes_val);
        ELSE dbms_output.put_line('No such data type');
      END CASE;
 
    END LOOP;

    -- Use either clean_all or clean to clean up the message store when the user 
    -- do not plan to do paylaod retrieving on this message anymore
    message.clean(id);
    -- sys.aq$_jms_stream_message.cleElan_all();

    EXCEPTION 
    WHEN java_exp THEN
      dbms_output.put_line('exception information:');
      display_exp(sys.aq$_jms_stream_message.get_exception());

END;
/

commit;

JMS MapMessage Examples

This section includes examples that illustrate enqueuing and dequeuing of a JMS MapMessage.

Example 16-6 shows how to use JMS type member functions with DBMS_AQ functions to populate and enqueue a JMS MapMessage represented as sys.aq$_jms_map_message type in the database. This message later can be dequeued by a JAVA OJMS client.

Example 16-6 Populating and Enqueuing a JMS MapMessage

set echo off
set verify off
 
connect sys
 
DROP USER jmsuser CASCADE;
 
ACCEPT password CHAR PROMPT 'Enter the password for JMSUSER: ' HIDE
 
CREATE USER jmsuser IDENTIFIED BY &password;
GRANT DBA, AQ_ADMINISTRATOR_ROLE, AQ_USER_ROLE to jmsuser;
GRANT EXECUTE ON DBMS_AQADM TO jmsuser;
GRANT EXECUTE ON DBMS_AQ TO jmsuser;
GRANT EXECUTE ON DBMS_LOB TO jmsuser;
GRANT EXECUTE ON DBMS_JMS_PLSQL TO jmsuser;
connect jmsuser/&password

SET ECHO ON
set serveroutput on

DECLARE

    id                 pls_integer;
    agent              sys.aq$_agent := sys.aq$_agent(' ', null, 0);
    message            sys.aq$_jms_map_message;
    enqueue_options    dbms_aq.enqueue_options_t;
    message_properties dbms_aq.message_properties_t;
    msgid raw(16);

    java_exp           exception;
    pragma EXCEPTION_INIT(java_exp, -24197);
BEGIN

    -- Consturct a empty map message object
    message := sys.aq$_jms_map_message.construct;

    -- Shows how to set the JMS header 
    message.set_replyto(agent);
    message.set_type('tkaqpet1');
    message.set_userid('jmsuser');
    message.set_appid('plsql_enq');
    message.set_groupid('st');
    message.set_groupseq(1);

    -- Shows how to set JMS user properties
    message.set_string_property('color', 'RED');
    message.set_int_property('year', 1999);
    message.set_float_property('price', 16999.99);
    message.set_long_property('mileage', 300000);
    message.set_boolean_property('import', True);
    message.set_byte_property('password', -127);
 
    -- Shows how to populate the message payload of aq$_jms_map_message 

    -- Passing -1 reserve a new slot within the message store of sys.aq$_jms_map_message.
    -- The maximum number of sys.aq$_jms_map_message type of messges to be operated at
    -- the same time within a session is 20. Calling clean_body function with parameter -1 
    -- might result a ORA-24199 error if the messages currently operated is already 20. 
    -- The user is responsible to call clean or clean_all function to clean up message store.
    id := message.clear_body(-1);

    -- Write data into the message paylaod. These functions are analogy of JMS JAVA api's.
    -- See the document for detail.

    -- Set a byte entry in map message payload
    message.set_byte(id, 'BYTE', 10);

    -- Set a byte array entry using RAW data in map message payload
    message.set_bytes(id, 'BYTES', UTL_RAW.XRANGE(HEXTORAW('00'), HEXTORAW('FF')));

    -- Set a byte array entry using only a portion of the RAW data in map message payload
    -- Note the offset follows JAVA convention, starting from 0
    message.set_bytes(id, 'BYTES_PART', UTL_RAW.XRANGE(HEXTORAW('00'), HEXTORAW('FF')), 0, 16);

    -- Set a char entry in map message payload
    message.set_char(id, 'CHAR', 'A');

    -- Set a double entry in map message payload
    message.set_double(id, 'DOUBLE', 9999.99);

    -- Set a float entry in map message payload
    message.set_float(id, 'FLOAT', 99.99);

    -- Set a int entry in map message payload
    message.set_int(id, 'INT', 12345);

    -- Set a long entry in map message payload
    message.set_long(id, 'LONG', 1234567);

    -- Set a short entry in map message payload
    message.set_short(id, 'SHORT', 123);

    -- Set a String entry in map message payload
    message.set_string(id, 'STRING', 'Hello World!');

    -- Flush the data from JAVA stored procedure (JServ) to PL/SQL side 
    -- Without doing this, the PL/SQL message is still empty.
    message.flush(id);

    -- Use either clean_all or clean to clean up the message store when the user 
    -- do not plan to do paylaod population on this message anymore
    sys.aq$_jms_map_message.clean_all();
    --message.clean(id);

    -- Enqueue this message into AQ queue using DBMS_AQ package
    dbms_aq.enqueue(queue_name => 'jmsuser.jms_map_que',
                    enqueue_options => enqueue_options,
                    message_properties => message_properties,
                    payload => message,
                    msgid => msgid);

END;
/

commit;

Example 16-7 illustrates how to use JMS type member functions with DBMS_AQ functions to dequeue and retrieve data from a JMS MapMessage represented as sys.aq$_jms_map_message type in the database. This message can be enqueued by a Java OJMS client.

Example 16-7 Dequeuing and Retrieving Data From a JMS MapMessage

set echo off
set verify off
 
connect sys
 
DROP USER jmsuser CASCADE;
 
ACCEPT password CHAR PROMPT 'Enter the password for JMSUSER: ' HIDE
 
CREATE USER jmsuser IDENTIFIED BY &password;
GRANT DBA, AQ_ADMINISTRATOR_ROLE, AQ_USER_ROLE to jmsuser;
GRANT EXECUTE ON DBMS_AQADM TO jmsuser;
GRANT EXECUTE ON DBMS_AQ TO jmsuser;
GRANT EXECUTE ON DBMS_LOB TO jmsuser;
GRANT EXECUTE ON DBMS_JMS_PLSQL TO jmsuser;
connect jmsuser/&password

set echo on
set serveroutput on

DECLARE

    id                 pls_integer;
    blob_data          blob;
    clob_data          clob;
    message            sys.aq$_jms_map_message;
    agent              sys.aq$_agent;
    dequeue_options    dbms_aq.dequeue_options_t;
    message_properties dbms_aq.message_properties_t;
    msgid              raw(16);
    name_arr           sys.aq$_jms_namearray;
    gdata              sys.aq$_jms_value;

    java_exp           exception;
    pragma EXCEPTION_INIT(java_exp, -24197);
BEGIN
    DBMS_OUTPUT.ENABLE (20000);

    -- Dequeue this message from AQ queue using DBMS_AQ package
    dbms_aq.dequeue(queue_name => 'jmsuser.jms_map_que',
                    dequeue_options => dequeue_options,
                    message_properties => message_properties,
                    payload => message,
                    msgid => msgid);

    -- Retrieve the header 
    agent := message.get_replyto;

    dbms_output.put_line('Type: ' || message.get_type || 
                         ' UserId: ' || message.get_userid || 
                         ' AppId: ' || message.get_appid || 
                         ' GroupId: ' || message.get_groupid || 
                         ' GroupSeq: ' || message.get_groupseq);

    -- Retrieve the user properties
    dbms_output.put_line('price: ' || message.get_float_property('price'));
    dbms_output.put_line('color: ' || message.get_string_property('color'));
    IF message.get_boolean_property('import') = TRUE THEN
       dbms_output.put_line('import: Yes' );
    ELSIF message.get_boolean_property('import') = FALSE THEN
       dbms_output.put_line('import: No' );
    END IF;
    dbms_output.put_line('year: ' || message.get_int_property('year'));
    dbms_output.put_line('mileage: ' || message.get_long_property('mileage'));
    dbms_output.put_line('password: ' || message.get_byte_property('password'));


    -- Shows how to retrieve the message payload of aq$_jms_map_message

    -- 'Prepare' sends the content in the PL/SQL aq$_jms_map_message object to 
    -- Java stored procedure(Jserv) in the form of byte array. 
    -- Passing -1 reserve a new slot within the message store of 
    -- sys.aq$_jms_map_message. The maximum number of sys.aq$_jms_map_message
    -- type of messges to be operated at the same time within a session is 20.
    -- Calling clean_body function with parameter -1 
    -- might result a ORA-24199 error if the messages currently operated is
    -- already 20. The user is responsible to call clean or clean_all function
    -- to clean up message store.
    id := message.prepare(-1);

    -- Assume the users know the names and types in the map message payload. 
    -- The user can use names to get the corresponsing values.
    -- These functions are analogous to JMS Java API's. See JMS Types chapter
    -- for detail.
    dbms_output.put_line('Retrieve payload by Name:');

    -- Get a byte entry from the map message payload
    dbms_output.put_line('get_byte:' || message.get_byte(id, 'BYTE'));

    -- Get a byte array entry from the map message payload
    dbms_output.put_line('get_bytes:');
    message.get_bytes(id, 'BYTES', blob_data);
    display_blob(blob_data);

    -- Get another byte array entry from the map message payload
    dbms_output.put_line('get_bytes:');
    message.get_bytes(id, 'BYTES_PART', blob_data);
    display_blob(blob_data);

    -- Get a char entry from the map message payload
    dbms_output.put_line('get_char:'|| message.get_char(id, 'CHAR'));

    -- get a double entry from the map message payload
    dbms_output.put_line('get_double:'|| message.get_double(id, 'DOUBLE'));

    -- Get a float entry from the map message payload
    dbms_output.put_line('get_float:'|| message.get_float(id, 'FLOAT'));

    -- Get a int entry from the map message payload
    dbms_output.put_line('get_int:'|| message.get_int(id, 'INT'));

    -- Get a long entry from the map message payload
    dbms_output.put_line('get_long:'|| message.get_long(id, 'LONG'));

    -- Get a short entry from the map message payload
    dbms_output.put_line('get_short:'|| message.get_short(id, 'SHORT'));

    -- Get a String entry from the map message payload
    dbms_output.put_line('get_string:');
    message.get_string(id, 'STRING', clob_data);
    display_clob(clob_data);

    -- Assume users do not know names and types in map message payload. 
    -- User can first retrieve the name array containing all names in the
    -- payload and iterate through the name list and get the corresponding
    -- value. These functions are analogous to JMS Java API's. 
    -- See JMS Type chapter for detail.
    dbms_output.put_line('Retrieve payload by iteration:');

    -- Get the name array from the map message payload
    name_arr := message.get_names(id);

    -- Iterate through the name array to retrieve the value for each of the name.
    FOR i IN name_arr.FIRST..name_arr.LAST LOOP

    -- Test if a name exist in the map message payload
    -- (It is not necessary in this case, just a demostration on how to use it)
      IF message.item_exists(id, name_arr(i)) THEN
        dbms_output.put_line('item exists:'||name_arr(i));

    -- Because we do not know the type of entry, we must use sys.aq$_jms_value 
    -- type object for the data returned 
       message.get_object(id, name_arr(i), gdata);
       IF gdata IS NOT NULL THEN
        CASE gdata.type
        WHEN   sys.dbms_jms_plsql.DATA_TYPE_BYTE
          THEN dbms_output.put_line('get_object/byte:' || gdata.num_val);
        WHEN   sys.dbms_jms_plsql.DATA_TYPE_SHORT
          THEN dbms_output.put_line('get_object/short:' || gdata.num_val); 
        WHEN   sys.dbms_jms_plsql.DATA_TYPE_INTEGER
          THEN dbms_output.put_line('get_object/int:' || gdata.num_val); 
        WHEN   sys.dbms_jms_plsql.DATA_TYPE_LONG
          THEN dbms_output.put_line('get_object/long:' || gdata.num_val); 
        WHEN   sys.dbms_jms_plsql.DATA_TYPE_FLOAT
          THEN dbms_output.put_line('get_object/float:' || gdata.num_val); 
        WHEN   sys.dbms_jms_plsql.DATA_TYPE_DOUBLE
          THEN dbms_output.put_line('get_object/double:' || gdata.num_val); 
        WHEN   sys.dbms_jms_plsql.DATA_TYPE_BOOLEAN
          THEN dbms_output.put_line('get_object/boolean:' || gdata.num_val); 
        WHEN   sys.dbms_jms_plsql.DATA_TYPE_CHARACTER 
          THEN dbms_output.put_line('get_object/char:' || gdata.char_val);
        WHEN   sys.dbms_jms_plsql.DATA_TYPE_STRING
          THEN dbms_output.put_line('get_object/string:'); 
               display_clob(gdata.text_val);
        WHEN sys.dbms_jms_plsql.DATA_TYPE_BYTES
        THEN 
             dbms_output.put_line('get_object/bytes:'); 
             display_blob(gdata.bytes_val);
          ELSE dbms_output.put_line('No such data type');
          END CASE;
        END IF;
      ELSE
        dbms_output.put_line('item not exists:'||name_arr(i));
      END IF;
 
    END LOOP;


    -- Use either clean_all or clean to clean up the message store when the user 
    -- do not plan to do paylaod population on this message anymore
    message.clean(id);
    -- sys.aq$_jms_map_message.clean_all();

    EXCEPTION 
    WHEN java_exp THEN
      dbms_output.put_line('exception information:');
      display_exp(sys.aq$_jms_stream_message.get_exception());

END;
/

commit;

More Oracle Streams Advanced Queuing JMS Examples

The sample program in Example 16-8 enqueues a large TextMessage (along with JMS user properties) in an Oracle Streams Advanced Queuing queue created through the OJMS administrative interfaces to hold JMS TEXT messages. Both the TextMessage and BytesMessage enqueued in this example can be dequeued using OJMS Java clients.

Example 16-8 Enqueuing a Large TextMessage

DECLARE 

    text        varchar2(32767); 
    agent       sys.aq$_agent   := sys.aq$_agent(' ', null, 0); 
    message     sys.aq$_jms_text_message; 

    enqueue_options    dbms_aq.enqueue_options_t; 
    message_properties dbms_aq.message_properties_t; 
    msgid               raw(16); 

BEGIN 

    message := sys.aq$_jms_text_message.construct; 

    message.set_replyto(agent); 
    message.set_type('tkaqpet2'); 
    message.set_userid('jmsuser'); 
    message.set_appid('plsql_enq'); 
    message.set_groupid('st'); 
    message.set_groupseq(1); 

    message.set_boolean_property('import', True); 
    message.set_string_property('color', 'RED'); 
    message.set_short_property('year', 1999); 
    message.set_long_property('mileage', 300000); 
    message.set_double_property('price', 16999.99); 
    message.set_byte_property('password', 127); 

    FOR i IN 1..500 LOOP 
        text := CONCAT (text, '1234567890'); 
    END LOOP; 

    message.set_text(text); 

    dbms_aq.enqueue(queue_name => 'jmsuser.jms_text_t1', 
                       enqueue_options => enqueue_options, 
                       message_properties => message_properties, 
                       payload => message, 
                       msgid => msgid); 

END; 

The sample program in Example 16-9 enqueues a large BytesMessage.

Example 16-9 Enqueuing a Large BytesMessage

DECLARE 

    text        VARCHAR2(32767); 
    bytes       RAW(32767); 
    agent       sys.aq$_agent   := sys.aq$_agent(' ', null, 0); 
    message     sys.aq$_jms_bytes_message; 
    body        BLOB; 
    position    INT; 

    enqueue_options    dbms_aq.enqueue_options_t; 
    message_properties dbms_aq.message_properties_t; 
    msgid raw(16); 

BEGIN 

    message := sys.aq$_jms_bytes_message.construct; 

    message.set_replyto(agent); 
    message.set_type('tkaqper4'); 
    message.set_userid('jmsuser'); 
    message.set_appid('plsql_enq_raw'); 
    message.set_groupid('st'); 
    message.set_groupseq(1); 

    message.set_boolean_property('import', True); 
    message.set_string_property('color', 'RED'); 
    message.set_short_property('year', 1999); 
    message.set_long_property('mileage', 300000); 
    message.set_double_property('price', 16999.99); 

--  prepare a huge payload into a blob 

    FOR i IN 1..1000 LOOP 
        text := CONCAT (text, '0123456789ABCDEF'); 
    END LOOP; 

    bytes := HEXTORAW(text); 

    dbms_lob.createtemporary(lob_loc => body, cache => TRUE); 
    dbms_lob.open (body, DBMS_LOB.LOB_READWRITE); 
    position := 1 ; 
    FOR i IN 1..10 LOOP 
        dbms_lob.write ( lob_loc => body, 
                amount => FLOOR((LENGTH(bytes)+1)/2), 
                offset => position, 
                buffer => bytes); 
        position := position + FLOOR((LENGTH(bytes)+1)/2) ; 
    END LOOP; 

-- end of the preparation 

    message.set_bytes(body); 
    dbms_aq.enqueue(queue_name => 'jmsuser.jms_bytes_t1', 
                       enqueue_options => enqueue_options, 
                       message_properties => message_properties, 
                       payload => message, 
                       msgid => msgid); 

    dbms_lob.freetemporary(lob_loc => body); 
END; 
PK$PK-AOEBPS/aq_admin.htm Oracle Streams Advanced Queuing Administrative Interface

8 Oracle Streams Advanced Queuing Administrative Interface

This chapter describes the Oracle Streams Advanced Queuing (AQ) administrative interface.

This chapter contains these topics:


See Also:


Managing Queue Tables

This section contains these topics:

Creating a Queue Table

DBMS_AQADM.CREATE_QUEUE_TABLE(
   queue_table          IN      VARCHAR2,
   queue_payload_type   IN      VARCHAR2,
   [storage_clause      IN      VARCHAR2        DEFAULT NULL,]
   sort_list            IN      VARCHAR2        DEFAULT NULL,
   multiple_consumers   IN      BOOLEAN         DEFAULT FALSE,
   message_grouping     IN      BINARY_INTEGER  DEFAULT NONE,
   comment              IN      VARCHAR2        DEFAULT NULL,
   primary_instance     IN      BINARY_INTEGER  DEFAULT 0, 
   secondary_instance   IN      BINARY_INTEGER  DEFAULT 0,
   compatible           IN      VARCHAR2        DEFAULT NULL,
   secure               IN      BOOLEAN         DEFAULT FALSE);

This procedure creates a queue table for messages of a predefined type. It has the following required and optional parameters:

ParameterDescription
queue_tableThis required parameter specifies the queue table name.

Mixed case (upper and lower case together) queue table names are supported if database compatibility is 10.0, but the names must be enclosed in double quote marks. So abc.efg means the schema is ABC and the name is EFG, but "abc"."efg" means the schema is abc and the name is efg.

Queue table names must not be longer than 24 characters. If you attempt to create a queue table with a longer name, error ORA-24019 results.

queue_payload_typeThis required parameter specifies the payload type as RAW or an object type. See "Payload Type" for more information.
storage_clauseThis optional parameter specifies a tablespace for the queue table. See "Storage Clause" for more information.
sort_listThis optional parameter specifies one or two columns to be used as sort keys in ascending order. It has the format sort_column1,sort_column2. See "Sort Key" for more information.
multiple_consumersThis optional parameter specifies the queue table as single-consumer or multiconsumer. The default FALSE means queues created in the table can have only one consumer for each message. TRUE means queues created in the table can have multiple consumers for each message.
message_groupingThis optional parameter specifies whether messages are grouped or not. The default NONE means each message is treated individually. TRANSACTIONAL means all messages enqueued in one transaction are considered part of the same group and can be dequeued as a group of related messages.
commentThis optional parameter is a user-specified description of the queue table. This user comment is added to the queue catalog.
primary_instanceThis optional parameter specifies the primary owner of the queue table. Queue monitor scheduling and propagation for the queues in the queue table are done in this instance. The default value 0 means queue monitor scheduling and propagation is done in any available instance.

You can specify and modify this parameter only if compatible is 8.1 or higher.

secondary_instanceThis optional parameter specifies the owner of the queue table if the primary instance is not available. The default value 0 means that the queue table will fail over to any available instance.

You can specify and modify this parameter only if primary_instance is also specified and compatible is 8.1 or higher.

compatibleThis optional parameter specifies the lowest database version with which the queue table is compatible. The possible values are 8.0, 8.1, and 10.0. If the database is in 10.1-compatible mode, then the default value is 10.0. If the database is in 8.1-compatible or 9.2-compatible mode, then the default value is 8.1. If the database is in 8.0-compatible mode, then the default value is 8.0. The 8.0 value is deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2).

For more information on compatibility, see "Oracle Streams Advanced Queuing Compatibility Parameters".

secureThis optional parameter must be set to TRUE if you want to use the queue table for secure queues. Secure queues are queues for which AQ agents must be associated explicitly with one or more database users who can perform queue operations, such as enqueue and dequeue. The owner of a secure queue can perform all queue operations on the queue, but other users cannot unless they are configured as secure queue users

Payload Type

To specify the payload type as an object type, you must define the object type.


Note:

If you have created synonyms on object types, then you cannot use them in DBMS_AQADM.CREATE_QUEUE_TABLE. Error ORA-24015 results.

CLOB, BLOB, and BFILE objects are valid in an Oracle Streams Advanced Queuing message. You can propagate these object types using Oracle Streams Advanced Queuing propagation with Oracle software since Oracle8i release 8.1.x. To enqueue an object type that has a LOB, you must first set the LOB_attribute to EMPTY_BLOB() and perform the enqueue. You can then select the LOB locator that was generated from the queue table's view and use the standard LOB operations.


Note:

Payloads containing LOBs require users to grant explicit Select, Insert and Update privileges on the queue table for doing enqueues and dequeues.

Storage Clause

The storage_clause argument can take any text that can be used in a standard CREATE TABLE storage_clause argument.

Once you pick the tablespace, any index-organized table (IOT) or index created for that queue table goes to the specified tablespace. You do not currently have a choice to split them between different tablespaces.


Note:

The qmon processes in the 11g Release 2 (11.2) perform auto-coalesce of the the dequeue IOT, history IOT, and the time manager IOT. It is not required to manually coalesce AQ IOTs. However, it can be performed as a workaround if a performance degradation is observed.

If you choose to create the queue table in a locally managed tablespace or with freelist groups > 1, then Queue Monitor Coordinator will skip the cleanup of those blocks. This can cause a decline in performance over time.

Coalesce the dequeue IOT by running

ALTER TABLE AQ$_queue_table_I COALESCE;

You can run this command while there are concurrent dequeuers and enqueuers of the queue, but these concurrent users might see a slight decline in performance while the command is running.


Sort Key

The sort_list parameter determines the order in which messages are dequeued. You cannot change the message sort order after you have created the queue table. Your choices are:

  • ENQ_TIME

  • ENQ_TIME,PRIORITY

  • PRIORITY

  • PRIORITY,ENQ_TIME

  • PRIORITY,COMMIT_TIME

  • COMMIT_TIME

The COMMIT_TIME choice is a new feature in Oracle Streams Advanced Queuing 10g Release 2 (10.2). If it is specified, then any queue that uses the queue table is a commit-time queue, and Oracle Streams Advanced Queuing computes an approximate CSCN for each enqueued message when its transaction commits.

If you specify COMMIT_TIME as the sort key, then you must also specify the following:

  • multiple_consumers = TRUE

  • message_grouping = TRANSACTIONAL

  • compatible = 8.1 or higher

Commit-time ordering is useful when transactions are interdependent or when browsing the messages in a queue must yield consistent results.

Other Tables and Views

The following objects are created at table creation time:

  • AQ$_queue_table_name, a read-only view which is used by Oracle Streams Advanced Queuing applications for querying queue data

  • AQ$_queue_table_name_E, the default exception queue associated with the queue table

  • AQ$_queue_table_name_I, an index or an index-organized table (IOT) in the case of multiple consumer queues for dequeue operations

  • AQ$_queue_table_name_T, an index for the queue monitor operations

The following objects are created only for 8.1-compatible multiconsumer queue tables:

  • AQ$_queue_table_name_S, a table for storing information about subscribers

  • AQ$_queue_table_name_H, an index organized table (IOT) for storing dequeue history data

  • AQ$_queue_table_name_L, dequeue log table, used for storing message identifiers of committed dequeue operations on the queue


Note:

Oracle Streams Advanced Queuing does not support the use of triggers on these internal AQ queue tables.

If you do not specify a schema, then you default to the user's schema.

If GLOBAL_TOPIC_ENABLED = TRUE when a queue table is created, then a corresponding Lightweight Directory Access Protocol (LDAP) entry is also created.

If the queue type is ANYDATA, then a buffered queue and two additional objects are created. The buffered queue stores logical change records created by a capture process. The logical change records are staged in a memory buffer associated with the queue; they are not ordinarily written to disk.

If they have been staged in the buffer for a period of time without being dequeued, or if there is not enough space in memory to hold all of the captured events, then they are spilled to:

  • AQ$_queue_table_name_P, a table for storing the captured events that spill from memory

  • AQ$_queue_table_name_D, a table for storing information about the propagations and apply processes that are eligible for processing each event


See Also:

Chapter 3, "Streams Staging and Propagation" in Oracle Streams Concepts and Administration

Examples

The following examples assume you are in a SQL*Plus testing environment. In Example 8-1, you create users in preparation for the other examples in this chapter. For this example, you must connect as a user with administrative privileges. For most of the other examples in this chapter, you can connect as user test_adm. A few examples must be run as test with EXECUTE privileges on DBMS_AQADM.

Example 8-1 Setting Up AQ Administrative Users

CREATE USER test_adm IDENTIFIED BY test_adm DEFAULT TABLESPACE example;
GRANT DBA, CREATE ANY TYPE TO test_adm; 
GRANT EXECUTE ON DBMS_AQADM TO test_adm;
GRANT aq_administrator_role TO test_adm;
BEGIN
   DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE(
      privilege          =>    'MANAGE_ANY', 
      grantee            =>    'test_adm', 
      admin_option       =>     FALSE);
END;
/
CREATE USER test IDENTIFIED BY test;
GRANT DBA TO test; 
GRANT EXECUTE ON dbms_aq TO test;

Example 8-2 Setting Up AQ Administrative Example Types

CREATE TYPE test.message_typ AS object(
   sender_id              NUMBER,
   subject                VARCHAR2(30),
   text                   VARCHAR2(1000));
/
CREATE TYPE test.msg_table AS TABLE OF test.message_typ;
/
CREATE TYPE test.order_typ AS object(
   custno                 NUMBER,
   item                   VARCHAR2(30),
   description            VARCHAR2(1000));
/
CREATE TYPE test.lob_typ AS object(
   id                     NUMBER, 
   subject                VARCHAR2(100), 
   data                   BLOB, 
   trailer                NUMBER);
/ 

Example 8-3 Creating a Queue Table for Messages of Object Type

BEGIN
   DBMS_AQADM.CREATE_QUEUE_TABLE(
      queue_table            => 'test.obj_qtab',
      queue_payload_type     => 'test.message_typ');
END;
/

Example 8-4 Creating a Queue Table for Messages of RAW Type

BEGIN
   DBMS_AQADM.CREATE_QUEUE_TABLE( 
      queue_table            => 'test.raw_qtab', 
      queue_payload_type     => 'RAW'); 
END;
/

Example 8-5 Creating a Queue Table for Messages of LOB Type

BEGIN
   DBMS_AQADM.CREATE_QUEUE_TABLE(
      queue_table            => 'test.lob_qtab',
      queue_payload_type     => 'test.lob_typ');
END;
/

Example 8-6 Creating a Queue Table for Messages of XMLType

BEGIN
  DBMS_AQADM.CREATE_QUEUE_TABLE(
     queue_table         => 'test.xml_qtab', 
     queue_payload_type  => 'SYS.XMLType',
     multiple_consumers  => TRUE, 
     compatible          => '8.1',
     comment             => 'Overseas Shipping multiconsumer orders queue table');
END;
/

Example 8-7 Creating a Queue Table for Grouped Messages

BEGIN
   DBMS_AQADM.CREATE_QUEUE_TABLE( 
      queue_table          => 'test.group_qtab',
      queue_payload_type   => 'test.message_typ',
      message_grouping     => DBMS_AQADM.TRANSACTIONAL);
END;
/

Example 8-8 Creating Queue Tables for Prioritized Messages and Multiple Consumers

BEGIN
   DBMS_AQADM.CREATE_QUEUE_TABLE(
      queue_table            => 'test.priority_qtab', 
      queue_payload_type     => 'test.order_typ',
      sort_list              => 'PRIORITY,ENQ_TIME', 
      multiple_consumers     => TRUE);
   DBMS_AQADM.CREATE_QUEUE_TABLE(
      queue_table            => 'test.multiconsumer_qtab',
      queue_payload_type     => 'test.message_typ',
      sort_list              => 'PRIORITY,ENQ_TIME', 
      multiple_consumers     => TRUE);
END;
/

Example 8-9 Creating a Queue Table with Commit-Time Ordering

BEGIN
   DBMS_AQADM.CREATE_QUEUE_TABLE(
      queue_table            => 'test.commit_time_qtab',
      queue_payload_type     => 'test.message_typ',
      sort_list              => 'COMMIT_TIME', 
      multiple_consumers     => TRUE, 
      message_grouping       => DBMS_AQADM.TRANSACTIONAL,
      compatible             => '10.0');
END;
/

Example 8-10 Creating an 8.1-Compatible Queue Table for Multiple Consumers

BEGIN
   DBMS_AQADM.CREATE_QUEUE_TABLE(
      queue_table            => 'test.multiconsumer_81_qtab',
      queue_payload_type     => 'test.message_typ',
      multiple_consumers     =>  TRUE,
      compatible             => '8.1'); 
END;
/

Example 8-11 Creating a Queue Table in a Specified Tablespace

BEGIN
   DBMS_AQADM.CREATE_QUEUE_TABLE( 
      queue_table        => 'test.example_qtab',
      queue_payload_type => 'test.message_typ',
      storage_clause     => 'tablespace example');
END;
/

Example 8-12 Creating a Queue Table with Freelists or Freelist Groups

BEGIN 
   DBMS_AQADM.CREATE_QUEUE_TABLE( 
      queue_table            => 'test.freelist_qtab', 
      queue_payload_type     => 'RAW', 
      storage_clause         => 'STORAGE (FREELISTS 4 FREELIST GROUPS 2)',
      compatible             => '8.1');
END;
/

Altering a Queue Table

DBMS_AQADM.ALTER_QUEUE_TABLE (
   queue_table          IN   VARCHAR2, 
   comment              IN   VARCHAR2       DEFAULT NULL,
   primary_instance     IN   BINARY_INTEGER DEFAULT NULL, 
   secondary_instance   IN   BINARY_INTEGER DEFAULT NULL);

This procedure alters the existing properties of a queue table.

ParameterDescription
queue_tableThis required parameter specifies the queue table name.
commentThis optional parameter is a user-specified description of the queue table. This user comment is added to the queue catalog.
primary_instanceThis optional parameter specifies the primary owner of the queue table. Queue monitor scheduling and propagation for the queues in the queue table are done in this instance.

You can specify and modify this parameter only if compatible is 8.1 or higher.

secondary_instanceThis optional parameter specifies the owner of the queue table if the primary instance is not available.

You can specify and modify this parameter only if primary_instance is also specified and compatible is 8.1 or higher.



Note:

In general, DDL statements are not supported on queue tables and may even render them inoperable. For example, issuing an ALTER TABLE ... SHRINK statement against a queue table results in an internal error, and all subsequent attempts to use the queue table will also result in errors. Oracle recommends that you not use DDL statements on queue tables.

If GLOBAL_TOPIC_ENABLED = TRUE when a queue table is modified, then a corresponding LDAP entry is also altered.

Example 8-13 Altering a Queue Table by Changing the Primary and Secondary Instances

BEGIN
   DBMS_AQADM.ALTER_QUEUE_TABLE( 
      queue_table          => 'test.obj_qtab', 
      primary_instance     => 3, 
      secondary_instance   => 2);
END;
/

Example 8-14 Altering a Queue Table by Changing the Comment

BEGIN
   DBMS_AQADM.ALTER_QUEUE_TABLE( 
      queue_table          => 'test.obj_qtab', 
      comment              => 'revised usage for queue table');
END;
/

Dropping a Queue Table

DBMS_AQADM.DROP_QUEUE_TABLE(
   queue_table       IN    VARCHAR2,
   force             IN    BOOLEAN DEFAULT FALSE,

This procedure drops an existing queue table. You must stop and drop all the queues in a queue table before the queue table can be dropped. You must do this explicitly if force is set to FALSE. If force is set to TRUE, then all queues in the queue table and their associated propagation schedules are dropped automatically.

If GLOBAL_TOPIC_ENABLED = TRUE when a queue table is dropped, then a corresponding LDAP entry is also dropped.

Example 8-15 Dropping a Queue Table

BEGIN
   DBMS_AQADM.DROP_QUEUE_TABLE(
      queue_table        => 'test.obj_qtab');
END;
/

Example 8-16 Dropping a Queue Table with force Option

BEGIN
   DBMS_AQADM.DROP_QUEUE_TABLE( 
      queue_table        => 'test.raw_qtab', 
      force              => TRUE); 
END;
/

Purging a Queue Table

DBMS_AQADM.PURGE_QUEUE_TABLE(
   queue_table        IN   VARCHAR2,
   purge_condition    IN   VARCHAR2,
   purge_options      IN   aq$_purge_options_t);

This procedure purges messages from a queue table. It has the following parameters:

ParameterDescription
queue_tableThis required parameter specifies the queue table name.
purge_conditionThe purge condition must be in the format of a SQL WHERE clause, and it is case-sensitive. The condition is based on the columns of aq$queue_table_name view. Each column name in the purge condition must be prefixed with "qtview."

All purge conditions supported for persistent messages are also supported for buffered messages.

To purge all queues in a queue table, set purge_condition to either NULL (a bare null word, no quotes) or '' (two single quotes).

purge_optionsType aq$_purge_options_t contains a block parameter. If block is TRUE, then an exclusive lock on all the queues in the queue table is held while purging the queue table. This will cause concurrent enqueuers and dequeuers to block while the queue table is purged. The purge call always succeeds if block is TRUE. The default for block is FALSE. This will not block enqueuers and dequeuers, but it can cause the purge to fail with an error during high concurrency times.

Type aq$_purge_options_t also contains a delivery_mode parameter. If it is the default PERSISTENT, then only persistent messages are purged. If it is set to BUFFERED, then only buffered messages are purged. If it is set to PERSISTENT_OR_BUFFERED, then both types are purged.


A trace file is generated in the udump destination when you run this procedure. It details what the procedure is doing. The procedure commits after it has processed all the messages.


See Also:

"DBMS_AQADM" in Oracle Database PL/SQL Packages and Types Reference for more information on DBMS_AQADM.PURGE_QUEUE_TABLE

Example 8-17 Purging All Messages in a Queue Table

DECLARE
po dbms_aqadm.aq$_purge_options_t;
BEGIN
   po.block := FALSE;
   DBMS_AQADM.PURGE_QUEUE_TABLE(
     queue_table     => 'test.obj_qtab',
     purge_condition => NULL,
     purge_options   => po);
END;
/

Example 8-18 Purging All Messages in a Named Queue

DECLARE
po dbms_aqadm.aq$_purge_options_t;
BEGIN
   po.block := TRUE;
   DBMS_AQADM.PURGE_QUEUE_TABLE(
     queue_table     => 'test.obj_qtab',
     purge_condition => 'qtview.queue = ''TEST.OBJ_QUEUE''',
     purge_options   => po);
END;
/

Example 8-19 Purging All PROCESSED Messages in a Named Queue

DECLARE
po dbms_aqadm.aq$_purge_options_t;
BEGIN
   po.block := TRUE;
   DBMS_AQADM.PURGE_QUEUE_TABLE(
     queue_table     => 'test.obj_qtab',
     purge_condition => 'qtview.queue = ''TEST.OBJ_QUEUE'' 
                         and qtview.msg_state = ''PROCESSED''',
     purge_options   => po);
END;
/

Example 8-20 Purging All Messages in a Named Queue and for a Named Consumer

DECLARE
po dbms_aqadm.aq$_purge_options_t;
BEGIN
   po.block := TRUE;
   DBMS_AQADM.PURGE_QUEUE_TABLE(
     queue_table     => 'test.multiconsumer_81_qtab',
     purge_condition => 'qtview.queue = ''TEST.MULTICONSUMER_81_QUEUE'' 
                         and qtview.consumer_name = ''PAYROLL_APP''',
     purge_options   => po);
END;
/

Note:

Some purge conditions, such as consumer_name in Example 8-20 and sender_name in Example 8-21, are supported only in 8.1-compatible queue tables. For more information, see Table 9-1, "AQ$Queue_Table_Name View".

Example 8-21 Purging All Messages from a Named Sender

DECLARE
po dbms_aqadm.aq$_purge_options_t;
BEGIN
   po.block := TRUE;
   DBMS_AQADM.PURGE_QUEUE_TABLE(
     queue_table     => 'test.multiconsumer_81_qtab',
     purge_condition => 'qtview.sender_name = ''TEST.OBJ_QUEUE''',
     purge_options   => po);
END;
/

Migrating a Queue Table

DBMS_AQADM.MIGRATE_QUEUE_TABLE(
   queue_table   IN   VARCHAR2,
   compatible    IN   VARCHAR2);

This procedure migrates a queue table from 8.0, 8.1, or 10.0 to 8.0, 8.1, or 10.0. Only the owner of the queue table can migrate it.


Caution:

This procedure requires that the EXECUTE privilege on DBMS_AQADM be granted to the queue table owner, who is probably an ordinary queue user. If you do not want ordinary queue users to be able to create and drop queues and queue tables, add and delete subscribers, and so forth, then you must revoke the EXECUTE privilege as soon as the migration is done.


Note:

Queues created in a queue table with compatible set to 8.0 (referred to in this guide as 8.0-style queues) are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2). Oracle recommends that any new queues you create be 8.1-style or newer and that you migrate existing 8.0-style queues at your earliest convenience.

If a schema was created by an import of an export dump from a lower release or has Oracle Streams Advanced Queuing queues upgraded from a lower release, then attempts to drop it with DROP USER CASCADE will fail with ORA-24005. To drop such schemas:

  1. Event 10851 should be set to level 1.

  2. Drop all tables of the form AQ$_queue_table_name_NR from the schema.

  3. Turn off event 10851.

  4. Drop the schema.

Example 8-22 Upgrading a Queue Table from 8.1-Compatible to 10.0-Compatible

BEGIN
   DBMS_AQADM.MIGRATE_QUEUE_TABLE (
           queue_table    => 'test.xml_qtab', 
           compatible     => '10.0');
END;
/

Managing Queues

This section contains these topics:

Creating a Queue

DBMS_AQADM.CREATE_QUEUE(
   queue_name          IN       VARCHAR2,
   queue_table         IN       VARCHAR2,
   queue_type          IN       BINARY_INTEGER DEFAULT NORMAL_QUEUE,
   max_retries         IN       NUMBER         DEFAULT NULL,
   retry_delay         IN       NUMBER         DEFAULT 0,
   retention_time      IN       NUMBER         DEFAULT 0,
   dependency_tracking IN       BOOLEAN        DEFAULT FALSE,
   comment             IN       VARCHAR2       DEFAULT NULL,

This procedure creates a queue. It has the following parameters:

ParameterDescription
queue_nameThis required parameter specifies the name of the new queue.

Mixed case (upper and lower case together) queue names are supported if database compatibility is 10.0, but the names must be enclosed in double quote marks. So abc.efg means the schema is ABC and the name is EFG, but "abc"."efg" means the schema is abc and the name is efg.

User-generated queue names must not be longer than 24 characters. If you attempt to create a queue with a longer name, error ORA-24019 results. Queue names generated by Oracle Streams Advanced Queuing, such as those listed in "Other Tables and Views", cannot be longer than 30 characters.

queue_tableThis required parameter specifies the queue table in which the queue is created.
queue_typeThis parameter specifies what type of queue to create. The default NORMAL_QUEUE produces a normal queue. EXCEPTION_QUEUE produces an exception queue.
max_retriesThis parameter limits the number of times a dequeue with the REMOVE mode can be attempted on a message. The maximum value of max_retries is 2**31 -1.
retry_delayThis parameter specifies the number of seconds after which this message is scheduled for processing again after an application rollback. The default is 0, which means the message can be retried as soon as possible. This parameter has no effect if max_retries is set to 0.

This parameter is supported for single-consumer queues and 8.1-style or higher multiconsumer queues but not for 8.0-style multiconsumer queues, which are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2).

retention_timeThis parameter specifies the number of seconds a message is retained in the queue table after being dequeued from the queue. When retention_time expires, messages are removed by the time manager process. INFINITE means the message is retained forever. The default is 0, no retention.
dependency_trackingThis parameter is reserved for future use. FALSE is the default. TRUE is not permitted in this release.
commentThis optional parameter is a user-specified description of the queue. This user comment is added to the queue catalog.

All queue names must be unique within a schema. Once a queue is created with CREATE_QUEUE, it can be enabled by calling START_QUEUE. By default, the queue is created with both enqueue and dequeue disabled. To view retained messages, you can either dequeue by message ID or use SQL. If GLOBAL_TOPIC_ENABLED = TRUE when a queue is created, then a corresponding LDAP entry is also created.

The following examples (Example 8-23 through Example 8-30) use data structures created in Example 8-1 through Example 8-12.

Example 8-23 Creating a Queue for Messages of Object Type

BEGIN
   DBMS_AQADM.CREATE_QUEUE(
      queue_name         =>  'test.obj_queue',
      queue_table        =>  'test.obj_qtab');
END;
/

Example 8-24 Creating a Queue for Messages of RAW Type

BEGIN
   DBMS_AQADM.CREATE_QUEUE( 
      queue_name          => 'test.raw_queue', 
      queue_table         => 'test.raw_qtab'); 
END;
/

Example 8-25 Creating a Queue for Messages of LOB Type

BEGIN
   DBMS_AQADM.CREATE_QUEUE( 
      queue_name          => 'test.lob_queue', 
      queue_table         => 'test.lob_qtab'); 
END;
/

Example 8-26 Creating a Queue for Grouped Messages

BEGIN
   DBMS_AQADM.CREATE_QUEUE( 
      queue_name          => 'test.group_queue', 
      queue_table         => 'test.group_qtab'); 
END;
/

Example 8-27 Creating a Queue for Prioritized Messages

BEGIN
   DBMS_AQADM.CREATE_QUEUE(
      queue_name         => 'test.priority_queue', 
      queue_table        => 'test.priority_qtab');
END;
/

Example 8-28 Creating a Queue for Prioritized Messages and Multiple Consumers

BEGIN
   DBMS_AQADM.CREATE_QUEUE(
      queue_name         => 'test.multiconsumer_queue',
      queue_table        => 'test.multiconsumer_qtab');
END;
/

Example 8-29 Creating a Queue to Demonstrate Propagation

BEGIN
   DBMS_AQADM.CREATE_QUEUE(
      queue_name        => 'test.another_queue',
      queue_table       => 'test.multiconsumer_qtab');
END;
/

Example 8-30 Creating an 8.1-Style Queue for Multiple Consumers

BEGIN
   DBMS_AQADM.CREATE_QUEUE( 
      queue_name         => 'test.multiconsumer_81_queue', 
      queue_table        => 'test.multiconsumer_81_qtab'); 
END;
/

Altering a Queue

DBMS_AQADM.ALTER_QUEUE(
   queue_name        IN    VARCHAR2,
   max_retries       IN    NUMBER   DEFAULT NULL,
   retry_delay       IN    NUMBER   DEFAULT NULL,
   retention_time    IN    NUMBER   DEFAULT NULL,
   comment           IN    VARCHAR2 DEFAULT NULL);

This procedure alters existing properties of a queue.

Only max_retries, comment, retry_delay, and retention_time can be altered. To view retained messages, you can either dequeue by message ID or use SQL. If GLOBAL_TOPIC_ENABLED = TRUE when a queue is modified, then a corresponding LDAP entry is also altered.

Example 8-31 changes retention time, saving messages for 1 day after dequeuing.

Example 8-31 Altering a Queue by Changing Retention Time

BEGIN
   DBMS_AQADM.ALTER_QUEUE( 
      queue_name        => 'test.another_queue', 
      retention_time    => 86400);
END;
/

Starting a Queue

DBMS_AQADM.START_QUEUE( 
   queue_name      IN     VARCHAR2,
   enqueue         IN     BOOLEAN DEFAULT TRUE,
   dequeue         IN     BOOLEAN DEFAULT TRUE);

This procedure enables the specified queue for enqueuing or dequeuing.

After creating a queue, the administrator must use START_QUEUE to enable the queue. The default is to enable it for both enqueue and dequeue. Only dequeue operations are allowed on an exception queue. This operation takes effect when the call completes and does not have any transactional characteristics.

Example 8-32 Starting a Queue with Both Enqueue and Dequeue Enabled

BEGIN
   DBMS_AQADM.START_QUEUE (
      queue_name         => 'test.obj_queue');
END;
/

Example 8-33 Starting a Queue for Dequeue Only

BEGIN
   DBMS_AQADM.START_QUEUE( 
      queue_name         => 'test.raw_queue', 
      dequeue            => TRUE, 
      enqueue            => FALSE); 
END;
/

Stopping a Queue

DBMS_AQADM.STOP_QUEUE(
   queue_name      IN   VARCHAR2,
   enqueue         IN   BOOLEAN DEFAULT TRUE,
   dequeue         IN   BOOLEAN DEFAULT TRUE,
   wait            IN   BOOLEAN DEFAULT TRUE);

This procedure disables enqueuing, dequeuing, or both on the specified queue.

By default, this call disables both enqueue and dequeue. A queue cannot be stopped if there are outstanding transactions against the queue. This operation takes effect when the call completes and does not have any transactional characteristics.

Example 8-34 Stopping a Queue

BEGIN
   DBMS_AQADM.STOP_QUEUE(
      queue_name        => 'test.obj_queue');
END;
/

Dropping a Queue

DBMS_AQADM.DROP_QUEUE(
   queue_name        IN    VARCHAR2,

This procedure drops an existing queue. DROP_QUEUE is not allowed unless STOP_QUEUE has been called to disable the queue for both enqueuing and dequeuing. All the queue data is deleted as part of the drop operation.

If GLOBAL_TOPIC_ENABLED = TRUE when a queue is dropped, then a corresponding LDAP entry is also dropped.

Example 8-35 Dropping a Standard Queue

BEGIN
   DBMS_AQADM.DROP_QUEUE(
      queue_name         => 'test.obj_queue');
END;
/

Managing Transformations

Transformations change the format of a message, so that a message created by one application can be understood by another application. You can use transformations on both persistent and buffered messages.

This section contains these topics:

Creating a Transformation

DBMS_TRANSFORM.CREATE_TRANSFORMATION(
    schema               VARCHAR2(30),
    name                 VARCHAR2(30),
    from_schema          VARCHAR2(30),
    from_type            VARCHAR2(30),
    to_schema            VARCHAR2(30),
    to_type              VARCHAR2(30),
    transformation       VARCHAR2(4000)); 

This procedure creates a message format transformation. The transformation must be a SQL function with input type from_type, returning an object of type to_type. It can also be a SQL expression of type to_type, referring to from_type. All references to from_type must be of the form source.user_data.

You must be granted EXECUTE privilege on dbms_transform to use this feature. This privilege is included in the AQ_ADMINISTRATOR_ROLE.


See Also:

"Oracle Streams Advanced Queuing Security" for more information on administrator and user roles

You must also have EXECUTE privilege on the user-defined types that are the source and destination types of the transformation, and have EXECUTE privileges on any PL/SQL function being used in the transformation function. The transformation cannot write the database state (that is, perform DML operations) or commit or rollback the current transaction.

Example 8-36 Creating a Transformation

BEGIN
   DBMS_TRANSFORM.CREATE_TRANSFORMATION(
      schema         => 'test',
      name           => 'message_order_transform', 
      from_schema    => 'test',
      from_type      => 'message_typ', 
      to_schema      => 'test',
      to_type        => 'order_typ',
      transformation => 'test.order_typ(
         source.user_data.sender_id,
         source.user_data.subject,
         source.user_data.text)');
END;
/

Modifying a Transformation

DBMS_TRANSFORM.MODIFY_TRANSFORMATION(
    schema            VARCHAR2(30),
    name              VARCHAR2(30),
    attribute_number  INTEGER,
    transformation    VARCHAR2(4000));

This procedure changes the transformation function and specifies transformations for each attribute of the target type. If the attribute number 0 is specified, then the transformation expression singularly defines the transformation from the source to target types.

All references to from_type must be of the form source.user_data. All references to the attributes of the source type must be prefixed by source.user_data</code>.

You must be granted EXECUTE privileges on dbms_transform to use this feature. You must also have EXECUTE privileges on the user-defined types that are the source and destination types of the transformation, and have EXECUTE privileges on any PL/SQL function being used in the transformation function.

Dropping a Transformation

DBMS_TRANSFORM.DROP_TRANSFORMATION (
    schema      VARCHAR2(30),
    name        VARCHAR2(30));

This procedure drops a transformation.

You must be granted EXECUTE privileges on dbms_transform to use this feature. You must also have EXECUTE privileges on the user-defined types that are the source and destination types of the transformation, and have EXECUTE privileges on any PL/SQL function being used in the transformation function.

Granting and Revoking Privileges

This section contains these topics:

Granting Oracle Streams Advanced Queuing System Privileges

DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE(
   privilege         IN    VARCHAR2,
   grantee           IN    VARCHAR2,
   admin_option      IN    BOOLEAN := FALSE);

This procedure grants Oracle Streams Advanced Queuing system privileges to users and roles. The privileges are ENQUEUE_ANY, DEQUEUE_ANY, MANAGE_ANY. Initially, only SYS and SYSTEM can use this procedure successfully.

Users granted the ENQUEUE_ANY privilege are allowed to enqueue messages to any queues in the database. Users granted the DEQUEUE_ANY privilege are allowed to dequeue messages from any queues in the database. Users granted the MANAGE_ANY privilege are allowed to run DBMS_AQADM calls on any schemas in the database.

Example 8-37 Granting AQ System Privileges

BEGIN
   DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE(
      privilege          =>    'ENQUEUE_ANY', 
      grantee            =>    'test', 
      admin_option       =>     FALSE);
   DBMS_AQADM.GRANT_SYSTEM_PRIVILEGE(
      privilege          =>     'DEQUEUE_ANY', 
      grantee            =>     'test', 
      admin_option       =>      FALSE);
END;
/

Revoking Oracle Streams Advanced Queuing System Privileges

DBMS_AQADM.REVOKE_SYSTEM_PRIVILEGE(
   privilege         IN   VARCHAR2,
   grantee           IN   VARCHAR2);

This procedure revokes Oracle Streams Advanced Queuing system privileges from users and roles. The privileges are ENQUEUE_ANY, DEQUEUE_ANY and MANAGE_ANY. The ADMIN option for a system privilege cannot be selectively revoked.

Users granted the ENQUEUE_ANY privilege are allowed to enqueue messages to any queues in the database. Users granted the DEQUEUE_ANY privilege are allowed to dequeue messages from any queues in the database. Users granted the MANAGE_ANY privilege are allowed to run DBMS_AQADM calls on any schemas in the database.

Example 8-38 Revoking AQ System Privileges

BEGIN
   DBMS_AQADM.REVOKE_SYSTEM_PRIVILEGE(
      privilege          =>    'DEQUEUE_ANY', 
      grantee            =>    'test');
END;
/

Granting Queue Privileges

DBMS_AQADM.GRANT_QUEUE_PRIVILEGE(
   privilege        IN    VARCHAR2,
   queue_name       IN    VARCHAR2,
   grantee          IN    VARCHAR2,
   grant_option     IN    BOOLEAN := FALSE);

This procedure grants privileges on a queue to users and roles. The privileges are ENQUEUE, DEQUEUE, or ALL. Initially, only the queue table owner can use this procedure to grant privileges on the queues.


Caution:

This procedure requires that EXECUTE privileges on DBMS_AQADM be granted to the queue table owner, who is probably an ordinary queue user. If you do not want ordinary queue users to be able to create and drop queues and queue tables, add and delete subscribers, and so forth, then you must revoke the EXECUTE privilege as soon as the initial GRANT_QUEUE_PRIVILEGE is done.

Example 8-39 Granting Queue Privilege

BEGIN
   DBMS_AQADM.GRANT_QUEUE_PRIVILEGE (
      privilege     =>     'ALL', 
      queue_name    =>     'test.multiconsumer_81_queue',
      grantee       =>     'test_adm', 
      grant_option  =>      TRUE);
END;
/

Revoking Queue Privileges

DBMS_AQADM.REVOKE_QUEUE_PRIVILEGE (
   privilege         IN      VARCHAR2,
   queue_name        IN      VARCHAR2,
   grantee           IN      VARCHAR2);

This procedure revokes privileges on a queue from users and roles. The privileges are ENQUEUE or DEQUEUE.

To revoke a privilege, the revoker must be the original grantor of the privilege. The privileges propagated through the GRANT option are revoked if the grantor's privileges are revoked.

You can revoke the dequeue right of a grantee on a specific queue, leaving the grantee with only the enqueue right as in Example 8-40.

Example 8-40 Revoking Dequeue Privilege

BEGIN
   DBMS_AQADM.REVOKE_QUEUE_PRIVILEGE(
      privilege     =>     'DEQUEUE', 
      queue_name    =>     'test.multiconsumer_81_queue', 
      grantee       =>     'test_adm');
END;

Managing Subscribers

This section contains these topics:

Adding a Subscriber

DBMS_AQADM.ADD_SUBSCRIBER (
   queue_name     IN    VARCHAR2,
   subscriber     IN    sys.aq$_agent,
   rule           IN    VARCHAR2 DEFAULT NULL,
   transformation IN    VARCHAR2 DEFAULT NULL,
   queue_to_queue IN    BOOLEAN DEFAULT FALSE,
   delivery_mode  IN    PLS_INTEGER DEFAULT PERSISTENT);

This procedure adds a default subscriber to a queue.

An application can enqueue messages to a specific list of recipients or to the default list of subscribers. This operation succeeds only on queues that allow multiple consumers, and the total number of subscribers must be 1024 or less. This operation takes effect immediately and the containing transaction is committed. Enqueue requests that are executed after the completion of this call reflect the new action. Any string within the rule must be quoted (with single quotation marks) as follows:

rule   => 'PRIORITY <= 3 AND CORRID =  ''FROM JAPAN'''

User data properties or attributes apply only to object payloads and must be prefixed with tab.userdata in all cases.

If GLOBAL_TOPIC_ENABLED is set to true when a subscriber is created, then a corresponding LDAP entry is also created.

Specify the name of the transformation to be applied during dequeue or propagation. The transformation must be created using the DBMS_TRANSFORM package.


See Also:

Oracle Database PL/SQL Packages and Types Reference for more information on the DBMS_TRANSFORM package

For queues that contain payloads with XMLType attributes, you can specify rules that contain operators such as XMLType.existsNode() and XMLType.extract().

If parameter queue_to_queue is set to TRUE, then the added subscriber is a queue-to-queue subscriber. When queue-to-queue propagation is set up between a source queue and a destination queue, queue-to-queue subscribers receive messages through that propagation schedule.

If the delivery_mode parameter is the default PERSISTENT, then the subscriber receives only persistent messages. If it is set to BUFFERED, then the subscriber receives only buffered messages. If it is set to PERSISTENT_OR_BUFFERED, then the subscriber receives both types. You cannot alter this parameter with ALTER_SUBSCRIBER.

The agent name should be NULL if the destination queue is a single consumer queue.


Note:

ADD_SUBSCRIBER is an administrative operation on a queue. Although Oracle Streams AQ does not prevent applications from issuing administrative and operational calls concurrently, they are executed serially. ADD_SUBSCRIBER blocks until pending calls that are enqueuing or dequeuing messages complete. It will not wait for the pending transactions to complete.

Example 8-41 Adding a Subscriber at a Designated Queue at a Database Link

DECLARE 
   subscriber          sys.aq$_agent; 
BEGIN 
   subscriber := sys.aq$_agent('subscriber1', 'test2.msg_queue2@london', null); 
   DBMS_AQADM.ADD_SUBSCRIBER(
      queue_name         => 'test.multiconsumer_81_queue', 
      subscriber         =>  subscriber); 
END;
/

Example 8-42 Adding a Single Consumer Queue at a Dababase Link as a Subscriber

DECLARE 
   subscriber          sys.aq$_agent; 
BEGIN 
   subscriber := sys.aq$_agent('subscriber1', 'test2.msg_queue2@london', null); 
   DBMS_AQADM.ADD_SUBSCRIBER(
      queue_name         => 'test.multiconsumer_81_queue', 
      subscriber         =>  subscriber); 
END;
/

Example 8-43 Adding a Subscriber with a Rule

DECLARE 
   subscriber       sys.aq$_agent; 
BEGIN 
   subscriber := sys.aq$_agent('subscriber2', 'test2.msg_queue2@london', null); 
   DBMS_AQADM.ADD_SUBSCRIBER(
      queue_name =>  'test.multiconsumer_81_queue', 
      subscriber =>   subscriber, 
      rule       =>  'priority < 2'); 
END;
/

Example 8-44 Adding a Subscriber and Specifying a Transformation

DECLARE 
   subscriber       sys.aq$_agent; 
BEGIN 
   subscriber := sys.aq$_agent('subscriber3', 'test2.msg_queue2@london', null); 
   DBMS_AQADM.ADD_SUBSCRIBER(
      queue_name     => 'test.multiconsumer_81_queue', 
      subscriber     =>  subscriber, 
      transformation => 'test.message_order_transform');
END;
/

Example 8-45 Propagating from a Multiple-Consumer Queue to a Single Consumer Queue

DECLARE 
   subscriber          SYS.AQ$_AGENT; 
BEGIN 
  subscriber := SYS.AQ$_AGENT(NULL, 'test2.single_consumer__queue@london', 
null); 
  DBMS_AQADM.ADD_SUBSCRIBER( 
      queue_name         => 'test.multiconsumer_81_queue', 
      subscriber         =>  subscriber); 
END; 

Altering a Subscriber

DBMS_AQADM.ALTER_SUBSCRIBER (
   queue_name     IN    VARCHAR2,
   subscriber     IN    sys.aq$_agent,
   rule           IN    VARCHAR2
   transformation IN    VARCHAR2);

This procedure alters existing properties of a subscriber to a specified queue.

The rule, the transformation, or both can be altered. If you alter only one of these attributes, then specify the existing value of the other attribute to the alter call. If GLOBAL_TOPIC_ENABLED = TRUE when a subscriber is modified, then a corresponding LDAP entry is created.

Example 8-46 Altering a Subscriber Rule

DECLARE 
   subscriber       sys.aq$_agent; 
BEGIN 
   subscriber := sys.aq$_agent('subscriber2', 'test2.msg_queue2@london', null); 
   DBMS_AQADM.ALTER_SUBSCRIBER(
      queue_name => 'test.multiconsumer_81_queue', 
      subscriber =>  subscriber, 
      rule       => 'priority = 1'); 
END;
/

Removing a Subscriber

DBMS_AQADM.REMOVE_SUBSCRIBER (
   queue_name         IN         VARCHAR2,
   subscriber         IN         sys.aq$_agent);

This procedure removes a default subscriber from a queue.

This operation takes effect immediately and the containing transaction is committed. All references to the subscriber in existing messages are removed as part of the operation. If GLOBAL_TOPIC_ENABLED = TRUE when a subscriber is dropped, then a corresponding LDAP entry is also dropped.

It is not an error to run the REMOVE_SUBSCRIBER procedure even when there are pending messages that are available for dequeue by the consumer. These messages are automatically made unavailable for dequeue when the REMOVE_SUBSCRIBER procedure finishes.


Note:

REMOVE_SUBSCRIBER is an administrative operation on a queue. Although Oracle Streams AQ does not prevent applications from issuing administrative and operational calls concurrently, they are executed serially. REMOVE_SUBSCRIBER blocks until pending calls that are enqueuing or dequeuing messages complete. It will not wait for the pending transactions to complete.

Example 8-47 Removing a Subscriber

DECLARE
   subscriber       sys.aq$_agent;
BEGIN
   subscriber := sys.aq$_agent ('subscriber2', 'test2.msg_queue2@london', null);
   DBMS_AQADM.REMOVE_SUBSCRIBER(
      queue_name => 'test.multiconsumer_81_queue',
      subscriber => subscriber);
END;
/

Managing Propagations

The propagation schedules defined for a queue can be changed or dropped at any time during the life of the queue. You can also temporarily disable a schedule instead of dropping it. All administrative calls can be made irrespective of whether the schedule is active or not. If a schedule is active, then it takes a few seconds for the calls to be processed.

This section contains these topics:

Scheduling a Queue Propagation

DBMS_AQADM.SCHEDULE_PROPAGATION (
   queue_name         IN  VARCHAR2,
   destination        IN  VARCHAR2 DEFAULT NULL,
   start_time         IN  DATE     DEFAULT SYSDATE,
   duration           IN  NUMBER   DEFAULT NULL,
   next_time          IN  VARCHAR2 DEFAULT NULL,
   latency            IN  NUMBER   DEFAULT 60,
   destination_queue  IN  VARCHAR2 DEFAULT NULL);

This procedure schedules propagation of messages.

The destination can be identified by a database link in the destination parameter, a queue name in the destination_queue parameter, or both. Specifying only a database link results in queue-to-dblink propagation. If you propagate messages to several queues in another database, then all propagations have the same frequency.

If a private database link in the schema of the queue table owner has the same name as a public database link, AQ always uses the private database link.

Specifying the destination queue name results in queue-to-queue propagation was introduce in Oracle Streams Advanced Queuing 10g Release 2 (10.2). If you propagate messages to several queues in another database, queue-to-queue propagation enables you to configure each schedule independently of the others. You can enable or disable individual propagations.


Note:

If you want queue-to-queue propagation to a queue in another database, then you must specify parameters destination and destination_queue.

Queue-to-queue propagation mode supports transparent failover when propagating to a destination Oracle Real Application Clusters (Oracle RAC) system. With queue-to-queue propagation, it is not required to repoint a database link if the owner instance of the queue fails on Oracle RAC.

Messages can also be propagated to other queues in the same database by specifying a NULL destination. If a message has multiple recipients at the same destination in either the same or different queues, then the message is propagated to all of them at the same time.

The source queue must be in a queue table meant for multiple consumers. If you specify a single-consumer queue, than error ORA-24039 results. Oracle Streams Advanced Queuing does not support the use of synonyms to refer to queues or database links.

If you specify a propagation next_time and duration, propagation will run periodically for the specified duration.If you specify a latency of zero with no next_time or duration, the resulting propagation will run forever, propagating messages as they appear in the queue, and idling otherwise. If a non-zero latency is specified, with no next_time or duration (default), the propagation schedule will be event-based. It will be scheduled to run when there are messages in the queue to be propagated. When there are no more messages for a system-defined period of time, the job will stop running until there are new messages to be propagated.The time at which the job runs depends on other factors, such as the number of ready jobs and the number of job queue processes.


See Also:


Propagation uses a linear backoff scheme for retrying propagation from a schedule that encountered a failure. If a schedule continuously encounters failures, then the first retry happens after 30 seconds, the second after 60 seconds, the third after 120 seconds and so forth. If the retry time is beyond the expiration time of the current window, then the next retry is attempted at the start time of the next window. A maximum of 16 retry attempts are made after which the schedule is automatically disabled.


Note:

Once a retry attempt slips to the next propagation window, it will always do so; the exponential backoff scheme no longer governs retry scheduling. If the date function specified in the next_time parameter of DBMS_AQADM.SCHEDULE_PROPAGATION results in a short interval between windows, then the number of unsuccessful retry attempts can quickly reach 16, disabling the schedule.

If you specify a value for destination that does not exist, then this procedure still runs without throwing an error. You can query runtime propagation errors in the LAST_ERROR_MSG column of the USER_QUEUE_SCHEDULES view.

Example 8-48 Scheduling a Propagation to Queues in the Same Database

BEGIN
   DBMS_AQADM.SCHEDULE_PROPAGATION(
      queue_name    =>    'test.multiconsumer_queue');
END;
/

Example 8-49 Scheduling a Propagation to Queues in Another Database

BEGIN
   DBMS_AQADM.SCHEDULE_PROPAGATION(
      queue_name    =>    'test.multiconsumer_queue', 
      destination   =>    'another_db.world');
END;
/

Example 8-50 Scheduling Queue-to-Queue Propagation

BEGIN
   DBMS_AQADM.SCHEDULE_PROPAGATION(
      queue_name         =>    'test.multiconsumer_queue', 
      destination        =>    'another_db.world'
      destination_queue  =>    'target_queue');
END;
/

Verifying Propagation Queue Type

DBMS_AQADM.VERIFY_QUEUE_TYPES(
   src_queue_name    IN    VARCHAR2,
   dest_queue_name   IN    VARCHAR2,
   destination       IN    VARCHAR2 DEFAULT NULL,
   rc                OUT   BINARY_INTEGER);

This procedure verifies that the source and destination queues have identical types. The result of the verification is stored in the dictionary table SYS.AQ$_MESSAGE_TYPES, overwriting all previous output of this command.

If the source and destination queues do not have identical types and a transformation was specified, then the transformation must map the source queue type to the destination queue type.


Note:

SYS.AQ$_MESSAGE_TYPES can have multiple entries for the same source queue, destination queue, and database link, but with different transformations.

Example 8-51 Verifying a Queue Type

SET SERVEROUTPUT ON
DECLARE 
rc      BINARY_INTEGER; 
BEGIN 
   DBMS_AQADM.VERIFY_QUEUE_TYPES(
      src_queue_name  => 'test.multiconsumer_queue', 
      dest_queue_name => 'test.another_queue',
      rc              =>  rc); 
   DBMS_OUTPUT.PUT_LINE('Compatible: '||rc);
END;
/

Example 8-51 involves two queues of the same type. It returns:

VQT: new style queue
Compatible: 1

If the same example is run with test.raw_queue (a queue of type RAW) in place of test.another_queue, then it returns:

VQT: new style queue
Compatible: 0

Altering a Propagation Schedule

DBMS_AQADM.ALTER_PROPAGATION_SCHEDULE( 
   queue_name         IN  VARCHAR2, 
   destination        IN  VARCHAR2 DEFAULT NULL,
   duration           IN  NUMBER   DEFAULT NULL, 
   next_time          IN  VARCHAR2 DEFAULT NULL, 
   latency            IN  NUMBER   DEFAULT 60,
   destination_queue  IN  VARCHAR2 DEFAULT NULL);

This procedure alters parameters for a propagation schedule. The destination_queue parameter for queue-to-queue propagation cannot be altered.

Example 8-52 Altering a Propagation Schedule to Queues in the Same Database

BEGIN
   DBMS_AQADM.ALTER_PROPAGATION_SCHEDULE(
      queue_name    =>    'test.multiconsumer_queue', 
      duration      =>    '2000', 
      next_time     =>    'SYSDATE + 3600/86400',
      latency       =>    '32'); 
END;
/

Example 8-53 Altering a Propagation Schedule to Queues in Another Database

BEGIN
   DBMS_AQADM.ALTER_PROPAGATION_SCHEDULE(
      queue_name    =>    'test.multiconsumer_queue', 
      destination   =>    'another_db.world', 
      duration      =>    '2000', 
      next_time     =>    'SYSDATE + 3600/86400',
      latency       =>    '32');
END;
/

Enabling a Propagation Schedule

DBMS_AQADM.ENABLE_PROPAGATION_SCHEDULE( 
   queue_name        IN   VARCHAR2, 
   destination       IN   VARCHAR2 DEFAULT NULL,
   destination_queue IN   VARCHAR2 DEFAULT NULL);

This procedure enables a previously disabled propagation schedule.

Example 8-54 Enabling a Propagation to Queues in the Same Database

BEGIN
   DBMS_AQADM.ENABLE_PROPAGATION_SCHEDULE(
      queue_name   =>   'test.multiconsumer_queue');
END;
/

Example 8-55 Enabling a Propagation to Queues in Another Database

BEGIN
   DBMS_AQADM.ENABLE_PROPAGATION_SCHEDULE(
      queue_name    =>    'test.multiconsumer_queue', 
      destination   =>    'another_db.world');
END;
/

Disabling a Propagation Schedule

DBMS_AQADM.DISABLE_PROPAGATION_SCHEDULE( 
   queue_name        IN   VARCHAR2, 
   destination       IN   VARCHAR2 DEFAULT NULL,
   destination_queue IN   VARCHAR2 DEFAULT NULL);

This procedure disables a previously enabled propagation schedule.

Example 8-56 Disabling a Propagation to Queues in the Same Database

BEGIN
   DBMS_AQADM.DISABLE_PROPAGATION_SCHEDULE(
      queue_name   =>   'test.multiconsumer_queue');
END;
/

Example 8-57 Disabling a Propagation to Queues in Another Database

BEGIN
   DBMS_AQADM.DISABLE_PROPAGATION_SCHEDULE(
      queue_name    =>    'test.multiconsumer_queue', 
      destination   =>    'another_db.world');
END;
/

Unscheduling a Queue Propagation

DBMS_AQADM.UNSCHEDULE_PROPAGATION (
   queue_name        IN  VARCHAR2,
   destination       IN  VARCHAR2 DEFAULT NULL,
   destination_queue IN  VARCHAR2 DEFAULT NULL);

This procedure unschedules a previously scheduled propagation of messages from a queue to a destination. The destination is identified by a specific database link in the destination parameter or by name in the destination_queue parameter.

Example 8-58 Unscheduling a Propagation to Queues in the Same Database

BEGIN
   DBMS_AQADM.UNSCHEDULE_PROPAGATION(
      queue_name => 'test.multiconsumer_queue'); 
END;
/

Example 8-59 Unscheduling a Propagation to Queues in Another Database

BEGIN
   DBMS_AQADM.UNSCHEDULE_PROPAGATION(
      queue_name    =>   'test.multiconsumer_queue', 
      destination   =>   'another_db.world');
END;
/

Managing Oracle Streams Advanced Queuing Agents

This section contains these topics:

Creating an Oracle Streams Advanced Queuing Agent

DBMS_AQADM.CREATE_AQ_AGENT (
  agent_name                IN VARCHAR2,
  certificate_location      IN VARCHAR2 DEFAULT NULL,
  enable_http               IN BOOLEAN DEFAULT FALSE,
  enable_anyp               IN BOOLEAN DEFAULT FALSE);

This procedure registers an agent for Oracle Streams Advanced Queuing Internet access using HTTP protocols.

The SYS.AQ$INTERNET_USERS view has a list of all Oracle Streams Advanced Queuing Internet agents. When an agent is created, altered, or dropped, an LDAP entry is created for the agent if the following are true:

  • GLOBAL_TOPIC_ENABLED = TRUE

  • certificate_location is specified

Altering an Oracle Streams Advanced Queuing Agent

DBMS_AQADM.ALTER_AQ_AGENT (
  agent_name                IN VARCHAR2,
  certificate_location      IN VARCHAR2 DEFAULT NULL,
  enable_http               IN BOOLEAN DEFAULT FALSE,
  enable_anyp               IN BOOLEAN DEFAULT FALSE);

This procedure alters an agent registered for Oracle Streams Advanced Queuing Internet access.

When an Oracle Streams Advanced Queuing agent is created, altered, or dropped, an LDAP entry is created for the agent if the following are true:

  • GLOBAL_TOPIC_ENABLED = TRUE

  • certificate_location is specified

Dropping an Oracle Streams Advanced Queuing Agent

DBMS_AQADM.DROP_AQ_AGENT (
  agent_name     IN VARCHAR2);

This procedure drops an agent that was previously registered for Oracle Streams Advanced Queuing Internet access.

When an Oracle Streams Advanced Queuing agent is created, altered, or dropped, an LDAP entry is created for the agent if the following are true:

  • GLOBAL_TOPIC_ENABLED = TRUE

  • certificate_location is specified

Enabling Database Access

DBMS_AQADM.ENABLE_DB_ACCESS (
  agent_name                IN VARCHAR2,
  db_username               IN VARCHAR2)

This procedure grants an Oracle Streams Advanced Queuing Internet agent the privileges of a specific database user. The agent should have been previously created using the CREATE_AQ_AGENT procedure.

The SYS.AQ$INTERNET_USERS view has a list of all Oracle Streams Advanced Queuing Internet agents and the names of the database users whose privileges are granted to them.


See Also:

Oracle Streams Concepts and Administration for information about secure queues

Disabling Database Access

DBMS_AQADM.DISABLE_DB_ACCESS (
  agent_name                IN VARCHAR2,
  db_username               IN VARCHAR2)

This procedure revokes the privileges of a specific database user from an Oracle Streams Advanced Queuing Internet agent. The agent should have been previously granted those privileges using the ENABLE_DB_ACCESS procedure.


See Also:

Oracle Streams Concepts and Administration for information about secure queues

Adding an Alias to the LDAP Server

DBMS_AQADM.ADD_ALIAS_TO_LDAP(
   alias          IN VARCHAR2,
   obj_location   IN VARCHAR2);

This procedure adds an alias to the LDAP server.

This call takes the name of an alias and the distinguished name of an Oracle Streams Advanced Queuing object in LDAP, and creates the alias that points to the Oracle Streams Advanced Queuing object. The alias is placed immediately under the distinguished name of the database server. The object to which the alias points can be a queue, an agent, or a ConnectionFactory.


See Also:

Oracle Streams Concepts and Administration for information about secure queues

Deleting an Alias from the LDAP Server

DBMS_AQADM.DEL_ALIAS_FROM_LDAP(
   alias IN VARCHAR2);

This procedure removes an alias from the LDAP server.

This call takes the name of an alias as the argument, and removes the alias entry in the LDAP server. It is assumed that the alias is placed immediately under the database server in the LDAP directory.

PKjJPK-AOEBPS/mg_trnsfm.htm Oracle Messaging Gateway Message Conversion

20 Oracle Messaging Gateway Message Conversion

This chapter discusses how Oracle Messaging Gateway (MGW) converts message formats from one messaging system to another. A conversion is generally necessary when moving messages between Oracle Streams Advanced Queuing and another system, because different messaging systems have different message formats. Java Message Service (JMS) messages are a special case. A JMS message can be propagated only to a JMS destination, making conversion a simple process.

This chapter contains these topics:

Converting Oracle Messaging Gateway Non-JMS Messages

MGW converts the native message format of the source messaging system to the native message format of the destination messaging system during propagation. MGW uses canonical types and a model centering on Oracle Streams Advanced Queuing for the conversion.

Overview of the Non-JMS Message Conversion Process

When a message is propagated by MGW, the message is converted from the native format of the source queue to the native format of the destination queue.

A native message usually contains a message header and a message body. The header contains the fixed header fields that all messages in that messaging system have, such as message properties in Oracle Streams Advanced Queuing and the fixed header in WebSphere MQ. The body contains message contents, such as the Oracle Streams Advanced Queuing payload, the WebSphere MQ message body, or the entire TIB/Rendezvous message. MGW converts both message header and message body components.

Figure 20-1 shows how non-JMS messages are converted in two stages. A message is first converted from the native format of the source queue to the MGW internal message format, and then it is converted from the internal message format to the native format of the destination queue.

Figure 20-1 Non-JMS Message Conversion

Description of Figure 20-1 follows
Description of "Figure 20-1 Non-JMS Message Conversion"

The MGW agent uses an internal message format consisting of a header that is similar to the Oracle Streams Advanced Queuing message properties and a body that is a representation of an MGW canonical type.

Oracle Messaging Gateway Canonical Types

MGW defines canonical types to support message conversion between Oracle Streams Advanced Queuing and non-Oracle messaging systems. A canonical type is a message type representation in the form of a PL/SQL Oracle type in Oracle Database. The canonical types are RAW, SYS.MGW_BASIC_MSG_T, and SYS.MGW_TIBRV_MSG_T.

WebSphere MQ propagation supports the canonical types SYS.MGW_BASIC_MSG_T and RAW. TIB/Rendezvous propagation supports the canonical types SYS.MGW_TIBRV_MSG_T and RAW.


See Also:

"DBMS_MGWMSG" in Oracle Database PL/SQL Packages and Types Reference for Syntax and attribute information for SYS.MGW_BASIC_MSG_T and SYS.MGW_TIBRV_MSG_T

Message Header Conversion

MGW provides default mappings between Oracle Streams Advanced Queuing message properties and non-Oracle message header fields that have a counterpart in Oracle Streams Advanced Queuing message properties with the same semantics. Where MGW does not provide a mapping, the message header fields are set to a default value, usually the default value defined by the messaging system.

Handling Arbitrary Payload Types Using Message Transformations

When converting to or from Oracle Streams Advanced Queuing messages, the MGW agent uses only its canonical types. Arbitrary payload types are supported, however, with the assistance of user-defined Oracle Streams Advanced Queuing message transformations to convert between an Oracle Streams Advanced Queuing queue payload and an MGW canonical type.

For MGW to propagate messages from an Oracle Streams Advanced Queuing queue with an arbitrary ADT payload (outbound propagation), you must provide a mapping to an MGW canonical ADT. The transformation is invoked when the MGW agent dequeues messages from the Oracle Streams Advanced Queuing queue. Similarly, for MGW to propagate messages to an Oracle Streams Advanced Queuing queue with an arbitrary ADT payload (inbound propagation), you must provide a mapping from an MGW canonical ADT. The transformation is invoked when the MGW agent enqueues messages to the Oracle Streams Advanced Queuing queue.

Figure 20-2 Oracle Streams Advanced Queuing Message Conversion

Description of Figure 20-2 follows
Description of "Figure 20-2 Oracle Streams Advanced Queuing Message Conversion"

The transformation is always executed in the context of the MGW agent, which means that the MGW agent user (the user specified using DBMS_MGWADM.CREATE_AGENT or DBMS_MGWADM.ALTER_AGENT) must have EXECUTE privileges on the transformation function and the Oracle Streams Advanced Queuing payload type. This can be accomplished by granting the EXECUTE privilege to PUBLIC or by granting the EXECUTE privilege directly to the MGW agent user.

To configure a MGW propagation job with a transformation:

  1. Create the transformation function.

  2. Grant EXECUTE to the MGW agent user or to PUBLIC on the function and the object types it references.

  3. Call DBMS_TRANSFORM.CREATE_TRANSFORMATION to register the transformation.

  4. Call DBMS_MGWADM.CREATE_JOB to create a MGW propagation job using the transformation, or DBMS_MGWADM.ALTER_JOB to alter an existing job.

The value passed in the transformation parameter for these APIs must be the registered transformation name and not the function name. For example, trans_sampleadt_to_mgw_basic is a stored procedure representing a transformation function with the signature shown in Example 20-1.


Note:

All commands in the examples must be run as a user granted MGW_ADMINISTRATOR_ROLE, except for the commands to create transformations.

Example 20-1 Transformation Function Signature

FUNCTION trans_sampleadt_to_mgw_basic(in_msg IN mgwuser.sampleADT)
RETURN SYS.MGW_BASIC_MSG_T;

You can create a transformation using DBMS_TRANSFORM.CREATE_TRANSFORMATION, as shown in Example 20-2.

Example 20-2 Creating a Transformation

BEGIN
  DBMS_TRANSFORM.CREATE_TRANSFORMATION(
        schema         => 'mgwuser',
        name           => 'sample_adt_to_mgw_basic',
        from_schema    => 'mgwuser',
        from_type      => 'sampleadt',
        to_schema      => 'sys',
        to_type        => 'MGW_BASIC_MSG_T',
        transformation => 'mgwuser.trans_sampleadt_to_mgw_basic(user_data)');
END;

Once created, this transformation can be registered with MGW when creating a propagation job. Example 20-3 creates job job_aq2mq, for whom messages are propagated from Oracle Streams Advanced Queuing queue mgwuser.srcq to non-Oracle messaging system queue destq@mqlink using transformation mgwuser.sample_adt_to_mgw_basic.

Example 20-3 Registering a Transformation

BEGIN
  DBMS_MGWADM.CREATE_JOB(
    job_name          =>   'job_aq2mq',
    propagation_type  =>    DBMS_MGWADM.OUTBOUND_PROPAGATION,
    source            =>   'mgwuser.srcq',
    destination       =>   'destq.mqlink',
    transformation    =>   'mgwuser.sample_adt_to_mgw_basic',
    exception_queue   =>   'mgwuser.excq');
END;

See Also:

"DBMS_MGWADM", "DBMS_MGWMSG", and "DBMS_TRANSFORM" in Oracle Database PL/SQL Packages and Types Reference

An error that occurs while attempting a user-defined transformation is usually considered a message conversion exception, and the message is moved to the exception queue if it exists.

Handling Logical Change Records

MGW provides facilities to propagate Logical Change Records (LCRs). Routines are provided to help in creating transformations to handle the propagation of both row LCRs and DDL LCRs stored in queues with payload type ANYDATA. An LCR is propagated as an XML string stored in the appropriate message type.


Note:

For LCR propagation, you must load the XDB package.

Because Oracle Streams uses ANYDATA queues to store LCRs, an ANYDATA queue is the source for outbound propagation. The transformation must first convert the ANYDATA object containing an LCR into an XMLType object using the MGW routine DBMS_MGWMSG.LCR_TO_XML. If the ANYDATA object does not contain an LCR, then this routine raises an error. The XML document string of the LCR is then extracted from the XMLType and placed in the appropriate MGW canonical type (SYS.MGW_BASIC_MSG_T or SYS.MGW_TIBRV_MSG_T).

Example 20-4 illustrates a simplified transformation used for LCR outbound propagation. The transformation converts an ANYDATA payload containing an LCR to a SYS.MGW_TIBRV_MSG_T object. The string representing the LCR as an XML document is put in a field named ORACLE_LCR.

Example 20-4 Outbound LCR Transformation

create or replace function any2tibrv(adata in anydata)
return SYS.MGW_TIBRV_MSG_T is
    v_xml   XMLType;
    v_text  varchar2(2000);
    v_tibrv sys.mgw_tibrv_msg_t;
BEGIN
    v_xml   := dbms_mgwmsg.lcr_to_xml(adata);
    -- assume the lcr is smaller than 2000 characters long.
    v_text  := v_xml.getStringVal();
    v_tibrv := SYS.MGW_TIBRV_MSG_T.CONSTRUCT;
    v_tibrv.add_string('ORACLE_LCR', 0, v_text);
    return v_tibrv;
END any2tibrv;

For LCR inbound propagation, an MGW canonical type (SYS.MGW_BASIC_MSG_T or SYS.MGW_TIBRV_MSG_T) is the transformation source type. A string in the format of an XML document representing an LCR must be contained in the canonical type. The transformation function must extract the string from the message, create an XMLType object from it, and convert it to an ANYDATA object containing an LCR with the MGW routine DBMS_MGWMSG.XML_TO_LCR. If the original XML document does not represent an LCR, then this routine raises an error.

Example 20-5 illustrates a simplified transformation used for LCR inbound propagation. The transformation converts a SYS.MGW_TIBRV_MSG_T object with a field containing an XML string representing an LCR to an ANYDATA object. The string representing the LCR as an XML document is taken from a field named ORACLE_LCR.

Example 20-5 Inbound LCR Transformation

create or replace function tibrv2any(tdata in sys.mgw_tibrv_msg_t)
return anydata is 
    v_field   sys.mgw_tibrv_field_t;
    v_xml     XMLType;
    v_text    varchar2(2000);
    v_any     anydata;
BEGIN
    v_field := tdata.get_field_by_name('ORACLE_LCR');
    -- type checking
    v_text  := v_field.text_value;
    -- assume it is not null
    v_xml  := XMLType.createXML(v_text);
    v_any  := dbms_mgwmsg.xml_to_lcr(v_xml); 
    return v_any;
END tibrv2any;

See Also:


Message Conversion for WebSphere MQ

MGW converts between the MGW canonical types and the WebSphere MQ native message format. WebSphere MQ native messages consist of a fixed message header and a message body. The message body is treated as either a TEXT value or RAW (bytes) value. The canonical types supported for WebSphere MQ propagation are SYS.MGW_BASIC_MSG_T and RAW.

Figure 20-3 Message Conversion for WebSphere MQ Using MGW_BASIC_MSG_T

Description of Figure 20-3 follows
Description of "Figure 20-3 Message Conversion for WebSphere MQ Using MGW_BASIC_MSG_T"

Figure 20-3 illustrates the message conversion performed by the MGW WebSphere MQ driver when using the canonical type SYS.MGW_BASIC_MSG_T. For outbound propagation, the driver maps the Oracle Streams Advanced Queuing message properties and canonical message to a WebSphere MQ message having a fixed header and a message body. For inbound propagation, the driver maps a native message to a set of Oracle Streams Advanced Queuing message properties and a canonical message. When the canonical type is RAW, the mappings are the same, except no canonical headers exist.

WebSphere MQ Message Header Mappings

When the MGW canonical type used in an outbound propagation job is RAW, no WebSphere MQ header information is set from the RAW message body. Similarly, for inbound propagation no WebSphere MQ header information is preserved in the RAW message body. MGW canonical type SYS.MGW_BASIC_MSG_T, however, has a header that can be used to specify WebSphere MQ header fields for outbound propagation, and preserve WebSphere MQ header fields for inbound propagation.

This section describes the message properties supported for the WebSphere MQ messaging system when using SYS.MGW_BASIC_MSG_T as the canonical type. Table 20-1 defines the MGW {name, value} pairs used to describe the WebSphere MQ header properties. The first column refers to valid string values for the SYS.MGW_NAME_VALUE_T.NAME field in the SYS.MGW_BASIC_MSG_T header. The second column refers to the SYS.MGW_NAME_VALUE_T.TYPE value corresponding to the name. (Refer to "Notes on Table 20-1" for explanations of the numbers in parentheses.)

For inbound propagation, the WebSphere MQ driver generates {name,value} pairs based on the source message header and stores them in the header part of the canonical message of the SYS.MGW_BASIC_MSG_T type. For outbound propagation, the WebSphere MQ driver sets the message header and enqueue options from {name,value} pairs for these properties stored in the header part of the SYS.MGW_BASIC_MSG_T canonical message.

Table 20-1 MGW Names for WebSphere MQ Header Values

MGW NameMGW TypeWebSphere MQ Property NameUsed For
MGW_MQ_accountingToken
RAW_VALUE (size 32)
accountingToken

Outbound (1), Inbound

MGW_MQ_applicationIdData
TEXT_VALUE (size 32)
applicationIdData 

Outbound (1), Inbound

MGW_MQ_applicationOriginData
TEXT_VALUE (size 4)
applicationOriginData

Outbound (1), Inbound

MGW_MQ_backoutCount
INTEGER_VALUE
backoutCount

Inbound

MGW_MQ_characterSet
INTEGER_VALUE
characterSet

Outbound, Inbound

MGW_MQ_correlationId
RAW_VALUE (size 24)
correlationId

Outbound (1), Inbound

MGW_MQ_encoding
INTEGER_VALUE
encoding

Outbound, Inbound

MGW_MQ_expiry
INTEGER_VALUE
expiry

Outbound, Inbound

MGW_MQ_feedback
INTEGER_VALUE
feedback

Outbound, Inbound

MGW_MQ_format
TEXT_VALUE (size 8)
format

Outbound (1), Inbound

MGW_MQ_groupId
RAW_VALUE (size 24)
groupId

Outbound (1), Inbound

MGW_MQ_messageFlags
INTEGER_VALUE
messageFlags

Outbound, Inbound

MGW_MQ_messageId
RAW_VALUE (size 24)
messageId

Outbound, Inbound

MGW_MQ_messageSequenceNumber
INTEGER_VALUE
messageSequenceNumber

Outbound, Inbound

MGW_MQ_messageType
INTEGER_VALUE
messageType

Outbound, Inbound

MGW_MQ_offset
INTEGER_VALUE
offset

Outbound, Inbound

MGW_MQ_originalLength
INTEGER_VALUE
originalLength

Outbound, Inbound

MGW_MQ_persistence
INTEGER_VALUE
persistence

Inbound

MGW_MQ_priority
INTEGER_VALUE
priority

Outbound, Inbound

MGW_MQ_putApplicationName
TEXT_VALUE (size 28)
putApplicationName

Outbound (1), Inbound

MGW_MQ_putApplicationType
INTEGER_VALUE
putApplicationType

Outbound (1), Inbound

MGW_MQ_putDateTime
DATE_VALUE
putDateTime

Inbound

MGW_MQ_putMessageOptions
INTEGER_VALUE
putMessageOptions

Outbound (1) (2)

MGW_MQ_replyToQueueManagerName
TEXT_VALUE (size 48)
replyToQueueManagerName

Outbound, Inbound

MGW_MQ_replyToQueueName
TEXT_VALUE (size 48)
replyToQueueName

Outbound, Inbound

MGW_MQ_report
INTEGER_VALUE
report

Outbound (1), Inbound

MGW_MQ_userId
TEXT_VALUE (size 12)
userId

Outbound, Inbound


Notes on Table 20-1

  1. This use is subject to WebSphere MQ restrictions. For example, if MGW_MQ_accountingToken is set for an outgoing message, then WebSphere MQ overrides its value unless MGW_MQ_putMessageOptions is set to the WebSphere MQ constant MQPMD_SET_ALL_CONTEXT.

  2. MGW_MQ_putMessageOptions is used as the putMessageOptions argument to the WebSphere MQ Base Java Queue.put() method. It is not part of the WebSphere MQ header information and is therefore not an actual message property.

    The value for the openOptions argument of the WebSphere MQ Base Java MQQueueManager.accessQueue method is specified when the WebSphere MQ queue is registered using the DBMS_MGWADM.REGISTER_FOREIGN_QUEUE call. Dependencies can exist between the two. For instance, for MGW_MQ_putMessageOptions to include MQPMD_SET_ALL_CONTEXT, the MQ_openMessageOptions queue option must include MQOO_SET_CONTEXT.

    The MGW agent adds the value MQPMO_SYNCPOINT to any value that you can specify.

MGW sets default values for two WebSphere MQ message header fields: messageType defaults to MQMT_DATAGRAM and putMessageOptions defaults to MQPMO_SYNCPOINT.

MGW provides two default mappings between Oracle Streams Advanced Queuing message properties and WebSphere MQ header fields.

One maps the Oracle Streams Advanced Queuing message property expiration, representing the time-to-live of the message at the time the message becomes available in the queue, to the WebSphere MQ header field expiry, representing the time-to-live of the message. For outbound propagation, the value used for expiry is determined by subtracting the time the message was available in the queue from the expiration, converted to tenths of a second. Oracle Streams Advanced Queuing value NEVER is mapped to MQEI_UNLIMITED. For inbound propagation, the value of expiration is simply expiry converted to seconds. WebSphere MQ value MQEI_UNLIMITED is mapped to NEVER.

The other default maps Oracle Streams Advanced Queuing message property priority with the WebSphere MQ header field priority. It is described in Table 20-2.

Table 20-2 Default Priority Mappings for Propagation

Propagation TypeMessage SystemPriority Values

Outbound

Oracle Streams Advanced Queuing


0

1

2

3

4

5

6

7

8

9

Outbound

WebSphere MQ

9

8

7

6

5

4

3

2

1

0

Inbound

Oracle Streams Advanced Queuing


9

8

7

6

5

4

3

2

1

0

Inbound

WebSphere MQ

0

1

2

3

4

5

6

7

8

9



Note:

For outbound propagation, Oracle Streams Advanced Queuing priority values less than 0 are mapped to WebSphere MQ priority 9, and Oracle Streams Advanced Queuing priority values greater than 9 are mapped to WebSphere MQ priority 0.

WebSphere MQ Outbound Propagation

If no message transformation is provided for outbound propagation, then the Oracle Streams Advanced Queuing source queue payload type must be either SYS.MGW_BASIC_MSG_T or RAW. If a message transformation is specified, then the target ADT of the transformation must be SYS.MGW_BASIC_MSG_T, but the source ADT can be any ADT supported by Oracle Streams Advanced Queuing.

If the Oracle Streams Advanced Queuing queue payload is RAW, then the resulting WebSphere MQ message has the message body set to the value of the RAW bytes and, by default, the format field set to the value "MGW_Byte".

If the Oracle Streams Advanced Queuing queue payload or transformation target ADT is SYS.MGW_BASIC_MSG_T, then the message is mapped to a WebSphere MQ native message as follows:

  • The WebSphere MQ fixed header fields are based on the internal Oracle Streams Advanced Queuing message properties and the SYS.MGW_BASIC_MSG_T.header attribute of the canonical message, as described in "WebSphere MQ Message Header Mappings".

  • If the canonical message has a TEXT body, then the WebSphere MQ format header field is set to MQFMT_STRING unless overridden by the header property MGW_MQ_format. The message body is treated as text.

  • If the canonical message has a RAW body, then the WebSphere MQ format header field is set to "MGW_Byte" unless overridden by the header property MGW_MQ_format. The message body is treated as raw bytes.

  • If the canonical message has both a TEXT and RAW body, then message conversion fails.

  • If the canonical message has neither a TEXT nor RAW body, then no message body is set, and the WebSphere MQ format header field is MQFMT_NONE.

  • If the canonical message has a TEXT body with both small and large values set (SYS.MGW_BASIC_MSG_T.TEXT_BODY.small_value and SYS.MGW_BASIC_MSG_T.TEXT_BODY.large_value not empty), then message conversion fails.

  • If the canonical message has a RAW body with both small and large values set (SYS.MGW_BASIC_MSG_T.RAW_BODY.small_value and SYS.MGW_BASIC_MSG_T.RAW_BODY.large_value not empty), then message conversion fails.

If the job option PreserveMessageID is specified with a value of TRUE, then the correlationId field of the WebSphere message header will be set to the AQ source message identifier. The correlationId value will be a 24-byte value of the form "AQMSGID:"+AQ_msgid where AQ_msgid represents the 16-byte Streams AQ message identifier.

WebSphere MQ Inbound Propagation

If no message transformation is provided for inbound propagation, then the Oracle Streams Advanced Queuing destination queue payload type must be either SYS.MGW_BASIC_MSG_T or RAW. If a message transformation is specified, then the source ADT of the transformation must be SYS.MGW_BASIC_MSG_T, but the destination ADT can be any ADT supported by Oracle Streams Advanced Queuing.

If the Oracle Streams Advanced Queuing queue payload is RAW and the incoming WebSphere MQ message has a format of MQFMT_STRING, then message conversion fails. Otherwise the message body is considered as raw bytes and enqueued directly to the destination queue. If the number of bytes is greater than 32KB, then message conversion fails. The actual limit is 32512 bytes rather than 32767 bytes.

If the Oracle Streams Advanced Queuing queue payload or transformation source ADT is SYS.MGW_BASIC_MSG_T, then the WebSphere MQ message is mapped to a SYS.MGW_BASIC_MSG_T message as follows:

  • Specific WebSphere MQ header fields are mapped to Oracle Streams Advanced Queuing message properties as previously described.

  • The SYS.MGW_BASIC_MSG_T.header attribute of the canonical message is set to {name, value} pairs based on the WebSphere MQ header fields, as described in Table 20-1. These values preserve the original content of the WebSphere MQ message header.

  • If the WebSphere MQ format header field is MQFMT_STRING, then the WebSphere MQ message body is treated as text, and its value is mapped to SYS.MGW_BASIC_MSG_T.text_body. For any other format value, the message body is treated as raw bytes, and its value is mapped to SYS.MGW_BASIC_MSG_T.raw_body.

Message Conversion for TIB/Rendezvous

MGW regards a TIB/Rendezvous message as a set of fields and supplementary information. Figure 20-4 shows how messages are converted between MGW and TIB/Rendezvous.

Figure 20-4 Message Conversion for TIB/Rendezvous

Description of Figure 20-4 follows
Description of "Figure 20-4 Message Conversion for TIB/Rendezvous"

When a message conversion failure occurs, messages are moved to an exception queue (if one has been provided), so that MGW can continue propagation of the remaining messages in the source queue. In inbound propagation from TIB/Rendezvous, an exception queue is a registered subject.

All TIB/Rendezvous wire format datatypes for TIB/Rendezvous fields are supported, except for the datatypes with unsigned integers and the nested message type. User-defined custom datatypes are not supported in this release. If a message contains data of the unsupported datatypes, then a message conversion failure occurs when the message is processed. A message conversion failure results in moving the failed message from the source queue to the exception queue, if an exception queue is provided.

Table 20-3 shows the datatype mapping used when MGW converts between a native TIB/Rendezvous message and the canonical ADT. For each supported TIB/Rendezvous wire format type, it shows the Oracle type used to store the data and the DBMS_MGWMSG constant that represents that type.

Table 20-3 TIB/Rendezvous Datatype Mapping

TIB/Rendezvous Wire FormatOracle TypeADT Field Type

Bool

NUMBER

TIBRVMSG_BOOL

F32

NUMBER

TIBRVMSG_F32

F64

NUMBER

TIBRVMSG_F64

I8

NUMBER

TIBRVMSG_I8

I16

NUMBER

TIBRVMSG_I16

I32

NUMBER

TIBRVMSG_I32

I64

NUMBER

TIBRVMSG_I64

U8

not supported

not supported

U16

not supported

not supported

U32

not supported

not supported

U64

not supported

not supported

IPADDR32

VARCHAR2

TIBRVMSG_IPADDR32

IPPORT16

NUMBER

TIBRVMSG_IPPORT16

DATETIME

DATE

TIBRVMSG_DATETIME

F32ARRAY

SYS.MGW_NUMBER_ARRAY_T

TIBRVMSG_F32ARRAY

F64ARRAY

SYS.MGW_NUMBER_ARRAY_T

TIBRVMSG_F64ARRAY

I8ARRAY

SYS.MGW_NUMBER_ARRAY_T

TIBRVMSG_I8ARRAY

I16ARRAY

SYS.MGW_NUMBER_ARRAY_T

TIBRVMSG_I16ARRAY

I32ARRAY

SYS.MGW_NUMBER_ARRAY_T

TIBRVMSG_I32ARRAY

I64ARRAY

SYS.MGW_NUMBER_ARRAY_T

TIBRVMSG_I64ARRAY

U8ARRAY

not supported

not supported

U16ARRAY

not supported

not supported

U32ARRAY

not supported

not supported

U64ARRAY

not supported

not supported

MSG

not supported

not supported

OPAQUE

RAW or BLOB

TIBRVMSG_OPAQUE

STRING

VARCHAR2 or CLOB

TIBRVMSG_STRING

XML

RAW or BLOB

TIBRVMSG_XML


For propagation between Oracle Streams Advanced Queuing and TIB/Rendezvous, MGW provides direct support for the Oracle Streams Advanced Queuing payload types RAW and SYS.MGW_TIBRV_MSG_T. To support any other Oracle Streams Advanced Queuing payload type, you must supply a transformation.

AQ Message Property Mapping for TIB/Rendezvous

This section describes the mapping between Oracle Streams AQ message properties and TIB/Rendezvous fields. This mapping is used to preserve Streams AQ message properties during outbound propagation, and set Streams AQ message properties during inbound propagation.

Table 20-4 describes the Streams AQ message properties supported using TIB/Rendezvous fields. The first column indicates the DBMS_AQ.MESSAGE_PROPERTIES_T field for the Streams AQ message property. The second and third columns indicate the name and datatype used for the TIB/Rendezvous field. The last column indicates if the message property is supported for inboDEund and outbound propagation.

Table 20-4 TIB/Rendezvous and MGW Names for Oracle Streams Advanced Queuing Message Properties

Oracle Streams Advanced Queuing Message PropertyMGW NameTIB/Rendezvous Wire Format DatatypeUsed For

priority

MGW_AQ_priority

TibrvMsg.I32

Outbound, Inbound

expiration

MGW_AQ_expiration

TibrvMsg.I32

Outbound, Inbound

delay

MGW_AQ_delay

TibrvMsg.I32

Outbound, Inbound

correlation

MGW_AQ_correlation

TibrvMsg.STRING

Outbound, Inbound

exception_queue

MGW_AQ_exception_queue

TibrvMsg.STRING

Outbound, Inbound

enqueue_time

MGW_AQ_enqueue_time

TibrvMsg.DATETIME

Outbound

original_msgid

MGW_AQ_original_msgid

TibrvMsg.OPAQUE

Outbound

msgid (1)

MGW_AQ_messageID

TibrvMsg.OPAQUE

Outbound


Notes on Table 20-4:

  1. The msgid Streams AQ property represents the Streams AQ message identifier, rather than a particular field of the DBMS_AQ.MESSAGE_PROPERTIES_T record.

TIB/Rendezvous Outbound Propagation

If no propagation transformation is provided for outbound propagation, then the Oracle Streams Advanced Queuing source queue payload type must be either SYS.MGW_TIBRV_MSG_T or RAW. If a propagation transformation is specified, then the target ADT of the transformation must be SYS.MGW_TIBRV_MSG_T, but the source ADT can be any ADT supported by Oracle Streams Advanced Queuing.

If the Oracle Streams Advanced Queuing queue payload or transformation target ADT is SYS.MGW_TIBRV_MSG_T, then:

  • Every field in the source message is converted to a TIB/Rendezvous message field of the resulting TIB/Rendezvous message.

  • If the reply_subject attribute is not NULL, then the reply subject supplementary information is set.

  • The send_subject field is ignored.

If the Oracle Streams Advanced Queuing queue payload is RAW, then:

  • The resulting message contains a field named MGW_RAW_MSG with value TibrvMsg.OPAQUE. The field ID is set to 0.

If the job option AQ_MsgProperties is specified with a value of TRUE, then the MGW agent generates fields to preserve the Streams AQ message properties in the TIB/Rendezvous message according to Table 20-4.

If the PreserveMessageID job option is specified with a value of TRUE, then the Streams AQ message identifier (msgid) is preserved in the TIB/Rendezvous message according to Table 20-4.

TIB/Rendezvous Inbound Propagation

If no propagation transformation is provided for inbound propagation, then the Oracle Streams Advanced Queuing destination queue payload type must be either RAW or SYS.MGW_TIBRV_MSG_T. If a propagation transformation is specified, then the target ADT of the transformation can be any ADT supported by Oracle Streams Advanced Queuing, but the source ADT of the transformation must be SYS.MGW_TIBRV_MSG_T.

If the Oracle Streams Advanced Queuing queue payload or transformation source ADT is SYS.MGW_TIBRV_MSG_T, then:

  • Every field in the source TIB/Rendezvous message is converted to a field of the resulting message of the SYS.MGW_TIBRV_MSG_T type.

  • The MGW agent extracts the send subject name from the source TIB/Rendezvous message and sets the send_subject attribute in SYS.MGW_TIBRV_MSG_T. The send subject name is usually the same as the subject name of the registered propagation source queue, but it might be different when wildcards are used.

  • The MGW agent extracts the reply subject name from the source TIB/Rendezvous message, if it exists, and sets the reply_subject attribute in SYS.MGW_TIBRV_MSG_T.

  • If the source TIB/Rendezvous message contains more than three large text fields (greater than 4000 bytes of text) or more than three large bytes fields (greater than 2000 bytes), then message conversion fails.

If the Oracle Streams Advanced Queuing queue payload is RAW, then:

  • The Oracle Streams Advanced Queuing message payload is the field data if the source TIB/Rendezvous message has a field named MGW_RAW_MSG of type TibrvMsg.OPAQUE or TibrvMsg.XML. The field name and ID are ignored. If no such field exists or has an unexpected type, then a message conversion failure occurs.

  • A message conversion failure occurs if the RAW data size is greater than 32KB. This is due to a restriction on the data size allowed for a bind variable. Also, the actual limit is 32512 rather than 32767.

If the job option AQ_MsgProperties is specified with a value of TRUE, then the MGW agent searches for fields in the original TIB/Rendezvous messages with reserved field names. Table 20-4 shows the field name strings and the corresponding values used in the TIB/Rendezvous message.

If such fields exist, then the MGW agent uses the field value to set the corresponding Oracle Streams Advanced Queuing message properties, instead of using the default values. If there is more than one such field with the same name, then only the first one is used. Such fields are removed from the resulting payload only if the Oracle Streams Advanced Queuing queue payload is RAW. If a field with the reserved name does not have the expected datatype, then it causes a message conversion failure.


See Also:

"DBMS_MGWMSG" in Oracle Database PL/SQL Packages and Types Reference for the value datatypes

JMS Messages

MGW propagates only JMS messages between Oracle JMS and non-Oracle JMS systems, without changing the message content. Figure 20-5 shows JMS message propagation.

MGW supports only the standard JMS message types. It does not support:

  • JMS provider extensions, because any such extensions would not be recognized by the destination JMS system. An attempt to propagate any such non-JMS message results in an error.

  • User transformations for JMS propagation.

  • Propagation of Logical Change Records (LCRs).

Figure 20-5 JMS Message Propagation

Description of Figure 20-5 follows
Description of "Figure 20-5 JMS Message Propagation"

For the purposes of this discussion, a JMS message is a Java object of a class that implements one of the five JMS message interfaces. Table 20-5 shows the JMS message interfaces and the corresponding Oracle JMS ADTs. The table also shows the interface, javax.jms.Message, which can be any one of the five specific types, and the corresponding generic Oracle JMS type SYS.AQ$_JMS_MESSAGE.

Table 20-5 Oracle JMS Message Conversion

JMS MessageADT

javax.jms.TextMessage

SYS.AQ$_JMS_TEXT_MESSAGE

javax.jms.BytesMessage

SYS.AQ$_JMS_BYTES_MESSAGE

javax.jms.MapMessage

SYS.AQ$_JMS_MAP_MESSAGE

javax.jms.StreamMessage

SYS.AQ$_JMS_STREAM_MESSAGE

javax.jms.ObjectMessage

SYS.AQ$_JMS_OBJECT_MESSAGE

javax.jms.Message

SYS.AQ$_JMS_MESSAGE


When a propagation job is activated, the MGW agent checks the Oracle Streams Advanced Queuing payload type for the propagation source or destination. If the type is one of those listed in Table 20-5 or ANYDATA, then message propagation is attempted. Otherwise an exception is logged and propagation is not attempted.

The MGW agent may add a JMS String property named OracleMGW_OriginalMessageID to the JMS message sent to the destination queue in order to preserve the original message identifier of the source message. This property is added if the PreserveMessageID job option is specified with a value of TRUE. It will also be added for any message moved to an exception queue upon a message conversion failure.

JMS Outbound Propagation

When dequeuing a message from an Oracle Streams Advanced Queuing queue, Oracle JMS converts instances of the ADTs shown in Table 20-5 into JMS messages. In addition it can convert instances of ANYDATA into JMS messages, depending on the content.

A queue with payload type ANYDATA can hold messages that do not map to a JMS message. MGW fails to dequeue such a message. An error is logged and propagation of messages from that queue does not continue until the message is removed.

JMS Inbound Propagation

Every message successfully dequeued using WebSphere MQ JMS is a JMS message. No message conversion is necessary prior to enqueuing using Oracle JMS. However, if the payload ADT of the propagation destination does not accept the type of the inbound message, then an exception is logged and an attempt is made to place the message in an exception queue. An example of such type mismatches is a JMS TextMessage and a queue payload type SYS.AQ$_JMS_BYTES_MESSAGE.

PKq DDPK-AOEBPS/jm_create.htm Introducing Oracle JMS

11 Introducing Oracle JMS

This chapter describes the Oracle Java Message Service (JMS) interface to Oracle Streams Advanced Queuing (AQ).

This chapter contains these topics:

General Features of JMS and Oracle JMS

This section contains these topics:

JMS Connection and Session

This section contains these topics:

ConnectionFactory Objects

A ConnectionFactory encapsulates a set of connection configuration parameters that has been defined by an administrator. A client uses it to create a connection with a JMS provider. In this case Oracle JMS, part of Oracle Database, is the JMS provider.

The three types of ConnectionFactory objects are:

  • ConnectionFactory

  • QueueConnectionFactory

  • TopicConnectionFactory

Using AQjmsFactory to Obtain ConnectionFactory Objects

You can use the AQjmsFactory class to obtain a handle to a ConnectionFactory, QueueConnectionFactory, or TopicConnectionFactory object.

To obtain a ConnectionFactory, which supports both point-to-point and publish/subscribe operations, use AQjmsFactory.getConnectionFactory(). To obtain a QueueConnectionFactory, use AQjmsFactory.getQueueConnectionFactory(). To obtain a TopicConnectionFactory, use AQjmsFactory.getTopicConnectionFactory().

The ConnectionFactory, QueueConnectionFactory, or TopicConnectionFactory can be created using hostname, port number, and SID driver or by using JDBC URL and properties.

Using JNDI to Look Up ConnectionFactory Objects

A JMS administrator can register ConnectionFactory objects in a Lightweight Directory Access Protocol (LDAP) server. The following setup is required to enable Java Naming and Directory Interface (JNDI) lookup in JMS:

  1. Register Database

    When the Oracle Database server is installed, the database must be registered with the LDAP server. This can be accomplished using the Database Configuration Assistant (DBCA). Figure 11-1 shows the structure of Oracle Streams Advanced Queuing entries in the LDAP server. ConnectionFactory information is stored under <cn=OracleDBConnections>, while topics and queues are stored under <cn=OracleDBQueues>.

    Figure 11-1 Structure of Oracle Streams Advanced Queuing Entries in LDAP Server

    Description of Figure 11-1 follows
    Description of "Figure 11-1 Structure of Oracle Streams Advanced Queuing Entries in LDAP Server"

  2. Set Parameter GLOBAL_TOPIC_ENABLED.

    The GLOBAL_TOPIC_ENABLED system parameter for the database must be set to TRUE. This ensures that all queues and topics created in Oracle Streams Advanced Queuing are automatically registered with the LDAP server. This parameter can be set by using ALTER SYSTEM SET GLOBAL_TOPIC_ENABLED = TRUE.

  3. Register ConnectionFactory Objects

    After the database has been set up to use an LDAP server, the JMS administrator can register ConnectionFactory, QueueConnectionFactory, and TopicConnectionFactory objects in LDAP by using AQjmsFactory.registerConnectionFactory().

    The registration can be accomplished in one of the following ways:

    • Connect directly to the LDAP server

      The user must have the GLOBAL_AQ_USER_ROLE to register connection factories in LDAP.

      To connect directly to LDAP, the parameters for the registerConnectionFactory method include the LDAP context, the name of the ConnectionFactory, QueueConnectionFactory, or TopicConnectionFactory, hostname, database SID, port number, JDBC driver (thin or oci8) and factory type (queue or topic).

    • Connect to LDAP through the database server

      The user can log on to Oracle Database first and then have the database update the LDAP entry. The user that logs on to the database must have the AQ_ADMINISTRATOR_ROLE to perform this operation.

      To connect to LDAP through the database server, the parameters for the registerConnectionFactory method include a JDBC connection (to a user having AQ_ADMINISTRATOR_ROLE), the name of the ConnectionFactory, QueueConnectionFactory, or TopicConnectionFactory, hostname, database SID, port number, JDBC driver (thin or oci8) and factory type (queue or topic).

JMS Connection

A JMS Connection is an active connection between a client and its JMS provider. A JMS Connection performs several critical services:

  • Encapsulates either an open connection or a pool of connections with a JMS provider

  • Typically represents an open TCP/IP socket (or a set of open sockets) between a client and a provider's service daemon

  • Provides a structure for authenticating clients at the time of its creation

  • Creates Sessions

  • Provides connection metadata

  • Supports an optional ExceptionListener

A JMS Connection to the database can be created by invoking createConnection(), createQueueConnection(), or createTopicConnection() and passing the parameters username and password on the ConnectionFactory, QueueConnectionFactory, or TopicConnectionFactory object respectively.

Some of the methods that are supported on the Connection object are

  • start()

    This method starts or restart delivery of incoming messages.

  • stop()

    This method temporarily stops delivery of incoming messages. When a Connection object is stopped, delivery to all of its message consumers is inhibited. Also, synchronous receive's block and messages are not delivered to message listener.

  • close()

    This method closes the JMS session and releases all associated resources.

  • createSession(true, 0)

    This method creates a JMS Session using a JMS Connection instance.

  • createQueueSession(true, 0)

    This method creates a QueueSession.

  • createTopicSession(true, 0)

    This method creates a TopicSession.

  • setExceptionListener(ExceptionListener)

    This method sets an exception listener for the Connection. This allows a client to be notified of a problem asynchronously. If a Connection only consumes messages, then it has no other way to learn it has failed.

  • getExceptionListener()

    This method gets the ExceptionListener for this Connection.

A JMS client typically creates a Connection, a Session and a number of MessageProducer and MessageConsumer objects. In the current version only one open Session for each Connection is allowed, except in the following cases:

  • If the JDBC oci8 driver is used to create the JMS connection

  • If the user provides an OracleOCIConnectionPool instance during JMS connection creation

When a Connection is created it is in stopped mode. In this state no messages can be delivered to it. It is typical to leave the Connection in stopped mode until setup is complete. At that point the Connection start() method is called and messages begin arriving at the Connection consumers. This setup convention minimizes any client confusion that can result from asynchronous message delivery while the client is still in the process of setup.

It is possible to start a Connection and to perform setup subsequently. Clients that do this must be prepared to handle asynchronous message delivery while they are still in the process of setting up. A MessageProducer can send messages while a Connection is stopped.

JMS Session

A JMS Session is a single threaded context for producing and consuming messages. Although it can allocate provider resources outside the Java Virtual Machine (JVM), it is considered a lightweight JMS object.

A Session serves several purposes:

  • Constitutes a factory for MessageProducer and MessageConsumer objects

  • Provides a way to get a handle to destination objects (queues/topics)

  • Supplies provider-optimized message factories

  • Supports a single series of transactions that combines work spanning session MessageProducer and MessageConsumer objects, organizing these into units

  • Defines a serial order for the messages it consumes and the messages it produces

  • Serializes execution of MessageListener objects registered with it

In Oracle Database 10g, you can create as many JMS Sessions as resources allow using a single JMS Connection, when using either JDBC thin or JDBC thick (OCI) drivers.

Because a provider can allocate some resources on behalf of a Session outside the JVM, clients should close them when they are not needed. Relying on garbage collection to eventually reclaim these resources may not be timely enough. The same is true for MessageProducer and MessageConsumer objects created by a Session.

Methods on the Session object include:

  • commit()

    This method commits all messages performed in the transaction and releases locks currently held.

  • rollback()

    This method rolls back any messages accomplished in the transaction and release locks currently held.

  • close()

    This method closes the Session.

  • getDBConnection()

    This method gets a handle to the underlying JDBC connection. This handle can be used to perform other SQL DML operations as part of the same Session. The method is specific to Oracle JMS.

  • acknowledge()

    This method acknowledges message receipt in a nontransactional session.

  • recover()

    This method restarts message delivery in a nontransactional session. In effect, the series of delivered messages in the session is reset to the point after the last acknowledged message.

The following are some Oracle JMS extensions:

  • createQueueTable()

    This method creates a queue table.

  • getQueueTable()

    This method gets a handle to an existing queue table.

  • createQueue()

    This method creates a queue.

  • getQueue()

    This method gets a handle to an existing queue.

  • createTopic()

    This method creates a topic.

  • getTopic()

    This method gets a handle to an existing topic.

The Session object must be cast to AQjmsSession to use any of the extensions.


Note:

The JMS specification expects providers to return null messages when receives are accomplished on a JMS Connection instance that has not been started.

After you create a javax.jms.Connection instance, you must call the start() method on it before you can receive messages. If you add a line like t_conn.start(); any time after the connection has been created, but before the actual receive, then you can receive your messages.


JMS Destination

A Destination is an object a client uses to specify the destination where it sends messages, and the source from which it receives messages. A Destination object can be a Queue or a Topic. In Oracle Streams Advanced Queuing, these map to a schema.queue at a specific database. Queue maps to a single-consumer queue, and Topic maps to a multiconsumer queue.

Using a JMS Session to Obtain Destination Objects

Destination objects are created from a Session object using the following domain-specific Session methods:

  • AQjmsSession.getQueue(queue_owner, queue_name)

    This method gets a handle to a JMS queue.

  • AQjmsSession.getTopic(topic_owner, topic_name)

    This method gets a handle to a JMS topic.

Using JNDI to Look Up Destination Objects

The database can be configured to register schema objects with an LDAP server. If a database has been configured to use LDAP and the GLOBAL_TOPIC_ENABLED parameter has been set to TRUE, then all JMS queues and topics are automatically registered with the LDAP server when they are created. The administrator can also create aliases to the queues and topics registered in LDAP. Queues and topics that are registered in LDAP can be looked up through JNDI using the name or alias of the queue or topic.

JMS Destination Methods

Methods on the Destination object include:

  • alter()

    This method alters a Queue or a Topic.

  • schedulePropagation()

    This method schedules propagation from a source to a destination.

  • unschedulePropagation()

    This method unschedules a previously scheduled propagation.

  • enablePropagationSchedule()

    This method enables a propagation schedule.

  • disablePropagationSchedule()

    This method disables a propagation schedule.

  • start()

    This method starts a Queue or a Topic. The queue can be started for enqueue or dequeue. The topic can be started for publish or subscribe.

  • stop()

    This method stops a Queue or a Topic. The queue is stopped for enqueue or dequeue. The topic is stopped for publish or subscribe.

  • drop()

    This method drops a Queue or a Topic.

System-Level Access Control in JMS

Oracle8i or higher supports system-level access control for all queuing operations. This feature allows an application designer or DBA to create users as queue administrators. A queue administrator can invoke administrative and operational JMS interfaces on any queue in the database. This simplifies administrative work, because all administrative scripts for the queues in a database can be managed under one schema.

When messages arrive at the destination queues, sessions based on the source queue schema name are used for enqueuing the newly arrived messages into the destination queues. This means that you must grant enqueue privileges for the destination queues to schemas of the source queues.

To propagate to a remote destination queue, the login user (specified in the database link in the address field of the agent structure) should either be granted the ENQUEUE_ANY privilege, or be granted the rights to enqueue to the destination queue. However, you are not required to grant any explicit privileges if the login user in the database link also owns the queue tables at the destination.

Destination-Level Access Control in JMS

Oracle8i or higher supports access control for enqueue and dequeue operations at the queue or topic level. This feature allows the application designer to protect queues and topics created in one schema from applications running in other schemas. You can grant only minimal access privileges to the applications that run outside the schema of the queue or topic. The supported access privileges on a queue or topic are ENQUEUE, DEQUEUE and ALL.

Retention and Message History in JMS

Messages are often related to each other. For example, if a message is produced as a result of the consumption of another message, then the two are related. As the application designer, you may want to keep track of such relationships. Oracle Streams Advanced Queuing allows users to retain messages in the queue table, which can then be queried in SQL for analysis.

Along with retention and message identifiers, Oracle Streams Advanced Queuing lets you automatically create message journals, also called tracking journals or event journals. Taken together, retention, message identifiers and SQL queries make it possible to build powerful message warehouses.

Supporting Oracle Real Application Clusters in JMS

Oracle Real Application Clusters (Oracle RAC) can be used to improve Oracle Streams Advanced Queuing performance by allowing different queues to be managed by different instances. You do this by specifying different instance affinities (preferences) for the queue tables that store the queues. This allows queue operations (enqueue/dequeue) or topic operations (publish/subscribe) on different queues or topics to occur in parallel.

The Oracle Streams Advanced Queuing queue monitor process continuously monitors the instance affinities of the queue tables. The queue monitor assigns ownership of a queue table to the specified primary instance if it is available, failing which it assigns it to the specified secondary instance.

If the owner instance of a queue table terminates, then the queue monitor changes ownership to a suitable instance such as the secondary instance.

Oracle Streams Advanced Queuing propagation is able to make use of Oracle Real Application Clusters, although it is transparent to the user. The affinities for jobs submitted on behalf of the propagation schedules are set to the same values as that of the affinities of the respective queue tables. Thus, a job_queue_process associated with the owner instance of a queue table is handling the propagation from queues stored in that queue table, thereby minimizing pinging.

Supporting Statistics Views in JMS

Each instance keeps its own Oracle Streams Advanced Queuing statistics information in its own System Global Area (SGA), and does not have knowledge of the statistics gathered by other instances. Then, when a GV$AQ view is queried by an instance, all other instances funnel their statistics information to the instance issuing the query.

The GV$AQ view can be queried at any time to see the number of messages in waiting, ready or expired state. The view also displays the average number of seconds messages have been waiting to be processed.

Structured Payload/Message Types in JMS

JMS messages are composed of a header, properties, and a body.

The header consists of header fields, which contain values used by both clients and providers to identify and route messages. All messages support the same set of header fields.

Properties are optional header fields. In addition to standard properties defined by JMS, there can be provider-specific and application-specific properties.

The body is the message payload. JMS defines various types of message payloads, and a type that can store JMS messages of any or all JMS-specified message types.

This section contains these topics:

JMS Message Headers

A JMS message header contains the following fields:

  • JMSDestination

    This field contains the destination to which the message is sent. In Oracle Streams Advanced Queuing this corresponds to the destination queue/topic. It is a Destination type set by JMS after the Send method has completed.

  • JMSDeliveryMode

    This field determines whether the message is logged or not. JMS supports PERSISTENT delivery (where messages are logged to stable storage) and NONPERSISTENT delivery (messages not logged). It is a INTEGER set by JMS after the Send method has completed. JMS permits an administrator to configure JMS to override the client-specified value for JMSDeliveryMode.

  • JMSMessageID

    This field uniquely identifies a message in a provider. All message IDs must begin with the string ID:. It is a String type set by JMS after the Send method has completed.

  • JMSTimeStamp

    This field contains the time the message was handed over to the provider to be sent. This maps to Oracle Streams Advanced Queuing message enqueue time. It is a Long type set by JMS after the Send method has completed.

  • JMSCorrelationID

    This field can be used by a client to link one message with another. It is a String type set by the JMS client.

  • JMSReplyTo

    This field contains a Destination type supplied by a client when a message is sent. Clients can use oracle.jms.AQjmsAgent; javax.jms.Queue; or javax.jms.Topic.

  • JMSType

    This field contains a message type identifier supplied by a client at send time. It is a String type. For portability Oracle recommends that the JMSType be symbolic values.

  • <li>

    JMSExpiration

    This field is the sum of the enqueue time and the TimeToLive in non-J2EE compliance mode. In compliant mode, the JMSExpiration header value in a dequeued message is the sum of JMSTimeStamp when the message was enqueued (Greenwich Mean Time, in milliseconds) and the TimeToLive (in milliseconds). It is a Long type set by JMS after the Send method has completed. JMS permits an administrator to configure JMS to override the client-specified value for JMSExpiration.

  • JMSPriority

    This field contains the priority of the message. It is a INTEGER set by JMS after the Send method has completed. In J2EE-compliance mode, the permitted values for priority are 09, with 9 the highest priority and 4 the default, in conformance with the Sun Microsystem JMS 1.1 standard. Noncompliant mode is the default. JMS permits an administrator to configure JMS to override the client-specified value for JMSPriority.

  • JMSRedelivered

    This field is a Boolean set by the JMS provider.


See Also:

"J2EE Compliance"

JMS Message Properties

JMS properties are set either explicitly by the client or automatically by the JMS provider (these are generally read-only). Some JMS properties are set using the parameters specified in Send and Receive operations.

Properties add optional header fields to a message. Properties allow a client, using a messageSelector, to have a JMS provider select messages on its behalf using application-specific criteria. Property names are strings and values can be: Boolean, byte, short, int, long, float, double, and string.

JMS-defined properties, which all begin with "JMSX", include the following:

  • JMSXUserID

    This field is the identity of the user sending the message. It is a String type set by JMS after the Send method has completed.

  • JMSXAppID

    This field is the identity of the application sending the message. It is a String type set by JMS after the Send method has completed.

  • JMSXDeliveryCount

    This field is the number of message delivery attempts. It is an Integer set by JMS after the Send method has completed.

  • JMSXGroupid

    This field is the identity of the message group that this message belongs to. It is a String type set by the JMS client.

  • JMSXGroupSeq

    This field is the sequence number of a message within a group. It is an Integer set by the JMS client.

  • JMSXRcvTimeStamp

    This field is the time the message was delivered to the consumer (dequeue time). It is a String type set by JMS after the Receive method has completed.

  • JMSXState

    This field is the message state, set by the provider. The message state can be WAITING, READY, EXPIRED, or RETAINED.

Oracle-specific JMS properties, which all begin with JMS_Oracle, include the following:

  • JMS_OracleExcpQ

    This field is the queue name to send the message to if it cannot be delivered to the original destination. It is a String type set by the JMS client. Only destinations of type EXCEPTION can be specified in the JMS_OracleExcpQ property.

  • JMS_OracleDelay

    This field is the time in seconds to delay the delivery of the message. It is an Integer set by the JMS client. This can affect the order of message delivery.

  • JMS_OracleOriginalMessageId

    This field is set to the message identifier of the message in the source if the message is propagated from one destination to another. It is a String type set by the JMS provider. If the message is not propagated, then this property has the same value as JMSMessageId.

A client can add additional header fields to a message by defining properties. These properties can then be used in a messageSelector to select specific messages.

JMS Message Bodies

JMS provides five forms of message body:

StreamMessage

A StreamMessage object is used to send a stream of Java primitives. It is filled and read sequentially. It inherits from Message and adds a StreamMessage body. Its methods are based largely on those found in java.io.DataInputStream and java.io.DataOutputStream.

The primitive types can be read or written explicitly using methods for each type. They can also be read or written generically as objects. To use StreamMessage objects, create the queue table with the SYS.AQ$_JMS_STREAM_MESSAGE or AQ$_JMS_MESSAGE payload types.

StreamMessage objects support the conversions shown in Table 11-1. A value written as the row type can be read as the column type.

Table 11-1 StreamMessage Conversion

InputBooleanbyteshortcharintlongfloatdoubleStringbyte[]

Boolean

X

-

-

-

-

-

-

-

X

-

byte

-

X

X

-

X

X

-

-

X

-

short

-

-

X

-

X

X

-

-

X

-

char

-

-

-

X

-

-

-

-

X

-

int

-

-

-

-

X

X

-

-

X

-

long

-

-

-

-

-

X

-

-

X

-

float

-

-

-

-

-

-

X

X

X

-

double

-

-

-

-

-

-

-

X

X

-

string

X

X

X

X

X

X

X

X

X

-

byte[]

-

-

-

-

-

-

-

-

-

X


BytesMessage

A BytesMessage object is used to send a message containing a stream of uninterpreted bytes. It inherits Message and adds a BytesMessage body. The receiver of the message interprets the bytes. Its methods are based largely on those found in java.io.DataInputStream and java.io.DataOutputStream.

This message type is for client encoding of existing message formats. If possible, one of the other self-defining message types should be used instead.

The primitive types can be written explicitly using methods for each type. They can also be written generically as objects. To use BytesMessage objects, create the queue table with SYS.AQ$_JMS_BYTES_MESSAGE or AQ$_JMS_MESSAGE payload types.

MapMessage

A MapMessage object is used to send a set of name-value pairs where the names are String types, and the values are Java primitive types. The entries can be accessed sequentially or randomly by name. The order of the entries is undefined. It inherits from Message and adds a MapMessage body. The primitive types can be read or written explicitly using methods for each type. They can also be read or written generically as objects.

To use MapMessage objects, create the queue table with the SYS.AQ$_JMS_MAP_MESSAGE or AQ$_JMS_MESSAGE payload types. MapMessage objects support the conversions shown in Table 11-2. An "X" in the table means that a value written as the row type can be read as the column type.

Table 11-2 MapMessage Conversion

InputBooleanbyteshortcharintlongfloatdoubleStringbyte[]

Boolean

X

-

-

-

-

-

-

-

X

-

byte

-

X

X

-

X

X

-

-

X

-

short

-

-

X

-

X

X

-

-

X

-

char

-

-

-

X

-

-

-

-

X

-

int

-

-

-

-

X

X

-

-

X

-

long

-

-

-

-

-

X

-

-

X

-

float

-

-

-

-

-

-

X

X

X

-

double

-

-

-

-

-

-

-

X

X

-

string

X

X

X

X

X

X

X

X

X

-

byte[]

-

-

-

-

-

-

-

-

-

X


TextMessage

A TextMessage object is used to send a message containing a java.lang.StringBuffer. It inherits from Message and adds a TextMessage body. The text information can be read or written using methods getText() and setText(...). To use TextMessage objects, create the queue table with the SYS.AQ$_JMS_TEXT_MESSAGE or AQ$_JMS_MESSAGE payload types.

ObjectMessage

An ObjectMessage object is used to send a message that contains a serializable Java object. It inherits from Message and adds a body containing a single Java reference. Only serializable Java objects can be used. If a collection of Java objects must be sent, then one of the collection classes provided in JDK 1.4 can be used. The objects can be read or written using the methods getObject() and setObject(...).To use ObjectMessage objects, create the queue table with the SYS.AQ$_JMS_OBJECT_MESSAGE or AQ$_JMS_MESSAGE payload types.

AdtMessage

An AdtMessage object is used to send a message that contains a Java object that maps to an Oracle object type. These objects inherit from Message and add a body containing a Java object that implements the CustomDatum or ORAData interface.


See Also:

Oracle Database Java Developer's Guide for information about the CustomDatum and ORAData interfaces

To use AdtMessage objects, create the queue table with payload type as the Oracle object type. The AdtMessage payload can be read and written using the getAdtPayload and setAdtPayload methods.

You can also use an AdtMessage object to send messages to queues of type SYS.XMLType. You must use the oracle.xdb.XMLType class to create the message.

For AdtMessage objects, the client can get:

  • JMSXDeliveryCount

  • JMSXRecvTimeStamp

  • JMSXState

  • JMS_OracleExcpQ

  • JMS_OracleDelay

Using Message Properties with Different Message Types

The following message properties can be set by the client using the setProperty call. For StreamMessage, BytesMessage, ObjectMessage, TextMessage, and MapMessage objects, the client can set:

  • JMSXAppID

  • JMSXGroupID

  • JMSXGroupSeq

  • JMS_OracleExcpQ

  • JMS_OracleDelay

For AdtMessage objects, the client can set:

  • JMS_OracleExcpQ

  • JMS_OracleDelay

The following message properties can be obtained by the client using the getProperty call. For StreamMessage, BytesMessage, ObjectMessage, TextMessage, and MapMessage objects, the client can get:

  • JMSXuserID

  • JMSXAppID

  • JMSXDeliveryCount

  • JMSXGroupID

  • JMSXGroupSeq

  • JMSXRecvTimeStamp

  • JMSXState

  • JMS_OracleExcpQ

  • JMS_OracleDelay

  • JMS_OracleOriginalMessageID

Buffered Messaging with Oracle JMS

Users can send a nonpersistent JMS message by specifying the deliveryMode to be NON_PERSISTENT when sending a message. JMS nonpersistent messages are not required to be logged to stable storage, so they can be lost after a JMS system failure. JMS nonpersistent messages are similar to the buffered messages now available in Oracle Streams Advanced Queuing, but there are also important differences between the two.


Note:

Do not confuse Oracle JMS nonpersistent messages with Oracle Streams Advanced Queuing nonpersistent queues, which are deprecated in Oracle Database 10g Release 2 (10.2).

Transaction Commits and Client Acknowledgments

The JMS deliveryMode is orthogonal to the transaction attribute of a message. JMS nonpersistent messages can be sent and received by either a transacted session or a nontransacted session. If a JMS nonpersistent message is sent and received by a transacted session, then the effect of the JMS operation is only visible after the transacted session commits. If it is received by a nontransacted session with CLIENT_ACKNOWLEDGE acknowledgment mode, then the effect of receiving this message is only visible after the client acknowledges the message. Without the acknowledgment, the message is not removed and will be redelivered if the client calls Session.recover.

Oracle Streams Advanced Queuing buffered messages, on the other hand, do not support these transaction or acknowledgment concepts. Both sending and receiving a buffered message must be in the IMMEDIATE visibility mode. The effects of the sending and receiving operations are therefore visible to the user immediately, no matter whether the session is committed or the messages are acknowledged.

Different APIs

Messages sent with the regular JMS send and publish methods are treated by Oracle Streams Advanced Queuing as persistent messages. The regular JMS receive methods receive only AQ persistent messages. To send and receive buffered messages, you must use the Oracle extension APIs bufferSend, bufferPublish, and bufferReceive.


See Also:

Oracle Streams Advanced Queuing Java API Reference for more information on bufferSend, bufferPublish, and bufferReceive

Payload Limits

The Oracle Streams Advanced Queuing implementation of buffered messages does not support LOB attributes. This places limits on the payloads for the five types of standard JMS messages:

  • JMS TextMessage payloads cannot exceed 4000 bytes.

    This limit might be even lower with some database character sets, because during the Oracle JMS character set conversion, Oracle JMS sometimes must make a conservative choice of using CLOB instead of VARCHAR to store the text payload in the database.

  • JMS BytesMessage payloads cannot exceed 2000 bytes.

  • JMS ObjectMessage, StreamMessage, and MapMessage data serialized by JAVA cannot exceed 2000 bytes.

  • For all other Oracle JMS ADT messages, the corresponding Oracle database ADT cannot contain LOB attributes.

Different Constants

The Oracle Streams Advanced Queuing and Oracle JMS APIs use different numerical values to designate buffered and persistent messages, as shown in Table 11-3.

Table 11-3 Oracle Streams AQ and Oracle JMS Buffered Messaging Constants

APIPersistent MessageBuffered Message

Oracle Streams Advanced Queuing


PERSISTENT := 1

BUFFERED :=2

Oracle JMS

PERSISTENT := 2

NON_PERSISTENT := 1


JMS Point-to-Point Model Features

In the point-to-point model, clients exchange messages from one point to another. Message producers and consumers send and receive messages using single-consumer queues. An administrator creates the single-consumer queues with the createQueue method in AQjmsSession. Before they can be used, the queues must be enabled for enqueue/dequeue using the start call in AQjmsDestination. Clients obtain a handle to a previously created queue using the getQueue method on AQjmsSession.

In a single-consumer queue, a message can be consumed exactly once by a single consumer. If there are multiple processes or operating system threads concurrently dequeuing from the same queue, then each process dequeues the first unlocked message at the head of the queue. A locked message cannot be dequeued by a process other than the one that has created the lock.

After processing, the message is removed if the retention time of the queue is 0, or it is retained for a specified retention time. As long as the message is retained, it can be either queried using SQL on the queue table view or dequeued by specifying the message identifier of the processed message in a QueueBrowser.

QueueSender

A client uses a QueueSender to send messages to a queue. It is created by passing a queue to the createSender method in a client Session. A client also has the option of creating a QueueSender without supplying a queue. In that case a queue must be specified on every send operation.

A client can specify a default delivery mode, priority and TimeToLive for all messages sent by the QueueSender. Alternatively, the client can define these options for each message.

QueueReceiver

A client uses a QueueReceiver to receive messages from a queue. It is created using the createQueueReceiver method in a client Session. It can be created with or without a messageSelector.

QueueBrowser

A client uses a QueueBrowser to view messages on a queue without removing them. The browser method returns a java.util.Enumeration that is used to scan messages in the queue. The first call to nextElement gets a snapshot of the queue. A QueueBrowser can be created with or without a messageSelector.

A QueueBrowser can also optionally lock messages as it is scanning them. This is similar to a "SELECT... for UPDATE" command on the message. This prevents other consumers from removing the message while they are being scanned.

MessageSelector

A messageSelector allows the client to restrict messages delivered to the consumer to those that match the messageSelector expression. A messageSelector for queues containing payloads of type TextMessage, StreamMessage, BytesMessage, ObjectMessage, or MapMessage can contain any expression that has one or more of the following:

  • JMS message identifier prefixed with "ID:"

    JMSMessageID ='ID:23452345'
    
  • JMS message header fields or properties

    JMSPriority < 3 AND JMSCorrelationID = 'Fiction'
    
    JMSCorrelationID LIKE 'RE%'
    
  • User-defined message properties

    color IN ('RED', BLUE', 'GREEN') AND price < 30000 
    

The messageSelector for queues containing payloads of type AdtMessage can contain any expression that has one or more of the following:

  • Message identifier without the "ID:" prefix

    msgid = '23434556566767676'
    
  • Priority, correlation identifier, or both

    priority < 3 AND corrid = 'Fiction'
    
  • Message payload

    tab.user_data.color = 'GREEN' AND tab.user_data.price < 30000
    

JMS Publish/Subscribe Model Features

This section contains these topics:

JMS Publish/Subscribe Overview

JMS enables flexible and dynamic communication between applications functioning as publishers and applications playing the role of subscribers. The applications are not coupled together; they interact based on messages and message content.

In distributing messages, publisher applications are not required to handle or manage message recipients explicitly. This allows new subscriber applications to be added dynamically without changing any publisher application logic.

Similarly, subscriber applications receive messages based on message content without regard to which publisher applications are sending messages. This allows new publisher applications to be added dynamically without changing any subscriber application logic.

Subscriber applications specify interest by defining a rule-based subscription on message properties or the message content of a topic. The system automatically routes messages by computing recipients for published messages using the rule-based subscriptions.

In the publish/subscribe model, messages are published to and received from topics. A topic is created using the CreateTopic() method in an AQjmsSession. A client can obtain a handle to a previously-created topic using the getTopic() method in AQjmsSession.

DurableSubscriber

A client creates a DurableSubscriber with the createDurableSubscriber() method in a client Session. It can be created with or without a messageSelector.

A messageSelector allows the client to restrict messages delivered to the subscriber to those that match the selector. The syntax for the selector is described in detail in createDurableSubscriber in Oracle Streams Advanced Queuing Java API Reference.


See Also:

"MessageSelector"

When subscribers use the same name, durable subscriber action depends on the J2EE compliance mode set for an Oracle Java Message Service (OJMS) client at runtime.


See Also:

"J2EE Compliance"

In noncompliant mode, two durable TopicSubscriber objects with the same name can be active against two different topics. In compliant mode, durable subscribers with the same name are not allowed. If two subscribers use the same name and are created against the same topic, but the selector used for each subscriber is different, then the underlying Oracle Streams Advanced Queuing subscription is altered using the internal DBMS_AQJMS.ALTER_SUBSCRIBER() call.

If two subscribers use the same name and are created against two different topics, and if the client that uses the same subscription name also originally created the subscription name, then the existing subscription is dropped and the new subscription is created.

If two subscribers use the same name and are created against two different topics, and if a different client (a client that did not originate the subscription name) uses an existing subscription name, then the subscription is not dropped and an error is thrown. Because it is not known if the subscription was created by JMS or PL/SQL, the subscription on the other topic should not be dropped.

RemoteSubscriber

Remote subscribers are defined using the createRemoteSubscriber call. The remote subscriber can be a specific consumer at the remote topic or all subscribers at the remote topic

A remote subscriber is defined using the AQjmsAgent structure. An AQjmsAgent consists of a name and address. The name refers to the consumer_name at the remote topic. The address refers to the remote topic:

schema.topic_name[@dblink]

To publish messages to a particular consumer at the remote topic, the subscription_name of the recipient at the remote topic must be specified in the name field of AQjmsAgent. The remote topic must be specified in the address field of AQjmsAgent.

To publish messages to all subscribers of the remote topic, the name field of AQjmsAgent must be set to null. The remote topic must be specified in the address field of AQjmsAgent.

TopicPublisher

Messages are published using TopicPublisher, which is created by passing a Topic to a createPublisher method. A client also has the option of creating a TopicPublisher without supplying a Topic. In this case, a Topic must be specified on every publish operation. A client can specify a default delivery mode, priority and TimeToLive for all messages sent by the TopicPublisher. It can also specify these options for each message.

Recipient Lists

In the JMS publish/subscribe model, clients can specify explicit recipient lists instead of having messages sent to all the subscribers of the topic. These recipients may or may not be existing subscribers of the topic. The recipient list overrides the subscription list on the topic for this message. Recipient lists functionality is an Oracle extension to JMS.

TopicReceiver

If the recipient name is explicitly specified in the recipient list, but that recipient is not a subscriber to the queue, then messages sent to it can be received by creating a TopicReceiver. If the subscriber name is not specified, then clients must use durable subscribers at the remote site to receive messages. TopicReceiver is an Oracle extension to JMS.

A TopicReceiver can be created with a messageSelector. This allows the client to restrict messages delivered to the recipient to those that match the selector.


See Also:

"MessageSelector"

TopicBrowser

A client uses a TopicBrowser to view messages on a topic without removing them. The browser method returns a java.util.Enumeration that is used to scan topic messages. Only durable subscribers are allowed to create a TopicBrowser. The first call to nextElement gets a snapshot of the topic.

A TopicBrowser can optionally lock messages as it is scanning them. This is similar to a SELECT... for UPDATE command on the message. This prevents other consumers from removing the message while it is being scanned.

A TopicBrowser can be created with a messageSelector. This allows the client to restrict messages delivered to the browser to those that match the selector.


See Also:

"MessageSelector"

TopicBrowser supports a purge feature. This allows a client using a TopicBrowser to discard all messages that have been seen during the current browse operation on the topic. A purge is equivalent to a destructive receive of all of the seen messages (as if performed using a TopicSubscriber).

For a purge, a message is considered seen if it has been returned to the client using a call to the nextElement() operation on the java.lang.Enumeration for the TopicBrowser. Messages that have not yet been seen by the client are not discarded during a purge. A purge operation can be performed multiple times on the same TopicBrowser.

The effect of a purge becomes stable when the JMS Session used to create the TopicBrowser is committed. If the operations on the session are rolled back, then the effects of the purge operation are also undone.

Setting Up JMS Publish/Subscribe Operations

Follow these steps to use the publish/subscribe model of communication in JMS:

  1. Set up one or more topics to hold messages. These topics represent an area or subject of interest. For example, a topic can represent billed orders.

  2. Enable enqueue/dequeue on the topic using the start call in AQjmsDestination.

  3. Create a set of durable subscribers. Each subscriber can specify a messageSelector that selects the messages that the subscriber wishes to receive. A null messageSelector indicates that the subscriber wishes to receive all messages published on the topic.

    Subscribers can be local or remote. Local subscribers are durable subscribers defined on the same topic on which the message is published. Remote subscribers are other topics, or recipients on other topics that are defined as subscribers to a particular queue. In order to use remote subscribers, you must set up propagation between the source and destination topics. Remote subscribers and propagation are Oracle extensions to JMS.

  4. Create TopicPublisher objects using the createPublisher() method in the publisher Session. Messages are published using the publish call. Messages can be published to all subscribers to the topic or to a specified subset of recipients on the topic.

  5. Subscribers receive messages on the topic by using the receive method.

  6. Subscribers can also receive messages asynchronously by using message listeners.

JMS MessageProducer Features

Priority and Ordering of Messages

Message ordering dictates the order in which messages are received from a queue or topic. The ordering method is specified when the queue table for the queue or topic is created. Currently, Oracle Streams Advanced Queuing supports ordering on message priority and enqueue time, producing four possible ways of ordering:

  • First-In, First-Out (FIFO)

    If enqueue time was chosen as the ordering criteria, then messages are received in the order of the enqueue time. The enqueue time is assigned to the message by Oracle Streams Advanced Queuing at message publish/send time. This is also the default ordering.

  • Priority Ordering

    If priority orderiz1ng was chosen, then each message is assigned a priority. Priority can be specified as a message property at publish/send time by the MessageProducer. The messages are received in the order of the priorities assigned.

  • FIFO Priority

    If FIFO priority ordering was chosen, then the topic/queue acts like a priority queue. If two messages are assigned the same priority, then they are received in the order of their enqueue time.

  • Enqueue Time Followed by Priority

    Messages with the same enqueue time are received according to their priorities. If the ordering criteria of two message is the same, then the order they are received is indeterminate. However, Oracle Streams Advanced Queuing does ensure that messages produced in one session with a particular ordering criteria are received in the order they were sent.

Specifying a Message Delay

Messages can be sent/published to a queue/topic with delay. The delay represents a time interval after which the message becomes available to the message consumer. A message specified with a delay is in a waiting state until the delay expires. Receiving by message identifier overrides the delay specification.

Delay is an Oracle Streams Advanced Queuing extension to JMS message properties. It requires the Oracle Streams Advanced Queuing background process queue monitor to be started.

Specifying a Message Expiration

Producers of messages can specify expiration limits, or TimeToLive for messages. This defines the period of time the message is available for a Message Consumer.

TimeToLive can be specified at send/publish time or using the set TimeToLive method of a MessageProducer, with the former overriding the latter. The Oracle Streams Advanced Queuing background process queue monitor must be running to implement TimeToLive.

Message Grouping

Messages belonging to a queue/topic can be grouped to form a set that can be consumed by only one consumer at a time. This requires the queue/topic be created in a queue table that is enabled for transactional message grouping. All messages belonging to a group must be created in the same transaction, and all messages created in one transaction belong to the same group.

Message grouping is an Oracle Streams Advanced Queuing extension to the JMS specification.

You can use this feature to divide a complex message into a linked series of simple messages. For example, an invoice directed to an invoices queue could be divided into a header message, followed by several messages representing details, followed by the trailer message.

Message grouping is also very useful if the message payload contains complex large objects such as images and video that can be segmented into smaller objects.

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

Message grouping is preserved during propagation. The destination topic must be enabled for transactional grouping.


See Also:

"Dequeue Features" for a discussion of restrictions you must keep in mind if message grouping is to be preserved while dequeuing messages from a queue enabled for transactional grouping

JMS Message Consumer Features

This section contains these topics:

Receiving Messages

A JMS application can receive messages by creating a message consumer. Messages can be received synchronously using the receive call or asynchronously using a message listener.

There are three modes of receive:

  • Block until a message arrives for a consumer

  • Block for a maximum of the specified time

  • Nonblocking

Message Navigation in Receive

If a consumer does not specify a navigation mode, then its first receive in a session retrieves the first message in the queue or topic, its second receive gets the next message, and so on. If a high priority message arrives for the consumer, then the consumer does not receive the message until it has cleared the messages that were already there before it.

To provide the consumer better control in navigating the queue for its messages, Oracle Streams Advanced Queuing offers several navigation modes as JMS extensions. These modes can be set at the TopicSubscriber, QueueReceiver or the TopicReceiver.

Two modes are available for ungrouped messages:

  • FIRST_MESSAGE

    This mode resets the position to the beginning of the queue. It is useful for priority ordered queues, because it allows the consumer to remove the message on the top of the queue.

  • NEXT_MESSAGE

    This mode gets whatever message follows the established position of the consumer. For example, a NEXT_MESSAGE applied when the position is at the fourth message will get the fifth message in the queue. This is the default action.

Three modes are available for grouped messages:

  • FIRST_MESSAGE

    This mode resets the position to the beginning of the queue.

  • NEXT_MESSAGE

    This mode sets the position to the next message in the same transaction.

  • NEXT_TRANSACTION

    This mode sets the position to the first message in the next transaction.

The transaction grouping property can be negated if messages are received in the following ways:

  • Receive by specifying a correlation identifier in the selector

  • Receive by specifying a message identifier in the selector

  • Committing before all the messages of a transaction group have been received

If the consumer reaches the end of the queue while using the NEXT_MESSAGE or NEXT_TRANSACTION option, and you have specified a blocking receive(), then the navigating position is automatically changed to the beginning of the queue.

By default, a QueueReceiver, TopicReceiver, or TopicSubscriber uses FIRST_MESSAGE for the first receive call, and NEXT_MESSAGE for subsequent receive() calls.

Browsing Messages

Aside from the usual receive, which allows the dequeuing client to delete the message from the queue, JMS provides an interface that allows the JMS client to browse its messages in the queue. A QueueBrowser can be created using the createBrowser method from QueueSession.

If a message is browsed, then it remains available for further processing. That does not necessarily mean that the message will remain available to the JMS session after it is browsed, because a receive call from a concurrent session might remove it.

To prevent a viewed message from being removed by a concurrent JMS client, you can view the message in the locked mode. To do this, you must create a QueueBrowser with the locked mode using the Oracle Streams Advanced Queuing extension to the JMS interface. The lock on the message is released when the session performs a commit or a rollback.

To remove a message viewed by a QueueBrowser, the session must create a QueueReceiver and use the JMSmesssageID as the selector.

Remove No Data

The consumer can remove a message from a queue or topic without retrieving it using the receiveNoData call. This is useful when the application has already examined the message, perhaps using a QueueBrowser. This mode allows the JMS client to avoid the overhead of retrieving a payload from the database, which can be substantial for a large message.

Retry with Delay Interval

If a transaction receiving a message from a queue/topic fails, then it is regarded as an unsuccessful attempt to remove the message. Oracle Streams Advanced Queuing records the number of failed attempts to remove the message in the message history.

An application can specify the maximum number of retries supported on messages at the queue/topic level. If the number of failed attempts to remove a message exceeds this maximum, then the message is moved to an exception queue.

Oracle Streams Advanced Queuing allows users to specify a retry_delay along with max_retries. This means that a message that has undergone a failed attempt at retrieving remains visible in the queue for dequeue after retry_delay interval. Until then it is in the WAITING state. The Oracle Streams Advanced Queuing background process time manager enforces the retry delay property.

The maximum retries and retry delay are properties of the queue/topic. They can be set when the queue/topic is created or by using the alter method on the queue/topic. The default value for MAX_RETRIES is 5.

Asynchronously Receiving Messages Using MessageListener

The JMS client can receive messages asynchronously by setting the MessageListener using the setMessageListener method.

When a message arrives for the consumer, the onMessage method of the message listener is invoked with the message. The message listener can commit or terminate the receipt of the message. The message listener does not receive messages if the JMS Connection has been stopped. The receive call must not be used to receive messages once the message listener has been set for the consumer.

The JMS client can receive messages asynchronously for all consumers in the session by setting the MessageListener at the session. No other mode for receiving messages must be used in the session once the message listener has been set.

Exception Queues

An exception queue is a repository for all expired or unserviceable messages. Applications cannot directly enqueue into exception queues. However, an application that intends to handle these expired or unserviceable messages can receive/remove them from the exception queue.

To retrieve messages from exception queues, the JMS client must use the point-to-point interface. The exception queue for messages intended for a topic must be created in a queue table with multiple consumers enabled. Like any other queue, the exception queue must be enabled for receiving messages using the start method in the AQOracleQueue class. You get an exception if you try to enable it for enqueue.

The exception queue is an Oracle-specific message property called "JMS_OracleExcpQ" that can be set with the message before sending/publishing it. If an exception queue is not specified, then the default exception queue is used. The default exception queue is automatically created when the queue table is created and is named AQ$_queue_table_name_E.

Messages are moved to the exception queue under the following conditions:

  • The message was not dequeued within the specified timeToLive.

    For messages intended for more than one subscriber, the message is moved to the exception queue if one or more of the intended recipients is not able to dequeue the message within the specified timeToLive.

  • The message was received successfully, but the application terminated the transaction that performed the receive because of an error while processing the message. The message is returned to the queue/topic and is available for any applications that are waiting to receive messages.

    A receive is considered rolled back or undone if the application terminates the entire transaction, or if it rolls back to a savepoint that was taken before the receive.

    Because this was a failed attempt to receive the message, its retry count is updated. If the retry count of the message exceeds the maximum value specified for the queue/topic where it resides, then it is moved to the exception queue.

    If a message has multiple subscribers, then the message is moved to the exception queue only when all the recipients of the message have exceeded the retry limit.


Note:

If a dequeue transaction failed because the server process died (including ALTER SYSTEM KILL SESSION) or SHUTDOWN ABORT on the instance, then RETRY_COUNT is not incremented.

JMS Propagation

This section contains these topics:

RemoteSubscriber

Oracle Streams Advanced Queuing allows a subscriber at another database to subscribe to a topic. If a message published to the topic meets the criterion of the remote subscriber, then it is automatically propagated to the queue/topic at the remote database specified for the remote subscriber. Propagation is performed using database links and Oracle Net Services. This enables applications to communicate with each other without having to be connected to the same database.

There are two ways to implement remote subscribers:

  • The createRemoteSubscriber method can be used to create a remote subscriber to/on the topic. The remote subscriber is specified as an instance of the class AQjmsAgent.

  • The AQjmsAgent has a name and an address. The address consists of a queue/topic and the database link to the database of the subscriber.

There are two kinds of remote subscribers:

  • The remote subscriber is a topic.

    This occurs when no name is specified for the remote subscriber in the AQjmsAgent object and the address is a topic. The message satisfying the subscriber's subscription is propagated to the remote topic. The propagated message is now available to all the subscriptions of the remote topic that it satisfies.

  • A specific remote recipient is specified for the message.

    The remote subscription can be for a particular consumer at the remote database. If the name of the remote recipient is specified (in the AQjmsAgent object), then the message satisfying the subscription is propagated to the remote database for that recipient only. The recipient at the remote database uses the TopicReceiver interface to retrieve its messages. The remote subscription can also be for a point-to-point queue.

Scheduling Propagation

Propagation must be scheduled using the schedule_propagation method for every topic from which messages are propagated to target destination databases.

A schedule indicates the time frame during which messages can be propagated from the source topic. This time frame can depend on a number of factors such as network traffic, the load at the source database, the load at the destination database, and so on. The schedule therefore must be tailored for the specific source and destination. When a schedule is created, a job is automatically submitted to the job_queue facility to handle propagation.

The administrative calls for propagation scheduling provide great flexibility for managing the schedules. The duration or propagation window parameter of a schedule specifies the time frame during which propagation must take place. If the duration is unspecified, then the time frame is an infinite single window. If a window must be repeated periodically, then a finite duration is specified along with a next_time function that defines the periodic interval between successive windows.

The propagation schedules defined for a queue can be changed or dropped at any time during the life of the queue. In addition there are calls for temporarily disabling a schedule (instead of dropping the schedule) and enabling a disabled schedule. A schedule is active when messages are being propagated in that schedule. All the administrative calls can be made irrespective of whether the schedule is active or not. If a schedule is active, then it takes a few seconds for the calls to be executed.

Job queue processes must be started for propagation to take place. At least 2 job queue processes must be started. The database links to the destination database must also be valid. The source and destination topics of the propagation must be of the same message type. The remote topic must be enabled for enqueue. The user of the database link must also have enqueue privileges to the remote topic.

Enhanced Propagation Scheduling Capabilities

Catalog views defined for propagation provide the following information about active schedules:

  • Name of the background process handling the schedule

  • SID (session and serial number) for the session handling the propagation

  • Instance handling a schedule (if using Oracle RAC)

  • Previous successful execution of a schedule

  • Next planned execution of a schedule

The following propagation statistics are maintained for each schedule, providing useful information to queue administrators for tuning:

  • The total number of messages propagated in a schedule

  • Total number of bytes propagated in a schedule

  • Maximum number of messages propagated in a window

  • Maximum number of bytes propagated in a window

  • Average number of messages propagated in a window

  • Average size of propagated messages

  • Average time to propagated a message

Propagation has built-in support for handling failures and reporting errors. For example, if the database link specified is invalid, or if the remote database is unavailable, or if the remote topic/queue is not enabled for enqueuing, then the appropriate error message is reported. Propagation uses an exponential backoff scheme for retrying propagation from a schedule that encountered a failure. If a schedule continuously encounters failures, then the first retry happens after 30 seconds, the second after 60 seconds, the third after 120 seconds and so forth. If the retry time is beyond the expiration time of the current window, then the next retry is attempted at the start time of the next window. A maximum of 16 retry attempts are made after which the schedule is automatically disabled.


Note:

Once a retry attempt slips to the next propagation window, it will always do so; the exponential backoff scheme no longer governs retry scheduling. If the date function specified in the next_time parameter of DBMS_AQADM.SCHEDULE_PROPAGATION() results in a short interval between windows, then the number of unsuccessful retry attempts can quickly reach 16, disabling the schedule.

When a schedule is disabled automatically due to failures, the relevant information is written into the alert log. It is possible to check at any time if there were failures encountered by a schedule and if so how many successive failures were encountered, the error message indicating the cause for the failure and the time at which the last failure was encountered. By examining this information, an administrator can fix the failure and enable the schedule.

If propagation is successful during a retry, then the number of failures is reset to 0.

Propagation has built-in support for Oracle Real Application Clusters and is transparent to the user and the administrator. The job that handles propagation is submitted to the same instance as the owner of the queue table where the source topic resides. If at any time there is a failure at an instance and the queue table that stores the topic is migrated to a different instance, then the propagation job is also automatically migrated to the new instance. This minimizes the pinging between instances and thus offers better performance. Propagation has been designed to handle any number of concurrent schedules.

The number of job_queue_processes is limited to a maximum of 1000 and some of these can be used to handle jobs unrelated to propagation. Hence, propagation has built in support for multitasking and load balancing. The propagation algorithms are designed such that multiple schedules can be handled by a single snapshot (job_queue) process. The propagation load on a job_queue processes can be skewed based on the arrival rate of messages in the different source topics. If one process is overburdened with several active schedules while another is less loaded with many passive schedules, then propagation automatically redistributes the schedules among the processes such that they are loaded uniformly.

Exception Handling During Propagation

When a system error such as a network failure occurs, Oracle Streams Advanced Queuing continues to attempt to propagate messages using an exponential back-off algorithm. In some situations that indicate application errors in queue-to-dblink propagations, Oracle Streams Advanced Queuing marks messages as UNDELIVERABLE and logs a message in alert.log. Examples of such errors are when the remote queue does not exist or when there is a type mismatch between the source queue and the remote queue. The trace files in the background_dump_dest directory can provide additional information about the error.

When a new job queue process starts, it clears the mismatched type errors so the types can be reverified. If you have capped the number of job queue processes and propagation remains busy, then you might not want to wait for the job queue process to terminate and restart. Queue types can be reverified at any time using DBMS_AQADM.VERIFY_QUEUE_TYPES.


Note:

When a type mismatch is detected in queue-to-queue propagation, propagation stops and throws an error. In such situations you must query the DBA_SCHEDULES view to determine the last error that occurred during propagation to a particular destination. The message is not marked as UNDELIVERABLE.

Message Transformation with JMS AQ

A transformation can be defined to map messages of one format to another. Transformations are useful when applications that use different formats to represent the same information must be integrated. Transformations can be SQL expressions and PL/SQL functions. Message transformation is an Oracle Streams Advanced Queuing extension to the standard JMS interface.

The transformations can be created using the DBMS_TRANSFORM.create_transformation procedure. Transformation can be specified for the following operations:

  • Sending a message to a queue or topic

  • Receiving a message from a queue or topic

  • Creating a TopicSubscriber

  • Creating a RemoteSubscriber. This enables propagation of messages between topics of different formats.

J2EE Compliance

In Oracle Database 10g, Oracle JMS conforms to the Sun Microsystems JMS 1.1 standard. You can define the J2EE compliance mode for an Oracle Java Message Service (OJMS) client at runtime. For compliance, set the Java property oracle.jms.j2eeCompliant to TRUE as a command line option. For noncompliance, do nothing. FALSE is the default value.

Features in Oracle Streams Advanced Queuing that support J2EE compliance (and are also available in the noncompliant mode) include:

  • Nontransactional sessions

  • Durable subscribers

  • Temporary queues and topics

  • Nonpersistent delivery mode

  • Multiple JMS messages types on a single JMS queue or topic (using Oracle Streams Advanced Queuing queues of the AQ$_JMS_MESSAGE type)

  • The noLocal option for durable subscribers


    See Also:

    • Java Message Service Specification, version 1.1, March 18, 2002, Sun Microsystems, Inc.

    • "JMS Message Headers" for information on how the Java property oracle.jms.j2eeCompliant affects JMSPriority and JMSExpiration

    • "DurableSubscriber" for information on how the Java property oracle.jms.j2eeCompliant affects durable subscribers


PK3SPK-AOEBPS/aq_opers.htm Oracle Streams Advanced Queuing Operations Using PL/SQL

10 Oracle Streams Advanced Queuing Operations Using PL/SQL

This chapter describes the Oracle Streams Advanced Queuing (AQ) PL/SQL operational interface.

This chapter contains these topics:


See Also:


Using Secure Queues

For secure queues, you must specify the sender_id in the messages_properties parameter. See "MESSAGE_PROPERTIES_T Type" in Oracle Database PL/SQL Packages and Types Reference for more information about sender_id.

When you use secure queues, the following are required:

Enqueuing Messages

DBMS_AQ.ENQUEUE(
   queue_name          IN      VARCHAR2,
   enqueue_options     IN      enqueue_options_t,
   message_properties  IN      message_properties_t,
   payload             IN      "type_name",
   msgid               OUT     RAW);

This procedure adds a message to the specified queue.

It is not possible to update the message payload after a message has been enqueued. If you want to change the message payload, then you must dequeue the message and enqueue a new message.

To store a payload of type RAW, Oracle Streams Advanced Queuing creates a queue table with LOB column as the payload repository. The maximum size of the payload is determined by which programmatic interface you use to access Oracle Streams Advanced Queuing. For PL/SQL, Java and precompilers the limit is 32K; for the OCI the limit is 4G.

If a message is enqueued to a multiconsumer queue with no recipient and the queue has no subscribers (or rule-based subscribers that match this message), then Oracle error ORA 24033 is raised. This is a warning that the message will be discarded because there are no recipients or subscribers to whom it can be delivered.

If several messages are enqueued in the same second, then they all have the same enq_time. In this case the order in which messages are dequeued depends on step_no, a variable that is monotonically increasing for each message that has the same enq_time. There is no situation when both enq_time and step_no are the same for two messages enqueued in the same session.

Enqueue Options

The enqueue_options parameter specifies the options available for the enqueue operation. It has the following attributes:

  • visibility

    The visibility attribute specifies the transactional behavior of the enqueue request. ON_COMMIT (the default) makes the enqueue is part of the current transaction. IMMEDIATE makes the enqueue operation an autonomous transaction which commits at the end of the operation.

    Do not use the IMMEDIATE option when you want to use LOB locators. LOB locators are valid only for the duration of the transaction. Your locator will not be valid, because the immediate option automatically commits the transaction.

    You must set the visibility attribute to IMMEDIATE to use buffered messaging.

  • relative_msgid

    The relative_msgid attribute specifies the message identifier of the message referenced in the sequence deviation operation. This parameter is ignored unless sequence_deviation is specified with the BEFORE attribute.

  • sequence_deviation

    The sequence_deviation attribute specifies when the message should be dequeued, relative to other messages already in the queue. BEFORE puts the message ahead of the message specified by relative_msgid. TOP puts the message ahead of any other messages.

    Specifying sequence_deviation for a message introduces some restrictions for the delay and priority values that can be specified for this message. The delay of this message must be less than or equal to the delay of the message before which this message is to be enqueued. The priority of this message must be greater than or equal to the priority of the message before which this message is to be enqueued.


    Note:

    The sequence_deviation attribute has no effect in releases prior to Oracle Streams Advanced Queuing 10g Release 1 (10.1) if message_grouping is set to TRANSACTIONAL.

    The sequence deviation feature is deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2).


  • transformation

    The transformation attribute specifies a transformation that will be applied before enqueuing the message. The return type of the transformation function must match the type of the queue.

  • delivery_mode

    If the delivery_mode attribute is the default PERSISTENT, then the message is enqueued as a persistent message. If it is set to BUFFERED, then the message is enqueued as an buffered message. Null values are not allowed.

Message Properties

The message_properties parameter contains the information that Oracle Streams Advanced Queuing uses to manage individual messages. It has the following attributes:

  • priority

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

  • delay

    The delay attribute specifies the number of seconds during which a message is in the WAITING state. After this number of seconds, the message is in the READY state and available for dequeuing. If you specify NO_DELAY, then the message is available for immediate dequeuing. Dequeuing by msgid overrides the delay specification.


    Note:

    Delay is not supported with buffered messaging.

  • expiration

    The expiration attribute specifies the number of seconds during which the message is available for dequeuing, starting from when the message reaches the READY state. If the message is not dequeued before it expires, then it is moved to the exception queue in the EXPIRED state. If you specify NEVER, then the message does not expire.


    Note:

    Message delay and expiration are enforced by the queue monitor (QMN) background processes. You must start the QMN processes for the database if you intend to use the delay and expiration features of Oracle Streams Advanced Queuing.

  • correlation

    The correlation attribute is an identifier supplied by the producer of the message at enqueue time.

  • attempts

    The attemps attribute specifies the number of attempts that have been made to dequeue the message. This parameter cannot be set at enqueue time.

  • recipient_list

    The recipient_list parameter is valid only for queues that allow multiple consumers. The default recipients are the queue subscribers.

  • exception_queue

    The exception_queue attribute specifies the name of the queue into which the message is moved if it cannot be processed successfully. 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 log.

  • delivery_mode

    Any value for delivery_mode specified in message properties at enqueue time is ignored. The value specified in enqueue options is used to set the delivery mode of the message. If the delivery mode in enqueue options is left unspecified, then it defaults to persistent.

  • enqueue_time

    The enqueue_time attribute specifies the time the message was enqueued. This value is determined by the system and cannot be set by the user at enqueue time.


    Note:

    Because information about seasonal changes in the system clock (switching between standard time and daylight-saving time, for example) is stored with each queue table, seasonal changes are automatically reflected in enqueue_time. If the system clock is changed for some other reason, then you must restart the database for Oracle Streams Advanced Queuing to pick up the changed time.

  • state

    The state attribute specifies the state of the message at the time of the dequeue. This parameter cannot be set at enqueue time.

  • sender_id

    The sender_id attribute is an identifier of type aq$_agent specified at enqueue time by the message producer.

  • original_msgid

    The original_msgid attribute is used by Oracle Streams AQ for propagating messages.

  • transaction_group

    The transaction_group attribute specifies the transaction group for the message. This attribute is set only by DBMS_AQ.DEQUEUE_ARRAY. This attribute cannot be used to set the transaction group of a message through DBMS_AQ.ENQUEUE or DBMS_AQ.ENQUEUE_ARRAY.

  • user_property

    The user_property attribute is optional. It is used to store additional information about the payload.

The examples in this chapter use the same users, message types, queue tables, and queues as do the examples in Chapter 8, "Oracle Streams Advanced Queuing Administrative Interface". If you have not already created these structures in your test environment, then you must run the following examples:

For Example 8-1, you must connect as a user with administrative privileges. For the other examples in the preceding list, you can connect as user test_adm. After you have created the queues, you must start them as shown in "Starting a Queue". Except as noted otherwise, you can connect as ordinary queue user 'test' to run all examples appearing in this chapter.

Example 10-1 Enqueuing a Message, Specifying Queue Name and Payload

DECLARE
   enqueue_options     DBMS_AQ.enqueue_options_t;
   message_properties  DBMS_AQ.message_properties_t;
   message_handle      RAW(16);
   message             test.message_typ;
BEGIN
   message := test.message_typ(001, 'TEST MESSAGE', 'First message to obj_queue');
   DBMS_AQ.ENQUEUE(
      queue_name              => 'test.obj_queue',
      enqueue_options         => enqueue_options,
      message_properties      => message_properties,
      payload                 => message,
      msgid                   => message_handle);
   COMMIT;
END;
/

Example 10-2 Enqueuing a Message, Specifying Priority

DECLARE 
   enqueue_options       DBMS_AQ.enqueue_options_t; 
   message_properties    DBMS_AQ.message_properties_t; 
   message_handle        RAW(16); 
   message               test.order_typ; 
BEGIN 
   message := test.order_typ(002, 'PRIORITY MESSAGE', 'priority 30'); 
   message_properties.priority := 30; 
   DBMS_AQ.ENQUEUE(
      queue_name              => 'test.priority_queue', 
      enqueue_options         => enqueue_options, 
      message_properties      => message_properties, 
      payload                 => message, 
      msgid                   => message_handle); 
   COMMIT; 
END;
/

Enqueuing a LOB Type Message

Example 10-3 creates procedure blobenqueue() using the test.lob_type message payload object type created in Example 8-1. On enqueue, the LOB attribute is set to EMPTY_BLOB. After the enqueue completes, but before the transaction is committed, the LOB attribute is selected from the user_data column of the test.lob_qtab queue table. The LOB data is written to the queue using the LOB interfaces (which are available through both OCI and PL/SQL). The actual enqueue operation is shown in

On dequeue, the message payload will contain the LOB locator. You can use this LOB locator after the dequeue, but before the transaction is committed, to read the LOB data. This is shown in Example 10-14.

Example 10-3 Creating an Enqueue Procedure for LOB Type Messages

CREATE OR REPLACE PROCEDURE blobenqueue(msgno IN NUMBER) AS
   enq_userdata          test.lob_typ; 
   enq_msgid             RAW(16); 
   enqueue_options       DBMS_AQ.enqueue_options_t; 
   message_properties    DBMS_AQ.message_properties_t; 
   lob_loc               BLOB; 
   buffer                RAW(4096); 
BEGIN 
   buffer       := HEXTORAW(RPAD('FF', 4096, 'FF')); 
   enq_userdata := test.lob_typ(msgno, 'Large Lob data', EMPTY_BLOB(), msgno); 
   DBMS_AQ.ENQUEUE(
      queue_name          => 'test.lob_queue',
      enqueue_options     => enqueue_options,
      message_properties  => message_properties,
      payload             => enq_userdata, 
      msgid               => enq_msgid); 
   SELECT t.user_data.data INTO lob_loc 
      FROM lob_qtab t 
      WHERE t.msgid = enq_msgid; 
   DBMS_LOB.WRITE(lob_loc, 2000, 1, buffer ); 
   COMMIT; 
END;
/ 

Example 10-4 Enqueuing a LOB Type Message

BEGIN 
   FOR i IN 1..5 LOOP 
      blobenqueue(i); 
   END LOOP; 
END;
/

Enqueuing Multiple Messages to a Single-Consumer Queue

Example 10-5 enqueues six messages to test.obj_queue. These messages are dequeued in Example 10-17.

Example 10-5 Enqueuing Multiple Messages

SET SERVEROUTPUT ON
DECLARE
   enqueue_options     DBMS_AQ.enqueue_options_t;
   message_properties  DBMS_AQ.message_properties_t;
   message_handle      RAW(16);
   message             test.message_typ;
BEGIN
   message := test.message_typ(001, 'ORANGE', 'ORANGE enqueued first.');
   DBMS_AQ.ENQUEUE(
         queue_name           => 'test.obj_queue', 
         enqueue_options      => enqueue_options,
         message_properties   => message_properties,
         payload              => message,
         msgid                => message_handle);
   message := test.message_typ(001, 'ORANGE', 'ORANGE also enqueued second.');
   DBMS_AQ.ENQUEUE(
         queue_name           => 'test.obj_queue', 
         enqueue_options      => enqueue_options,
         message_properties   => message_properties,
         payload              => message,
         msgid                => message_handle);
   message := test.message_typ(001, 'YELLOW', 'YELLOW enqueued third.');
   DBMS_AQ.ENQUEUE(
         queue_name           => 'test.obj_queue', 
         enqueue_options      => enqueue_options,
         message_properties   => message_properties,
         payload              => message,
         msgid                => message_handle);
   message := test.message_typ(001, 'VIOLET', 'VIOLET enqueued fourth.');
   DBMS_AQ.ENQUEUE(
         queue_name           => 'test.obj_queue', 
         enqueue_options      => enqueue_options,
         message_properties   => message_properties,
         payload              => message,
         msgid                => message_handle);
   message := test.message_typ(001, 'PURPLE', 'PURPLE enqueued fifth.');
   DBMS_AQ.ENQUEUE(
         queue_name           => 'test.obj_queue', 
         enqueue_options      => enqueue_options,
         message_properties   => message_properties,
         payload              => message,
         msgid                => message_handle);
   message := test.message_typ(001, 'PINK', 'PINK enqueued sixth.');
   DBMS_AQ.ENQUEUE(
         queue_name           => 'test.obj_queue', 
         enqueue_options      => enqueue_options,
         message_properties   => message_properties,
         payload              => message,
         msgid                => message_handle);
   COMMIT;
END;
/

Enqueuing Multiple Messages to a Multiconsumer Queue

Example 10-6 requires that you connect as user 'test_adm' to add subscribers RED and GREEN to queue test.multiconsumer_queue. The subscribers are required for Example 10-7.

Example 10-6 Adding Subscribers RED and GREEN

DECLARE
   subscriber         sys.aq$_agent;
BEGIN
   subscriber     :=  sys.aq$_agent('RED', NULL, NULL);
   DBMS_AQADM.ADD_SUBSCRIBER(
      queue_name  =>  'test.multiconsumer_queue',
      subscriber  =>  subscriber);

   subscriber     :=  sys.aq$_agent('GREEN', NULL, NULL);
   DBMS_AQADM.ADD_SUBSCRIBER(
      queue_name  =>  'test.multiconsumer_queue',
      subscriber  =>  subscriber); 
END;
/

Example 10-7 enqueues multiple messages from sender 001. MESSAGE 1 is intended for all queue subscribers. MESSAGE 2 is intended for RED and BLUE. These messages are dequeued in Example 10-17.

Example 10-7 Enqueuing Multiple Messages to a Multiconsumer Queue

DECLARE
   enqueue_options     DBMS_AQ.enqueue_options_t;
   message_properties  DBMS_AQ.message_properties_t;
   recipients          DBMS_AQ.aq$_recipient_list_t;
   message_handle      RAW(16);
   message             test.message_typ;
BEGIN
   message := test.message_typ(001, 'MESSAGE 1','For queue subscribers');
   DBMS_AQ.ENQUEUE(
      queue_name          => 'test.multiconsumer_queue',
      enqueue_options     => enqueue_options,
      message_properties  => message_properties,
      payload             => message,
      msgid               => message_handle);

   message := test.message_typ(001, 'MESSAGE 2', 'For two recipients');
   recipients(1) := sys.aq$_agent('RED', NULL, NULL);
   recipients(2) := sys.aq$_agent('BLUE', NULL, NULL);
   message_properties.recipient_list := recipients;
   DBMS_AQ.ENQUEUE(
      queue_name          => 'test.multiconsumer_queue',
      enqueue_options     => enqueue_options,
      message_properties  => message_properties,
      payload             => message,
      msgid               => message_handle);
   COMMIT;
END;
/

Enqueuing Grouped Messages

Example 10-8 enqueues three groups of messages, with three messages in each group. These messages are dequeued in Example 10-16.

Example 10-8 Enqueuing Grouped Messages

DECLARE
   enqueue_options     DBMS_AQ.enqueue_options_t;
   message_properties  DBMS_AQ.message_properties_t;
   message_handle      RAW(16);
   message             test.message_typ;
BEGIN
  FOR groupno in 1..3 LOOP
    FOR msgno in 1..3 LOOP
      message := test.message_typ(
               001,
               'GROUP ' || groupno, 
               'Message ' || msgno || ' in group ' || groupno);
      DBMS_AQ.ENQUEUE(
         queue_name             => 'test.group_queue',
         enqueue_options        => enqueue_options,
         message_properties     => message_properties,
         payload                => message,
         msgid                  => message_handle);
    END LOOP;
    COMMIT; 
  END LOOP;
END;
/

Enqueuing a Message with Delay and Expiration

In Example 10-9, an application wants a message to be dequeued no earlier than a week from now, but no later than three weeks from now. Because expiration is calculated from the earliest dequeue time, this requires setting the expiration time for two weeks.

Example 10-9 Enqueuing a Message, Specifying Delay and Expiration

DECLARE
   enqueue_options     DBMS_AQ.enqueue_options_t;
   message_properties  DBMS_AQ.message_properties_t;
   message_handle      RAW(16);
   message             test.message_typ;
BEGIN
   message := test.message_typ(001, 'DELAYED', 'Message is delayed one week.');
   message_properties.delay      := 7*24*60*60;
   message_properties.expiration := 2*7*24*60*60;
   DBMS_AQ.ENQUEUE(
      queue_name           => 'test.obj_queue',
      enqueue_options      => enqueue_options,
      message_properties   => message_properties,
      payload              => message,
      msgid                => message_handle);
   COMMIT;
END;
/

Example 10-10 Enqueuing a Message, Specifying a Transformation

DECLARE
   enqueue_options     DBMS_AQ.enqueue_options_t;
   message_properties  DBMS_AQ.message_properties_t;
   message_handle      RAW(16);
   message             test.message_typ;
BEGIN
   message := test.message_typ(001, 'NORMAL MESSAGE', 'enqueued to obj_queue');
   enqueue_options.transformation := 'message_order_transform';
   DBMS_AQ.ENQUEUE(
      queue_name              => 'test.priority_queue', 
      enqueue_options         => enqueue_options,
      message_properties      => message_properties,
      payload                 => message,
      msgid                   => message_handle);
   COMMIT;
END;
/

See Also:

"Using Advanced Queuing Interfaces" in Oracle Objects for OLE Developer's Guide for OO4O message-enqueuing examples

Enqueuing an Array of Messages

DBMS_AQ.ENQUEUE_ARRAY(
   queue_name                IN   VARCHAR2,
   enqueue_options           IN   enqueue_options_t,
   array_size                IN   PLS_INTEGER,
   message_properties_array  IN   message_properties_array_t,
   payload_array             IN   VARRAY,
   msid_array                OUT  msgid_array_t)
RETURN PLS_INTEGER;

Use the ENQUEUE_ARRAY function to enqueue an array of payloads using a corresponding array of message properties. The output is an array of message identifiers of the enqueued messages. The function returns the number of messages successfully enqueued.

Array enqueuing is not supported for buffered messages, but you can still use DBMS_AQ.ENQUEUE_ARRAY() to enqueue buffered messages by setting array_size to 1.


See Also:

"Enqueue Options"

The message_properties_array parameter is an array of message properties. Each element in the payload array must have a corresponding element in this record. All messages in an array have the same delivery mode.

The payload structure can be a VARRAY or nested table. The message IDs are returned into an array of RAW(16) entries of type DBMS_AQ.msgid_array_t.

As with array operations in the relational world, it is not possible to provide a single optimum array size that will be correct in all circumstances. Application developers must experiment with different array sizes to determine the optimal value for their particular applications.

Example 10-11 Enqueuing an Array of Messages

DECLARE
  enqueue_options       DBMS_AQ.enqueue_options_t;
  msg_prop_array        DBMS_AQ.message_properties_array_t;
  msg_prop              DBMS_AQ.message_properties_t;
  payload_array         test.msg_table;
  msgid_array           DBMS_AQ.msgid_array_t;
  retval                PLS_INTEGER;
BEGIN
  payload_array  := msg_table(
      message_typ(001, 'MESSAGE  1', 'array enqueued to obj_queue'), 
      message_typ(001, 'MESSAGE  2', 'array enqueued to obj_queue'));
  msg_prop_array := DBMS_AQ.message_properties_array_t(msg_prop, msg_prop);
 
  retval := DBMS_AQ.ENQUEUE_ARRAY( 
                 queue_name               => 'test.obj_queue',
                 enqueue_options          => enqueue_options,
                 array_size               => 2,
                 message_properties_array => msg_prop_array,
                 payload_array            => payload_array,
                 msgid_array              => msgid_array);
  COMMIT;
END;/

Listening to One or More Queues

DBMS_AQ.LISTEN(
   agent_list             IN    aq$_agent_list_t,
   wait                   IN    BINARY_INTEGER DEFAULT FOREVER, 
   listen_delivery_mode   IN    PLS_INTEGER DEFAULT PERSISTENT,
   agent                  OUT   sys.aq$_agent
   message_delivery_mode  OUT   PLS_INTEGER);

TYPE aq$_agent_list_t IS TABLE of aq$_agent INDEXED BY BINARY_INTEGER;

This procedure specifies which queue or queues to monitor.

This call takes a list of agents as an argument. Each agent is identified by a unique combination of name, address, and protocol.


See Also:

"AQ Agent Type"

You specify the queue to be monitored in the address field of each agent listed. Agents must have dequeue privileges on each monitored queue. You must specify the name of the agent when monitoring multiconsumer queues; but you must not specify an agent name for single-consumer queues. Only local queues are supported as addresses. Protocol is reserved for future use.


Note:

Listening to multiconsumer queues is not supported in the Java API.

The listen_delivery_mode parameter specifies what types of message interest the agent. If it is the default PERSISTENT, then the agent is informed about persistent messages only. If it is set to BUFFERED, then the agent is informed about buffered messages only. If it is set to PERSISTENT_OR_BUFFERED, then the agent is informed about both types.

This is a blocking call that returns the agent and message type when there is a message ready for consumption for an agent in the list. If there are messages for more than one agent, then only the first agent listed is returned. If there are no messages found when the wait time expires, then an error is raised.

A successful return from the listen call is only an indication that there is a message for one of the listed agents in one of the specified queues. The interested agent must still dequeue the relevant message.


Note:

You cannot call LISTEN on nonpersistent queues.

Example 10-12 Listening to a Single-Consumer Queue with Zero Timeout

SET SERVEROUTPUT ON
DECLARE
   agent            sys.aq$_agent;
   test_agent_list  DBMS_AQ.aq$_agent_list_t;
BEGIN
   test_agent_list(1) := sys.aq$_agent(NULL, 'test.obj_queue',  NULL);
   test_agent_list(2) := sys.aq$_agent(NULL, 'test.priority_queue', NULL);
   DBMS_AQ.LISTEN(
      agent_list   =>   test_agent_list, 
      wait         =>   0, 
      agent        =>   agent);
   DBMS_OUTPUT.PUT_LINE('Message in Queue: ' ||  agent.address);
END;
/

Even though both test.obj_queue and test.priority_queue contain messages (enqueued in Example 10-1 and Example 10-2 respectively) Example 10-12 returns only:

Message in Queue: "TEST"."OBJ_QUEUE"

If the order of agents in test_agent_list is reversed, so test.priority_queue appears before test.obj_queue, then the example returns:

Message in Queue: "TEST"."PRIORITY_QUEUE"

Dequeuing Messages

DBMS_AQ.DEQUEUE(
   queue_name          IN      VARCHAR2,
   dequeue_options     IN      dequeue_options_t,
   message_properties  OUT     message_properties_t,
   payload             OUT     "type_name",
   msgid               OUT     RAW);

This procedure dequeues a message from the specified queue. Beginning with Oracle Streams Advanced Queuing 10g Release 2 (10.2), you can choose to dequeue only persistent messages, only buffered messages, or both. See delivery_mode in the following list of dequeue options.

Dequeue Options

The dequeue_options parameter specifies the options available for the dequeue operation. It has the following attributes:

  • consumer_name

    A consumer can dequeue a message from a queue by supplying the name that was used in the AQ$_AGENT type of the DBMS_AQADM.ADD_SUBSCRIBER procedure or the recipient list of the message properties. If a value is specified, then only those messages matching consumer_name are accessed. If a queue is not set up for multiple consumers, then this field must be set to NULL (the default).

  • dequeue_mode

    The dequeue_mode attribute specifies the locking behavior associated with the dequeue. If BROWSE is specified, then the message is dequeued without acquiring any lock. If LOCKED is specified, then the message is dequeued with a write lock that lasts for the duration of the transaction. If REMOVE is specified, then the message is dequeued and deleted (the default). The message can be retained in the queue table based on the retention properties. If REMOVE_NO_DATA is specified, then the message is marked as updated or deleted.

  • navigation

    The navigation attribute specifies the position of the dequeued message. If FIRST_MESSAGE is specified, then the first available message matching the search criteria is dequeued. If NEXT_MESSAGE is specified, then the next available message matching the search criteria is dequeued (the default). If the previous message belongs to a message group, then the next available message matching the search criteria in the message group is dequeued.

    If NEXT_TRANSACTION is specified, then any messages in the current transaction group are skipped and the first message of the next transaction group is dequeued. This setting can only be used if message grouping is enabled for the queue.

  • visibility

    The visibility attribute specifies when the new message is dequeued. If ON_COMMIT is specified, then the dequeue is part of the current transaction (the default). If IMMEDIATE is specified, then the dequeue operation is an autonomous transaction that commits at the end of the operation. The visibility attribute is ignored in BROWSE dequeue mode.

    Visibility must always be IMMEDIATE when dequeuing messages with delivery mode DBMS_AQ.BUFFERED or DBMS_AQ.PERSISTENT_OR_BUFFERED.

  • wait

    The wait attribute specifies the wait time if there is currently no message available matching the search criteria. If a number is specified, then the operation waits that number of seconds. If FOREVER is specified, then the operation waits forever (the default). If NO_WAIT is specified, then the operation does not wait.

  • msgid

    The msgid attribute specifies the message identifier of the dequeued message. Only messages in the READY state are dequeued unless msgid is specified.

  • correlation

    The correlation attribute specifies the correlation identifier of the dequeued message. The correlation identifier cannot be changed between successive dequeue calls without specifying the FIRST_MESSAGE navigation option.

    Correlation identifiers are application-defined identifiers that are not interpreted by Oracle Streams Advanced Queuing. You can use special pattern matching characters, such as the percent sign and the underscore. If more than one message satisfies the pattern, then the order of dequeuing is indeterminate, and the sort order of the queue is not honored.


    Note:

    Although dequeue options correlation and deq_condition are both supported for buffered messages, it is not possible to create indexes to optimize these queries.

  • deq_condition

    The deq_condition attribute is a Boolean expression 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.

    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 attribute cannot exceed 4000 characters. If more than one message satisfies the dequeue condition, then the order of dequeuing is indeterminate, and the sort order of the queue is not honored.

  • transformation

    The transformation attribute specifies a transformation that will be applied after the message is dequeued but before returning the message to the caller.

  • delivery_mode

    The delivery_mode attribute specifies what types of messages to dequeue. If it is set to DBMS_AQ.PERSISTENT, then only persistent messages are dequeued. If it is set to DBMS_AQ.BUFFERED, then only buffered messages are dequeued.

    If it is the default DBMS_AQ.PERSISTENT_OR_BUFFERED, then both persistent and buffered messages are dequeued. The delivery_mode attribute in the message properties of the dequeued message indicates whether the dequeued message was buffered or persistent.

The dequeue order is determined by the values specified at the time the queue table is created unless overridden by the message identifier and correlation identifier in dequeue options.

The database consistent read mechanism is applicable for queue operations. For example, a BROWSE call may not see a message that is enqueued after the beginning of the browsing transaction.

In a commit-time queue, a new feature of Oracle Streams Advanced Queuing 10g Release 2 (10.2), messages are not visible to BROWSE or DEQUEUE calls until a deterministic order can be established among them based on an approximate CSCN.

If the navigation attribute of the dequeue_conditions parameter is NEXT_MESSAGE (the default), then subsequent dequeues retrieve messages from the queue based on the snapshot obtained in the first dequeue. A message enqueued after the first dequeue command, therefore, will be processed only after processing all remaining messages in the queue. This is not a problem if all the messages have already been enqueued or if the queue does not have priority-based ordering. But if an application must process the highest-priority message in the queue, then it must use the FIRST_MESSAGE navigation option.


Note:

It can also be more efficient to use the FIRST_MESSAGE navigation option when there are messages being concurrently enqueued. If the FIRST_MESSAGE option is not specified, then Oracle Streams Advanced Queuing continually generates the snapshot as of the first dequeue command, leading to poor performance. If the FIRST_MESSAGE option is specified, then Oracle Streams Advanced Queuing uses a new snapshot for every dequeue command.

Messages enqueued in the same transaction into a queue that has been enabled for message grouping form a group. If only one message is enqueued in the transaction, then this effectively forms a group of one message. There is no upper limit to the number of messages that can be grouped in a single transaction.

In queues that have not been enabled for message grouping, a dequeue in LOCKED or REMOVE mode locks only a single message. By contrast, a dequeue operation that seeks to dequeue a message that is part of a group locks the entire group. This is useful when all the messages in a group must be processed as a unit.

When all the messages in a group have been dequeued, the dequeue returns an error indicating that all messages in the group have been processed. The application can then use NEXT_TRANSACTION to start dequeuing messages from the next available group. In the event that no groups are available, the dequeue times out after the period specified in the wait attribute of dequeue_options.

Typically, you expect the consumer of messages to access messages using the dequeue interface. You can view processed messages or messages still to be processed by browsing by message ID or by using SELECT commands.

Example 10-13 returns the message enqueued in Example 10-1. It returns:

From Sender No.1
Subject: TEST MESSAGE
Text: First message to obj_queue

Example 10-13 Dequeuing Object Type Messages

SET SERVEROUTPUT ON
DECLARE
dequeue_options     DBMS_AQ.dequeue_options_t;
message_properties  DBMS_AQ.message_properties_t;
message_handle      RAW(16);
message             test.message_typ;
BEGIN
   dequeue_options.navigation := DBMS_AQ.FIRST_MESSAGE;
   DBMS_AQ.DEQUEUE(
      queue_name          =>     'test.obj_queue',
      dequeue_options     =>     dequeue_options,
      message_properties  =>     message_properties,
      payload             =>     message,
      msgid               =>     message_handle);
   DBMS_OUTPUT.PUT_LINE('From Sender No.'|| message.sender_id);
   DBMS_OUTPUT.PUT_LINE('Subject: '||message.subject);
   DBMS_OUTPUT.PUT_LINE('Text: '||message.text);
   COMMIT;
END;
/

Dequeuing LOB Type Messages

Example 10-14 creates procedure blobdequeue() to dequeue the LOB type messages enqueued in Example 10-4. The actual dequeue is shown in Example 10-15. It returns:

Amount of data read: 2000
Amount of data read: 2000
Amount of data read: 2000
Amount of data read: 2000
Amount of data read: 2000

Example 10-14 Creating a Dequeue Procedure for LOB Type Messages

CREATE OR REPLACE PROCEDURE blobdequeue(msgno IN NUMBER) AS
   dequeue_options     DBMS_AQ.dequeue_options_t; 
   message_properties  DBMS_AQ.message_properties_t; 
   msgid               RAW(16); 
   payload             test.lob_typ; 
   lob_loc             BLOB; 
   amount              BINARY_INTEGER; 
   buffer              RAW(4096); 
BEGIN 
   DBMS_AQ.DEQUEUE(
      queue_name          =>  'test.lob_queue',
      dequeue_options     =>   dequeue_options, 
      message_properties  =>   message_properties, 
      payload             =>   payload,
      msgid               =>   msgid); 
   lob_loc                :=   payload.data;
   amount                 :=   2000; 
   DBMS_LOB.READ(lob_loc, amount, 1, buffer);
   DBMS_OUTPUT.PUT_LINE('Amount of data read: '|| amount); 
   COMMIT;
END;
/

Example 10-15 Dequeuing LOB Type Messages

BEGIN 
   FOR i IN 1..5 LOOP 
     blobdequeue(i); 
   END LOOP; 
END;
/

Dequeuing Grouped Messages

You can dequeue the grouped messages enqueued in Example 10-8 by running Example 10-16. It returns:

GROUP 1: Message 1 in group 1
GROUP 1: Message 2 in group 1
GROUP 1: Message 3 in group 1
Finished GROUP 1
GROUP 2: Message 1 in group 2
GROUP 2: Message 2 in group 2
GROUP 2: Message 3 in group 2
Finished GROUP 2
GROUP 3: Message 1 in group 3
GROUP 3: Message 2 in group 3
GROUP 3: Message 3 in group 3
Finished GROUP 3
No more messages

Example 10-16 Dequeuing Grouped Messages

SET SERVEROUTPUT ON
DECLARE
   dequeue_options       DBMS_AQ.dequeue_options_t;
   message_properties    DBMS_AQ.message_properties_t;
   message_handle        RAW(16);
   message               test.message_typ;
   no_messages           exception;
   end_of_group          exception;
   PRAGMA EXCEPTION_INIT (no_messages, -25228);
   PRAGMA EXCEPTION_INIT (end_of_group, -25235);
BEGIN
   dequeue_options.wait       := DBMS_AQ.NO_WAIT;
   dequeue_options.navigation := DBMS_AQ.FIRST_MESSAGE;
   LOOP
     BEGIN
     DBMS_AQ.DEQUEUE(
        queue_name         => 'test.group_queue',
        dequeue_options    => dequeue_options,
        message_properties => message_properties,
        payload            => message,
        msgid              => message_handle);
     DBMS_OUTPUT.PUT_LINE(message.subject || ': ' || message.text );
     dequeue_options.navigation := DBMS_AQ.NEXT_MESSAGE;
     EXCEPTION
       WHEN end_of_group THEN
         DBMS_OUTPUT.PUT_LINE ('Finished ' || message.subject);
         COMMIT;
         dequeue_options.navigation := DBMS_AQ.NEXT_TRANSACTION;
     END;
   END LOOP;
   EXCEPTION
     WHEN no_messages THEN
       DBMS_OUTPUT.PUT_LINE ('No more messages');
END;
/

Dequeuing from a Multiconsumer Queue

You can dequeue the messages enqueued for RED in Example 10-7 by running Example 10-17. If you change RED to GREEN and then to BLUE, you can use it to dequeue their messages as well. The output of the example will be different in each case.

RED is a subscriber to the multiconsumer queue and is also a specified recipient of MESSAGE 2, so it gets both messages:

Message: MESSAGE 1 .. For queue subscribers
Message: MESSAGE 2 .. For two recipients
No more messages for RED

GREEN is only a subscriber, so it gets only those messages in the queue for which no recipients have been specified (in this case, MESSAGE 1):

Message: MESSAGE 1 .. For queue subscribers
No more messages for GREEN

BLUE, while not a subscriber to the queue, is nevertheless specified to receive MESSAGE 2.

Message: MESSAGE 2 .. For two recipients
No more messages for BLUE

Example 10-17 Dequeuing Messages for RED from a Multiconsumer Queue

SET SERVEROUTPUT ON
DECLARE
  dequeue_options       DBMS_AQ.dequeue_options_t;
  message_properties    DBMS_AQ.message_properties_t;
  message_handle        RAW(16);
  message               test.message_typ;
  no_messages           exception;
  PRAGMA EXCEPTION_INIT (no_messages, -25228);
BEGIN
  dequeue_options.wait          := DBMS_AQ.NO_WAIT;
  dequeue_options.consumer_name := 'RED';
  dequeue_options.navigation    := DBMS_AQ.FIRST_MESSAGE;
  LOOP
   BEGIN
    DBMS_AQ.DEQUEUE(
      queue_name         => 'test.multiconsumer_queue',
      dequeue_options    => dequeue_options,
      message_properties => message_properties,
      payload            => message,
      msgid              => message_handle);
    DBMS_OUTPUT.PUT_LINE('Message: '|| message.subject ||' .. '|| message.text );
    dequeue_options.navigation := DBMS_AQ.NEXT_MESSAGE;
   END;
  END LOOP;
  EXCEPTION
    WHEN no_messages THEN
    DBMS_OUTPUT.PUT_LINE ('No more messages for RED');
  COMMIT;
END;
/

Example 10-18 browses messages enqueued in Example 10-5 until it finds PINK, which it removes. The example returns:

Browsed Message Text: ORANGE enqueued first.
Browsed Message Text: ORANGE also enqueued second.
Browsed Message Text: YELLOW enqueued third.
Browsed Message Text: VIOLET enqueued fourth.
Browsed Message Text: PURPLE enqueued fifth.
Browsed Message Text: PINK enqueued sixth.
Removed Message Text: PINK enqueued sixth.

Dequeue Modes

Example 10-18 Dequeue in Browse Mode and Remove Specified Message

SET SERVEROUTPUT ON
DECLARE
   dequeue_options     DBMS_AQ.dequeue_options_t;
   message_properties  DBMS_AQ.message_properties_t;
   message_handle      RAW(16);
   message             test.message_typ;
BEGIN
   dequeue_options.dequeue_mode := DBMS_AQ.BROWSE;
   LOOP
      DBMS_AQ.DEQUEUE(
        queue_name              => 'test.obj_queue',
        dequeue_options         => dequeue_options,
        message_properties      => message_properties,
        payload                 => message,
        msgid                   => message_handle);
      DBMS_OUTPUT.PUT_LINE ('Browsed Message Text: ' || message.text);
      EXIT WHEN message.subject = 'PINK';
   END LOOP;
   dequeue_options.dequeue_mode := DBMS_AQ.REMOVE;
   dequeue_options.msgid        := message_handle;
   DBMS_AQ.DEQUEUE(
           queue_name           => 'test.obj_queue',
           dequeue_options      => dequeue_options,
           message_properties   => message_properties,
           payload              => message,
           msgid                => message_handle);
   DBMS_OUTPUT.PUT_LINE('Removed Message Text: ' || message.text);
   COMMIT;
END;
/

Example 10-19 previews in locked mode the messages enqueued in Example 10-5 until it finds PURPLE, which it removes. The example returns:

Locked Message Text: ORANGE enqueued first.
Locked Message Text: ORANGE also enqueued second.
Locked Message Text: YELLOW enqueued third.
Locked Message Text: VIOLET enqueued fourth.
Locked Message Text: PURPLE enqueued fifth.
Removed Message Text: PURPLE enqueued fifth.

Example 10-19 Dequeue in Locked Mode and Remove Specified Message

SET SERVEROUTPUT ON
DECLARE
   dequeue_options     DBMS_AQ.dequeue_options_t;
   message_properties  DBMS_AQ.message_properties_t;
   message_handle      RAW(16);
   message             test.message_typ;
BEGIN
   dequeue_options.dequeue_mode := DBMS_AQ.LOCKED;
   LOOP
      DBMS_AQ.dequeue(
        queue_name         => 'test.obj_queue',
        dequeue_options    => dequeue_options,
        message_properties => message_properties,
        payload            => message,
        msgid              => message_handle);
      DBMS_OUTPUT.PUT_LINE('Locked Message Text: ' || message.text);
      EXIT WHEN message.subject = 'PURPLE';
   END LOOP;
   dequeue_options.dequeue_mode := DBMS_AQ.REMOVE;
   dequeue_options.msgid        := message_handle;
   DBMS_AQ.DEQUEUE(
     queue_name           => 'test.obj_queue',
     dequeue_options      => dequeue_options,
     message_properties   => message_properties,
     payload              => message,
     msgid                => message_handle);
   DBMS_OUTPUT.PUT_LINE('Removed Message Text: ' || message.text);
   COMMIT;
END;
/

See Also:

"Using Advanced Queuing Interfaces" in Oracle Objects for OLE Developer's Guide for OO4O message-dequeuing examples

<=i/div>

Dequeuing an Array of Messages

DBMS_AQ.DEQUEUE_ARRAY(
   queue_name                IN      VARCHAR2,
   dequeue_options           IN      dequeue_options_t,
   array_size                IN      PLS_INTEGER, 
   message_properties_array  OUT     message_properties_array_t,
   payload_array             OUT     VARRAY,
   msgid_array               OUT     msgid_array_t)
RETURN PLS_INTEGER;

Use the DEQUEUE_ARRAY function to dequeue an array of payloads and a corresponding array of message properties. The output is an array of payloads, message IDs, and message properties of the dequeued messages. The function returns the number of messages successfully dequeued.

Array dequeuing is not supported for buffered messages, but you can still use DBMS_AQ.DEQUEUE_ARRAY() to dequeue buffered messages by setting array_size to 1.

The payload structure can be a VARRAY or nested table. The message identifiers are returned into an array of RAW(16) entries of type DBMS_AQ.msgid_array_t. The message properties are returned into an array of type DBMS_AQ.message_properties_array_t.

As with array operations in the relational world, it is not possible to provide a single optimum array size that will be correct in all circumstances. Application developers must experiment with different array sizes to determine the optimal value for their particular applications.

All dequeue options available with DBMS_AQ.DEQUEUE are also available with DBMS_AQ.DEQUEUE_ARRAY. Beginning with Oracle Streams Advanced Queuing 10g Release 2 (10.2), you can choose to dequeue only persistent messages, only buffered messages, or both. In addition, the navigation attribute of dequeue_options offers two options specific to DBMS_AQ.DEQUEUE_ARRAY.

When dequeuing messages, you might want to dequeue all the messages for a transaction group with a single call. You might also want to dequeue messages that span multiple transaction groups. You can specify either of these methods by using one of the following navigation methods:

  • NEXT_MESSAGE_ONE_GROUP

  • FIRST_MESSAGE_ONE_GROUP

  • NEXT_MESSAGE_MULTI_GROUP

  • FIRST_MESSAGE_MULTI_GROUP

Navigation method NEXT_MESSAGE_ONE_GROUP dequeues messages that match the search criteria from the next available transaction group into an array. Navigation method FIRST_MESSAGE_ONE_GROUP resets the position to the beginning of the queue and dequeues all the messages in a single transaction group that are available and match the search criteria.

The number of messages dequeued is determined by an array size limit. If the number of messages in the transaction group exceeds array_size, then multiple calls to DEQUEUE_ARRAY must be made to dequeue all the messages for the transaction group.

Navigation methods NEXT_MESSAGE_MULTI_GROUP and FIRST_MESSAGE_MULTI_GROUP work like their ONE_GROUP counterparts, but they are not limited to a single transaction group. Each message that is dequeued into the array has an associated set of message properties. Message property transaction_group determines which messages belong to the same transaction group.

Example 10-20 dequeues the messages enqueued in Example 10-11. It returns:

Number of messages dequeued: 2

Example 10-20 Dequeuing an Array of Messages

SET SERVEROUTPUT ON
DECLARE
  dequeue_options       DBMS_AQ.dequeue_options_t;
  msg_prop_array        DBMS_AQ.message_properties_array_t := 
                        DBMS_AQ.message_properties_array_t();
  payload_array         test.msg_table;
  msgid_array           DBMS_AQ.msgid_array_t;
  retval                PLS_INTEGER;
BEGIN
  retval := DBMS_AQ.DEQUEUE_ARRAY( 
              queue_name               => 'test.obj_queue',
              dequeue_options          => dequeue_options,
              array_size               => 2,
              message_properties_array => msg_prop_array,
              payload_array            => payload_array,
              msgid_array              => msgid_array);
  DBMS_OUTPUT.PUT_LINE('Number of messages dequeued: ' || retval);
END;/
 

Registering for Notification

DBMS_AQ.REGISTER(
   reg_list     IN SYS.AQ$_REG_INFO_LIST,
   reg_count    IN NUMBER);

This procedure registers an e-mail address, user-defined PL/SQL procedure, or HTTP URL for message notification.


Note:

In releases before Oracle Database 10g Release 2 (10.2), the Oracle Streams Advanced Queuing notification feature was not supported for queues with names longer than 30 characters. This restriction no longer applies. The 24-character limit on names of user-generated queues still applies. See "Creating a Queue".

The reg_list parameter is a list of SYS.AQ$_REG_INFO objects. You can specify notification quality of service, a new feature in Oracle Streams Advanced Queuing 10g Release 2 (10.2), with the qosflags attribute of SYS.AQ$_REG_INFO.


See Also:

"AQ Registration Information Type" for more information on SYS.AQ$_REG_INFO objects

The reg_count parameter specifies the number of entries in the reg_list. Each subscription requires its own reg_list entry. Interest in several subscriptions can be registered at one time.

When PL/SQL notification is received, the Oracle Streams Advanced Queuing message properties descriptor that the callback is invoked with specifies the delivery_mode of the message notified as DBMS_AQ.PERSISTENT or DBMS_AQ.BUFFERED.


See Also:

"AQ Notification Descriptor Type" for more information on the message properties descriptor

If you register for e-mail notifications, then you must set the host name and port name for the SMTP server that will be used by the database to send e-mail notifications. If required, you should set the send-from e-mail address, which is set by the database as the sent from field. You need a Java-enabled database to use this feature.

If you register for HTTP notifications, then you might want to set the host name and port number for the proxy server and a list of no-proxy domains that will be used by the database to post HTTP notifications.

An internal queue called SYS.AQ_SRVNTFN_TABLE_Q stores the notifications to be processed by the job queue processes. If notification fails, then Oracle Streams Advanced Queuing retries the failed notification up to MAX_RETRIES attempts.


Note:

You can change the MAX_RETRIES and RETRY_DELAY properties of SYS.AQ_SRVNTFN_TABLE_Q. The new settings are applied across all notifications.

Example 10-21 Registering for Notifications

DECLARE
  reginfo             sys.aq$_reg_info;
  reg_list            sys.aq$_reg_info_list;
BEGIN
  reginfo := sys.aq$_reg_info(
                      'test.obj_queue',
                      DBMS_AQ.NAMESPACE_ANONYMOUS,
                      'http://www.company.com:8080', 
                      HEXTORAW('FF'));
  reg_list  := sys.aq$_reg_info_list(reginfo);
  DBMS_AQ.REGISTER(
    reg_list     => reg_list, 
    reg_count    => 1);
  COMMIT;
END;
/

Unregistering for Notification

DBMS_AQ.UNREGISTER(
   reg_list     IN SYS.AQ$_REG_INFO_LIST,
   reg_count    IN NUMBER);

This procedure unregisters an e-mail address, user-defined PL/SQL procedure, or HTTP URL for message notification.

Posting for Subscriber Notification

DBMS_AQ.POST(
  post_list       IN  SYS.AQ$_POST_INFO_LIST,
  post_count      IN  NUMBER);

This procedure posts to a list of anonymous subscriptions, allowing all clients who are registered for the subscriptions to get notifications of persistent messages. This feature is not supported with buffered messages.

The count parameter specifies the number of entries in the post_list. Each posted subscription must have its own entry in the post_list. Several subscriptions can be posted to at one time.

The post_list parameter specifies the list of anonymous subscriptions to which you want to post. It has three attributes:

  • name

    The name attribute specifies the name of the anonymous subscription to which you want to post.

  • namespace

    The namespace attribute specifies the namespace of the subscription. To receive notifications from other applications through DBMS_AQ.POST the namespace must be DBMS_AQ.NAMESPACE_ANONYMOUS.

  • payload

    The payload attribute specifies the payload to be posted to the anonymous subscription. It is possible for no payload to be associated with this call.

This call provides a best-effort guarantee. A notification goes to registered clients at most once. This call is primarily used for lightweight notification. If an application needs more rigid guarantees, then it can enqueue to a queue.

Example 10-22 Posting Object-Type Messages

DECLARE
  postinfo            sys.aq$_post_info;
  post_list           sys.aq$_post_info_list;
BEGIN
  postinfo  := sys.aq$_post_info('test.obj_queue',0,HEXTORAW('FF')); 
  post_list := sys.aq$_post_info_list(postinfo);
  DBMS_AQ.POST(
    post_list       => post_list,
    post_count      => 1);
  COMMIT;
END;
/

Adding an Agent to the LDAP Server

DBMS_AQ.BIND_AGENT(
   agent        IN SYS.AQ$_AGENT,
   certificate  IN VARCHAR2 default NULL);

This procedure creates an entry for an Oracle Streams Advanced Queuing agent in the Lightweight Directory Access Protocol (LDAP) server.

The agent parameter specifies the Oracle Streams Advanced Queuing Agent that is to be registered in LDAP server.


See Also:

"AQ Agent Type"

The certificate parameter specifies the location (LDAP distinguished name) of the OrganizationalPerson entry in LDAP whose digital certificate (attribute usercertificate) is to be used for this agent. For example, "cn=OE, cn=ACME, cn=com" is a distinguished name for a OrganizationalPerson OE whose certificate will be used with the specified agent. If the agent does not have a digital certificate, then this parameter is defaulted to null.

Removing an Agent from the LDAP Server

DBMS_AQ.UNBIND_AGENT(
   agent    IN SYS.AQ$_AGENT);

This procedure removes the entry for an Oracle Streams Advanced Queuing agent from the LDAP server.

PKf5==PK-AOEBPS/aq_stage.htm Using ANYDATA Queues for User Messages

22 Using ANYDATA Queues for User Messages

This chapter describes how to use and manage Oracle Streams Advanced Queuing when enqueuing and propagating. It describes ANYDATA queues and user messages.

Oracle Streams uses queues of type ANYDATA to store three types of messages:

  • Captured logical change record (LCR)

    This message type, produced by an Oracle Streams capture process, is not discussed in this guide.


    See Also:

    "Streams Capture Process" in Oracle Streams Concepts and Administration

  • User-enqueued LCR

    This is a message containing an LCR that was enqueued by a user or application.

  • User message

    This is a non-LCR message created and enqueued by a user or application.

All three types of messages can be used for information sharing within a single database or between databases.

This chapter contains these topics:


See Also:

Oracle Database PL/SQL Packages and Types Reference for more information about the ANYDATA type

ANYDATA Queues and User Messages

This section contains these topics:

ANYDATA Wrapper for User Messages Payloads

You can wrap almost any type of payload in an ANYDATA payload with the Convertdata_type static functions of the ANYDATA type, where data_type is the type of object to wrap. These functions take the object as input and return an ANYDATA object.

The following datatypes cannot be wrapped in an ANYDATA wrapper:

  • Nested table

  • NCLOB

  • ROWID and UROWID

The following datatypes can be directly wrapped in an ANYDATA wrapper, but they cannot be present in a user-defined type payload wrapped in an ANYDATA wrapper:

Programmatic Interfaces for Enqueue and Dequeue of User Messages

Your applications can use the following programmatic interfaces to enqueue user messages into an ANYDATA queue and dequeue user messages from an ANYDATA queue:

The following sections provide information about using these interfaces to enqueue user messages into and dequeue user messages from an ANYDATA queue.


See Also:

Chapter 3, "Oracle Streams Advanced Queuing: Programmatic Interfaces" for more information about these programmatic interfaces

Enqueuing User Messages Using PL/SQL

To enqueue a user message containing an LCR into an ANYDATA queue using PL/SQL, first create the LCR to be enqueued. You use the constructor for the SYS.LCR$_ROW_RECORD type to create a row LCR, and you use the constructor for the SYS.LCR$_DDL_RECORD type to create a DDL LCR. Then you use the ANYDATA.ConvertObject function to convert the LCR into an ANYDATA payload and enqueue it using the DBMS_AQ.ENQUEUE procedure.

To enqueue a user message containing a non-LCR object into an ANYDATA queue using PL/SQL, you use one of the ANYDATA.Convert* functions to convert the object into an ANYDATA payload and enqueue it using the DBMS_AQ.ENQUEUE procedure.

Enqueuing User Messages Using OCI or JMS

To enqueue a user message containing an LCR into an ANYDATA queue using JMS or OCI, you must represent the LCR in XML format. To construct an LCR, use the oracle.xdb.XMLType class. LCRs are defined in the SYS schema. The LCR schema must be loaded into the SYS schema using the catxlcr.sql script in ORACLE_HOME/rdbms/admin.

To enqueue a message using OCI, perform the same actions that you would to enqueue a message into a typed queue. To enqueue a message using JMS, a user must have EXECUTE privilege on the DBMS_AQ, DBMS_AQIN and DBMS_AQJMS packages.


Note:

Enqueue of JMS types and XML types does not work with ANYDATA queues unless you call DBMS_AQADM.ENABLE_JMS_TYPES(queue_table_name) after DBMS_STREAMS_ADM.SET_UP_QUEUE(queue_name). Enabling a queue for these types may affect import/export of the queue table.

A non-LCR user message can be a message of any user-defined type or a JMS type. The JMS types include the following:

  • javax.jms.TextMessage

  • javax.jms.MapMessage

  • javax.jms.StreamMessage

  • javax.jms.ObjectMessage

  • javax.jms.BytesMessage

When using user-defined types, you must generate the Java class for the message using Jpublisher, which implements the ORAData interface. To enqueue a message into an ANYDATA queue, you can use methods QueueSender.send or TopicPublisher.publish.


See Also:


Dequeuing User Messages Using PL/SQL

To dequeue a user message from an ANYDATA queue using PL/SQL, you use the DBMS_AQ.DEQUEUE procedure and specify ANYDATA as the payload. The user message can contain an LCR or another type of object.

Dequeuing User Messages Using OCI or JMS

In an ANYDATA queue, user messages containing LCRs in XML format are represented as oracle.xdb.XMLType. Non-LCR messages can be any user-defined type or a JMS type.

To dequeue a message from an ANYDATA queue using JMS, you can use methods QueueReceiver, TopicSubscriber, or TopicReceiver. Because the queue can contain different types of objects wrapped in ANYDATA wrappers, you must register a list of SQL types and their corresponding Java classes in the type map of the JMS session. JMS types are already preregistered in the type map.

For example, suppose a queue contains user-enqueued LCR messages represented as oracle.xdb.XMLType and non-LCR messages of type person and address. The classes JPerson.java and JAddress.java are the ORAData mappings for person and address, respectively. Before dequeuing the message, the type map must be populated as follows:

java.util.Map map = ((AQjmsSession)q_sess).getTypeMap();

map.put("SCOTT.PERSON", Class.forName("JPerson"));
map.put("SCOTT.ADDRESS", Class.forName("JAddress"));
map.put("SYS.XMLTYPE", Class.forName("oracle.xdb.XMLType"));  // For LCRs

When using a messageSelector with a QueueReceiver or TopicPublisher, the selector can contain any SQL expression that has a combination of one or more of the following:

  • JMS message header fields or properties

    These include JMSPriority, JMSCorrelationID, JMSType, JMSXUserI, JMSXAppID, JMSXGroupID, and JMSXGroupSeq. An example of a JMS message field messageSelector is:

    JMSPriority < 3 AND JMSCorrelationID = 'Fiction'
    
  • User-defined message properties

    An example of a user-defined message properties messageSelector is:

    color IN ('RED', 'BLUE', 'GREEN') AND price < 30000
    
  • PL/SQL functions

    An example of a PL/SQL function messageSelector is:

    hr.GET_TYPE(tab.user_data) = 'HR.EMPLOYEES'  
    

To dequeue a message from an ANYDATA queue using OCI, perform the same actions that you would to dequeue a message from a typed queue.


See Also:


Message Propagation and ANYDATA Queues

ANYDATA queues can interoperate with typed queues. Table 22-1 shows the types of propagation possible between queues.

Table 22-1 Propagation Between Different Types of Queues

Source QueueDestination QueueTransformation

ANYDATA

ANYDATA

None

Typed

ANYDATA

Implicit

Note: Propagation is possible only if the messages in the typed queue meet the restrictions outlined in "Object Type Support".

ANYDATA

Typed

Requires a rule to filter messages and a user-defined transformation. Only messages containing a payload of the same type as the typed queue can be propagated to the typed queue.

Typed

Typed

Follows Oracle Streams Advanced Queuing rules



Note:

Propagations cannot propagate user-enqueued ANYDATA messages that encapsulate payloads of object types, varrays, or nested tables between databases with different character sets. Propagations can propagate such messages between databases with the same character set.

Although you cannot use Simple Object Access Protocol (SOAP) to interact directly with an ANYDATA queue, you can use SOAP by propagating messages between an ANYDATA queue and a typed queue. If you want to enqueue a message into an ANYDATA queue using SOAP, you must first configure propagation from a typed queue to the ANYDATA queue. Then you can use SOAP to enqueue a message into the typed queue. The message is propagated automatically from the typed queue to the ANYDATA queue.

If you want to use SOAP to dequeue a message that is in an ANYDATA queue, then you can configure propagation from the ANYDATA queue to a typed queue. The message is propagated automatically from the ANYDATA queue to the typed queue, where it is available for access using SOAP.


See Also:

"Propagating Messages Between an ANYDATA Queue and a Typed Queue" in Oracle Streams Concepts and Administration

Enqueuing User Messages in ANYDATA Queues

This section provides examples of enqueuing messages into an ANYDATA queue. The examples assume you are in a SQL*Plus testing environment with access to two databases named db01 and db02. The first few examples prepare the testing environment for the other examples in this chapter.

In Example 22-1, you connect as a user with administrative privileges at databases db01 and db02 to create administrator user strmadmin and to grant EXECUTE privilege on the DBMS_AQ package to sample schema user oe.

Example 22-1 Creating ANYDATA Users

GRANT EXECUTE ON DBMS_AQ TO oe;
CREATE USER strmadmin IDENTIFIED BY strmadmin DEFAULT TABLESPACE example;
GRANT DBA TO strmadmin; 
GRANT EXECUTE ON DBMS_STREAMS_ADM TO strmadmin;
GRANT EXECUTE ON DBMS_TRANSFORM TO strmadmin;

In Example 22-2, you connect to db01 as strmadmin to create ANYDATA queue oe_queue_any. The oe user is configured automatically as a secure user of the oe_queue_any queue and is given ENQUEUE and DEQUEUE privileges on the queue.

Example 22-2 Creating an ANYDATA Queue

CONNECT strmadmin;
Enter password: password
BEGIN
  DBMS_STREAMS_ADM.SET_UP_QUEUE(
    queue_table  => 'oe_qtab_any',
    queue_name   => 'oe_queue_any',
    queue_user   => 'oe');
END;
/

In Example 22-3, you add a subscriber to the oe_queue_any queue. This subscriber performs explicit dequeues of messages. The ADD_SUBSCRIBER procedure will automatically create an AQ_AGENT.

Example 22-3 Adding a Subscriber to the ANYDATA Queue

DECLARE
  subscriber SYS.AQ$_AGENT;
BEGIN
  subscriber :=  SYS.AQ$_AGENT('LOCAL_AGENT', NULL, NULL);
  SYS.DBMS_AQADM.ADD_SUBSCRIBER(
    queue_name  =>  'strmadmin.oe_queue_any',
    subscriber  =>  subscriber);
END;
/

In Example 22-4, you associate the oe user with the local_agent agent.

Example 22-4 Associating a User with an AQ_AGENT

BEGIN
  DBMS_AQADM.ENABLE_DB_ACCESS(
    agent_name  => 'local_agent',
    db_username => 'oe');
END;
/

In Example 22-5, you connect to database db01 as user oe to create an enqueue procedure. It takes an object of ANYDATA type as an input parameter and enqueues a message containing the payload into an existing ANYDATA queue.

Example 22-5 Creating an Enqueue Procedure

set echo off
set verify off
ACCEPT password CHAR PROMPT 'Enter the password for OE: ' HIDE
CONNECT oe/&password@db01;
 
set echo on
CREATE PROCEDURE oe.enq_proc (payload ANYDATA)  IS 
  enqopt     DBMS_AQ.ENQUEUE_OPTIONS_T;
  mprop      DBMS_AQ.MESSAGE_PROPERTIES_T;
  enq_msgid  RAW(16);
BEGIN
  mprop.SENDER_ID := SYS.AQ$_AGENT('LOCAL_AGENT', NULL, NULL); 
  DBMS_AQ.ENQUEUE(
    queue_name          =>  'strmadmin.oe_queue_any',
    enqueue_options     =>  enqopt,
    message_properties  =>  mprop,
    payload             =>  payload,
    msgid               =>  enq_msgid);
END;
/

In Example 22-6, you use procedure oe.enq_proc to enqueue a message of type VARCHAR2 into an ANYDATA queue.

Example 22-6 Enqueuing a VARCHAR2 Message into an ANYDATA Queue

EXEC oe.enq_proc(ANYDATA.ConvertVarchar2('Chemicals - SW'));
COMMIT;

In Example 22-7, you use procedure oe.enq_proc to enqueue a message of type NUMBER into an ANYDATA queue.

Example 22-7 Enqueuing a NUMBER Message into an ANYDATA Queue

EXEC oe.enq_proc(ANYDATA.ConvertNumber('16'));
COMMIT;

In Example 22-8, you use procedure oe.enq_proc to enqueue a user-defined type message into an ANYDATA queue.

Example 22-8 Enqueuing a User-Defined Type Message into an ANYDATA Queue

BEGIN
  oe.enq_proc(ANYDATA.ConvertObject(oe.cust_address_typ(
    '1646 Brazil Blvd','361168','Chennai','Tam', 'IN')));
END;
/
COMMIT;

See Also:

"Viewing the Contents of User-Enqueued Events in a Queue" in Oracle Streams Concepts and Administration

Dequeuing User Messages from ANYDATA Queues

This section provides examples of dequeuing messages from an ANYDATA queue. The examples assume that you have completed the examples in "Enqueuing User Messages in ANYDATA Queues".

To dequeue messages, you must know the consumer of the messages. To find the consumer for the messages in a queue, connect as the owner of the queue and query the AQ$queue_table_name view, where queue_table_name is the name of the queue table containing the queue.

In Example 22-9, you connect to database db01 as strmadmin, the owner of queue oe_queue_any, and perform a query on the AQ$OE_QTAB_ANY view. The query returns three rows, with LOCAL_AGENT as the CONSUMER_NAME in each row.

Example 22-9 Determining the Consumer of Messages in a Queue

CONNECT strmadmin;
Enter password: password
SELECT MSG_ID, MSG_STATE, CONSUMER_NAME FROM AQ$OE_QTAB_ANY;

In Example 22-10, you connect to database db01 as user oe to create a dequeue procedure that takes as an input the consumer of the messages you want to dequeue, dequeues messages of oe.cust_address_typ, and prints the contents of the messages.

Example 22-10 Creating a Dequeue Procedure for an ANYDATA Queue

CONNECT oe; -- @db01
Enter password: password

CREATE PROCEDURE oe.get_cust_address (
consumer IN VARCHAR2) AS
  address         OE.CUST_ADDRESS_TYP;
  deq_address     ANYDATA; 
  msgidTg           RAW(16); 
  deqopt          DBMS_AQ.DEQUEUE_OPTIONS_T; 
  mprop           DBMS_AQ.MESSAGE_PROPERTIES_T;
  new_addresses   BOOLEAN := TRUE;
  next_trans      EXCEPTION;
  no_messages     EXCEPTION; 
  pragma exception_init (next_trans, -25235);
  pragma exception_init (no_messages, -25228);
  num_var         pls_integer;
BEGIN
  deqopt.consumer_name := consumer;
  deqopt.wait := 1;
  WHILE (new_addresses) LOOP
  BEGIN
    DBMS_AQ.DEQUEUE( 
      queue_name          =>  'strmadmin.oe_queue_any',
      dequeue_options     =>  deqopt,
      message_properties  =>  mprop,
      payload             =>  deq_address,
      msgid               =>  msgid);
    deqopt.navigation := DBMS_AQ.NEXT;
    DBMS_OUTPUT.PUT_LINE('****');
    IF (deq_address.GetTypeName() = 'OE.CUST_ADDRESS_TYP') THEN
       DBMS_OUTPUT.PUT_LINE('Message TYPE is: ' || deq_address.GetTypeName()); 
       num_var := deq_address.GetObject(address);
       DBMS_OUTPUT.PUT_LINE(' **** CUSTOMER ADDRESS **** ');
       DBMS_OUTPUT.PUT_LINE(address.street_address);
       DBMS_OUTPUT.PUT_LINE(address.postal_code);
       DBMS_OUTPUT.PUT_LINE(address.city);
       DBMS_OUTPUT.PUT_LINE(address.state_province);
       DBMS_OUTPUT.PUT_LINE(address.country_id);
    ELSE
       DBMS_OUTPUT.PUT_LINE('Message TYPE is: ' || deq_address.GetTypeName()); 
    END IF;
  COMMIT;
  EXCEPTION
     WHEN next_trans THEN
       deqopt.navigation := DBMS_AQ.NEXT_TRANSACTION;
     WHEN no_messages THEN
       new_addresses := FALSE;
       DBMS_OUTPUT.PUT_LINE('No more messages');
  END;
  END LOOP; 
END;
/

In Example 22-11, you use procedure oe.get_cust_address, created in Example 22-10, specifying LOCAL_AGENT as the consumer.

Example 22-11 Dequeuing Messages from an ANYDATA Queue

SET SERVEROUTPUT ON SIZE 100000
EXEC oe.get_cust_address('LOCAL_AGENT');

The example returns:

****
Message TYPE is: SYS.VARCHAR2
****
Message TYPE is: SYS.NUMBER
****
Message TYPE is: OE.CUST_ADDRESS_TYP
**** CUSTOMER ADDRESS ****
1646 Brazil Blvd
361168
Chennai
Tam
IN
No more messages

Propagating User Messages from ANYDATA Queues to Typed Queues

This section provides examples showing how to propagate non-LCR user messages between an ANYDATA queue and a typed queue.


Note:

The examples in this section assume that you have completed the examples in "Enqueuing User Messages in ANYDATA Queues".


See Also:

"Message Propagation and ANYDATA Queues" for more information about propagation between ANYDATA and typed queues

The first few examples set up propagation from the ANYDATA queue oe_queue_any, created in Example 22-2, to a typed queue in database db02. In Example 22-12, you connect as sample schema user oe to grant EXECUTE privilege on oe.cust_address_typ at databases db01 and db02 to administrator user strmadmin.

Example 22-12 Granting EXECUTE Privilege on a Type

CONNECT oe; -- @db01
Enter password: password

GRANT EXECUTE ON oe.cust_address_typ TO strmadmin;
CONNECT oe; -- @db02
Enter password: password

GRANT EXECUTE ON oe.cust_address_typ TO strmadmin;

In Example 22-13, you connect to database db02 as administrator user strmadmin and create a destination queue of type oe.cust_address_typ.

Example 22-13 Creating a Typed Destination Queue

CONNECT strmadmin;
Enter password: password

BEGIN 
  DBMS_AQADM.CREATE_QUEUE_TABLE(
    queue_table         => 'strmadmin.oe_qtab_address', 
    queue_payload_type  => 'oe.cust_address_typ', 
    multiple_consumers  => true);
  DBMS_AQADM.CREATE_QUEUE(
    queue_name          => 'strmadmin.oe_queue_address', 
    queue_table         => 'strmadmin.oe_qtab_address');
  DBMS_AQADM.START_QUEUE(
    queue_name          => 'strmadmin.oe_queue_address');
END;
/

In Example 22-14, you connect to database db01 as administrator user strmadmin to create a database link from db01 to db02.

Example 22-14 Creating a Database Link

CONNECT strmadmin;
Enter password: password

CREATE DATABASE LINK db02 CONNECT TO strmadmin IDENTIFIED BY password 
  USING 'db02'; 

In Example 22-15, you create function any_to_cust_address_typ in the strmadmin schema at db01 that takes an ANYDATA payload containing an oe.cust_address_typ object and returns an oe.cust_address_typ object.

Example 22-15 Creating a Function to Extract a Typed Object from an ANYDATA Object

CONNECT strmadmin;
Enter password: password

CREATE FUNCTION strmadmin.any_to_cust_address_typ(in_any IN ANYDATA) 
RETURN OE.CUST_ADDRESS_TYP
AS
  address       OE.CUST_ADDRESS_TYP;
  num_var       NUMBER;
  type_name     VARCHAR2(100);
BEGIN
  type_name := in_any.GetTypeName();
  IF (type_name = 'OE.CUST_ADDRESS_TYP') THEN
    num_var := in_any.GetObject(address);
    RETURN address;
  ELSE
    raise_application_error(-20101, 'Conversion failed - ' || type_name);
  END IF;
END;
/

In Example 22-16, you create a transformation at db01 using the DBMS_TRANSFORM package.

Example 22-16 Creating an ANYDATA to Typed Object Transformation

BEGIN
  DBMS_TRANSFORM.CREATE_TRANSFORMATION( 
   schema         => 'strmadmin', 
   name           => 'anytoaddress', 
   from_schema    => 'SYS', 
   from_type      => 'ANYDATA', 
   to_schema      => 'oe', 
   to_type        => 'cust_address_typ', 
   transformation => 'strmadmin.any_to_cust_address_typ(source.user_data)'); 
END;
/

In Example 22-17, you create a subscriber for the typed queue. The subscriber must contain a rule that ensures that only messages of the appropriate type are propagated to the destination queue.

Example 22-17 Creating Subscriber ADDRESS_AGENT_REMOTE

DECLARE 
  subscriber  SYS.AQ$_AGENT; 
BEGIN 
  subscriber := SYS.AQ$_AGENT ('ADDRESS_AGENT_REMOTE', 
                               'STRMADMIN.OE_QUEUE_ADDRESS@DB02', 
                               0); 
  DBMS_AQADM.ADD_SUBSCRIBER(
    queue_name     => 'strmadmin.oe_queue_any', 
    subscriber     => subscriber,
    rule           => 'TAB.USER_DATA.GetTypeName()=''OE.CUST_ADDRESS_TYP''',
    transformation => 'strmadmin.anytoaddress'); 
END; 
/

In Example 22-18, you schedule propagation between the ANYDATA queue at db01 and the typed queue at db02.

Example 22-18 Scheduling Propagation from an ANYDATA Queue to a Typed Queue

BEGIN 
  DBMS_AQADM.SCHEDULE_PROPAGATION(
    queue_name   => 'strmadmin.oe_queue_any', 
    destination  => 'db02'); 
END;
/

In Example 22-19, you connect to database db01 as sample schema user oe to enqueue a message of oe.cust_address_typ type wrapped in an ANYDATA wrapper. This example uses the enqueue procedure oe.enq_proc created in Example 22-5.

Example 22-19 Enqueuing a Typed Message in an ANYDATA Wrapper

CONNECT oe;
Enter password: password

BEGIN
  oe.enq_proc(ANYDATA.ConvertObject(oe.cust_address_typ(
    '1668 Chong Tao','111181','Beijing',NULL,'CN')));
END;
/
COMMIT;

After allowing some time for propagation, in Example 22-20 you query queue table AQ$OE_QTAB_ADDRESS at db02 to view the propagated message.

Example 22-20 Viewing the Propagated Message

CONNECT strmadmin;
Enter password: password

SELECT MSG_ID, MSG_STATE, CONSUMER_NAME FROM AQ$OE_QTAB_ADDRESS;

The example returns one message for ADDRESS_AGENT_REMOTE:

MSG_ID                           MSG_STATE        CONSUMER_NAME
-------------------------------- ---------------- ------------------------------
EBEF5CACC4665A6FE030578CE70A370D READY            ADDRESS_AGENT_REMOTE
 
1 row selected.

See Also:

Chapter 20, "Oracle Messaging Gateway Message Conversion" for more information about transformations during propagation

Propagating User-Enqueued LCRs from ANYDATA Queues to Typed Queues

You can propagate user-enqueued LCRs to an appropriate typed queue, but propagation of captured LCRs to a typed queue is not supported.


See Also:

"Streams Capture Process" in Oracle Streams Concepts and Administration for more information on capture processes

To propagate user-enqueued LCRs from an ANYDATA queue to a typed queue, you complete the same steps as you do for non-LCR messages, but Oracle supplies the transformation functions. You can use the following functions in the DBMS_STREAMS package to transform LCRs in ANYDATA queues to messages in typed queues:

  • CONVERT_ANYDATA_TO_LCR_ROW transforms an ANYDATA payload containing a row LCR into a SYS.LCR$_ROW_RECORD payload.

  • CONVERT_ANYDATA_TO_LCR_DDL transforms an ANYDATA payload containing a DDL LCR into a SYS.LCR$_DDL_RECORD payload.

The examples in this section set up propagation of row LCRs from an ANYDATA queue named oe_queue_any to a typed queue of type SYS.LCR$_ROW_RECORD named oe_queue_lcr. The source queue oe_queue_any is at database db01, and the destination queue oe_queue_lcr is created at database db02 in Example 22-21.


Note:

The examples in this section assume you have already run the examples in the preceding sections of this chapter.

Example 22-21 Creating a Queue of Type LCR$_ROW_RECORD

CONNECT strmadmin;
Enter password: password

BEGIN 
  DBMS_AQADM.CREATE_QUEUE_TABLE(
    queue_table         => 'strmadmin.oe_qtab_lcr', 
    queue_payload_type  => 'SYS.LCR$_ROW_RECORD', 
    multiple_consumers  => true);
  DBMS_AQADM.CREATE_QUEUE(
    queue_name   => 'strmadmin.oe_queue_lcr', 
    queue_table  => 'strmadmin.oe_qtab_lcr');
  DBMS_AQADM.START_QUEUE(
    queue_name   => 'strmadmin.oe_queue_lcr');
END;
/

In Example 22-22, you connect to db01 as administrator user strmadmin to create an ANYDATA to LCR$_ROW_RECORD transformation at db01 using the DBMS_TRANSFORM package.

Example 22-22 Creating an ANYDATA to LCR$_ROW_RECORD Transformation

CONNECT strmadmin;
Enter password: password

BEGIN
  DBMS_TRANSFORM.CREATE_TRANSFORMATION( 
    schema         => 'strmadmin', 
    name           => 'anytolcr', 
    from_schema    => 'SYS', 
    from_type      => 'ANYDATA', 
    to_schema      => 'SYS', 
    to_type        => 'LCR$_ROW_RECORD', 
    transformation =>
          'SYS.DBMS_STREAMS.CONVERT_ANYDATA_TO_LCR_ROW(source.user_data)'); 
END;
/

In Example 22-23, you create a subscriber at the typed queue. The subscriber specifies the anytolcr transformation created in Example 22-22 for the transformation parameter.

Example 22-23 Creating Subscriber ROW_LCR_AGENT_REMOTE

DECLARE 
  subscriber  SYS.AQ$_AGENT; 
BEGIN 
  subscriber := SYS.AQ$_AGENT(
    'ROW_LCR_AGENT_REMOTE', 
    'STRMADMIN.OE_QUEUE_LCR@DB02', 
    0); 
  DBMS_AQADM.ADD_SUBSCRIBER(
    queue_name     => 'strmadmin.oe_queue_any',
    subscriber     => subscriber,
    rule           => 'TAB.USER_DATA.GetTypeName()=''SYS.LCR$_ROW_RECORD''',
    transformation => 'strmadmin.anytolcr'); 
END; 
/

In Example 22-24, you connect to database db01 as sample schema user oe to create a procedure to construct and enqueue a row LCR into the strmadmin.oe_queue_any queue.

Example 22-24 Creating a Procedure to Construct and Enqueue a Row LCR

CONNECT oe;
Enter password: password

CREATE PROCEDURE oe.enq_row_lcr_proc(
  source_dbname  VARCHAR2,
  cmd_type       VARCHAR2,
  obj_owner      VARCHAR2,
  obj_name       VARCHAR2,
  old_vals       SYS.LCR$_ROW_LIST,
  new_vals       SYS.LCR$_ROW_LIST) 
AS
  eopt           DBMS_AQ.ENQUEUE_OPTIONS_T;
  mprop          DBMS_AQ.MESSAGE_PROPERTIES_T;
  enq_msgid      RAW(16);
  row_lcr        SYS.LCR$_ROW_RECORD;
BEGIN
  mprop.SENDER_ID := SYS.AQ$_AGENT('LOCAL_AGENT', NULL, NULL); 
  row_lcr := SYS.LCR$_ROW_RECORD.CONSTRUCT(
    source_database_name  =>  source_dbname,
    command_type          =>  cmd_type,
    object_owner          =>  obj_owner,
    object_name           =>  obj_name,
    old_values            =>  old_vals,
    new_values            =>  new_vals);
  DBMS_AQ.ENQUEUE(
    queue_name            =>  'strmadmin.oe_queue_any', 
    enqueue_options       =>  eopt,
    message_properties    =>  mprop,
    payload               =>  ANYDATA.ConvertObject(row_lcr),
    msgid                 =>  enq_msgid);
END enq_row_lcr_proc;
/

In Example 22-25, you use the oe.enq_row_lcr_proc procedure first to create a row LCR that inserts a row into the oe.inventories table, and then to enqueue the row LCR into the strmadmin.oe_queue_any queue.


Note:

This example does not insert a new row in the oe.inventories table. The new row is inserted when an Oracle Streams apply process dequeues the row LCR and applies it.

Example 22-25 Creating and Enqueuing a Row LCR

DECLARE
  newunit1  SYS.LCR$_ROW_UNIT;
  newunit2  SYS.LCR$_ROW_UNIT;
  newunit3  SYS.LCR$_ROW_UNIT;
  newvals   SYS.LCR$_ROW_LIST;
BEGIN
  newunit1 := SYS.LCR$_ROW_UNIT(
    'PRODUCT_ID', 
    ANYDATA.ConvertNumber(3503),
    DBMS_LCR.NOT_A_LOB,
    NULL,
    NULL);
  newunit2 := SYS.LCR$_ROW_UNIT(
    'WAREHOUSE_ID', 
    ANYDATA.ConvertNumber(1),
    DBMS_LCR.NOT_A_LOB,
    NULL,
    NULL);
  newunit3 := SYS.LCR$_ROW_UNIT(
    'QUANTITY_ON_HAND', 
    ANYDATA.ConvertNumber(157),
    DBMS_LCR.NOT_A_LOB,
    NULL,
    NULL);
  newvals := SYS.LCR$_ROW_LIST(newunit1,newunit2,newunit3);
oe.enq_row_lcr_proc(
  source_dbname  =>  'DB01',
  cmd_type       =>  'INSERT',
  obj_owner      =>  'OE',
  obj_name       =>  'INVENTORIES',
  old_vals       =>  NULL,
  new_vals       =>  newvals);
END;
/
COMMIT;

The LCR is propagated to database db02 by the schedule created in Example 22-18. After allowing some time for propagation, in Example 22-26 you query queue table AQ$OE_QTAB_LCR at db02 to view the propagated message.

Example 22-26 Viewing the Propagated LCR

CONNECT strmadmin;
Enter password: password

SELECT MSG_ID, MSG_STATE, CONSUMER_NAME FROM AQ$OE_QTAB_LCR;

The example returns one message for ROW_LCR_AGENT_REMOTE:

MSG_ID                           MSG_STATE        CONSUMER_NAME
-------------------------------- ---------------- ------------------------------
ECE2B0F912DDFF5EE030578CE70A04BB READY            ROW_LCR_AGENT_REMOTE

See Also:

"DBMS_STREAMS" in Oracle Database PL/SQL Packages and Types Reference for more information about the row LCR and DDL LCR conversion functions

PK7PK-AOEBPS/mg_intro.htm>F Introducing Oracle Messaging Gateway

17 Introducing Oracle Messaging Gateway

The Messaging Gateway administration package DBMS_MGWADM provides an interface for creating Messaging Gateway agents, managing agents, creating messaging system links, registering non-Oracle queues, and setting up propagation jobs.

This chapter contains these topics:

Introducing Oracle Messaging Gateway

Messaging Gateway enables communication between applications based on non-Oracle messaging systems and Oracle Streams Advanced Queuing.

Oracle Streams Advanced Queuing provides propagation between two Oracle Streams Advanced Queuing queues to enable e-business (HTTP through IDAP). Messaging Gateway extends this to applications based on non-Oracle messaging systems.

Because Messaging Gateway is integrated with Oracle Streams Advanced Queuing and Oracle Database, it offers reliable message delivery. Messaging Gateway guarantees that messages are delivered once and only once between Oracle Streams Advanced Queuing and non-Oracle messaging systems that support persistence. The PL/SQL interface provides an easy-to-learn administrative API, especially for developers already proficient in using Oracle Streams Advanced Queuing.

This release of Messaging Gateway supports the integration of Oracle Streams Advanced Queuing with applications based on WebSphere MQ 6.0 and TIB/Rendezvous 7.2.

Oracle Messaging Gateway Features

Messaging Gateway provides the following features:

  • Extends Oracle Streams Advanced Queuing message propagation

    Messaging Gateway propagates messages between Oracle Streams Advanced Queuing and non-Oracle messaging systems. Messages sent by Oracle Streams Advanced Queuing applications can be received by non-Oracle messaging system applications. Conversely, messages published by non-Oracle messaging system applications can be consumed by Oracle Streams Advanced Queuing applications.

  • Support for Java Message Service (JMS) messaging systems

    Messaging Gateway propagates messages between Oracle Java Message Service (Oracle JMS) and WebSphere MQ Java Message Service (WebSphere MQ JMS).

  • Native message format support

    Messaging Gateway supports the native message formats of messaging systems. Oracle Streams Advanced Queuing messages can have RAW or any Oracle object type payload. WebSphere MQ messages can be text or byte messages. TIB/Rendezvous messages can be any TIB/Rendezvous wire format datatype except the nested datatype MSG and those with unsigned integers.

  • Message conversion

    Messaging Gateway facilitates message conversion between Oracle Streams Advanced Queuing messages and non-Oracle messaging system messages. Messages are converted through either automatic routines provided by Messaging Gateway or customized message transformation functions that you provide.


    Note:

    Messaging Gateway does not support message propagation between JMS and non-JMS messaging systems.

  • Integration with Oracle Database

    Messaging Gateway is managed through a PL/SQL interface similar to that of Oracle Streams Advanced Queuing. Configuration information is stored in Oracle Database tables. Message propagation is carried out by an external process of the Oracle Database server.

  • Guaranteed message delivery

    If the messaging systems at the propagation source and propagation destination both support transactions, then Messaging Gateway guarantees that persistent messages are propagated exactly once. If messages are not persistent or transactions are not supported by the messaging systems at the propagation source or propagation destination, then at-most-once propagation is guaranteed.

  • Security support

    Messaging Gateway supports client authentication of Oracle Database and non-Oracle messaging systems.

    Messaging Gateway also allows Secure Socket Layer (SSL) support for IBM WebSphere MQ and WebSphere MQ JMS connections made by the Messaging Gateway agent.

  • Multiple agent support

    Messaging Gateway supports multiple agents for a given database. Users can partition propagation jobs based on functionality, organizations, or workload and assign them to different Messaging Gateway agents. This allows Messaging Gateway to scale in a Oracle RAC environment and enables propagation job grouping and isolation.

Oracle Messaging Gateway Architecture

Messaging Gateway has two main components:

  • Administration Package DBMS_MGWADM

  • Messaging Gateway Agent

Figure 17-1 shows how these components work together with Oracle Database and non-Oracle messaging systems.

Figure 17-1 Messaging Gateway Architecture

Description of Figure 17-1 follows
Description of "Figure 17-1 Messaging Gateway Architecture"

Administration Package DBMS_MGWADM

The Messaging Gateway administration package DBMS_MGWADM provides an interface for creating named Messaging Gateway agents, managing agents, creating messaging system links, registering non-Oracle queues, and setting up propagation jobs.

Users call the procedures in the package to make configuration changes regardless of whether the Messaging Gateway agent is running. If the Messaging Gateway agent is running, then the procedures in the package send notifications for configuration changes to the agent. The agent dynamically alters its configuration for most configuration changes, although some changes require that the agent be shut down and restarted before they take effect. All the procedures in the package are serialized to guarantee that the Messaging Gateway agent receives and processes notifications in the same order as they are made.


See Also:

Oracle Database PL/SQL Packages and Types Reference for more information on DBMS_MGWADM

Oracle Messaging Gateway Agent

The Messaging Gateway agent runs as an external process of the Oracle Database server and processes propagation jobs. It is started and shut down by calling the STARTUP and SHUTDOWN procedures in DBMS_MGWADM package.

The Messaging Gateway agent contains a multithreaded propagation engine and a set of drivers for messaging systems. The propagation engine fairly schedules propagation jobs and processes propagation jobs concurrently. The polling thread in the agent periodically polls the source queues of enabled propagation jobs and wakes up worker threads to process propagation jobs if messages are available. The drivers for non-Oracle messaging systems run as clients of the messaging systems for all messaging operations.

Oracle Database

As an Oracle Database feature, Messaging Gateway provides a mechanism of message propagation between Oracle Streams Advanced Queuing and non-Oracle messaging systems. Oracle Streams Advanced Queuing is involved in every propagation job as either propagation source or propagation destination.

Messaging Gateway is managed through the PL/SQL administration package DBMS_MGWADM. All configuration information and execution state information of Messaging Gateway are stored in Oracle Database and can be accessed through database views.

The Messaging Gateway agent runs as an external procedure of the Oracle Database server. Therefore, it runs only when its associated database server is running.

Non-Oracle Messaging Systems

The Messaging Gateway agent connects to non-Oracle messaging systems through messaging system links. Messaging system links are communication channels between the Messaging Gateway agent and non-Oracle messaging systems. Users can use the administration package DBMS_MGWADM to configure multiple links to the same or different non-Oracle messaging systems.

Queues in non-Oracle messaging systems, such as WebSphere MQ queues, TIB/Rendezvous subjects, and WebSphere MQ JMS destinations (queues and topics) can all serve as propagation sources and destinations for Messaging Gateway. They are referred to as foreign queues. All foreign queues involved in message propagation as source queues, destination queues, or exception queues must be registered through the administration package. The registration of a foreign queue does not create the physical queue in a non-Oracle messaging system, but merely records information about the queue, such as the messaging system link to access it, its native name, and its domain (queue or topic). The physical queue must be created through the administration interface of the non-Oracle messaging system.

Propagation Processing Overview

Propagation jobs must be defined in order for messages to be propagated from one messaging system to another. A propagation job defines the source queue, destination queue, and various other attributes that affect the processing of the propagation job.

If the propagation source is a queue (point-to-point), then the Messaging Gateway agent moves all messages in the queue to the destination. If the propagation source is a topic (publish/subscribe), then the Messaging Gateway agent creates a subscription on the propagation source topic. The agent moves all messages that are published to the topic after the subscription is created.

A propagation job is processed when it is enabled. Disabling a propagation job stops propagation processing but does not stop message subscription.

When the Messaging Gateway agent processes a propagation job, it dequeues messages from the source queue and enqueues the messages to the destination queue. As each message is propagated, it is converted from its native format in the source messaging system to its native format in the destination messaging system. Messaging Gateway provides automatic message conversions between simple and commonly used message formats. You can customize message conversions by providing your own message transformation functions.

When the Messaging Gateway agent fails to convert a message from the source format to the destination format, the agent moves the message from the source queue to an exception queue, if the exception queue exists, and continues to process the propagation job.

If the Messaging Gateway agent runs into failures when processing a propagation job, it retries up to sixteen times in an exponential backoff scheme (from two seconds up to thirty minutes) before it stops retrying.

To guarantee reliable message delivery, Messaging Gateway requires logging queues in messaging systems that support transactions and persistent messages. The Messaging Gateway agent uses the logging queues to store the processing states of propagation jobs so that it can restore propagation processing from failures.

Oracle Streams AQ Buffered Messages and Messaging Gateway

Messaging Gateway does not support propagation of buffered messages. In outbound propagation, the Messaging Gateway agent dequeues only persistent messages from AQ queues. In inbound propagation, the Messaging Gateway agent always enqueues persistent messages into AQ queues.

PKĀCF>FPK-AOEBPS/aq_trbl.html% Troubleshooting Oracle Streams Advanced Queuing

7 Troubleshooting Oracle Streams Advanced Queuing

This chapter describes how to troubleshoot Oracle Streams Advanced Queuing (AQ).

The chapter contains these topics:

Debugging Oracle Streams Advanced Queuing Propagation Problems

The following tips should help with debugging propagation problems. This discussion assumes that you have created queue tables and queues in source and target databases and defined a database link for the destination database. The notation assumes that you supply the actual name of the entity (without the brackets).

To begin debugging, do the following:

  1. Check that the propagation schedule has been created and that a job queue process has been assigned.

    Look for the entry in the DBA_QUEUE_SCHEDULES view and make sure that the status of the schedule is enabled. SCHEDULE_DISABLED must be set to 'N'. Check that it has a nonzero entry for JOBNO in table AQ$_SCHEDULES, and that there is an entry in table JOB$ with that JOBNO.

    To check if propagation is occurring, monitor the DBA_QUEUE_SCHEDULES view for the number of messages propagated (TOTAL_NUMBER).

    If propagation is not occurring, check the view for any errors. Also check the NEXT_RUN_DATE and NEXT_RUN_TIME in DBA_QUEUE_SCHEDULES to see if propagation is scheduled for a later time, perhaps due to errors or the way it is set up.

  2. Check if the database link to the destination database has been set up properly. Make sure that the queue owner can use the database link. You can do this with:

    select count(*) from table_name@dblink_name;
    
  3. Make sure that at least two job queue processes are running.

  4. Check for messages in the source queue with:

    select count (*) from AQ$<source_queue_table> 
      where q_name = 'source_queue_name';
    
  5. Check for messages in the destination queue with:

    select count (*) from AQ$<destination_queue_table> 
      where q_name = 'destination_queue_name';
    
  6. Check to see who is using job queue processes.

    Check which jobs are being run by querying dba_jobs_running. It is possible that other jobs are starving the propagation jobs.

  7. Check to see that the queue table sys.aq$_prop_table_instno exists in DBA_QUEUE_TABLES. The queue sys.aq$_prop_notify_queue_instno must also exist in DBA_QUEUES and must be enabled for enqueue and dequeue.

    In case of Oracle Real Application Clusters (Oracle RAC), this queue table and queue pair must exist for each Oracle RAC node in the system. They are used for communication between job queue processes and are automatically created.

  8. Check that the consumer attempting to dequeue a message from the destination queue is a recipient of the propagated messages.

    For 8.1-style queues, you can do the following:

    select consumer_name, deq_txn_id, deq_time, deq_user_id, 
      propagated_msgid from aq$<destination_queue_table> 
      where queue = 'queue_name';
    

    For 8.0-style queues, you can obtain the same information from the history column of the queue table:

    select h.consumer, h.transaction_id, h.deq_time, h.deq_user,
      h.propagated_msgid from aq$<destination_queue_table> t, table(t.history) h 
      where t.q_name = 'queue_name'; 
    

    Note:

    Queues created in a queue table with compatible set to 8.0 (referrred to in this guide as 8.0-style queues) are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2). Oracle recommends that any new queues you create be 8.1-style or newer and that you migrate existing 8.0-style queues at your earliest convenience.

  9. Turn on propagation tracing at the highest level using event 24040, level 10.

    Debugging information is logged to job queue trace files as propagation takes place. You can check the trace file for errors and for statements indicating that messages have been sent.

Oracle Streams Advanced Queuing Error Messages

ORA-1555

You might get this error when using the NEXT_MESSAGE navigation option for dequeue. NEXT_MESSAGE uses the snapshot created during the first dequeue call. After that, undo information may not be retained.

The workaround is to use the FIRST_MESSAGE option to dequeue the message. This reexecutes the cursor and gets a new snapshot. FIRST_MESSAGE does not perform as well as NEXT_MESSAGE, so Oracle recommends that you dequeue messages in batches: FIRST_MESSAGE for one, NEXT_MESSAGE for the next 1000 messages, then FIRST_MESSAGE again, and so on.

ORA-24033

This error is raised if a message is enqueued to a multiconsumer queue with no recipient and the queue has no subscribers (or rule-based subscribers that match this message). This is a warning that the message will be discarded because there are no recipients or subscribers to whom it can be delivered.

ORA-25237

When using the Oracle Streams Advanced Queuing navigation option, you must reset the dequeue position by using the FIRST_MESSAGE option if you want to continue dequeuing between services (such as xa_start and xa_end boundaries). This is because XA cancels the cursor fetch state after an xa_end. If you do not reset, then you get an error message stating that the navigation is used out of sequence.

ORA-25307

Flow control has been enabled for the message sender. This means that the fastest subscriber of the sender's message is not able to keep pace with the rate at which messages are enqueued. The buffered messaging application must handle this error and attempt again to enqueue messages after waiting for some time.

PKIQq%l%PK-AOEBPS/jm_point.htm Oracle JMS Point-to-Point

13 Oracle JMS Point-to-Point

This chapter describes the components of the Oracle Streams Advanced Queuing (AQ) Java Message Service (JMS) operational interface that are specific to point-to-point operations. Components that are shared by point-to-point and publish/subscribe are described in Chapter 15, "Oracle JMS Shared Interfaces".

This chapter contains these topics:

Creating a Connection with Username/Password

public javax.jms.Connection createConnection(
             java.lang.String username,
             java.lang.String password)
      throws JMSException

This method creates a connection supporting both point-to-point and publish/subscribe operations with the specified username and password. This method is new and supports JMS version 1.1 specifications. It has the following parameters:

ParameterDescription
usernameName of the user connecting to the database for queuing
passwordPassword for creating the connection to the server

Creating a Connection with Default ConnectionFactory Parameters

public javax.jms.Connection createConnection()
      throws JMSException

This method creates a connection supporting both point-to-point and publish/subscribe operations with default ConnectionFactory parameters. This method is new and supports JMS version 1.1 specifications. If the ConnectionFactory properties do not contain a default username and password, then it throws a JMSException.

Creating a QueueConnection with Username/Password

public javax.jms.QueueConnection createQueueConnection(
             java.lang.String username,
             java.lang.String password)
      throws JMSException

This method creates a queue connection with the specified username and password. It has the following parameters:

ParameterDescription
usernameName of the user connecting to the database for queuing
passwordPassword for creating the connection to the server

Example 13-1 Creating a QueueConnection with Username/Password

QueueConnectionFactory qc_fact = AQjmsFactory.getQueueConnectionFactory(
   "sun123", "oratest", 5521, "thin");
QueueConnection qc_conn = qc_fact.createQueueConnection("jmsuser", "jmsuser");

Creating a QueueConnection with an Open JDBC Connection

public static javax.jms.QueueConnection createQueueConnection(
   java.sql.Connection jdbc_connection)
   throws JMSException

This method creates a queue connection with an open JDBC connection. It is static and has the following parameter:

ParameterDescription
jdbc_connectionValid open connection to the database

The method in Example 13-2 can be used if the user wants to use an existing JDBC connection (say from a connection pool) for JMS operations. In this case JMS does not open a new connection, but instead uses the supplied JDBC connection to create the JMS QueueConnection object.

Example 13-2 Creating a QueueConnection with an Open JDBC Connection

Connection db_conn;     /* previously opened JDBC connection */
QueueConnection qc_conn = AQjmsQueueConnectionFactory.createQueueConnection(
           db_conn);

The method in Example 13-3 is the only way to create a JMS QueueConnection when using JMS from a Java stored procedures inside the database (JDBC Server driver)

Example 13-3 Creating a QueueConnection from a Java Procedure Inside Database

OracleDriver ora = new OracleDriver();
QueueConnection qc_conn = AQjmsQueueConnectionFactory.createQueueConnection(ora.defaultConnection());

Creating a QueueConnection with Default ConnectionFactory Parameters

public javax.jms.QueueConnection createQueueConnection()
      throws JMSException

This method creates a queue connection with default ConnectionFactory parameters. If the queue connection factory properties do not contain a default username and password, then it throws a JMSException.

Creating a QueueConnection with an Open OracleOCIConnectionPool

public static javax.jms.QueueConnection createQueueConnection(
          oracle.jdbc.pool.OracleOCIConnectionPool cpool)
   throws JMSException

This method creates a queue connection with an open OracleOCIConnectionPool. It is static and has the following parameter:

ParameterDescription
cpoolValid open OCI connection pool to the database

The method in Example 13-4 can be used if the user wants to use an existing OracleOCIConnectionPool instance for JMS operations. In this case JMS does not open an new OracleOCIConnectionPool instance, but instead uses the supplied OracleOCIConnectionPool instance to create the JMS QueueConnection object.

Example 13-4 Creating a QueueConnection with an Open OracleOCIConnectionPool

OracleOCIConnectionPool cpool; /* previously created OracleOCIConnectionPool */
QueueConnection qc_conn = AQjmsQueueConnectionFactory.createQueueConnection(cpool);

Creating a Session

public javax.jms.Session createSession(boolean transacted,
                                                 int ack_mode)
                                          throws JMSException

This method creates a Session, which supports both point-to-point and publish/subscribe operations. This method is new and supports JMS version 1.1 specifications. Transactional and nontransactional sessions are supported. It has the following parameters:

ParameterDescription
transactedIf set to true, then the session is transactional
ack_modeIndicates whether the consumer or the client will acknowledge any messages it receives. It is ignored if the session is transactional. Legal values are Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, and Session.DUPS_OK_ACKNOWLEDGE.

Creating a QueueSession

public javax.jms.QueueSession createQueueSession(
   boolean transacted, int ack_mode)
        throws JMSException

This method creates a QueueSession. Transactional and nontransactional sessions are supported. It has the following parameters:

ParameterDescription
transactedIf set to true, then the session is transactional
ack_modeIndicates whether the consumer or the client will acknowledge any messages it receives. It is ignored if the session is transactional. Legal values are Session.AUTO_ACKNOWLEDGE, Session.CLIENT_ACKNOWLEDGE, and Session.DUPS_OK_ACKNOWLEDGE.

Example 13-5 Creating a Transactional QueueSession

QueueConnection qc_conn;
QueueSession  q_sess = qc_conn.createQueueSession(true, 0);

Creating a QueueSender

public javax.jms.QueueSender createSender(javax.jms.Queue queue)
                                   throws JMSException

This method creates a QueueSender. If a sender is created without a default queue, then the destination queue must be specified on every send operation. It has the following parameter:

ParameterDescription
queueName of destination queue

Sending Messages Using a QueueSender with Default Send Options

public void send(javax.jms.Queue queue,
                 javax.jms.Message message)
          throws JMSException

This method sends a message using a QueueSender with default send options. This operation uses default values for message priority (1) and timeToLive (infinite). It has the following parameters:

ParameterDescription
queueQueue to send this message to
messageMessage to send

If the QueueSender has been created with a default queue, then the queue parameter may not necessarily be supplied in the send() call. If a queue is specified in the send() operation, then this value overrides the default queue of the QueueSender.

If the QueueSender has been created without a default queue, then the queue parameter must be specified in every send() call.

Example 13-6 Creating a Sender to Send Messages to Any Queue

/* Create a sender to send messages to any queue */
QueueSession  jms_sess;
QueueSender  sender1;
TextMessage  message;
sender1 = jms_sess.createSender(null); 
sender1.send(queue, message);

Example 13-7 Creating a Sender to Send Messages to a Specific Queue

/* Create a sender to send messages to a specific queue */
QueueSession jms_sess;
QueueSender sender2;
Queue   billed_orders_que;
TextMessage  message;
sender2 = jms_sess.createSender(billed_orders_que);
sender2.send(queue, message);

Sending Messages Using a QueueSender by Specifying Send Options

public void send(javax.jms.Queue queue,
                 javax.jms.Message message,
                 int deliveryMode,
                 int priority,
                 long timeToLive)
          throws JMSException

This method sends messages using a QueueSender by specifying send options. It has the following parameters:

ParameterDescription
queueQueue to send this message to
messageMessage to send
deliveryModeDelivery mode to use
priorityPriority for this message
timeToLiveMessage lifetime in milliseconds (zero is unlimited)

If the QueueSender has been created with a default queue, then the queue parameter may not necessarily be supplied in the send() call. If a queue is specified in the send() operation, then this value overrides the default queue of the QueueSender.

If the QueueSender has been created without a default queue, then the queue parameter must be specified in every send() call.

Example 13-8 Sending Messages Using a QueueSender by Specifying Send Options 1

/* Create a sender to send messages to any queue */ 
/* Send a message to new_orders_que with priority 2 and timetoLive 100000 
   milliseconds */
QueueSession  jms_sess;
QueueSender  sender1;
TextMessage mesg;
Queue   new_orders_que
sender1 = jms_sess.createSender(null); 
sender1.send(new_orders_que, mesg, DeliveryMode.PERSISTENT, 2, 100000);

Example 13-9 Sending Messages Using a QueueSender by Specifying Send Options 2

/* Create a sender to send messages to a specific queue */ 
/* Send a message with priority 1 and timetoLive 400000 milliseconds */
QueueSession jms_sess;
QueueSender sender2;
Queue   billed_orders_que;
TextMessage mesg;
sender2 = jms_sess.createSender(billed_orders_que);
sender2.send(mesg, DeliveryMode.PERSISTENT, 1, 400000);

Creating a QueueBrowser for Standard JMS Type Messages

public javax.jms.QueueBrowser createBrowser(javax.jms.Queue queue,
                                            java.lang.String messageSelector)
                                     throws JMSException

This method creates a QueueBrowser for queues with text, stream, objects, bytes or MapMessage message bodies. It has the following parameters:

ParameterDescription
queueQueue to access
messageSelectorOnly messages with properties matching the messageSelector expression are delivered


See Also:

"MessageSelector"

Use methods in java.util.Enumeration to go through list of messages.

Example 13-10 Creating a QueueBrowser Without a Selector

/* Create a browser without a selector */
QueueSession    jms_session;
QueueBrowser    browser;
Queue           queue;
browser = jms_session.createBrowser(queue);

Example 13-11 Creating a QueueBrowser With a Specified Selector

/* Create a browser for queues with a specified selector */
QueueSession    jms_session;
QueueBrowser    browser;
Queue           queue;
/* create a Browser to look at messages with correlationID = RUSH  */
browser = jms_session.createBrowser(queue, "JMSCorrelationID = 'RUSH'");

Creating a QueueBrowser for Standard JMS Type Messages, Locking Messages

public javax.jms.QueueBrowser createBrowser(javax.jms.Queue queue,
                                            java.lang.String messageSelector,
                                            boolean locked)
                                     throws JMSException

This method creates a QueueBrowser for queues with TextMessage, StreamMessage, ObjectMessage, BytesMessage, or MapMessage message bodies, locking messages while browsing. Locked messages cannot be removed by other consumers until the browsing session ends the transaction. It has the following parameters:

ParameterDescription
queueQueue to access
messageSelectorOnly messages with properties matching the messageSelector expression are delivered
lockedIf set to true, then messages are locked as they are browsed (similar to a SELECT for UPDATE)

Example 13-12 Creating a QueueBrowser Without a Selector, Locking Messages

<>lpre class="oac_no_warn"> /* Create a browser without a selector */ QueueSession jms_session; QueueBrowser browser; Queue queue; browser = jms_session.createBrowser(queue, null, true);

Example 13-13 Creating a QueueBrowser With a Specified Selector, Locking Messages

/* Create a browser for queues with a specified selector */
QueueSession    jms_session;
QueueBrowser    browser;
Queue           queue;
/* create a Browser to look at messages with 
correlationID = RUSH in lock mode */
browser = jms_session.createBrowser(queue, "JMSCorrelationID = 'RUSH'", true);

Creating a QueueBrowser for Oracle Object Type Messages

public javax.jms.QueueBrowser createBrowser(javax.jms.Queue queue, 
                                            java.lang.String messageSelector,
                                            java.lang.Object payload_factory)
                                     throws JMSException

This method creates a QueueBrowser for queues of Oracle object type messages. It has the following parameters:

ParameterDescription
queueQueue to access
messageSelectorOnly messages with properties matching the messageSelector expression are delivered
payload_factoryCustomDatumFactory or ORADataFactory for the java class that maps to the Oracle ADT


See Also:

"MessageSelector"

The CustomDatumFactory for a particular java class that maps to the SQL object payload can be obtained using the getFactory static method.


Note:

CustomDatum support will be deprecated in a future release. Use ORADataFactory payload factories instead.

Assume the queue test_queue has payload of type SCOTT.EMPLOYEE and the java class that is generated by Jpublisher for this Oracle object type is called Employee. The Employee class implements the CustomDatum interface. The CustomDatumFactory for this class can be obtained by using the Employee.getFactory() method.

Example 13-14 Creating a QueueBrowser for ADTMessages

/* Create a browser for a Queue with AdtMessage messages of type EMPLOYEE*/
QueueSession jms_session
QueueBrowser browser;
Queue        test_queue;
browser = ((AQjmsSession)jms_session).createBrowser(test_queue,
                                                   "corrid='EXPRESS'",
                                                    Employee.getFactory());

Creating a QueueBrowser for Oracle Object Type Messages, Locking Messages

public javax.jms.QueueBrowser createBrowser(javax.jms.Queue queue,
                                            java.lang.String messageSelector,
                                            java.lang.Object payload_factory,
                                            boolean locked)
                                     throws JMSException

This method creates a QueueBrowser for queues of Oracle object type messages, locking messages while browsing. It has the following parameters:

ParameterDescription
queueQueue to access
messageSelectorOnly messages with properties matching the messageSelector expression are delivered
payload_factoryCustomDatumFactory or ORADataFactory for the java class that maps to the Oracle ADT
lockedIf set to true, then messages are locked as they are browsed (similar to a SELECT for UPDATE)


Note:

CustomDatum support will be deprecated in a future release. Use ORADataFactory payload factories instead.

Example 13-15 Creating a QueueBrowser for AdtMessages, Locking Messages

/* Create a browser for a Queue with AdtMessage messagess of type EMPLOYEE* in lock mode/
QueueSession jms_session
QueueBrowser browser;
Queue        test_queue;
browser = ((AQjmsSession)jms_session).createBrowser(test_queue, 
                                                    null, 
                                                    Employee.getFactory(),
                                                    true);

Creating a QueueReceiver for Standard JMS Type Messages

public javax.jms.QueueReceiver createReceiver(javax.jms.Queue queue,
                                              java.lang.String messageSelector)
                                       throws JMSException

This method creates a QueueReceiver for queues of standard JMS type messages. It has the following parameters:

ParameterDescription
queueQueue to access
messageSelectorOnly messages with properties matching the messageSelector expression are delivered


See Also:

"MessageSelector"

Example 13-16 Creating a QueueReceiver Without a Selector

/* Create a receiver without a selector */
QueueSession    jms_session
QueueReceiver   receiver;
Queue           queue;
receiver = jms_session.createReceiver(queue);

Example 13-17 Creating a QueueReceiver With a Specified Selector

/* Create a receiver for queues with a specified selector */
QueueSession    jms_session;
QueueReceiver   receiver;
Queue           queue;
/* create Receiver to receive messages with correlationID starting with EXP  */
browser = jms_session.createReceiver(queue, "JMSCorrelationID LIKE 'EXP%'");

Creating a QueueReceiver for Oracle Object Type Messages

public javax.jms.QueueReceiver createReceiver(javax.jms.Queue queue,
                                              java.lang.String messageSelector,
                                              java.lang.Object payload_factory)
                                       throws JMSException

This method creates a QueueReceiver for queues of Oracle object type messages. It has the following parameters:

ParameterDescription
queueQueue to access
messageSelectorOnly messages with properties matching the messageSelector expression are delivered
payload_factoryCustomDatumFactory or ORADataFactory for the java class that maps to the Oracle ADT


See Also:

"MessageSelector"

The CustomDatumFactory for a particular java class that maps to the SQL object type payload can be obtained using the getFactory static method.


Note:

CustomDatum support will be deprecated in a future release. Use ORADataFactory payload factories instead.

Assume the queue test_queue has payload of type SCOTT.EMPLOYEE and the java class that is generated by Jpublisher for this Oracle object type is called Employee. The Employee class implements the CustomDatum interface. The ORADataFactory for this class can be obtained by using the Employee.getFactory() method.

Example 13-18 Creating a QueueReceiver for AdtMessage Messages

/* Create a receiver for a Queue with AdtMessage messages of type EMPLOYEE*/
QueueSession jms_session
QueueReceiver receiver;
Queue        test_queue;
browser = ((AQjmsSession)jms_session).createReceiver(
                 test_queue,
                "JMSCorrelationID = 'MANAGER', 
                 Employee.getFactory());
PKwzPK-AOEBPS/aq_views.htm Oracle Streams Advanced Queuing & Messaging Gateway Views

9 Oracle Streams Advanced Queuing & Messaging Gateway Views

This chapter describes the Oracle Streams Advanced Queuing (AQ) administrative interface views and Oracle Messaging Gateway (MGW) views.


Note:

All views not detailed in this chapter are described in the Oracle Database Reference.

This chapter contains these topics:

Oracle AQ Views

Oracle Messaging Gateway Views

DBA_QUEUE_TABLES: All Queue Tables in Database

The DBA_QUEUE_TABLES view contains information about the owner instance for a queue table. A queue table can contain multiple queues. In this case, each queue in a queue table has the same owner instance as the queue table. Its columns are the same as those in ALL_QUEUE_TABLES.

USER_QUEUE_TABLES: Queue Tables in User Schema

The USER_QUEUE_TABLES view is the same as DBA_QUEUE_TABLES with the exception that it only shows queue tables in the user's schema. It does not contain a column for OWNER.

ALL_QUEUE_TABLES: Queue Tables Queue Accessible to the Current User

The ALL_QUEUE_TABLES view describes queue tables accessible to the current user.

DBA_QUEUES: All Queues in Database

The DBA_QUEUES view specifies operational characteristics for every queue in a database. Its columns are the same as those ALL_QUEUES.

USER_QUEUES: Queues In User Schema

The USER_QUEUES view is the same as DBA_QUEUES with the exception that it only shows queues in the user's schema.

ALL_QUEUES: Queues for Which User Has Any Privilege

The ALL_QUEUES view describes all queues on which the current user has enqueue or dequeue privileges. If the user has any Advanced Queuing system privileges, like MANAGE ANY QUEUE, ENQUEUE ANY QUEUE or DEQUEUE ANY QUEUE, this view describes all queues in the database.

DBA_QUEUE_SCHEDULES: All Propagation Schedules

The DBA_QUEUE_SCHEDULES view describes all the current schedules in the database for propagating messages.

USER_QUEUE_SCHEDULES: Propagation Schedules in User Schema

The USER_QUEUE_SCHEDULES view is the same as DBA_QUEUE_SCHEDULES with the exception that it only shows queue schedules in the user's schema.

QUEUE_PRIVILEGES: Queues for Which User Has Queue Privilege

The QUEUE_PRIVILEGES view describes queues for which the user is the grantor, grantee, or owner. It also shows queues for which an enabled role on the queue is granted to PUBLIC.

AQ$Queue_Table_Name: Messages in Queue Table

The AQ$Queue_Table_Name view describes the queue table in which message data is stored. This view is automatically created with each queue table and should be used for querying the queue data. The dequeue history data (time, user identification and transaction identification) is only valid for single-consumer queues.

In a queue table that is created with the compatible parameter set to '8.1' or higher, messages that were not dequeued by the consumer are shown as "UNDELIVERABLE". You can dequeue these messages by msgid. If the Oracle Streams Advanced Queuing queue process monitor is running, then the messages are eventually moved to an exception queue. You can dequeue these messages from the exception queue with an ordinary dequeue.

A multiconsumer queue table created without the compatible parameter, or with the compatible parameter set to '8.0', does not display the state of a message on a consumer basis, but only displays the global state of the message.


Note:

Queues created in a queue table with compatible set to 8.0 (referred to in this guide as 8.0-style queues) are deprecated in Oracle Streams Advanced Queuing 10g Release 2 (10.2). Oracle recommends that any new queues you create be 8.1-style or newer and that you migrate existing 8.0-style queues at your earliest convenience.

When a message is dequeued using the REMOVE mode, DEQ_TIME, DEQ_USER_ID, and DEQ_TXN_ID are updated for the consumer that dequeued the message.

You can use MSGID and ORIGINAL_MSGID to chain propagated messages. When a message with message identifier m1 is propagated to a remote queue, m1 is stored in the ORIGINAL_MSGID column of the remote queue.

Beginning with Oracle Database 10g, AQ$Queue_Table_Name includes buffered messages. For buffered messages, the value of MSG_STATE is one of the following:

  • IN MEMORY

    Buffered messages enqueued by a user

  • DEFERRED

    Buffered messages enqueued by a capture process

  • SPILLED

    User-enqueued buffered messages that have been spilled to disk

  • DEFERRED SPILLED

    Capture-enqueued buffered messages that have been spilled to disk

  • BUFFERED EXPIRED

    Expired buffered messages

Table 9-1 AQ$Queue_Table_Name View

ColumnDatatypeNULLDescription

QUEUE

VARCHAR2(30)

-

Queue name

MSG_ID

RAW(16)

NOT NULL

Unique identifier of the message

CORR_ID

VARCHAR2(128)

-

User-provided correlation identifier

MSG_PRIORITY

NUMBER

-

Message priority

MSG_STATE

VARCHAR2(16)

-

Message state

DELAY

DATE

-

Time in date format at which the message in waiting state would become ready. Equals ENQUEUE_TIME + user specified DELAY

DELAY_TIMESTAMP

TIMESTAMP

-

Time as a timestamp format at which the message in waiting state would become ready. Equals ENQUEUE_TIMESTAMP + user specified DELAY

EXPIRATION

NUMBER

-

Number of seconds in which the message expires after being READY

ENQ_TIME

DATE

-

Enqueue time

ENQ_TIMESTAMP

TIMESTAMP

-

Enqueue time

ENQ_USER_ID

NUMBER

-

Enqueue user ID

ENQ_USER_ID (10.1 queue tables)

VARCHAR2(30)

-

Enqueue user name

ENQ_TXN_ID

VARCHAR2(30)

-

Enqueue transaction ID

DEQ_TIME

DATE

-

Dequeue time

DEQ_TIMESTAMP

TIMESTAMP

-

Dequeue time

DEQ_USER_ID

NUMBER

-

Dequeue user ID

DEQ_USER_ID (10.1 queue tables)

VARCHAR2(30)

-

Dequeue user name

DEQ_TXN_ID

VARCHAR2(30)

-

Dequeue transaction ID

RETRY_COUNT

NUMBER

-

Number of retries

EXCEPTION_QUEUE_OWNER

VARCHAR2(30)

-

Exception queue schema

EXCEPTION_QUEUE

VARCHAR2(30)

-

Exception queue name

USER_DATA

-

-

User data

SENDER_NAME

VARCHAR2(30)

-

Name of the agent enqueuing the message (valid only for 8.1-compatible queue tables)

SENDER_ADDRESS

VARCHAR2(1024)

-

Queue name and database name of the source (last propagating) queue (valid only for 8.1-compatible queue tables). The database name is not specified if the source queue is in the local database.

SENDER_PROTOCOL

NUMBER

-

Protocol for sender address (reserved for future use and valid only for 8.1-compatible queue tables)

ORIGINAL_MSGID

RAW(16)

-

Message ID of the message in the source queue (valid only for 8.1-compatible queue tables)

CONSUMER_NAME

VARCHAR2(30)

-

Name of the agent receiving the message (valid only for 8.1-compatible multiconsumer queue tables)

ADDRESS

VARCHAR2(1024)

-

Queue name and database link name of the agent receiving the message.The database link name is not specified if the address is in the local database. The address is NULL if the receiving agent is local to the queue (valid only for 8.1-compatible multiconsumer queue tables)

PROTOCOL

NUMBER

-

Protocol for address of receiving agent (valid only for 8.1-compatible queue tables)

PROPAGATED_MSGID

RAW(16)

-

Message ID of the message in the queue of the receiving agent (valid only for 8.1-compatible queue tables)

ORIGINAL_QUEUE_NAME

VARCHAR2(30)

-

Name of the queue the message came from

ORIGINAL_QUEUE_OWNER

VARCHAR2(30)

-

Owner of the queue the message came from

EXPIRATION_REASON

VARCHAR2(19)

-

Reason the message came into exception queue. Possible values are TIME_EXPIRATION (message expired after the specified expired time), MAX_RETRY_EXCEEDED (maximum retry count exceeded), and PROPAGATION_FAILURE (message became undeliverable during propagation).



Note:

A message is moved to an exception queue if RETRY_COUNT is greater than MAX_RETRIES. If a dequeue transaction fails because the server process dies (including ALTER SYSTEM KILL SESSION) or SHUTDOWN ABORT on the instance, then RETRY_COUNT is not incremented.

AQ$Queue_Table_Name_S: Queue Subscribers

The AQ$Queue_Table_Name_S view provides information about subscribers for all the queues in any given queue table. It shows subscribers created by users with DBMS_AQADM.ADD_SUBSCRIBER and subscribers created for the apply process to apply user-created events. It also displays the transformation for the subscriber, if it was created with one. It is generated when the queue table is created.

This view provides functionality that is equivalent to the DBMS_AQADM.QUEUE_SUBSCRIBERS() procedure. For these queues, Oracle recommends that the view be used instead of this procedure to view queue subscribers. This view is created only for 8.1-compatible queue tables.

Table 9-2 AQ$Queue_Table_Name_S View

ColumnDatatypeNULLDescription

QUEUE

VARCHAR2(30)

NOT NULL

Name of queue for which subscriber is defined

NAME

VARCHAR2(30)

-

Name of agent

ADDRESS

VARCHAR2(1024)

-

Address of agent

PROTOCOL

NUMBER

-

Protocol of agent

TRANSFORMATION

VARCHAR2(61)

-

Name of the transformation (can be null)


AQ$Queue_Table_Name_R: Queue Subscribers and Their Rules

The AQ$Queue_Table_Name_R view displays only the subscribers based on rules for all queues in a given queue table, including the text of the rule defined by each subscriber. It also displays the transformation for the subscriber, if one was specified. It is generated when the queue table is created.

This view is created only for 8.1-compatible queue tables.

Table 9-3 AQ$Queue_Table_Name_R View

ColumnDatatypeNULLDescription

QUEUE

VARCHAR2(30)

NOT NULL

Name of queue for which subscriber is defined

NAME

VARCHAR2(30)

-

Name of agent

ADDRESS

VARCHAR2(1024)

-

Address of agent

PROTOCOL

NUMBER

-

Protocol of agent

RULE

CLOB

-

Text of defined rule

RULE_SET

VARCHAR2(65)

-

Set of rules

TRANSFORMATION

VARCHAR2(61)

-

Name of the transformation (can be null)


DBA_QUEUE_SUBSCRIBERS: All Queue Subscribers in Database

The DBA_QUEUE_SUBSCRIBERS view returns a list of all subscribers on all queues in the database. Its columns are the same as those in ALL_QUEUE_SUBSCRIBERS.

USER_QUEUE_SUBSCRIBERS: Queue Subscribers in User Schema

The USER_QUEUE_SUBSCRIBERS view returns a list of subscribers on queues in the schema of the current user. Its columns are the same as those in ALL_QUEUE_SUBSCRIBERS except that it does not contain the OWNER column.

ALL_QUEUE_SUBSCRIBERS: Subscribers for Queues Where User Has Queue Privileges

The ALL_QUEUE_SUBSCRIBERS view returns a list of subscribers to queues that the current user has privileges to dequeue from.

DBA_TRANSFORMATIONS: All Transformations

The DBA_TRANSFORMATIONS view displays all the transformations in the database. These transformations can be specified with Advanced Queue operations like enqueue, dequeue and subscribe to automatically integrate transformations in messaging. This view is accessible only to users having DBA privileges.

DBA_ATTRIBUTE_TRANSFORMATIONS: All Transformation Functions

The DBA_ATTRIBUTE_TRANSFORMATIONS view displays the transformation functions for all the transformations in the database.

USER_TRANSFORMATIONS: User Transformations

The USER_TRANSFORMATIONS view displays all the transformations owned by the user. To view the transformation definition, query USER_ATTRIBUTE_TRANSFORMATIONS.

USER_ATTRIBUTE_TRANSFORMATIONS: User Transformation Functions

The USER_ATTRIBUTE_TRANSFORMATIONS view displays the transformation functions for all the transformations of the user.

DBA_SUBSCR_REGISTRATIONS: All Subscription Registrations

The DBA_SUBSCR_REGISTRATIONS view lists all the subscription registrations in the database.

USER_SUBSCR_REGISTRATIONS: User Subscription Registrations

The USER_SUBSCR_REGISTRATIONS view lists the subscription registrations in the database for the current user. Its columns are the same as those in DBA_SUBSCR_REGISTRATIONS.

AQ$INTERNET_USERS: Oracle Streams Advanced Queuing Agents Registered for Internet Access

The AQ$INTERNET_USERS view provides information about the agents registered for Internet access to Oracle Streams Advanced Queuing. It also provides the list of database users that each Internet agent maps to.

Table 9-4 AQ$INTERNET_USERS View

ColumnDatatypeNULLDescription

AGENT_NAME

VARCHAR2(30)

-

Name of the Oracle Streams Advanced Queuing Internet agent

DB_USERNAME

VARCHAR2(30)

-

Name of database user that this Internet agent maps to

HTTP_ENABLED

VARCHAR2(4)

-

Indicates whether this agent is allowed to access Oracle Streams Advanced Queuing through HTTP (YES or NO)

FTP_ENABLED

VARCHAR2(4)

-

Indicates whether this agent is allowed to access Oracle Streams Advanced Queuing through FTP (always NO in current release)


(G)V$AQ: Number of Messages in Different States in Database

The (G)V$AQ view provides information about the number of messages in different states for the whole database.

In a Oracle Real Application Clusters environment, each instance keeps its own Oracle Streams Advanced Queuing statistics information in its own System Global Area (SGA), and does not have knowledge of the statistics gathered by other instances. When a GV$AQ view is queried by an instance, all other instances funnel their Oracle Streams Advanced Queuing statistics information to the instance issuing the query.

(G)V$BUFFERED_QUEUES: All Buffered Queues in the Instance.

The V$BUFFERED_QUEUES view displays information about all buffered queues in the instance. There is one row per queue.

(G)V$BUFFERED_SUBSCRIBERS: Subscribers for All Buffered Queues in the Instance

The V$BUFFERED_SUBSCRIBERS view displays information about the subscribers for all buffered queues in the instance. There is one row per subscriber per queue.

(G)V$BUFFERED_PUBLISHERS: All Buffered Publishers in the Instance

The V$BUFFERED_PUBLISHERS view displays information about all buffered publishers in the instance. There is one row per queue per sender. The values are reset to zero when the database (or instance in an Oracle RAC environment) restarts.

(G)V$PERSISTENT_QUEUES: All Active Persistent Queues in the Instance

The V$PERSISTENT_QUEUES view displays information about all active persistent queues in the database since the queues' first activity time. There is one row per queue. The rows are deleted when the database (or instance in an Oracle RAC environment) restarts.

(G)V$PERSISTENT_QMN_CACHE: Performance Statistics on Background Tasks for Persistent Queues

The V$PERSISTENT_QMN_CACHE view displays detailed statistics about all background activities relating to all queue tables in the database. There is one row per queue table. The values are reset when the database (or instance in an Oracle RAC environment) restarts.

(G)V$PERSISTENT_SUBSCRIBERS: All Active Subscribers of the Persistent Queues in the Instance

The V$PERSISTENT_SUBSCRIBERS view displays information about all active subscribers of the persistent queues in the database. There is one row per instance per queue per subscriber. The rows are deleted when the database (or instance in an Oracle RAC environment) restarts.

(G)V$PERSISTENT_PUBLISHERS: All Active Publishers of the Persistent Queues in the Instance

The V$PERSISTENT_PUBLISHERS view displays information about all active publishers of the persistent queues in the database. There is one row per instance per queue per publisher. The rows are deleted when the database (or instance in an Oracle RAC environment) restarts.

(G)V$PROPAGATION_SENDER: Buffer Queue Propagation Schedules on the Sending (Source) Side

The V$PROPAGATION_SENDER view displays information about buffer queue propagation schedules on the sending (source) side. The values are reset to zero when the database (or instance in a Oracle Real Application Clusters (Oracle RAC) environment) restarts, when propagation migrates to another instance, or when an unscheduled propagation is attempted.

(G)V$PROPAGATION_RECEIVER: Buffer Queue Propagation Schedules on the Receiving (Destination) Side

The V$PROPAGATION_RECEIVER view displays information about buffer queue propagation schedules on the receiving (destination) side. The values are reset to zero when the database (or instance in a Oracle Real Application Clusters (Oracle RAC) environment) restarts, when propagation migrates to another instance, or when an unscheduled propagation is attempted.

(G)V$SUBSCR_REGISTRATION_STATS: Diagnosability of Notifications

The V$SUBSCR_REGISTRATION_STATS view provides information for diagnosability of notifications.

V$METRICGROUP: Information about the Metric Group

This V$METRICGROUP view displays information about the metric group for each of the four major Streams components: capture, propagation, apply, and queue.

(G)V$STREAMSMETRIC: Streams Metrics for the Most Recent Interval

This view displays the capture, propagation, and apply metrics for the most recent interval.

Table 9-5 GV$STREAMSMETRIC View

ColumnDatatypeDescription

INST_ID

Instance

ID (GV$ only)

BEGIN_TIME

DATE

Begin time of interval

END_TIME

DATE

End time of interval

INTSIZE_CSEC

NUMBER

Interval size (centi-seconds)

COMPONENT_TYPE

VARCHAR2(32)

Type of the component (either 'CAPTURE', 'PROPAGATION', or 'APPLY')

COMPONENT_NAME

VARCHAR2(32)

Name of streams component

COMPONENT_START_TIME

DATE

Time that component started

RATE1_VALUE

NUMBER

Value of rate 1

RATE1_NAME

VARCHAR2(64)

Name of rate1

RATE1_UNIT

VARCHAR2(64)

Unit of measurement of rate1

RATE2_VALUE

NUMBER

Value of rate 2

RATE2_NAME

VARCHAR2(64)

Name of rate2

RATE2_UNIT

VARCHAR2(64)

Unit of measurement of rate2

LATENCY

NUMBER

Latency from time last message processed by component was written to redo to time the message was processed by this component


(G)V$STREAMSMETRIC_HISTORY: Streams Metrics Over Past Hour

This view returns all metric values for streams messages over the past hour. It has the same form as (G)V$STREAMSMETRIC: Streams Metrics for the Most Recent Interval.

DBA_HIST_STREAMSMETRIC: Streams Metric History

This view displays view provides catalog access to streams metric history.

Table 9-6 DBA_HIST_STREAMSMETRIC View

ColumnDatatypeDescription

SNAP_ID

NUMBER

Required by AWR, snapshot ID

DBID

NUMBER

Required by AWR, database ID

INSTANCE_NUMBER

NUMBER

Required by AWR, instance number

BEGIN_TIME

DATE

Begin time of interval

END_TIME

DATE

End time of interval

INTSIZE

NUMBER

Interval size (centi-seconds)

COMPONENT_TYPE

VARCHAR2(32)

Type of the component (either 'CAPTURE', 'PROPAGATION', or 'APPLY')

COMPONENT_NAME

VARCHAR2(32)

Name of streams component

COMPONENT_START_TIME

DATE

Time that component started

RATE1_VALUE

NUMBER

Value of rate 1

RATE2_VALUE

NUMBER

Value of rate 2

LATENCY

NUMBER

Latency from time last message processed by component was written to redo to time the message was processed by this component


DBA_HIST_QUEUEMETRIC: Queue Metric History

This view displays view provides catalog access to queue metric history.

Table 9-7 DBA_ATTRIBUTE_TRANSFORMATIONS View

ColumnDatatypeDescription

SNAP_ID

NUMBER

Required by AWR, snapshot ID

DBID

NUMBER

Required by AWR, database ID

INSTANCE_NUMBER

NUMBER

Required by AWR, instance number

QUEUE_NAME

VARCHAR2(32)

Name of queue process

QUEUE_START_TIME

DATE

Time when queue started

BEGIN_TIME

DATE

Begin time of interval

END_TIME

DATE

End time of interval

INTSIZE

NUMBER

Interval size (centi-seconds)

ENQUEUED_PER_SECOND

NUMBER

Messages enqueue per second

SPILLED_PER_SECOND

NUMBER

Messages spilled per second

NUMMESSAGES

NUMBER

Number of messages in the queue


MGW_GATEWAY: Configuration and Status Information

This view lists configuration and status information for Messaging Gateway.

Table 9-8 MGW_GATEWAY View Properties

NameTypeDescription

AGENT_DATABASE

VARCHAR2

The database connect string used by the Messaging Gateway agent. NULL indicates that a local connection is used.

AGENT_INSTANCE

NUMBER

The database instance on which the Messaging Gateway agent is currently running. This should be NULL if the agent is not running.

AGENT_JOB

NUMBER

[Deprecated] Job number of the queued job used to start the Messaging Gateway agent process. The job number is set when Messaging Gateway is started and cleared when it shuts down.

AGENT_NAME

VARCHAR2

Name of the Messaging Gateway agent

AGENT_PING

VARCHAR2

Gateway agent ping status. Values:

  • NULL means no ping attempt was made.

  • REACHABLE means ping attempt was successful.

  • UNREACHABLE means ping attempt failed.

AGENT_PING attempts to contact the Messaging Gateway agent. There is a short delay (up to 5 seconds) if the ping attempt fails. No ping is attempted if the AGENT_STATUS is NOT_STARTED or START_SCHEDULED.

AGENT_START_TIME

TIMESTAMP

The time when the Messaging Gateway agent job currently running was started. This should be NULL if the agent is not running.

AGENT_STATUS

VARCHAR2

Status of the Messaging Gateway agent. Values:

  • NOT_STARTED means the Messaging Gateway agent has not been started

  • START_SCHEDULED means Messaging Gateway agent has been scheduled to start. That is, Messaging Gateway has been started using DBMS_MGWADM.STARTUP, but the queued job used to start the Messaging Gateway agent has not yet run.

  • STARTING means Messaging Gateway agent is starting. That is, Messaging Gateway has been started using DBMS_MGWADM.STARTUP, the queued job has run, and the Messaging Gateway agent is starting up.

  • INITIALIZING means the Messaging Gateway agent has started and is initializing

  • RUNNING means the Messaging Gateway agent is running

  • SHUTTING_DOWN means the Messaging Gateway agent is shutting down

  • BROKEN means an unexpected condition has been encountered that prevents the Messaging Gateway agent from starting. DBMS_MGWADM.CLEANUP_GATEWAY must be called before the agent can be started.

AGENT_USER

VARCHAR2

Database username used by the Messaging Gateway agent to connect to the database

COMMENTS

VARCHAR2

Comments for the agent

CONNTYPE

VARCHAR2

Connection type used by the agent:

  • JDBC_OCI if the JDBC OCI driver is used

  • JDBC_THIN if the JDBC Thin driver is used

INITFILE

VARCHAR2

Name of the Messaging Gateway initialization file used by the agent. NULL indicates that the default initialization file is used.

LAST_ERROR_DATE

DATE

Date of last Messaging Gateway agent error. The last error information is cleared when Messaging Gateway is started. It is set if the Messaging Gateway agent fails to start or terminates due to an abnormal condition.

LAST_ERROR_MSG

VARCHAR2

Message for last Messaging Gateway agent error

LAST_ERROR_TIME

VARCHAR2

Time of last Messaging Gateway agent error

MAX_CONNECTIONS

NUMBER

[Deprecated] Maximum number of messaging connections to Oracle Database

MAX_MEMORY

NUMBER

Maximum heap size used by the Messaging Gateway agent (in MB)

MAX_THREADS

NUMBER

Maximum number of messaging threads created by the Messaging Gateway agent

SERVICE

VARCHAR2

Name of the database service that is associated with an Oracle Scheduler job class used by the agent


MGW_AGENT_OPTIONS: Supplemental Options and Properties

This view lists supplemental options and properties for a Messaging Gateway agent.

Table 9-9 MGW_AGENT_OPTIONS View

ColumnTypeDescription

AGENT_NAME

VARCHAR2

Name of the Messaging Gateway agent

ENCRYPTED

VARCHAR2

Indicates whether the value is stored as encrypted:

  • TRUE if the value is stored encrypted

  • FALSE if the value is stored as cleartext

NAME

VARCHAR2

Name of the option

TYPE

VARCHAR2

Option type or usage: JAVA_SYSTEM_PROP if the option is used to set a Java System property

VALUE

VARCHAR2

Value for the option. This will be <<ENCRYPTED>> if the value is stored in an encrypted form.


MGW_LINKS: Names and Types of Messaging System Links

This view lists the names and types of messaging system links currently defined.

Table 9-10 MGW_LINKS View Properties

NameTypeDescription

AGENT_NAME

VARCHAR2

Name of the Messaging Gateway agent that will process propagation jobs for this link

LINK_COMMENT

VARCHAR2

User comment for the link

LINK_NAME

VARCHAR2

Name of the messaging system link

LINK_TYPE

VARCHAR2

Type of messaging system link. Values

  • MQSERIES is for WebSphere MQ links.

  • TIBRV is for TIB/Rendezvous links.


MGW_MQSERIES_LINKS: WebSphere MQ Messaging System Links

This view lists information for the WebSphere MQ messaging system links. The view includes most of the messaging system properties specified when the link is created.

Table 9-11 MGW_MQSERIES_LINKS View Properties

NameTypeDescription

AGENT_NAME

VARCHAR2

Name of the Messaging Gateway agent that will process propagation jobs for this link

CHANNEL

VARCHAR2

Connection channel

HOSTNAME

VARCHAR2

Name of the WebSphere MQ host

INBOUND_LOG_QUEUE

VARCHAR2

Inbound propagation log queue

INTERFACE_TYPE

VARCHAR2

Messaging interface type. Values:

  • BASE_JAVA is for WebSphere MQ Base Java interface

  • JMS_CONNECTION is for WebSphere MQ JMS unified, domain-independent connections

  • JMS_QUEUE_CONNECTION is for WebSphere MQ JMS queue connections

  • JMS_TOPIC_CONNECTION is for WebSphere MQ JMS topic connections

LINK_COMMENT

VARCHAR2

User comment for the link

LINK_NAME

VARCHAR2

Name of the messaging system link

MAX_CONNECTIONS

NUMBER

Maximum number of messaging connections

OPTIONS

SYS.MGW_PROPERTIES

Link options

OUTBOUND_LOG_QUEUE

VARCHAR2

Outbound propagation log queue

PORT

NUMBER

Port number

QUEUE_MANAGER

VARCHAR2

Name of the WebSphere MQ queue manager


MGW_TIBRV_LINKS: TIB/Rendezvous Messaging System Links

This view lists information for TIB/Rendezvous messaging system links. The view}Z includes most of the messaging system properties specified when the link was created.

Table 9-12 MGW_TIBRV_LINKS View Properties

Property NameTypeDescription

AGENT_NAME

VARCHAR2

Name of the Messaging Gateway agent that will process propagation jobs for this link

CM_LEDGER

VARCHAR2

TIB/Rendezvous CM ledger file name

CM_NAME

VARCHAR2

TIB/Rendezvous CM correspondent name

DAEMON

VARCHAR2

TIB/Rendezvous daemon parameter for RVD transport

LINK_COMMENT

VARCHAR2

User comment for the link

LINK_NAME

VARCHAR2

Name of the messaging system link

NETWORK

VARCHAR2

TIB/Rendezvous network parameter for rvd transport

OPTIONS

SYS.MGW_PROPERTIES

Link options

SERVICE

VARCHAR2

TIB/Rendezvous service parameter for rvd transport


MGW_FOREIGN_QUEUES: Foreign Queues

This view lists information for foreign queues. The view includes most of the queue properties specified when the queue is registered.

Table 9-13 MGW_FOREIGN_QUEUES View Properties

NameTypeDescription

DOMAIN

VARCHAR2

Queue domain type. Values:

  • NULL means the queue domain type is automatically determined by the messaging system

  • QUEUE is for a queue (point-to-point) model

  • TOPIC is for a topic (publish-subscribe) model

LINK_NAME

VARCHAR2

Name of the messaging system link

NAME

VARCHAR2

Name of the registered queue

OPTIONS

SYS.MGW_PROPERTIES

Optional queue properties

PROVIDER_QUEUE

VARCHAR2

Message provider (native) queue name

QUEUE_COMMENT

VARCHAR2

User comment for the foreign queue


MGW_JOBS: Messaging Gateway Propagation Jobs

This view lists information for Messaging Gateway propagation jobs. The view includes most of the job properties specified when the propagation job was created, as well as other status and statistical information.

Table 9-14 MGW_JOBS View

ColumnTypeDescription

AGENT_NAME

VARCHAR2

Name of the Messaging Gateway agent that processes this job

COMMENTS

VARCHAR2

Comments for the propagation job

DESTINATION

VARCHAR2

Destination queue to which messages are propagated

ENABLED

VARCHAR2

Indicates whether the job is enabled or not:

  • TRUE if the job is enabled

  • FALSE if the job is disabled

EXCEPTION_QUEUE

VARCHAR2

Exception queue used for propagation logging purposes

EXCEPTIONQ_MSGS

NUMBER

Option type or usage: JAVA_SYSTEM_PROP if the option is used to set a Java System property

FAILURES

NUMBER

Number of messages moved to exception queue since the last time the agent was started

JOB_NAME

VARCHAR2

Name of the propagation job

LAST_ERROR_MSG

VARCHAR2

Message for the last propagation error

LAST_ERROR_DATE

DATE

Date of the last propagation error

LAST_ERROR_TIME

VARCHAR2

Time of the last propagation error

LINK_NAME

VARCHAR2

Name of the Messaging Gateway link used by this job

OPTIONS

SYS.MGW_PROPERTIES

Job options

POLL_INTERVAL

INTEGER

Propagation poll interval (in seconds)

PROPAGATED_MSGS

NUMBER

Number of messages propagated since the last time the agent was started

PROP_STYLE

VARCHAR2

Message propagation style:

  • NATIVE for native message propagation

  • JMS for JMS message propagation

PROPAGATION_TYPE

VARCHAR2

Propagation type:

  • OUTBOUND is for Oracle Streams AQ to non-Oracle propagation

  • INBOUND is for non-Oracle to Oracle Streams AQ propagation

RULE

VARCHAR2

Subscription rule used for the propagation source

SOURCE

VARCHAR2

Source queue from which messages are propagated

STATUS

VARCHAR2

Job status:

  • READY means the job is ready for propagation. The job must be enabled and the Messaging Gateway agent running before messages are actually propagated.

  • RETRY means the agent encountered errors when attempting to propagate messages for the job and will retry the operation

  • FAILED means the job has failed and agent has stopped trying to propagate messages. Usually this is due to an unrecoverable error or the propagation failure limit being reached. The job must be reset before the agent will attempt to propagate messages. The job is automatically reset each time the agent is started and can be manually reset by DBMS_MGWADM.RESET_JOB.

  • DELETE_PENDING means that job removal is pending. DBMS_MGWADM.REMOVE_JOB has been called but certain cleanup tasks for this job are still outstanding.

  • SUBSCRIBER_DELETE_PENDING means that removal is pending for the subscriber associated with the job. DBMS_MGWADM.REMOVE_SUBSCRIBER has been called but certain cleanup tasks are still outstanding.

TRANSFORMATION

VARCHAR2

Transformation used for message conversion


MGW_SUBSCRIBERS: Information for Subscribers

This view lists configuration and status information for Messaging Gateway subscribers. The view includes most of the subscriber properties specified when the subscriber is added, as well as other status and statistical information.

Table 9-15 MGW_SUBSCRIBERS View Properties

NameTypeDescription

DESTINATION

VARCHAR2

Destination queue to which messages are propagated

EXCEPTIONQ_MSGS

NUMBER

Number of messages moved to the propagation exception queue since the last time the agent was started

EXCEPTION_QUEUE

VARCHAR2

Exception queue used for logging purposes

FAILURES

NUMBER

Number of propagation failures

LAST_ERROR_DATE

DATE

Date of last propagation error

LAST_ERROR_MSG

VARCHAR2

Message for last propagation error

LAST_ERROR_TIME

VARCHAR2

Time of last propagation error

OPTIONS

SYS.MGW_PROPERTIES

Subscriber options

PROP_STYLE

VARCHAR2

Message propagation style. Values:

  • NATIVE is for native message propagation

  • JMS is for JMS message propagation

PROPAGATED_MSGS

NUMBER

Number of messages propagated to the destination queue since the last time the agent was started

PROPAGATION_TYPE

VARCHAR2

Propagation type. Values:

  • OUTBOUND is for Oracle Streams AQ to non-Oracle propagation

  • INBOUND is for non-Oracle to Oracle Streams AQ propagation

QUEUE_NAME

VARCHAR2

Subscriber source queue

RULE

VARCHAR2

Subscription rule

STATUS

VARCHAR2

Subscriber status. Values:

  • ENABLED means the subscriber is enabled

  • DELETE_PENDING means subscriber removal is pending, usually because DBMS_MGWADM.REMOVE_SUBSCRIBER has been called but certain cleanup tasks pertaining to this subscriber are still outstanding

SUBSCRIBER_ID

VARCHAR2

Propagation subscriber identifier

TRANSFORMATION

VARCHAR2

Transformation used for message conversion


MGW_SCHEDULES: Information about Schedules

This view lists configuration and status information for Messaging Gateway schedules. The view includes most of the schedule properties specified when the schedule is created, as well as other status information.

Table 9-16 MGW_SCHEDULES View Properties

NameTypeDescription

DESTINATION

VARCHAR2

Propagation destination

LATENCY

NUMBER

Propagation window latency (in seconds)

NEXT_TIME

VARCHAR2

Reserved for future use

PROPAGATION_TYPE

VARCHAR2

Propagation type. Values:

  • OUTBOUND is for Oracle Streams AQ to non-Oracle propagation

  • INBOUND is for non-Oracle to Oracle Streams AQ propagation

PROPAGATION_WINDOW

NUMBER

Reserved for future use

SCHEDULE_DISABLED

VARCHAR2

Indicates whether the schedule is disabled. Y means the schedule is disabled. N means the schedule is enabled.

SCHEDULE_ID

VARCHAR2

Propagation schedule identifier

SOURCE

VARCHAR2

Propagation source

START_DATE

DATE

Reserved for future use

START_TIME

VARCHAR2

Reserved for future use


PKȝPK-AOEBPS/aq_envir.htm Oracle Streams Advanced Queuing: Programmatic Interfaces

3 Oracle Streams Advanced Queuing: Programmatic Interfaces

This chapter describes the different language options and elements you must work with and issues to consider in preparing your Oracle Streams Advanced Queuing (AQ) application environment.


Note:

Java package oracle.AQ was deprecated in 10g Release 1 (10.1). Oracle recommends that you migrate existing Java AQ applications to Oracle JMS (or other Java APIs) and use Oracle JMS (or other Java APIs) to design your future Java AQ applications.

This chapter contains these topics:

Programmatic Interfaces for Accessing Oracle Streams Advanced Queuing

Table 3-1 lists Oracle Streams Advanced Queuing programmatic interfaces, functions supported in each interface, and syntax references.

Table 3-1 Oracle Streams Advanced Queuing Programmatic Interfaces

LanguagePrecompiler or Interface ProgramFunctions SupportedSyntax References

PL/SQL

DBMS_AQADM and DBMS_AQ Packages

Administrative and operational

Oracle Database PL/SQL Packages and Types Reference

C

Oracle Call Interface (OCI)

Operational only

Oracle Call Interface Programmer's Guide

Visual Basic

Oracle Objects for OLE (OO4O)

Operational only

Online help available from Application Development submenu of Oracle installation.

Java (JMS)

oracle.JMS package using JDBC API

Administrative and operational

Oracle Streams Advanced Queuing Java API Reference

AQ XML servlet

Internet Data Access Presentation (IDAP)

Operational only

Chapter 6, "Internet Access to Oracle Streams AQ"


Using PL/SQL to Access Oracle Streams Advanced Queuing

The PL/SQL packages DBMS_AQADM and DBMS_AQ support access to Oracle Streams Advanced Queuing administrative and operational functions using the native Oracle Streams Advanced Queuing interface. These functions include:

  • Create queue, queue table, nonpersistent queue, multiconsumer queue/topic, RAW message, or message with structured data

  • Get queue table, queue, or multiconsumer queue/topic

  • Alter queue table or queue/topic

  • Drop queue/topic

  • Start or stop queue/topic

  • Grant and revoke privileges

  • Add, remove, or alter subscriber

  • Add, remove, or alter an Oracle Streams Advanced Queuing Internet agent

  • Grant or revoke privileges of database users to Oracle Streams Advanced Queuing Internet agents

  • Enable, disable, or alter propagation schedule

  • Enqueue messages to single consumer queue (point-to-point model)

  • Publish messages to multiconsumer queue/topic (publish/subscribe model)

  • Subscribe for messages in multiconsumer queue

  • Browse messages in a queue

  • Receive messages from queue/topic

  • Register to receive messages asynchronously

  • Listen for messages on multiple queues/topics

  • Post messages to anonymous subscriptions

  • Bind or unbind agents in a Lightweight Directory Access Protocol (LDAP) server

  • Add or remove aliases to Oracle Streams Advanced Queuing objects in a LDAP server


    See Also:

    Oracle Database PL/SQL Packages and Types Reference for detailed documentation of DBMS_AQADM and DBMS_AQ, including syntax, parameters, parameter types, return values, and examples

Available PL/SQL DBMS_AQADM and DBMS_AQ functions are listed in detail in Table 3-2 through Table 3-9.

Using OCI to Access Oracle Streams Advanced Queuing

OCI provides an interface to Oracle Streams Advanced Queuing functions using the native Oracle Streams Advanced Queuing interface.

An OCI client can perform the following actions:

  • Enqueue messages

  • Dequeue messages

  • Listen for messages on sets of queues

  • Register to receive message notifications

In addition, OCI clients can receive asynchronous notifications for new messages in a queue using OCISubscriptionRegister.


See Also:

"OCI and Advanced Queuing" and "Publish-Subscribe Notification" in Oracle Call Interface Programmer's Guide for syntax details

Oracle Type Translator

For queues with user-defined payload types, the Oracle type translator must be used to generate the OCI/OCCI mapping for the Oracle type. The OCI client is responsible for freeing the memory of the Oracle Streams Advanced Queuing descriptors and the message payload.

Using OCCI to Access Oracle Streams Advanced Queuing

C++ applications can use OCCI, which has a set of Oracle Streams Advanced Queuing interfaces that enable messaging clients to access Oracle Streams Advanced Queuing. OCCI AQ supports all the operational functions required to send/receive and publish/subscribe messages in a message-enabled database. Synchronous and asynchronous message consumption is available, based on a message selection rule.


See Also:

"Oracle Streams Advanced Queuing" in Oracle C++ Call Interface Programmer's Guide

Using Visual Basic (OO4O) to Access Oracle Streams Advanced Queuing

Visual Basic (OO4O) supports access to Oracle Streams Advanced Queuing operational functions using the native Oracle Streams Advanced Queuing interface.

These functions include the following:

  • Create a connection, RAW message, or message with structured data

  • Enqueue messages to a single-consumer queue (point-to-point model)

  • Publish messages to a multiconsumer queue/topic (publish/subscribe model)

  • Browse messages in a queue

  • Receive messages from a queue/topic

  • Register to receive messages asynchronously


Note:

Because the database handles message propagation, OO4O does not differentiate between remote and local recipients. The same sequence of calls/steps are required to dequeue a message for local and remote recipients.

Using Oracle Java Message Service (OJMS) to Access Oracle Streams Advanced Queuing

Java Message Service (JMS) is a messaging standard defined by Sun Microsystems, Oracle, IBM, and other vendors. JMS is a set of interfaces and associated semantics that define how a JMS client accesses the facilities of an enterprise messaging product.

Oracle Java Message Service (OJMS) provides a Java API for Oracle Streams Advanced Queuing based on the JMS standard. OJMS supports the standard JMS interfaces and has extensions to support administrative operations and other features that are not a part of the standard.

Standard JMS features include:

  • Point-to-point model of communication using queues

  • Publish/subscribe model of communication using topics

  • ObjectMessage, StreamMessage, TextMessage, BytesMessage, and MapMessage message types

  • Asynchronous and synchronous delivery of messages

  • Message selection based on message header fields or properties

Oracle JMS extensions include:

  • Administrative API to create queue tables, queues and topics

  • Point-to-multipoint communication using recipient lists for topics

  • Message propagation between destinations, which allows the application to define remote subscribers

  • Support for transactional sessions, enabling JMS and SQL operations in one transaction

  • Message retention after messages have been dequeued

  • Message delay, allowing messages to be made visible after a certain delay

  • Exception handling, allowing messages to be moved to exception queues if they cannot be processed successfully

  • Support for AdtMessage

    These are stored in the database as Oracle objects, so the payload of the message can be queried after it is enqueued. Subscriptions can be defined on the contents of these messages as opposed to just the message properties.

  • Topic browsing

    This allows durable subscribers to browse through the messages in a publish/subscribe (topic) destination. It optionally allows these subscribers to purge the browsed messages, so they are no longer retained by Oracle Streams Advanced Queuing for that subscriber.


    See Also:


Accessing Standard and Oracle JMS Applications

Standard JMS interfaces are in the javax.jms package. Oracle JMS interfaces are in the oracle.jms package. You must have EXECUTE privilege on the DBMS_AQIN and DBMS_AQJMS packages to use the Oracle JMS interfaces. You can also acquire these rights through the AQ_USER_ROLE or the AQ_ADMINSTRATOR_ROLE. You also need the appropriate system and queue or topic privileges to send or receive messages.

Because Oracle JMS uses Java Database Connectivity (JDBC) to connect to the database, its applications can run outside the database using the JDBC OCI driver or JDBC thin driver.

Using JDBC OCI Driver or JDBC Thin Driver

To use JMS with clients running outside the database, you must include the appropriate JDBC driver, Java Naming and Directory Interface (JNDI) jar files, and Oracle Streams Advanced Queuing jar files in your CLASSPATH.

Note that the Oracle Database does not support JDK 1.2, JDK 1.3, JDK 1.4, and all classes12*.* files. You need to use the ojdbc5.jar and ojbc6.jar files with JDK 5.n and JDK 6.n, respectively. The following jar and zip files should be in the CLASSPATH based on the release of JDK you are using.

For JDK 1.5.x, the CLASSPATH must contain:

ORACLE_HOME/jdbc/lib/ojdbc5.jar

For JDK 1.6.x, the CLASSPATH must contain:

ORACLE_HOME/jdbc/lib/ojdbc6.jar 

The following files are used for either JDK version:

ORACLE_HOME/lib/jta.jar
ORACLE_HOME/xdk/lib/xmlparserv2.jar
ORACLE_HOME/rdbms/jlib/xdb.jar
ORACLE_HOME/jlib/aqapi.jar 
ORACLE_HOME/rdbms/jlib/jmscommon.jar

Using Oracle Server Driver in JServer

If your application is running inside the JServer, then you should be able to access the Oracle JMS classes that have been automatically loaded when the JServer was installed. If these classes are not available, then you must load jmscommon.jar followed by aqapi.jar using the $ORACLE_HOME/rdbms/admin/initjms SQL script.

Using Oracle Streams Advanced Queuing XML Servlet to Access Oracle Streams Advanced Queuing

You can use Oracle Streams Advanced Queuing XML servlet to access Oracle Streams Advanced Queuing over HTTP using Simple Object Access Protocol (SOAP) and an Oracle Streams Advanced Queuing XML message format called Internet Data Access Presentation (IDAP).

Using the Oracle Streams Advanced Queuing servlet, a client can perform the following actions:

  • Send messages to single-consumer queues

  • Publish messages to multiconsumer queues/topics

  • Receive messages from queues

  • Register to receive message notifications


See Also:

"Deploying the Oracle Streams Advanced Queuing XML Servlet" for more information on the Oracle Streams Advanced Queuing XML servlet

Comparing Oracle Streams Advanced Queuing Programmatic Interfaces

Available functions for the Oracle Streams Advanced Queuing programmatic interfaces are listed by use case in Table 3-2 through Table 3-9. Use cases are described in Chapter 8 through Chapter 10 and Chapter 12 through Chapter 15.

Oracle Streams Advanced Queuing Administrative Interfaces

Table 3-2 lists the equivalent Oracle Streams Advanced Queuing administrative functions for the PL/SQL and Java (JMS) programmatic interfaces.

Table 3-2 Comparison of Oracle Streams Advanced Queuing Programmatic Interfaces: Administrative Interface

Use CasePL/SQLJava (JMS)

Create a connection factory

N/A

AQjmsFactory.getQueue
ConnectionFactory
AQjmsFactory.getTopic
ConnectionFactory

Register a ConnectionFactory in an LDAP server

N/A

AQjmsFactory.register
ConnectionFactory

Create a queue table

DBMS_AQADM.CREATE_QUEUE_TABLE
AQjmsSession.createQueueTable

Get a queue table

Use schema.queue_table_name

AQjmsSession.getQueueTable

Alter a queue table

DBMS_AQADM.ALTER_QUEUE_TABLE
AQQueueTable.alter

Drop a queue table

DBMS_AQADM.DROP_QUEUE_TABLE
AQQueueTable.drop

Create a queue

DBMS_AQADM.CREATE_QUEUE
AQjmsSession.createQueue

Get a queue

Use schema.queue_name

AQjmsSession.getQueue

Create a multiconsumer queue/topic in a queue table with multiple consumers enabled

DBMS_AQADM.CREATE_QUEUE
AQjmsSession.createTopic

Get a multiconsumer queue/topic

Use schema.queue_name

AQjmsSession.getTopic

Alter a queue/topic

DBMS_AQADM.ALTER_QUEUE
AQjmsDestination.alter

Start a queue/topic

DBMS_AQADM.START_QUEUE
AQjmsDestination.start

Stop a queue/topic

DBMS_AQADM.STOP_QUEUE
AQjmsDestination.stop

Drop a queue/topic

DBMS_AQADM.DROP_QUEUE
AQjmsDestination.drop

Grant system privileges

DBMS_AQADM.GRANT_SYSTEM_
PRIVILEGE
AQjmsSession.grantSystem
Privilege

Revoke system privileges

DBMS_AQADM.REVOKE_SYSTEM_
PRIVILEGE
AQjmsSession.revokeSystem
Privilege

Grant a queue/topic privilege

DBMS_AQADM.GRANT_QUEUE_
PRIVILEGE
AQjmsDestination.grantQueue
Privilege
AQjmsDestination.grantTopic
Privilege

Revoke a queue/topic privilege

DBMS_AQADM.REVOKE_QUEUE_
PRIVILEGE
AQjmsDestination.revokeQueue
Privilege
AQjmsDestination.revokeTopic
Privilege

Verify a queue type

DBMS_AQADM.VERIFY_QUEUE_TYPES

Not supported

Add a subscriber

DBMS_AQADM.ADD_SUBSCRIBER

See Table 3-6

Alter a subscriber

DBMS_AQADM.ALTER_SUBSCRIBER

See Table 3-6

Remove a subscriber

DBMS_AQADM.REMOVE_SUBSCRIBER

See Table 3-6

Schedule propagation

DBMS_AQADM.SCHEDULE_PROPAGATION
AQjmsDestination.schedule
Propagation

Enable a propagation schedule

DBMS_AQADM.ENABLE_PROPAGATION_
SCHEDULE
AQjmsDestination.enable
PropagationSchedule

Alter a propagation schedule

DBMS_AQADM.ALTER_PROPAGATION_
SCHEDULE
AQjmsDestination.alter
PropagationSchedule

Disable a propagation schedule

DBMS_AQADM.DISABLE_PROPAGATION_
SCHEDULE
AQjmsDestination.disable
PropagationSchedule

Unschedule a propagation

DBMS_AQADM.UNSCHEDULE_
PROPAGATION
AQjmsDestination.unschedule
Propagation

Create an Oracle Streams Advanced Queuing Internet Agent

DBMS_AQADM.CREATE_AQ_AGENT

Not supported

Alter an Oracle Streams Advanced Queuing Internet Agent

DBMS_AQADM.ALTER_AQ_AGENT

Not supported

Drop an Oracle Streams Advanced Queuing Internet Agent

DBMS_AQADM.DROP_AQ_AGENT

Not supported

Grant database user privileges to an Oracle Streams Advanced Queuing Internet Agent

DBMS_AQADM.ENABLE_AQ_AGENT

Not supported

Revoke database user privileges from an Oracle Streams Advanced Queuing Internet Agent

DBMS_AQADM.DISABLE_AQ_AGENT

Not supported

Add alias for queue, agent, ConnectionFactory in a LDAP server

DBMS_AQADM.ADD_ALIAS_TO_LDAP

Not supported

Delete alias for queue, agent, ConnectionFactory in a LDAP server

DBMS_AQADM.DEL_ALIAS_FROM_LDAP

Not supported


Oracle Streams Advanced Queuing Operational Interfaces

Table 3-3 through Table 3-9 list equivalent Oracle Streams Advanced Queuing operational functions for the programmatic interfaces PL/SQL, OCI, Oracle Streams Advanced Queuing XML Servlet, and JMS, for various use cases.

Table 3-3 Comparison of Oracle Streams Advanced Queuing Programmatic Interfaces: Operational Interface—Create Connection, Session, Message Use Cases

Use CasePL/SQLOCIAQ XML ServletJMS

Create a connection

N/A

OCIServer
Attach

Open an HTTP connection after authenticating with the Web server

AQjmsQueueConnectionFactory
.createQueueConnection
AQjmsTopicConnectionFactory
.createTopicConnection

Create a session

N/A

OCISession
Begin

An HTTP servlet session is automatically started with the first SOAP request

QueueConnection.createQueue
Session
TopicConnection.createTopic
Session

Create a RAW message

Use SQL RAW type for message

Use OCIRaw for Message

Supply the hex representation of the message payload in the XML message. For example, <raw>023f4523</raw>

Not supported

Create a message with structured data

Use SQL Oracle object type for message

Use SQL Oracle object type for message

For Oracle object type queues that are not JMS queues (that is, they are not type AQ$_JMS_*), the XML specified in <message payload> must map to the SQL type of the payload for the queue table.

For JMS queues, the XML specified in the <message_payload> must be one of the following: <jms_text_message>, <jms_map_message>, <jms_bytes_message>, <jms_object_message>

Session.createTextMessage
Session.createObjectMessage
Session.createMapMessage
Session.createBytesMessage
Session.createStreamMessage
AQjmsSession.createAdtMessage

Create a message producer

N/A

N/A

N/A

QueueSession.createSender
TopicSession.createPublisher

Table 3-4 Comparison of Oracle Streams Advanced Queuing Programmatic Interfaces: Operational Interface—Enqueue Messages to a Single-Consumer Queue, Point-to-Point Model Use Cases

Use CasePL/SQLOCIAQ XML ServletJMS

Enqueue a message to a single-consumer queue

DBMS_AQ.enqueue
OCIAQEnq
<AQXmlSend>
QueueSender.send

Enqueue a message to a queue and specify visibility options

DBMS_AQ.enqueue

Specify visibility in

ENQUEUE_OPTIONS
OCIAQEnq

Specify OCI_ATTR_VISIBILITY in OCIAQEnqOptions

OCIAQEnqOptions
<AQXmlSend>

Specify <visibility> in

<producer_options>

Not supported

Enqueue a message to a single-consumer queue and specify message properties priority and expiration

DBMS_AQ.enqueue

Specify priority, expiration in

MESSAGE_PROPERTIES
OCIAQEnq

Specify OCI_ATTR_PRIORITY, OCI_ATTR_EXPIRATION in

OCIAQMsgProperties
<AQXmlSend>

Specify <priority>, <expiration> in

<message_header>

Specify priority and TimeToLive during

QueueSender.send

or

.setTimeToLive

and

MessageProducer.
setPriority

followed by

QueueSender.send

Enqueue a message to a single-consumer queue and specify message properties correlationID, delay, and exception queue

DBMS_AQ.enqueue

Specify correlation, delay, exception_queue in

MESSAGE_PROPERTIES
OCIAQEnq

Specify OCI_ATTR_CORRELATION, OCI_ATTR_DELAY, OCI_ATTR_EXCEPTION_QUEUE in

OCIAQMsgProperties
<AQXmlSend>

Specify <correlation_id>, <delay>, <exception_queue> in

<message_header>
Message.setJMS
CorrelationI

Delay and exception queue specified as provider specific message properties

JMS_OracleDelay
JMS_OracleExcpQ

followed by

QueueSender.send

Enqueue a message to a single-consumer queue and specify user-defined message properties

Not supported

Properties should be part of payload

Not supported

Properties should be part of payload

<AQXmlSend>

Specify <name> and <int_value>, <string_value>, <long_value>, and so on in

<user_properties>
Message.setInt
Property
Message.setString
Property
Message.setBoolean
Property

and so forth, followed by

QueueSender.send

Enqueue a message to a single-consumer queue and specify message transformation

DBMS_AQ.enqueue

Specify transformation in

ENQUEUE_OPTIONS
OCIAQEnq

Specify OCI_ATTR_TRANSFORMATION in

OCIAQEnqOptions
<AQXmlSend>

Specify <transformation> in

<producer_options>
AQjmsQueueSender.
setTransformation

followed by

QueueSender.send

Table 3-5 Comparison of Oracle Streams Advanced Queuing Programmatic Interfaces: Operational Interface—Publish Messages to a Multiconsumer Queue/Topic, Publish/Subscribe Model Use Cases

Use CasePL/SQLOCIAQ XML ServletJMS

Publish a message to a multiconsumer queue/topic using default subscription list

DBMS_AQ.enqueue

Set recipient_list to NULL in

MESSAGE_PROPERTIES
OCIAQEnq

Set OCI_ATTR_RECIPIENT_LIST to NULL in

OCIAQMsgProperties
<AQXmlPublish>
TopicPublisher.
publish

Publish a message to a multiconsumer queue/topic using specific recipient list

See footnote-1

DBMS_AQ.enqueue

Specify recipient list in

MESSAGE_PROPERTIES
OCIAQEnq

Specify OCI_ATTR_RECIPIENT_LIST in

OCIAQMsgProperties
<AQXmlPublish>

Specify <recipient_list> in

<message_header>
AQjmsTopic
Publisher.publish

Specify recipients as an array of AQjmsAgent

Publish a message to a multiconsumer queue/topic and specify message properties priority and expiration

DBMS_AQ.enqueue

Specify priority, expiration in

MESSAGE_PROPERTIES
OCIAQEnq

Specify OCI_ATTR_PRIORITY, OCI_ATTR_EXPIRATION in

OCIAQMsgProperties
<AQXmlPublish>

Specify <priority>, <expiration> in

<message_header>

Specify priority and TimeToLive during

TopicPublisher.
publish

or

MessageProducer.
setTimeToLive

and

MessageProducer.
setPriority

followed by

TopicPublisher.
publish

Publish a message to a multiconsumer queue/topic and specify send options correlationID, delay, and exception queue

DBMS_AQ.enqueue

Specify correlation, delay, exception_queue in

MESSAGE_PROPERTIES
OCIAQEnq

Specify OCI_ATTR_CORRELATION, OCI_ATTR_DELAY, OCI_ATTR_EXCEPTION_QUEUE in

OCIAQMsgProperties
<AQXmlPublish>

Specify <correlation_id>, <delay>, <exception_queue> in

<message_header>
Message.setJMS
CorrelationID

Delay and exception queue specified as provider-specific message properties

JMS_OracleDelay
JMS_OracleExcpQ

followed by

TopicPublisher.
publish

Publish a message to a topic and specify user-defined message properties

Not supported

Properties should be part of payload

Not supported

Properties should be part of payload

<AQXmlPublish>

Specify <name> and <int_value>, <string_value>, <long_value>, and so on in

<user_properties>
Message.setInt
Property
Message.setString
Property
Message.setBoolean
Property

and so forth, followed by

TopicPublisher.
publish

Publish a message to a topic and specify message transformation

DBMS_AQ.enqueue

Specify transformation in

ENQUEUE_OPTIONS
OCIAQEnq

Specify OCI_ATTR_TRANSFORMATION in

OCIAQEnqOptions
<AQXmlPublish>

Specify <transformation> in

<producer_options>
AQjmsTopic
Publisher.set
Transformation

followed by

TopicPublisher.
publish

Table 3-6 Comparison of Oracle Streams Advanced Queuing Programmatic Interfaces: Operational Interface—Subscribing for Messages in a Multiconsumer Queue/Topic, Publish/Subscribe Model Use Cases

Use CasePL/SQLOCIAQ XML ServletJMS

Add a subscriber

See administrative interfaces

Not supported

Not supported

TopicSession.
createDurable
Subscriber
AQjmsSession.
createDurable
Subscriber

Alter a subscriber

See administrative interfaces

Not supported

Not supported

TopicSession.
createDurable
Subscriber
AQjmsSession.
createDurable
Subscriber

using the new selector

Remove a subscriber

See administrative interfaces

Not supported

Not supported

AQjmsSession.
unsubscribe

Table 3-7 Comparison of Oracle Streams Advanced Queuing Programmatic Interfaces: Operational Interface—Browse Messages in a Queue Use Cases

Use CasePL/SQLOCIAQ XML ServletJMS

Browse messages in a queue/topic

DBMS_AQ.
dequeue

Set dequeue_mode to BROWSE in

DEQUEUE_OPTIONS
OCIAQDeq

Set OCI_ATTR_DEQ_MODE to BROWSE in

OCIAQDeqOptions
<AQXmlReceive>

Specify <dequeue_mode> BROWSE in

<consumer_options>
QueueSession.createBrowser
QueueBrowser.getEnumeration

Not supported on topics

oracle.jms.AQjmsSession.
createBrowser
oracle.jms.TopicBrowser.
getEnumeration

Browse messages in a queue/topic and lock messages while browsing

DBMS_AQ.dequeue

Set dequeue_mode to LOCKED in

DEQUEUE_OPTIONS
OCIAQDeq

Set OCI_ATTR_DEQ_MODE to LOCKED in

OCIAQDeqOptions
<AQXmlReceive>

Specify <dequeue_mode> LOCKED in

<consumer_options>
AQjmsSession.createBrowser

set locked to TRUE.

QueueBrowser.getEnumeration

Not supported on topics

oracle.jms.AQjmsSession.
createBrowser
oracle.jms.TopicBrowser.
getEnumeration

Table 3-8 Comparison of Oracle Streams Advanced Queuing Programmatic Interfaces: Operational Interface—Receive Messages from a Queue/Topic Use Cases

Use CasePL/SQLOCIAQ XML ServletJMS

Start a connection for receiving messages

N/A

N/A

N/A

Connection.start

Create a message consumer

N/A

N/A

N/A

QueueSession.
createQueueReceiver
TopicSession.create
DurableSubscriber 
AQjmsSession.create
TopicReceiver

Dequeue a message from a queue/topic and specify visibility

DBMS_AQ.dequeue

Specify visibility in

DEQUEUE_OPTIONS
OCIAQDeq

Specify OCI_ATTR_VISIBILITY in

OCIAQDeqOptions
<AQXmlReceive>

Specify <visibility> in

<consumer_options>

Not supported

Dequeue a message from a queue/topic and specify transformation

DBMS_AQ.dequeue

Specify transformation in

DEQUEUE_OPTIONS
OCIAQDeq

Specify OCI_ATTR_TRANSFORMATION in

OCIAQDeqOptions
<AQXmlReceive>

Specify <transformation> in

<consumer_options>
AQjmsQueueReceiver.
setTransformation
AQjmsTopicSubscriber.
setTransformation
AQjmsTopicReceiver.
setTransformation

Dequeue a message from a queue/topic and specify navigation mode

DBMS_AQ.dequeue

Specify navigation in

DEQUEUE_OPTIONS
OCIAQDeq

Specify OCI_ATTR_NAVIGATION in

OCIAQDeqOptions
<AQXmlReceive>

Specify <navigation> in

<consumer_options>
AQjmsQueueReceiver.
setNavigationMode
AQjmsTopicSubscriber.
setNavigationMode
AQjmsTopicReceiver.
setNavigationMode

Dequeue a message from a single-consumer queue

DBMS_AQ.dequeue

Set dequeue_mode to REMOVE in

DEQUEUE_OPTIONS
OCIAQDeq

Set OCI_ATTR_DEQ_MODE to REMOVE in

OCIAQDeqOptions
<AQXmlReceive>
QueueReceiver.receive

or

QueueReceiver.receive
NoWait

or

AQjmsQueueReceiver.
receiveNoData

Dequeue a message from a multiconsumer queue/topic using subscription name

DBMS_AQ.dequeue

Set dequeue_mode to REMOVE and set consumer_name to subscription name in

DEQUEUE_OPTIONS
OCIAQDeq

Set OCI_ATTR_DEQ_MODE to REMOVE and set OCI_ATTR_CONSUMER_NAME to subscription name in

OCIAQDeqOptions
<AQXmlReceive>

Specify <consumer_name> in

<consumer_options>

Create a durable TopicSubscriber on the topic using the subscription name, then

TopicSubscriber.
receive

or

TopicSubscriber.
receiveNoWait

or

AQjmsTopicSubscriber.
receiveNoData

Dequeue a message from a multiconsumer queue/topic using recipient name

DBMS_AQ.dequeue

Set dequeue_mode to REMOVE and set consumer_name to recipient name in

DEQUEUE_OPTIONS
OCIAQDeq

Set OCI_ATTR_DEQ_MODE to REMOVE and set OCI_ATTR_CONSUMER_NAME to recipient name in

OCIAQDeqOptions
<AQXmlReceive>

Specify <consumer_name> in

<consumer_options>

Create a TopicReceiver on the topic using the recipient name, then

AQjmsSession.create
TopicReceiver
AQjmsTopicReceiver.
receive

or

AQjmsTopicReceiver.
receiveNoWait

or

AQjmsTopicReceiver.
receiveNoData

Table 3-9 Comparison of Oracle Streams Advanced Queuing Programmatic Interfaces: Operational Interface—Register to Receive Messages Asynchronously from a Queue/Topic Use Cases

Use CasePL/SQLOCIAQ XML ServletJMS

Receive messages asynchronously from a single-consumer queue

Define a PL/SQL callback procedure

Register it using

DBMS_AQ.REGISTER
OCISubscription
Register

Specify queue_name as subscription name

OCISubscription
Enable
<AQXmlRegister>

Specify queue name in <destination> and notification mechanism in

<notify_url>

Create a QueueReceiver on the queue, then

QueueReceiver.set
MessageListener

Receive messages asynchronously from a multiconsumer queue/topic

Define a PL/SQL callback procedure

Register it using

DBMS_AQ.REGISTER
OCISubscription
Register

Specify queue:OCI_ATTR_CONSUMER_NAME as subscription name

OCISubscription
Enable
<AQXmlRegister>

Specify queue name in <destination>, consumer in <consumer_name> and notification mechanism in <notify_url>

Create a TopicSubscriber or TopicReceiver on the topic, then

TopicSubscriber.
setMessageListener

Listen for messages on multiple queues/topics

-

-

-

-

Listen for messages on one (many) single-consumer queues

DBMS_AQ.LISTEN

Use agent_name as NULL for all agents in agent_list

OCIAQListen

Use agent_name as NULL for all agents in agent_list

Not supported

Create multiple QueueReceivers on a QueueSession, then

QueueSession.set
MessageListener

Listen for messages on one (many) multiconsumer queues/Topics

DBMS_AQ.LISTEN

Specify agent_name for all agents in agent_list

OCIAQListen

Specify agent_name for all agents in agent_list

Not supported

Create multiple TopicSubscribers or TopicReceivers on a TopicSession, then

TopicSession.set
MessageListener

PKkRRPK -Aoa,mimetypePK-AO$nWR:iTunesMetadata.plistPK-AYuMETA-INF/container.xmlPK-Aÿ))OEBPS/qwnew.htmPK-A[pTO/OEBPS/cover.htmPK-Ad1n))X2OEBPS/aperrors.htmPK-AH\OEBPS/jm_pblsh.htmPK-Ak޿EOEBPS/title.htmPK-A3Kwgf<OEBPS/jm_opers.htmPK-AѴYi_|eOEBPS/componet.htmPK-A]5+%OEBPS/internet.htmPK-A߇ՇOEBPS/glossary.htmPK-A WZOEBPS/preface.htmPK-A`sOEBPS/index.htmPK-A_,+ OEBPS/mg_work.htmPK-AaV|IwIW OEBPS/perform.htmPK-AwZKf OEBPS/jm_share.htmPK-A&R&SMjHj OEBPS/img/adque449.gifPK-A񡣳= OEBPS/img/adque042.gifPK-AxHsH$ OEBPS/img/adque445.gifPK-AF3kp|p OEBPS/img/adque040.gifPK-AiW88]OEBPS/img/adque446.gifPK-A?8bW]WOEBPS/img/adque039.gifPK-AWA3<3dOEBPS/img/adque249.gifPK-At_8C3C!OEBPS/img/adque035.gifPK-A^ ueeOEBPS/img/adque437.gifPK-AM@0TsCnC(OEBPS/img/adque447.gifPK-A7F{6{63OEBPS/img/adque430.gifPK-A:HsYOjOEBPS/img/strms021.gifPK-Aíʖ))@OEBPS/img/adque250.gifPK-AkkWDRDOEBPS/img/adqmg005.gifPK-AYSS\OEBPS/img/adqmg003.gifPK-A:PPͰOEBPS/img/adqmg004.gifPK-AuD55OEBPS/img/adque037.gifPK-A&+|+O7OEBPS/img/adque448.gifPK-Af&ffcOEBPS/img/adque041.gifPK-ANazaOEBPS/img/adque450.gifPK-A%5+OEBPS/mg_trble.htmPK-AfR OEBPS/mg_start.htmPK-AWOEBPS/img_text/adque040.htmPK-A10|OEBPS/img_text/adqmg003.htmPK-A|,þOEBPS/img_text/adque430.htmPK-Aj"OEBPS/img_text/adque037.htmPK-A. "SNOEBPS/img_text/adque437.htmPK-A"OEBPS/img_text/strms021.htmPK-Anmyг OEBPS/img_text/adque448.htmPK-Ag-VQOEBPS/img_text/adque447.htmPK-AX$OEBPS/img_text/adque446.htmPK-ATOEBPS/img_text/adqmg004.htmPK-A n|wsOEBPS/img_text/adque042.htmPK-AHǟ8OEBPS/img_text/adque039.htmPK-A!ݵGBJOEBPS/img_text/adque249.htmPK-AOEBPS/img_text/adque445.htmPK-AUo=WROEBPS/img_text/adque035.htmPK-AUPNOEBPS/img_text/adqmg005.htmPK-AfnOEBPS/img_text/adque041.htmPK-AR?e` OEBPS/img_text/adque449.htmPK-AЄCjeOEBPS/img_text/adque450.htmPK-APOEBPS/img_text/adque250.htmPK-A]5d&U&)OEBPS/aq_demo.htmPK-A11=OEBPS/ap_nonpers.htmPK-A'XS oOEBPS/toc.ncxPK-A2WiWOEBPS/aq_intro.htmPK-A p6k6TOEBPS/content.opfPK-A][QOEBPS/manage.htmPK-A_ OEBPS/dcommon/prodbig.gifPK-AY@ OEBPS/dcommon/doclib.gifPK-A{ooFOEBPS/dcommon/oracle-logo.jpgPK-A/OEBPS/dcommon/contbig.gifPK-A5OEBPS/dcommon/darbbook.cssPK-AMά""!5OEBPS/dcommon/O_signature_clr.JPGPK-APz XOEBPS/dcommon/feedbck2.gifPK-A-SZOEBPS/dcommon/feedback.gifPK-Aː5haOEBPS/dcommon/booklist.gifPK-AN61bOEBPS/dcommon/cpyr.htmPK-A!:3.EuOEBPS/dcommon/masterix.gifPK-AeӺ1,vOEBPS/dcommon/doccd.cssPK-A7 6yOEBPS/dcommon/larrow.gifPK-A#]{OEBPS/dcommon/indxicon.gifPK-AS'"}OEBPS/dcommon/leftnav.gifPK-Ahu,6OEBPS/dcommon/uarrow.gifPK-Al-OJQOEBPS/dcommon/oracle.gifPK-A(OEBPS/dcommon/index.gifPK-AGC ,OEBPS/dcommon/bookbig.gifPK-AJV^LOEBPS/dcommon/rarrow.gifPK-A枰pkgOEBPS/dcommon/mix.gifPK-Ao"nR M OEBPS/dcommon/doccd_epub.jsPK-Av I OEBPS/dcommon/toc.gifPK-A r~$OEBPS/dcommon/topnav.gifPK-A1FAlOEBPS/dcommon/prodicon.gifPK-A3( # OEBPS/dcommon/bp_layout.cssPK-Ax[?:kOEBPS/dcommon/bookicon.gifPK-Ap*c^OEBPS/dcommon/conticon.gifPK-AʍOEBPS/dcommon/blafdoc.cssPK-A+&OEBPS/dcommon/rightnav.gifPK-Aje88OEBPS/dcommon/oracle-small.JPGPK-Aއ{&!POEBPS/dcommon/help.gifPK-Ahs OEBPS/toc.htmPK-A$OEBPS/jm_exmpl.htmPK-AjJOEBPS/aq_admin.htmPK-Aq DDcOEBPS/mg_trnsfm.htmPK-A3SOEBPS/jm_create.htmPK-Af5==ͣ!OEBPS/aq_opers.htmPK-A7"OEBPS/aq_stage.htmPK-AĀCF>F#OEBPS/mg_intro.htmPK-AIQq%l%#OEBPS/aq_trbl.htmPK-Awz"$OEBPS/jm_point.htmPK-Aȝ$OEBPS/aq_views.htmPK-AkRR&OEBPS/aq_envir.htmPKmm 2(