Spring JMS
Java Message Service (JMS) is an API that provides a standardized way for Java applications to create, send, receive, and read messages in messaging systems. Spring JMS uses idiomatic APIs to produce and consume messages with JMS, using the JMSTemplate class and @JMSListener annotations for producers and consumers, respectively.
In this section, we’ll implement a producer/consumer example using Spring JMS with Oracle Database Transactional Event Queues JMS APIs.
- Project Dependencies
- Configure Permissions and Create a JMS Queue
- Connect Spring JMS to Oracle Database
- JMSTemplate Producer
- Receive messages with @JMSListener
Project Dependencies
To start developing with Spring JMS for Oracle Database Transactional Event Queues, add the oracle-spring-boot-starter-aqjms dependency to your Maven project, along with the Spring Boot JDBC starter:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>com.oracle.database.spring</groupId>
<artifactId>oracle-spring-boot-starter-aqjms</artifactId>
<version>${oracle-database-starters.version}</version>
</dependency>
For Gradle users, add the following dependency to your project:
implementation "org.springframework.boot:spring-boot-starter-data-jdbc:${springBootVersion}"
implementation "com.oracle.database.spring:oracle-spring-boot-starter-aqjms:${oracleDatabaseStartersVersion}"
Configure Permissions and Create a JMS Queue
The following SQL script grants the necessary permissions to a database user for using Transactional Event Queues with JMS and creates a Transactional Event Queue with a JMS Payload Type for the user:
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;
begin
-- Create a JMS queue
dbms_aqadm.create_transactional_event_queue(
queue_name => 'testuser.testqueue',
queue_payload_type => DBMS_AQADM.JMS_TYPE,
-- FALSE means queues can only have one consumer for each message. This is the default.
-- TRUE means queues created in the table can have multiple consumers for each message.
multiple_consumers => false
);
-- Start the queue
dbms_aqadm.start_queue(
queue_name => 'testuser.testqueue'
);
end;
/
Connect Spring JMS to Oracle Database
Spring JMS with Oracle Database Transactional Event Queues uses a standard Oracle Database JDBC connection for message production and consumption. To configure this with YAML-style Spring datasource properties, it’ll look something like this (src/main/resources/application.yaml
):
spring:
datasource:
username: ${USERNAME}
password: ${PASSWORD}
url: ${JDBC_URL}
driver-class-name: oracle.jdbc.OracleDriver
type: oracle.ucp.jdbc.PoolDataSourceImpl
oracleucp:
initial-pool-size: 1
min-pool-size: 1
max-pool-size: 30
connection-pool-name: UCPSampleApplication
connection-factory-class-name: oracle.jdbc.pool.OracleDataSource
Additionally, you should define a JMS ConnectionFactory bean using the AQjmsFactory class. The ConnectionFactory bean ensures Spring JMS uses Oracle Database Transactional Event Queues as the JMS provider for message operations.
@Bean
public ConnectionFactory aqJmsConnectionFactory(DataSource ds) throws JMSException {
return AQjmsFactory.getConnectionFactory(ds);
}
JMSTemplate Producer
The Spring JMSTemplate bean provides an interface for JMS operations, including producing and consuming messages. The following class uses the jmsTemplate.convertAndSend()
method to produce a message to a queue.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;
@Component
public class Producer {
private final JmsTemplate jmsTemplate;
private final String queueName;
public Producer(JmsTemplate jmsTemplate,
@Value("${txeventq.queue.name:testqueue}") String queueName) {
this.jmsTemplate = jmsTemplate;
this.queueName = queueName;
}
public void enqueue(String message) {
jmsTemplate.convertAndSend(queueName, message);
}
}
Receive messages with @JMSListener
The @JMSListener
annotation may be applied to a method to configure a receiver for messages from a JMS queue.
The following class uses the @JMSListener annotation to read messages from a queue named testqueue
, printing each message to stdout.
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;
@Component
public class Consumer {
@JmsListener(destination = "${txeventq.queue.name:testqueue}", id = "sampleConsumer")
public void receiveMessage(String message) {
System.out.printf("Received message: %s%n", message);
}
}