概述


对事务机制进行测试。

测试实例


测试实例 结果预测
发送正常 3条消息入队
发送异常 0条消息入队
接收正常 3条消息出队
接收异常 0条消息出队

demo设计


设计图

测试分工

测试类 测试方法
TransactedProducer.java
- 测试发送
sendNormal():void
- 测试“发送正常”
sendIntentional():void
- 测试“发送异常”
TransactedConsumer.java
- 测试接收
receiveNormal():void
- 测试“接收正常”
receiveIntentional():void
- 测试“接收异常”

测试步骤和结果


1.测试发送

1.1.测试发送正常

测试步骤
  1. 在ActiveMQ管理页面,删除example.queue
    - 如果存在就删除
  2. 运行TransactedProducer#sendNormal()
    - 发送消息到example.queue
  3. 查看ActiveMQ管理页面
    - example.queue中有3条消息入队
测试结果
符合预期。

1.2.测试发送异常

测试步骤
  1. 在ActiveMQ管理页面,删除example.queue
    - 如果存在就删除
  2. 运行TransactedProducer#sendIntentional()
    - 发送消息到example.queue
  3. 查看控制台和ActiveMQ管理页面
    - 控制台有异常抛出
    - example.queue中入队消息0
测试结果
符合预期。

2.测试接收

2.1.测试接收正常

测试步骤
  1. 在ActiveMQ管理页面,删除example.queue
    - 如果存在就删除
  2. 运行TransactedProducer#sendNormal()
    - 发送消息到example.queue
  3. 查看ActiveMQ管理页面
    - example.queue中有3条消息入队
  4. 运行TransactedConsumer#receiveNormal()
    - 从example.queue中接收消息
  5. 查看控制台和ActiveMQ管理页面
    - 控制台打印出3条信息
    - 管理页面看到example.queue中的3条消息出队
测试结果
符合预期。

2.2.测试接收异常

测试步骤
  1. 在ActiveMQ管理页面,删除example.queue
    - 如果存在就删除
  2. 运行TransactedProducer#sendNormal()
    - 发送消息到example.queue
  3. 查看ActiveMQ管理页面
    - example.queue中有3条消息入队
  4. 运行TransactedConsumer#receiveIntentional()
    - 从example.queue中接收消息
  5. 查看控制台和ActiveMQ管理页面
    - 控制台打印出3条消息和异常信息
    - 管理页面看到example.queue中出队消息0条
测试结果
符合预期。

代码


文件目录结构

jms-producer
|---- src/main/resources/
|---- jndi.properties
|---- src/main/java/
|---- cn.sinobest.asj.producer.jms.transaction
|---- TransactedProducer.java # 测试发送
jms-consumer
|---- src/main/resources/
|---- jndi.properties # 和jms-producer中的jndi.properties一致
|---- src/main/java/
|---- cn.sinobest.asj.consumer.jms.transaction
|---- TransactedConsumer.java # 测试接收

文件内容

1.jndi.propertie

 java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory

 # use the following property to configure the default connector
java.naming.provider.url=tcp://localhost:61616 # register some queues in JNDI using the form
# queue.[jndiName] = [physicalName]
queue.exampleQueue=example.queue # register some topics in JNDI using the form
# topic.[jndiName] = [physicalName]
topic.exampleTopic=example.topic

2.TransactedProducer.java

 package cn.sinobest.asj.producer.jms.transaction;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.junit.Test;
