Spring 引导 JMS:当 JMS 接收器发生内部应用程序错误时如何不丢失 jms 消息

Spring boot JMS : How not to lose jms message when internal application error happens at the JMS receiver

如果JMS 接收方由于某些原因(例如数据库连接失败)而失败,那么JMS 消息将丢失。谁能建议我避免使用 spring 启动应用程序

丢失 JMS 消息的常见解决方案是什么

如果在接收端处理消息时出现错误,我是否应该将消息重新发送回其源队列?

这是我的场景源代码。

@SpringBootApplication
public class MainApp {

    public static void main(String[] args) {
        SpringApplication.run(MainApp.class, args);
    }

    @Bean
    public JmsListenerContainerFactory<?> sdbFactory(ConnectionFactory connectionFactory,
                                                    DefaultJmsListenerContainerFactoryConfigurer configurer) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        // This provides all boot's default to this factory, including the message converter
        configurer.configure(factory, connectionFactory);
        // You could still override some of Boot's default if necessary.
        return factory;
    }

    @Bean
    public Queue queue() {
        return new ActiveMQQueue("sdb.orderQueue");
    }



    @Bean
    public MessageConverter jacksonJmsMessageConverter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("_type");
        return converter;
    }

    @Bean
    public ModelMapper mapper() {
        ModelMapper mapper = new ModelMapper();
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
        return mapper;
    }

}

制作人

@RestController
@RequestMapping("/transaction")
public class OrderTransactionController {

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    private static final Logger LOGGER =
            LoggerFactory.getLogger(OrderTransactionController.class);

    @PostMapping("/send")
    public void send(@RequestBody OrderDTO order)  {
        LOGGER.info("Sending a transaction."+ order);
        jmsMessagingTemplate.convertAndSend("sdb.orderQueue", order);
    }
}

消费者

@Component
public class OrderMessageReceiver {

    @Autowired
    OrderService service;

    @Autowired
    ModelMapper modelMapper;

    @Autowired
    private JmsMessagingTemplate jmsMessagingTemplate;

    private static final Logger LOGGER =
            LoggerFactory.getLogger(OrderMessageReceiver.class);

    @JmsListener(destination = "sdb.orderQueue", containerFactory = "sdbFactory")
    public void receiveQueue(OrderDTO order) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        ModelMapper modelMapper = new ModelMapper();

        OrderEntity orderEntity = modelMapper.map(order, OrderEntity.class);
        try {
            service.createOrder(orderEntity);
        } catch (Exception e) {
            LOGGER.error("Error happend while trying to persist order : {} error is : {}",order, e);


        }
    }


}

您需要展示如何使用它以及配置,但默认情况下,DefaultMessageListenerContainer 会话将为 transacted 因此如果侦听器向容器抛出异常事务将回滚并将消息添加回队列。

如果侦听器正常退出,事务将提交并删除消息。