Monitoring Oracle AQ via JMS, triggering execution of Java programs as the database changes

Source: Internet
Author: User
Tags message queue oracleconnection

      • Environment description
      • An Oracle advanced Message Queuing AQ
        • Create Message Payload payload
        • Create a team list
        • Create a queue and start
        • Stop and delete of queues
        • Queued News
        • Message from the team
      • Two Java uses JMS to listen for and process Oracle AQ queues
        • To create a connection parameter class
        • Creating a Message Transformation class
        • Main class for message processing
      • Three monitor table record change notification Java
        • Create a table
        • Create a stored procedure
        • Create a Trigger

Environment description

This lab environment is based on Oracle 12C and JDK1.8, where Oracle 12C supports multi-tenancy features, using ' C # #用户名表示用户 ' compared to previous versions of Oracle, such as if the database user is called Kevin, then use C # #kevin进行登陆 when logging in.

I. Oracle advanced Message Queuing AQ

Oracle AQ is a message queue in Oracle, an advanced application in Oracle, each of which is continuously enhanced with the DBMS_AQ System package, which is the default component of Oracle and can be used as long as the Oracle database is installed. With AQ, you can transfer data across multiple Oracle databases, Oracle and Java, and C systems.

The following steps explain how to create an Oracle AQ

1. Create Message Payload payload

Messages passed in Oracle AQ are called payloads (payloads), and can be in the form of a user-defined object or a xmltype or anydata. In this example we create a simple object type for passing messages.

create type demo_queue_payload_type as object (message varchar2(4000));
2. Create a team list

The queue table is used to store messages, which are automatically saved to the table when queued and automatically deleted when the team is out. To create a data table using the DBMS_AQADM package, simply write the table name and set the appropriate properties. For queues that need to be set to Multiple_consumers to False, set to True if using the Publish/Subscribe mode.

begin  dbms_aqadm.create_queue_table(    queue_table   => ‘demo_queue_table‘,    queue_payload_type => ‘demo_queue_payload_type‘,    multiple_consumers => false  );end;

After execution you can view the Demo_queue_table table automatically generated in the Oracle table to see the affected sub-segments (meaning clearer).

3. Create a queue and start

To create a queue and start a queue:

begin  dbms_aqadm.create_queue (    queue_name  => ‘demo_queue‘,    queue_table => ‘demo_queue_table‘  );  dbms_aqadm.start_queue(    queue_name  =>  ‘demo_queue‘  );end;

At this point, we have created queue payloads, queue tables, and queues. You can view which related objects are created by the following systems:

SELECT object_name, object_type FROM user_objects WHERE object_name != ‘DEMO_QUEUE_PAYLOAD_TYPE‘;OBJECT_NAME OBJECT_TYPE------------------------------ ---------------DEMO_QUEUE_TABLE TABLESYS_C009392 INDEXSYS_LOB0000060502C00030$$ LOBAQ$_DEMO_QUEUE_TABLE_T INDEXAQ$_DEMO_QUEUE_TABLE_I INDEXAQ$_DEMO_QUEUE_TABLE_E QUEUEAQ$DEMO_QUEUE_TABLE VIEWDEMO_QUEUE QUEUE

We see a queue that brings out a series of auto-generated objects, some of which are used directly from behind. But interestingly, the second queue was created. This is known as the exception Queue (exception). If AQ cannot receive messages from our queue, it is logged in the exception queue.

When a message is processed more than once, the error is automatically transferred to the exception queue, and the author has not found the appropriate wording for the exception queue, because the scenario I use does not require that the message be handled one-on-one, as long as the notification is useful. So if the message is transferred to the exception queue, you can run the data in the empty queue table

delete from demo_queue_table;
4. Stopping and deleting a queue

If you need to delete or rebuild, you can do so using the following methods:

BEGIN   DBMS_AQADM.STOP_QUEUE(      queue_name => ‘demo_queue‘      );   DBMS_AQADM.DROP_QUEUE(      queue_name => ‘demo_queue‘      );   DBMS_AQADM.DROP_QUEUE_TABLE(      queue_table => ‘demo_queue_table‘      );END;
5. Queue News

