개발노트

25.03.17 RabbitMQ message 직렬화 문제 해결 본문

TroubleShooting

25.03.17 RabbitMQ message 직렬화 문제 해결

ddong-kka 2025. 3. 17. 15:36

개요

order 와 product 간의 메시지를 주고 받는 과정에서 ListenerExecutionFailedException: Listener method could not be invoked with the incoming message

에러가 발생해 해결한 과정을 정리해본다.

 


 

Message

package com.devsquad10.product.application.dto.message;

import java.util.UUID;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@ToString
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class StockDecrementMessage {
	private UUID orderId;

	private UUID productId;

	private Integer quantity;

	private String errorType;
}

 

두 서비스간에 동일한 message dto를 가지고 이벤트를 처리한다

그러나 전달은 되지만 직렬화 문제가 발생하고있다.

 

문제 발생 원인

  • order 서비스에서 StockDecrementMessage를 전송했지만, product 서비스에서 이를 정상적으로 역직렬화하지 못해 ListenerExecutionFailedException 발생.
  • RabbitMQ는 기본적으로 메시지를 바이트 배열(byte[])로 전달하지만 현재 내가 보는 StockDecrementMessage 
    메시지는 JSON 직렬화 방식을 사용해야한다.
  • UUID 타입을 포함하는 DTO를 JSON으로 주고받기 위해 Jackson2JsonMessageConverter 설정이 필요하다.

해결

@Configuration
public class OrderApplicationQueueConfig {

	@Value("${message.exchange}")
	private String exchange;

	@Value("${message.queue.product}")
	private String queueProduct;

	@Bean
	public TopicExchange exchange() {
		return new TopicExchange(exchange);
	}

	@Bean
	public Queue queueProduct() {
		return new Queue(queueProduct);
	}

	@Bean
	public Binding bindingProduct() {
		return BindingBuilder.bind(queueProduct()).to(exchange()).with(queueProduct);
	}

	@Bean
	public Jackson2JsonMessageConverter producerJackson2MessageConverter() {
		return new Jackson2JsonMessageConverter();
	}
}

 

@Configuration
public class ProductApplicationQueueConfig {

	@Bean
	public Jackson2JsonMessageConverter producerJackson2MessageConverter() {
		return new Jackson2JsonMessageConverter();
	}
}

 

메시지를 주고 받은 양쪽 서비스의 rabbitmq 설정에 Jackson2JsonMessageConverter 를 빈으로 등록해줬다.

이제 결과를 확인해본다. 

 


결과 확인

 

@Slf4j
@RequiredArgsConstructor
@Component
public class ProductEndPoint {

	private final ProductService productService;

	@RabbitListener(queues = "${message.queue.product}")
	public void handleStockDecrementRequest(StockDecrementMessage stockDecrementMessage) {
		System.out.println("-------------------" + stockDecrementMessage.getQuantity());
	}
}

 

1235 를 message 객체 안의 quantity 값으로 전달 해보았다.

 

메시지 전달 성공

정상적으로 전달되어 성공했다!