diff --git a/database/starters/oracle-spring-boot-starter-samples/README.md b/database/starters/oracle-spring-boot-starter-samples/README.md index 60ba2c04..513ba375 100644 --- a/database/starters/oracle-spring-boot-starter-samples/README.md +++ b/database/starters/oracle-spring-boot-starter-samples/README.md @@ -2,20 +2,24 @@ The Oracle Database Spring Boot Samples module provides a suite of comprehensive Spring Boot sample applications designed to enable developers with example code for application development. -### [Oracle UCP with JPA Sample](./oracle-spring-boot-sample-ucp-jpa/README.md) +## [Oracle UCP with JPA Sample](./oracle-spring-boot-sample-ucp-jpa/README.md) The Oracle UCP with JPA sample application demonstrates how to use the Oracle Spring Boot Starter UCP with Spring Data JPA, connecting your Oracle Database with powerful ORM abstractions that facilitate rapid development, all while using the best connection pooling library for Oracle Database with Spring Boot. -### [JSON Relational Duality Views Sample](./oracle-spring-boot-sample-json-duality/README.md) +## [JSON Relational Duality Views Sample](./oracle-spring-boot-sample-json-duality/README.md) The JSON Relational Duality Views sample application demonstrates how to use the Oracle Spring Boot Starter JSON Collections with [JSON Relational Duality Views](https://docs.oracle.com/en/database/oracle/oracle-database/23/jsnvu/overview-json-relational-duality-views.html). JSON Relational Duality Views layer the advantages of JSON document-style database over existing relational data structures — Powerful JSON views with full CRUD capabilities can be created on relational database schemas, nesting related data into a single document with unified access. -### [Kafka Java Client for Oracle Database Transactional Event Queues Sample](./oracle-spring-boot-starter-okafka/README.md) +## [Kafka Java Client for Oracle Database Transactional Event Queues Sample](./oracle-spring-boot-starter-okafka/README.md) This sample application demonstrates how to use the Oracle Spring Boot Starter for the [Kafka Java Client for Oracle Database Transactional Event Queues](https://github.com/oracle/okafka) Using an in-database message broker like Oracle Database Transactional Event Queues eliminates the need for external message brokers, reduces overall network traffic, simplifying your overall application architecture — and the Kafka Java Client for Oracle Database Transactional Event Queues library enables developers to create applications for Oracle Database Transactional Event Queues using familiar Kafka APIs for messaging. -### [Oracle UCP using Wallet](./oracle-spring-boot-sample-wallet) +## [Oracle UCP using Wallet](./oracle-spring-boot-sample-wallet) -This sample application demonstrates how to connect to an Autonomous database using the Oracle Spring Boot Starter UCP and Oracle Spring Boot Starter Wallet all while using the best connection pooling library for Oracle Database with Spring Boot. \ No newline at end of file +This sample application demonstrates how to connect to an Autonomous database using the Oracle Spring Boot Starter UCP and Oracle Spring Boot Starter Wallet all while using the best connection pooling library for Oracle Database with Spring Boot. + +## [Oracle Transactional Event Queues Producer and Consumer Example](./oracle-spring-boot-starter-sample-txeventqjms/) + +This sample demonstrates how to use [Transactional Event Queues (TxEventQ)](https://docs.oracle.com/en/database/oracle/oracle-database/23/adque/aq-introduction.html) and JMS using the Oracle Spring Boot Starter AQJMS. The sample has a Consumer and a Producer application. The Producer application puts messages on a TxEventQ and the Consumer application listens on the TxEventQ using a JMSListener. diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/README.md b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/README.md new file mode 100644 index 00000000..a723f457 --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/README.md @@ -0,0 +1,65 @@ +# Oracle Transactional Event Queues (TxEventQ) Producer and Consumer Example + +[Transactional Event Queues (TxEventQ)](https://docs.oracle.com/en/database/oracle/oracle-database/23/adque/aq-introduction.html) is a messaging platform built into Oracle Database that is used for application workflows, microservices, and event-triggered actions. + +This sample demonstrates how to use [Transactional Event Queues (TxEventQ)](https://docs.oracle.com/en/database/oracle/oracle-database/23/adque/aq-introduction.html) and JMS using the Oracle Spring Boot Starter AQJMS. The sample has a Consumer and a Producer application. The Producer application puts messages on a TxEventQ and the Consumer application listens on the TxEventQ using a JMSListener. + +## Install an Oracle Database 23ai + +Install an Oracle Database 23ai. This sample is using a Docker Container but any Oracle Database 23ai will work. Install and start the database using the following command: + +```shell +docker run --name free23ai -d -p 1521:1521 -e ORACLE_PWD=Welcome12345 \ +container-registry.oracle.com/database/free:latest-lite +``` + +## Create user and the Transactional Event Queue (TxEventQ) + +Log into the database as the `SYS` user and run the SQL script `setup.sql` located in the `sql` directory. The script creates a user called `TESTUSER` and a TxEventQ called `my_txeventq`. + +## Start the Consumer application + +Open a terminal window and go to the `consumer` directory and run `mvn spring-boot:run`. This will start the Consumer application that will listen to the TxEventQ `my_txeventq`. + +## Start the Producer application + +Open a terminal window and go to the `producer` directory and run `mvn spring-boot:run`. This will start the Producer application which will send messaged to the TxEventQ `my_txeventq`. + +## Send a message + +Open a terminal window and execute the following command to send a message via the Producer `/api/v1/message` endpoint: + +```shell +curl -X POST http://localhost:8080/api/v1/message?message=MyMessage +``` + +The command returns the message `Message was sent successfully`. + +In the Producer terminal window you will get a notification that looks like this: + +```log +2024-11-01T14:07:40.549-05:00 INFO 94573 --- [producer] [nio-8080-exec-2] c.o.d.s.t.producer.service.Producer : Sending message: MyMessage to topic my_txeventq +``` + +In the Consumer terminal window you will get a notification that looks like this: + +```log +2024-11-01T14:07:40.548-05:00 INFO 94524 --- [consumer] [ntContainer#0-1] c.o.d.s.t.consumer.service.Consumer : Received message: MyMessage +``` + +## Configure your project to use Oracle Spring Boot Starter for TxEventQ and JMS + +To use Oracle Spring Boot Starter for TxEventQ and JMS for your Spring Boot application, add the following Maven dependency to your project: + +```xml + + com.oracle.database.spring + oracle-spring-boot-starter-aqjms + +``` + +or if you are using Gradle: + +```text +implementation 'com.oracle.database.spring:oracle-spring-boot-starter-aqjms:24.3.0' +``` diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/pom.xml b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/pom.xml new file mode 100644 index 00000000..39515699 --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/pom.xml @@ -0,0 +1,69 @@ + + + + + 4.0.0 + + oracle-spring-boot-starter-samples + com.oracle.database.spring + 24.3.0 + ../../pom.xml + + + oracle-spring-boot-sample-txeventqjms-consumer + 24.3.0 + + Oracle Spring Boot Starter - Transactional Event Queue JMS Sample + Oracle Spring Boot Starter - Transactional Event Queue JMS Sample + + + Oracle America, Inc. + https://www.oracle.com + + + + + Oracle + obaas_ww at oracle.com + Oracle America, Inc. + https://www.oracle.com + + + + + + The Universal Permissive License (UPL), Version 1.0 + https://oss.oracle.com/licenses/upl/ + repo + + + + + https://github.com/oracle/spring-cloud-oracle + scm:git:https://github.com/oracle/spring-cloud-oracle.git + scm:git:git@github.com:oracle/spring-cloud-oracle.git + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + com.oracle.database.spring + oracle-spring-boot-starter-aqjms + ${project.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/java/com/oracle/database/spring/txeventqjms/consumer/ConsumerApplication.java b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/java/com/oracle/database/spring/txeventqjms/consumer/ConsumerApplication.java new file mode 100644 index 00000000..bd4284bc --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/java/com/oracle/database/spring/txeventqjms/consumer/ConsumerApplication.java @@ -0,0 +1,13 @@ +package com.oracle.database.spring.txeventqjms.consumer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ConsumerApplication { + + public static void main(String[] args) { + SpringApplication.run(ConsumerApplication.class, args); + } + +} diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/java/com/oracle/database/spring/txeventqjms/consumer/service/Consumer.java b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/java/com/oracle/database/spring/txeventqjms/consumer/service/Consumer.java new file mode 100644 index 00000000..43de253d --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/java/com/oracle/database/spring/txeventqjms/consumer/service/Consumer.java @@ -0,0 +1,17 @@ +package com.oracle.database.spring.txeventqjms.consumer.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jms.annotation.JmsListener; +import org.springframework.stereotype.Service; + +@Service +public class Consumer { + + private static final Logger log = LoggerFactory.getLogger(Consumer.class); + + @JmsListener(destination = "${txeventq.topic.name}") + public void receiveMessage(String message) { + log.info("Received message: {}", message); + } +} diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/resources/application.yaml b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/resources/application.yaml new file mode 100644 index 00000000..3dee8018 --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/resources/application.yaml @@ -0,0 +1,20 @@ +spring: + application: + name: consumer + + datasource: + url: jdbc:oracle:thin:@//localhost:1521/freepdb1 + username: testuser + password: Welcome12345 + driver-class-name: oracle.jdbc.OracleDriver + type: oracle.ucp.jdbc.PoolDataSource + oracleucp: + connection-factory-class-name: oracle.jdbc.pool.OracleDataSource + connection-pool-name: ConsumerConnectionPool + initial-pool-size: 15 + min-pool-size: 10 + max-pool-size: 30 + +txeventq: + topic: + name: my_txeventq \ No newline at end of file diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/resources/banner.txt b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/resources/banner.txt new file mode 100644 index 00000000..1f0295c3 --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/consumer/src/main/resources/banner.txt @@ -0,0 +1,7 @@ + ____ + / ___|___ _ __ ___ _ _ _ __ ___ ___ _ __ + | | / _ \| '_ \/ __| | | | '_ ` _ \ / _ \ '__| + | |__| (_) | | | \__ \ |_| | | | | | | __/ | + \____\___/|_| |_|___/\__,_|_| |_| |_|\___|_| + +Powered by Spring Boot ${spring-boot.version} diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/pom.xml b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/pom.xml new file mode 100644 index 00000000..287ec3cb --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/pom.xml @@ -0,0 +1,73 @@ + + + + + 4.0.0 + + oracle-spring-boot-starter-samples + com.oracle.database.spring + 24.3.0 + ../../pom.xml + + + oracle-spring-boot-sample-txeventqjms-producer + 24.3.0 + + Oracle Spring Boot Starter - Transactional Event Queue JMS Sample + Oracle Spring Boot Starter - Transactional Event Queue JMS Sample + + + Oracle America, Inc. + https://www.oracle.com + + + + + Oracle + obaas_ww at oracle.com + Oracle America, Inc. + https://www.oracle.com + + + + + + The Universal Permissive License (UPL), Version 1.0 + https://oss.oracle.com/licenses/upl/ + repo + + + + + https://github.com/oracle/spring-cloud-oracle + scm:git:https://github.com/oracle/spring-cloud-oracle.git + scm:git:git@github.com:oracle/spring-cloud-oracle.git + + + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.springframework.boot + spring-boot-starter-web + + + com.oracle.database.spring + oracle-spring-boot-starter-aqjms + ${project.version} + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/java/com/oracle/database/spring/txeventq/producer/ProducerApplication.java b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/java/com/oracle/database/spring/txeventq/producer/ProducerApplication.java new file mode 100644 index 00000000..6b94f4b6 --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/java/com/oracle/database/spring/txeventq/producer/ProducerApplication.java @@ -0,0 +1,13 @@ +package com.oracle.database.spring.txeventq.producer; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ProducerApplication { + + public static void main(String[] args) { + SpringApplication.run(ProducerApplication.class, args); + } + +} diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/java/com/oracle/database/spring/txeventq/producer/controller/MessageController.java b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/java/com/oracle/database/spring/txeventq/producer/controller/MessageController.java new file mode 100644 index 00000000..6b109375 --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/java/com/oracle/database/spring/txeventq/producer/controller/MessageController.java @@ -0,0 +1,24 @@ +package com.oracle.database.spring.txeventq.producer.controller; + +import com.oracle.database.spring.txeventq.producer.service.Producer; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1") +public class MessageController { + Producer producer; + + public MessageController(Producer producer) { + this.producer = producer; + } + + @PostMapping("/message") + public String receiveMessage(@RequestParam("message") String message) { + producer.sendMessageToTopic(message); + return "Message was sent successfully"; + } +} + diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/java/com/oracle/database/spring/txeventq/producer/service/Producer.java b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/java/com/oracle/database/spring/txeventq/producer/service/Producer.java new file mode 100644 index 00000000..957f3a1a --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/java/com/oracle/database/spring/txeventq/producer/service/Producer.java @@ -0,0 +1,28 @@ +package com.oracle.database.spring.txeventq.producer.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.jms.core.JmsTemplate; + +@Service +public class Producer { + + private static final Logger log = LoggerFactory.getLogger(Producer.class); + + JmsTemplate jmsTemplate; + + @Value("${txeventq.topic.name}") + private String topic; + + public Producer(JmsTemplate jmsTemplate) { + this.jmsTemplate = jmsTemplate; + } + + public void sendMessageToTopic(String message) + { + jmsTemplate.convertAndSend(topic,message); + log.info("Sending message: {} to topic {}", message, topic); + } +} diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/resources/application.yaml b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/resources/application.yaml new file mode 100644 index 00000000..3e4ff324 --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/resources/application.yaml @@ -0,0 +1,20 @@ +spring: + application: + name: producer + + datasource: + url: jdbc:oracle:thin:@//localhost:1521/freepdb1 + username: testuser + password: Welcome12345 + driver-class-name: oracle.jdbc.OracleDriver + type: oracle.ucp.jdbc.PoolDataSource + oracleucp: + connection-factory-class-name: oracle.jdbc.pool.OracleDataSource + connection-pool-name: ConsumerConnectionPool + initial-pool-size: 15 + min-pool-size: 10 + max-pool-size: 30 + +txeventq: + topic: + name: my_txeventq \ No newline at end of file diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/resources/banner.txt b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/resources/banner.txt new file mode 100644 index 00000000..68f2c1a7 --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/producer/src/main/resources/banner.txt @@ -0,0 +1,7 @@ + ____ _ + | _ \ _ __ ___ __| |_ _ ___ ___ _ __ + | |_) | '__/ _ \ / _` | | | |/ __/ _ \ '__| + | __/| | | (_) | (_| | |_| | (_| __/ | + |_| |_| \___/ \__,_|\__,_|\___\___|_| + +Powered by Spring Boot ${spring-boot.version} diff --git a/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/sql/setup.sql b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/sql/setup.sql new file mode 100644 index 00000000..a580e5d5 --- /dev/null +++ b/database/starters/oracle-spring-boot-starter-samples/oracle-spring-boot-starter-sample-txeventqjms/sql/setup.sql @@ -0,0 +1,25 @@ +-- This must be executed as SYS +create user testuser identified by Welcome12345; +grant resource, connect, unlimited tablespace to testuser; +grant aq_user_role to testuser; +grant execute on dbms_aq to testuser; +grant execute on dbms_aqadm to testuser; +grant execute ON dbms_aqin TO testuser; +grant execute ON dbms_aqjms TO testuser; +grant execute on dbms_teqk to testuser; +commit; + +-- create the TEQ +begin + dbms_aqadm.create_transactional_event_queue( + queue_name => 'TESTUSER.MY_TXEVENTQ', + -- when mutiple_consumers is true, this will create a pub/sub "topic" - the default is false + multiple_consumers => false + ); + + -- start the TEQ + dbms_aqadm.start_queue( + queue_name => 'TESTUSER.MY_TXEVENTQ' + ); +end; +/