The into row operation is a basic transaction (like an INSERT into a queue table), so we need to commit.

declare  r_enqueue_options DBMS_AQ.ENQUEUE_OPTIONS_T;  r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;  v_message_handle RAW(16);  o_payload demo_queue_payload_type;begin  o_payload := demo_queue_payload_type(‘what is you name ?‘);  dbms_aq.enqueue(    queue_name  => ‘demo_queue‘,    enqueue_options => r_enqueue_options,    message_properties => r_message_properties,    payload => o_payload,    msgid => v_message_handle  );  commit;end;

To see if a message is queued properly with an SQL statement:

select * from aq$demo_queue_table;select user_data from aq$demo_queue_table;
6. Message from the team

Using Oracle for the outbound operation, I did not experiment successfully (not sure whether it is related to dbms_output execution permissions), the code is as follows, the reader can debug:

declare  r_dequeue_options DBMS_AQ.DEQUEUE_OPTIONS_T;  r_message_properties DBMS_AQ.MESSAGE_PROPERTIES_T;  v_message_handle RAW(16);  o_payload demo_queue_payload_type;begin  DBMS_AQ.DEQUEUE(    queue_name => ‘demo_queue‘,    dequeue_options => r_dequeue_options,    message_properties => r_message_properties,    payload => o_payload,    msgid => v_message_handle  );  DBMS_OUTPUT.PUT_LINE(    ‘***** Browse message is [‘ || o_payload.message || ‘]****‘  );end;
Second, Java listens to and processes Oracle AQ queues using JMS

Java uses JMS for appropriate processing and requires the use of Oracle-provided jars, which can be found in the Oracle installation directory: You can use the Find command in Linux for lookups, such as