/**
* 事务的生产者.<br>
* 测试发送正常和发送异常.
* @author lijinlong
*
*/
public class TransactedProducer {
/** JNDI name for ConnectionFactory */
static final String CONNECTION_FACTORY_JNDI_NAME = "ConnectionFactory";
/** JNDI name for Queue Destination (use for PTP Mode) */
static final String QUEUE_JNDI_NAME = "exampleQueue"; /** 是否故意异常 */
boolean intentional = false; /**
* 测试发送正常.
*/
@Test
public void sendNormal() {
this.intentional = false;
send(QUEUE_JNDI_NAME);
} /**
* 测试发送异常.
*/
@Test
public void sendIntentional() {
this.intentional = true;
send(QUEUE_JNDI_NAME);
} /**
* 是否故意抛出异常.<br>
* 如果不抛出异常,会有3条消息入队;否则没有消息入队.
* @return
*/
private boolean isIntentional() {
return intentional;
} /**
* 发送到指定的目的地.
*
* @param destJndiName
* 目的地的JNDI name.
*/
private void send(String destJndiName) {
Context jndiContext = null;
ConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
Destination destination = null;
MessageProducer producer = null;
// create a JNDI API IntialContext object
try {
jndiContext = new InitialContext();
} catch (NamingException e) {
System.out.println("Could not create JNDI Context:"
+ e.getMessage());
System.exit(1);
}
// look up ConnectionFactory and Destination
try {
connectionFactory = (ConnectionFactory) jndiContext
.lookup(CONNECTION_FACTORY_JNDI_NAME);
destination = (Destination) jndiContext.lookup(destJndiName);
} catch (NamingException e) {
System.out.println("JNDI look up failed:" + e.getMessage());
System.exit(1);
}
// send Messages and finally release the resources.
try {
connection = connectionFactory.createConnection();
session = connection.createSession(Boolean.TRUE,
Session.SESSION_TRANSACTED);
producer = session.createProducer(destination); TextMessage message = session.createTextMessage();
for (int i = 0; i < 3; i++) {
message.setText(String.format("This is the %dth message.",
i + 1));
producer.send(message);
} if (isIntentional()) {
throw new JMSException("这是一个故意抛出的异常。");
} session.commit(); // 在最后提交
} catch (JMSException e) {
try {
session.rollback();
} catch (JMSException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
try {
if (session != null)
session.close();
if (connection != null)
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}

TransactedProducer.java

3.TransactedConsumer.java

 package cn.sinobest.asj.consumer.jms.transaction;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.junit.Test;
/**
* 事务的接收者.<br>
* 测试接收正常和接收异常.
* @author lijinlong
*
*/
public class TransactedConsumer {
/** JNDI name for ConnectionFactory */
static final String CONNECTION_FACTORY_JNDI_NAME = "ConnectionFactory";
/** JNDI name for Queue Destination (use for PTP Mode) */
static final String QUEUE_JNDI_NAME = "exampleQueue"; /** 是否故意异常 */
boolean intentional = false; @Test
public void receiveNormal() {
intentional = false;
receive(QUEUE_JNDI_NAME);
} @Test
public void receiveIntentional() {
intentional = true;
receive(QUEUE_JNDI_NAME);
} /**
* 是否故意抛出异常,以检查消息的出队情况.
* @return
*/
private boolean isIntentional() {
return intentional;
} /**
* 接收消息.<br>
*
* @param destJndiName
* 目的地的JNDI name.
*/
private void receive(String destJndiName) {
Context jndiContext = null;
ConnectionFactory connectionFactory = null;
Connection connection = null;
Session session = null;
Destination destination = null;
MessageConsumer consumer = null;
// create a JNDI API IntialContext object
try {
jndiContext = new InitialContext();
} catch (NamingException e) {
System.out.println("Could not create JNDI Context:"
+ e.getMessage());
System.exit(1);
}
// look up ConnectionFactory and Destination
try {
connectionFactory = (ConnectionFactory) jndiContext
.lookup(CONNECTION_FACTORY_JNDI_NAME);
destination = (Destination) jndiContext.lookup(destJndiName);
} catch (NamingException e) {
System.out.println("JNDI look up failed:" + e.getMessage());
System.exit(1);
}
// receive Messages and finally release the resources.
try {
connection = connectionFactory.createConnection();
connection.start(); // connection should be called in
// receiver-client
session = connection.createSession(Boolean.TRUE,
Session.SESSION_TRANSACTED);
consumer = session.createConsumer(destination); long timeout = 5 * 1000; // timeout:5 seconds
for (Message message = consumer.receive(timeout); message != null; message = consumer.receive(timeout)) {
String text = ((TextMessage) message).getText();
System.out.println(text);
} if (isIntentional()) {
throw new JMSException("这是一个故意抛出的异常。");
} session.commit();
} catch (JMSException e) {
try {
session.rollback();
} catch (JMSException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
try {
if (session != null)
session.close();
if (connection != null)
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
}
}

TransactedConsumer.java

AMQ学习笔记 - 17. 事务的测试的更多相关文章

  1. AMQ学习笔记 - 18. 持久化的测试

    概述 对持久化的有效性进行测试. 测试实例 测试实例 结果预测 持久化递送 重启ActiveMQ后,消息还在队列中 非持久化递送 重启ActiveMQ后,消息不在队列中 demo设计 jms-prod ...

  2. CUBRID学习笔记17 事务的回滚

    语法:ROLLBACK [ WORK ] 下面的语句会报错 ALTER TABLE code DROP s_name; INSERT INTO code (s_name, f_name) VALUES ...

  3. 软件测试之loadrunner学习笔记-01事务

    loadrunner学习笔记-01事务<转载至网络> 事务又称为Transaction,事务是一个点为了衡量某个action的性能,需要在开始和结束位置插入一个范围,定义这样一个事务. 作 ...

  4. Ext.Net学习笔记17:Ext.Net GridPanel Selection

    Ext.Net学习笔记17:Ext.Net GridPanel Selection 接下来是Ext.Net的GridPanel的另外一个功能:选择. 我们在GridPanel最开始的用法中已经见识过如 ...

  5. WCF学习笔记之事务编程

    WCF学习笔记之事务编程 一:WCF事务设置 事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元: WCF通过System.ServiceModel.TransactionFlowA ...

  6. SQL反模式学习笔记17 全文搜索

    目标:全文搜索 使用SQL搜索关键字,同时保证快速和精确,依旧是相当地困难. SQL的一个基本原理(以及SQL所继承的关系原理)就是一列中的单个数据是原子性的. 反模式:模式匹配 使用Like 或者正 ...

  7. golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍

    golang学习笔记17 爬虫技术路线图,python,java,nodejs,go语言,scrapy主流框架介绍 go语言爬虫框架:gocolly/colly,goquery,colly,chrom ...

  8. MySQL实战45讲学习笔记:事务隔离级别(第三讲)

    一.隔离性与隔离级别 1.事务的特性 原子性 一致性 隔离性 持久性 2.不同事务隔离级别的区别 读未提交:别人改数据的事务尚未提交,我在我的事务中也能读到.读已提交:别人改数据的事务已经提交,我在我 ...

  9. AMQ学习笔记 - 06. 可靠消息传送

    概述 本文介绍JMS中可能发生消息故障的3个隐患阶段,以及确保消息安全的3种保障机制. 故障分析 在介绍可靠传送的确保机制之前,先分析消息在传送的过程中可能在哪个阶段出现问题. 1.两个跃点 跃点的含 ...

随机推荐

  1. QoS 测量 (目标,方法,协议)

    本文翻译自ITU-T的Technical Paper:<How to increase QoS/QoE of IP-based platform(s) to regionally agreed ...

  2. $parse/$eval和$observe/$watch如何区分

    大家在看angular的时候,有时候偶尔会看到$parse,$eval和$observe,$watch这两对语法,随着深入使用angular,就不可避免使用到它.文章从内部运行机制跟实际需求的角度来解 ...

  3. Cocos2d html5 笔记 1: overview

    昨天接触到了cocos2d-html5的的东东了, 第一次看其源代码一头雾水,幸好samples目录下面有几个例子,可以从这个入手. MoonWarriors是一个射击类的游戏, 有点像以前玩的雷电, ...

  4. 0c-38-ARC快速入门

    2.ARC快速使用 int main(){ Student *s = [[Student alloc] init]; return 0; } 只需要写一行代码,编译器会在合适的位置释放学生对象,程序员 ...

  5. XCode4中的文本查找和文本替换功能

    转自:http://blog.csdn.net/zhuzhihai1988/article/details/7843186 1.如果是在打开的文档范围内:       查找: Command+ F   ...

  6. LeetCode23 Merge k Sorted Lists

    题意: Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexit ...

  7. WWH学习模式

    WWH是"What+Why+How"的简称,是对学习方法最完美的概括."如果不按照WWH这种模式来教学,90%的结果是老师没教好,学生学不好." 1.What( ...

  8. 探索多线程使用同一个数据库connection的后果

    在项目中看到有用到数据库的连接池,心里就思考着为什么需要数据库连接池,只用一个连接会造成什么影响?(只用一个connection)? 1  猜想:jdbc的事务是基于connection的,如果多线程 ...

  9. solr--搜索参数随笔

    1.默认搜索域.查询域的关系 qf字段的配置:query fields,指定solr从哪些field中搜索 在solrj中设置如下: params.setParam("qf", & ...

  10. spring mvc 接收页面表单List

    很少写博客,如果写的不好请多多包涵! 最近在用Spring mvc时遇到一个问题,在网上搜了很多资料.几乎没看到解决办法! 例如:当我们在做批量添加或者更新时,在Controller层接收表单数据的问 ...