JMS-Session事务管理

示例代码

web层

package com.example.demo.web;

import com.example.demo.service.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/customer")
public class CustomerResource {

    @Autowired
    private JmsTemplate jmsTemplate;
    @Autowired
    private CustomerService customerService;

    @PostMapping("/message1/listen")
    public void create(@RequestParam String msg) {
        jmsTemplate.convertAndSend("customer:msg1:new", msg);
    }

    @PostMapping("/message1/direct")
    public void handle(@RequestParam String msg) {
        customerService.handle(msg);
    }

    @GetMapping("/message")
    public String getMsg() {
        jmsTemplate.setReceiveTimeout(2000);
        Object reply = jmsTemplate.receiveAndConvert("customer:msg:reply");
        return String.valueOf(reply);
    }

}

service层

package com.example.demo.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;

@Service
public class CustomerService {

    private static final Logger logger = LoggerFactory.getLogger(CustomerService.class);

    @Autowired
    private JmsTemplate jmsTemplate;

    @JmsListener(destination = "customer:msg1:new")
    public void handle(String msg) {
        logger.info("Get msg1 : {}", msg);
        String reply = "Reply - " + msg;
        jmsTemplate.convertAndSend("customer:msg:reply", reply);
        if (msg.contains("error")) {
            simulateError();
        }
    }

    private void simulateError() {
        throw new RuntimeException("some Data error.");
    }

}

实验1 - controller层直接调service层的handle方法

  • 请求:
    http://localhost:6666/api/customer/message1/direct?msg=apple_error
  • 响应:
{
    "timestamp": 1530174516127,
    "status": 500,
    "error": "Internal Server Error",
    "exception": "java.lang.RuntimeException",
    "message": "some Data error.",
    "path": "/api/customer/message1/direct"
}
  • 查看消息是否发送到了customer:msg:reply:
    http://localhost:6666/api/customer/message
  • 结果:
Reply - apple_error

实验1结论:

  • 直接调service层的handle方法,session事务只存在于jmsTemplate.convertAndSend("customer:msg:reply", reply)中;
  • service的handle方法不存在事务;

实验2 - service层中的handle方法通过监听MQ中的消息被调用

  • 请求:
    http://localhost:6666/api/customer/message1/listen?msg=pineapple_error
  • 响应:
    service层handle方法重试了7次;
  • 查看消息是否发送到了customer:msg:reply:
    http://localhost:6666/api/customer/message
  • 结果:
null

实验2结论 :

  • 如果service层的handle方法是通过监听被调用,整个方法受session事务的控制,当方法出错,会重试7次,如果还出错,消息将被丢进死信队列,并不会发送到customer:msg:reply队列中;

你可能感兴趣的:(JMS-Session事务管理)