find `pwd‘jmscommon.jar‘

The required jars are:

    • App/oracle/product/12.1.0/dbhome_1/rdbms/jlib/jmscommon.jar
    • App/oracle/product/12.1.0/dbhome_1/jdbc/lib/ojdbc7.jar
    • App/oracle/product/12.1.0/dbhome_1/jlib/orai18n.jar
    • App/oracle/product/12.1.0/dbhome_1/jlib/jta.jar
    • App/oracle/product/12.1.0/dbhome_1/rdbms/jlib/aqapi_g.jar
1. Create a connection parameter class

In practice, parameter information can be configured in the properties file and injected using spring.

package org.kevin.jms;/** *  * @author 李文锴 *  连接参数信息 * */publicclass JmsConfig {    public"c##kevin";    public"a111111111";    public"jdbc:oracle:thin:@127.0.0.1:1521:orcl";    public"demo_queue";}
2. Create a Message transformation class

Because of the Oracle data type at the time of the message, you need to provide a conversion factory class to convert the Oracle type to Java type.

 PackageORG.KEVIN.JMS;ImportJava.sql.SQLException;ImportOracle.jdbc.driver.OracleConnection;ImportOracle.jdbc.internal.OracleTypes;ImportOracle.jpub.runtime.MutableStruct;ImportOracle.sql.CustomDatum;ImportOracle.sql.CustomDatumFactory;ImportOracle.sql.Datum;ImportOracle.sql.STRUCT;/** * * @author Li Wenxian * Data type conversion class * */@SuppressWarnings("Deprecation") Public  class queue_message_type implements customdatum, customdatumfactory  {     Public Static FinalString _sql_name ="Queue_message_type"; Public Static Final int_sql_typecode = oracletypes.struct; Mutablestruct _struct;//12 = string    Static int[] _sqltype = { A};Staticcustomdatumfactory[] _factory =Newcustomdatumfactory[1];Static FinalQueue_message_type _messagefactory =NewQueue_message_type (); Public StaticCustomdatumfactorygetfactory() {return_messagefactory; } Public Queue_message_type() {_struct =NewMutablestruct (Newobject[1], _sqltype, _factory); } PublicDatumtodatum(OracleConnection c)throwsSQLException {return_struct.todatum (c, _sql_name); } PublicCustomdatumCreate(Datum D,intSqlType)throwsSQLException {if(d = =NULL)return NULL; Queue_message_type o =NewQueue_message_type (); O._struct =NewMutablestruct (STRUCT) d, _sqltype, _factory);returnO } PublicStringgetcontent()throwsSQLException {return(String) _struct.getattribute (0); }}
3. Main class for message processing
 PackageORG.KEVIN.JMS;ImportJava.util.Properties;ImportJavax.jms.Message;ImportJavax.jms.MessageConsumer;ImportJavax.jms.MessageListener;ImportJavax.jms.Queue;ImportJavax.jms.QueueConnection;ImportJavax.jms.QueueConnectionFactory;ImportJavax.jms.Session;ImportOracle.jms.AQjmsAdtMessage;ImportOracle.jms.AQjmsDestination;ImportOracle.jms.AQjmsFactory;ImportOracle.jms.AQjmsSession;/** * * @author Li Wenxian Message Processing class * */ Public  class Main {     Public Static void Main(string[] args)throwsException {jmsconfig config =NewJmsconfig (); Queueconnectionfactory queueconnectionfactory = aqjmsfactory.getqueueconnectionfactory (CONFIG.JDBCURL,NewProperties ());        Queueconnection conn = queueconnectionfactory.createqueueconnection (Config.username, Config.password); Aqjmssession session = (aqjmssession) conn.createqueuesession (false, Session.auto_acknowledge);        Conn.start ();        Queue queue = (aqjmsdestination) session.getqueue (Config.username, config.queuename); Messageconsumer consumer = session.createconsumer (Queue,NULL, Queue_message_type.getfactory (),NULL,false); Consumer.setmessagelistener (NewMessageListener () {@Override             Public void OnMessage(Message message) {System.out.println ("OK"); Aqjmsadtmessage adtmessage = (aqjmsadtmessage) message;Try{Queue_message_type payload = (Queue_message_type) adtmessage.getadtpayload ();                System.out.println (Payload.getcontent ()); }Catch(Exception e)                {E.printstacktrace ();        }            }        }); Thread.Sleep (1000000); }}

Queue up with an Oracle block and see the data in the Queues table when Java is not started. After starting Java, the console correctly outputs the message, and writes the message again through the Oracle program block, discovering that the console is handling the message correctly. The JMS listener in Java is not processed immediately, and there may be a time difference in seconds.

Third, monitoring table record changes notice Java

The following example creates a data table and then adds a trigger to the table, and when the data changes, the trigger calls the stored procedure to send a message to Oracle AQ and then uses Java JMS to process the message.

1. Create a table

Create a student table that contains username and age two sub-segments, where username is the VARCHAR2 type, age number type.

2. Create a stored procedure

Create the send_aq_msg stored procedure, because the DBMS packet is called in the stored procedure, and the System package executes in the stored procedure that requires authorization (authorization with the SYS user):

grant execute on dbms_aq to c##kevin;

Note The stored procedure contains a commit statement.

create  or  replace  PROCEDURE  send_aq_msg (Info in  VARCHAR2) as  r_ Enqueue_options Dbms_aq. enqueue_options_t;  R_message_properties Dbms_aq. message_properties_t; V_message_handle RAW (16); O_payload Demo_queue_payload_type; begin  o_payload: = Demo_queue_payload_type (info);  Dbms_aq.enqueue (queue_name = ' Demo_queue ', enqueue_options = r_enqueue_options, message_properties => ; R_message_properties, payload = o_payload, MsgId = V_message_handle); commit ;  end  send_aq_msg;  
3. Create a Trigger

Create a trigger in the student table that, if age=18, is queued when the data is written to or updated. You need to call a stored procedure to send a message, but the trigger cannot contain a commit statement, so you need to use pragma autonomous_transaction; declare free things:

 CREATE or REPLACE TRIGGER student_tr  after INSERT or  UPDATE of age  on STUDENT   for each  ROW declare< /c14>pragma autonomous_transaction; BEGINif : new.age =   send_aq_msg (: new.username);       End if;   END;

To perform an INSERT or update operation after the trigger is created:

insert into student (username,age) values (‘jack.lee.3k‘, 18);update student set age=18 where username=‘jack003‘;

Java JMS can handle messages correctly.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Monitoring Oracle AQ via JMS, triggering execution of Java programs as the database changes

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.