Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Oracle AQ #3425

Closed
lukaseder opened this issue Jul 18, 2014 · 0 comments
Closed

Add support for Oracle AQ #3425

lukaseder opened this issue Jul 18, 2014 · 0 comments

Comments

@lukaseder
Copy link
Member

Using our code generator, we should implement a couple of awesome features around Oracle AQ. It should be very easy to dequeue a message from such a queue.

SQL types:

CREATE OR REPLACE TYPE book_t AS OBJECT (
  ID         NUMBER(7),
  title      VARCHAR2(100 CHAR),
  language   VARCHAR2(2 CHAR)
);
/

CREATE OR REPLACE TYPE books_t AS VARRAY(32) OF book_t;
/

CREATE OR REPLACE TYPE author_t AS OBJECT (
  ID         NUMBER(7),
  first_name VARCHAR2(100 CHAR),
  last_name  VARCHAR2(100 CHAR),
  books      books_t
);
/

CREATE OR REPLACE TYPE authors_t AS VARRAY(32) OF author_t;
/

Queue config

BEGIN
  DBMS_AQADM.CREATE_QUEUE_TABLE(
    queue_table => 'new_author_aq_t',
    queue_payload_type => 'author_t'
  );

  DBMS_AQADM.CREATE_QUEUE(
    queue_name => 'new_author_aq',
    queue_table => 'new_author_aq_t'
  );

  DBMS_AQADM.START_QUEUE(
    queue_name => 'new_author_aq'
  );
  COMMIT;
END;
/

Generated AQ references:

@javax.annotation.Generated(value    = { "http://www.jooq.org", "3.5.0" },
                            comments = "This class is generated by jOOQ")
@java.lang.SuppressWarnings({ "all", "unchecked", "rawtypes" })
public class Queues {

    /**
     * The queue <code>SP.NEW_AUTHOR_AQ</code>
     */
    public static final Queue<AuthorTRecord> NEW_AUTHOR_AQ = 
        new QueueImpl<AuthorTRecord>("NEW_AUTHOR_AQ", SP, AUTHOR_T);
}

Usage:

    @Test
    public void testAQ() {
        AuthorTRecord payload = new AuthorTRecord();
        payload.setFirstName("Paulo");
        payload.setLastName("Coelho");
        DBMS_AQ.enqueue(dsl.configuration(), NEW_AUTHOR_AQ, payload);

        for (int i = 0; i < 10; i++) {
            // Blocking call here:
            AuthorTRecord author = DBMS_AQ.dequeue(dsl.configuration(), NEW_AUTHOR_AQ);

            System.out.println(author);
            BooksTRecord books = author.getBooks();
            if (books != null)
                for (BookTRecord book : books.get())
                    System.out.println(book);
        }
    }

Sample output:

"SP"."AUTHOR_T"(null, Paulo, Coelho, null)

"SP"."AUTHOR_T"(1, George, Orwell, SP.BOOKS_T("SP"."BOOK_T"(1, 1984, en), "SP"."BOOK_T"(2, Animal Farm, en)))
"SP"."BOOK_T"(1, 1984, en)
"SP"."BOOK_T"(2, Animal Farm, en)

Remarks

The serialisation and deserialisation of nested OBJECT and TABLE, VARRAY types already works out of the box with stored procedures, in jOOQ. What's new is the fact that:

  • AQ references are generated and reference the relevant payload OBJECT type
  • Blocking enqueue() and dequeue() calls will be made available to users

More usage examples:

@Test
public void testAQSimple() throws Exception {

    // Enqueue all authors
    authors.stream().forEach(a -> {
        DBMS_AQ.enqueue(dsl.configuration(), NEW_AUTHOR_AQ, a);
    });

    // Dequeue them again
    authors.stream().forEach(a -> {
        assertEquals(a, DBMS_AQ.dequeue(dsl.configuration(), NEW_AUTHOR_AQ));
    });
}

@Test
public void testAQTransactions() throws Exception {
    dsl.transaction((ctx) -> {

        ENQUEUE_OPTIONS_T enq = new ENQUEUE_OPTIONS_T().visibility(IMMEDIATE);

        // Enqueue two authors
        DBMS_AQ.enqueue(dsl.configuration(), NEW_AUTHOR_AQ, authors.get(0), enq);
        DBMS_AQ.enqueue(dsl.configuration(), NEW_AUTHOR_AQ, authors.get(1), enq);

        // Dequeue them again
        DEQUEUE_OPTIONS_T deq = new DEQUEUE_OPTIONS_T().wait(NO_WAIT);

        assertEquals(authors.get(0), DBMS_AQ.dequeue(dsl.configuration(), NEW_AUTHOR_AQ, deq));
        assertEquals(authors.get(1), DBMS_AQ.dequeue(dsl.configuration(), NEW_AUTHOR_AQ, deq));

        // The queue is empty, this should fail
        assertThrows(DataAccessException.class, () -> {
            DBMS_AQ.dequeue(dsl.configuration(), NEW_AUTHOR_AQ, deq);
        });
    });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant