Reputation: 5646
If JMS receiver fails due to some reason like database connection failure, then JMS message will be lost. could anybody suggest me what is the common solution avoid losing JMS messages with spring boot application
Should I resend the message back to the queue where it originated in case of error while processing the message at the receiver end?
Here is my source code for the scenario.
@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;
}
}
producer
@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);
}
}
consumer
@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);
}
}
}
Upvotes: 0
Views: 2152
Reputation: 174759
You need to show how you are using it, together with configuration but, by default, with the DefaultMessageListenerContainer
the session will be transacted
so if the listener throws an exception to the container the transaction will roll back and the message added back to the queue.
If the listener exits normally, the transaction will commit and the message removed.
Upvotes: 1