我们同时完成数据库和JMS处理是聪明还是幸运?
Is our simultaneous completion of database and JMS processing smart or lucky?
我们使用 JMS 在 Java 1.8 SE 环境中处理消息。消息源自 Oracle (12) 高级队列。
我们想从 JMS 队列中读取一条消息,根据它做一些工作,并将结果保存在数据库中。我们不想丢失任何消息,也不想重复处理任何消息。换句话说,我们希望 JMS 消息和关联数据库的处理 activity 成为单个事务。
我们已经阅读了有关如何执行此操作的各种文章(包括 Transaction and redelivery in JMS, JMS Message Delivery Reliability and Acknowledgement Patterns, Reliable JMS with Transactions)。共识似乎是使用 JTA/XA,但我们希望使用更简单的东西。
我们使用 Oracle 的 Advanced Queuing 作为我们的 JMS 提供程序,因此我们决定看看是否可以对 JMS 和数据库使用相同的数据库连接 activity,以便一次提交对两个 JMS 都有效和数据库 activity。好像有效果。
在下面的代码中,我们在初始化 JMS 队列时使用现有的 SQL 连接创建了一个 QueueConnection。处理消息后,提交 JMS 会话也会提交数据库更改。
我们还没有看到其他地方讨论过这种方法,所以我们想知道
- 我们有适用于 Oracle Advanced 的可靠解决方案
排队,
- 我们有一个解决方案恰好可以解决某些问题
该版本的 Oracle Advanced Queueing 的时间到了,
- 我们刚刚得到
我们的测试用例真的非常幸运,这种方法充满了问题
有危险
请评论我们的方法是否可靠或我们是否应该使用 JTA/XA。
public class OracleJmsQueue {
private DataSource dataSource;
protected Queue queue;
protected QueueConnection queueConnection;
protected QueueReceiver queueReceiver;
protected QueueSession queueSession;
private java.sql.Connection dbConnection = null;
protected void initQueueSession()
throws JMSException, SQLException {
// Connect to the database source of messages
DataSource dataSource = getDataSource();
dbConnection = dataSource.getConnection();
dbConnection.setAutoCommit(false);
queueConnection = AQjmsQueueConnectionFactory.createQueueConnection(
dbConnection);
queueSession =
queueConnection.createQueueSession(true, Session.SESSION_TRANSACTED);
queue = ((AQjmsSession)queueSession).getQueue(queueUser, queueName);
queueReceiver = queueSession.createReceiver(queue);
}
public void run() {
initQueueSession();
// code omitted
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(200);
final Message message = queueReceiver.receiveNoWait();
if (message != null) {
processMessage(message); // alters DB tables
commitSession();
}
}
// catches omitted
}
}
protected void commitSession() throws JMSException {
logger.info("Committing " + queueName + " queue session");
queueSession.commit();
}
} // class OracleJmsQueue
鉴于 processMessage
使用 dbConnection
class 属性,看来您对 JMS 和 OAQ 的假设是正确的。
https://docs.oracle.com/javaee/7/api/javax/jms/QueueConnection.html
所以,回答你的问题:是的,你有一个可靠的解决方案(假设我之前提到过)。
我们使用 JMS 在 Java 1.8 SE 环境中处理消息。消息源自 Oracle (12) 高级队列。
我们想从 JMS 队列中读取一条消息,根据它做一些工作,并将结果保存在数据库中。我们不想丢失任何消息,也不想重复处理任何消息。换句话说,我们希望 JMS 消息和关联数据库的处理 activity 成为单个事务。
我们已经阅读了有关如何执行此操作的各种文章(包括 Transaction and redelivery in JMS, JMS Message Delivery Reliability and Acknowledgement Patterns, Reliable JMS with Transactions)。共识似乎是使用 JTA/XA,但我们希望使用更简单的东西。
我们使用 Oracle 的 Advanced Queuing 作为我们的 JMS 提供程序,因此我们决定看看是否可以对 JMS 和数据库使用相同的数据库连接 activity,以便一次提交对两个 JMS 都有效和数据库 activity。好像有效果。
在下面的代码中,我们在初始化 JMS 队列时使用现有的 SQL 连接创建了一个 QueueConnection。处理消息后,提交 JMS 会话也会提交数据库更改。 我们还没有看到其他地方讨论过这种方法,所以我们想知道
- 我们有适用于 Oracle Advanced 的可靠解决方案 排队,
- 我们有一个解决方案恰好可以解决某些问题 该版本的 Oracle Advanced Queueing 的时间到了,
- 我们刚刚得到 我们的测试用例真的非常幸运,这种方法充满了问题 有危险
请评论我们的方法是否可靠或我们是否应该使用 JTA/XA。
public class OracleJmsQueue {
private DataSource dataSource;
protected Queue queue;
protected QueueConnection queueConnection;
protected QueueReceiver queueReceiver;
protected QueueSession queueSession;
private java.sql.Connection dbConnection = null;
protected void initQueueSession()
throws JMSException, SQLException {
// Connect to the database source of messages
DataSource dataSource = getDataSource();
dbConnection = dataSource.getConnection();
dbConnection.setAutoCommit(false);
queueConnection = AQjmsQueueConnectionFactory.createQueueConnection(
dbConnection);
queueSession =
queueConnection.createQueueSession(true, Session.SESSION_TRANSACTED);
queue = ((AQjmsSession)queueSession).getQueue(queueUser, queueName);
queueReceiver = queueSession.createReceiver(queue);
}
public void run() {
initQueueSession();
// code omitted
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(200);
final Message message = queueReceiver.receiveNoWait();
if (message != null) {
processMessage(message); // alters DB tables
commitSession();
}
}
// catches omitted
}
}
protected void commitSession() throws JMSException {
logger.info("Committing " + queueName + " queue session");
queueSession.commit();
}
} // class OracleJmsQueue
鉴于 processMessage
使用 dbConnection
class 属性,看来您对 JMS 和 OAQ 的假设是正确的。
https://docs.oracle.com/javaee/7/api/javax/jms/QueueConnection.html
所以,回答你的问题:是的,你有一个可靠的解决方案(假设我之前提到过)。