해당 에러는 다양한 경우에 발생하는 에러입니다.
일단 에러로그 투척
Caused by: org.springframework.amqp.support.converter.MessageConversionException: Failed to convert Message content
at org.springframework.amqp.support.converter.AbstractJackson2MessageConverter.doFromMessage(AbstractJackson2MessageConverter.java:350) ~[spring-amqp-2.4.5.jar:2.4.5]
at org.springframework.amqp.support.converter.AbstractJackson2MessageConverter.fromMessage(AbstractJackson2MessageConverter.java:309) ~[spring-amqp-2.4.5.jar:2.4.5]
at org.springframework.amqp.support.converter.AbstractJackson2MessageConverter.fromMessage(AbstractJackson2MessageConverter.java:292) ~[spring-amqp-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:342) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter$MessagingMessageConverterAdapter.extractPayload(MessagingMessageListenerAdapter.java:366) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.support.converter.MessagingMessageConverter.fromMessage(MessagingMessageConverter.java:132) ~[spring-amqp-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.toMessagingMessage(MessagingMessageListenerAdapter.java:243) ~[spring-rabbit-2.4.5.jar:2.4.5]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:146) ~[spring-rabbit-2.4.5.jar:2.4.5]
... 11 common frames omitted
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.lang.String` from Object value (token `JsonToken.START_OBJECT`)
그리고 그 해당 에러가 발생하는 코드입니다.
@RabbitListener(queues = "#{@syncQueue}")
public String received(String message) throws JsonProcessingException {
// ... 내용 생략
}
제가 커스텀한 큐로 메세지가 받는데 String 으로 conversion이 실패하여 에러가 발생하였습니다. Dto 객체로 값을 받으면 conversion이 실패하지 않습니다. 이유는 무엇일까요?
@RabbitListener 로 데이터를 받을 때 자동으로 메시지 컨버터가 작동하기 때문입니다.
RabbitListenerContainerFactory에 MessageConverter를 null로 지정해주면 메시지 컨버터가 작동하고 string 값으로 받을 수 있습니다.
MyQueueConfig.java
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@RequiredArgsConstructor
@Slf4j
public class SyncQueueConfig {
@Value("${rabbitmq.host}")
private String host;
@Value("${rabbitmq.port}")
private int port;
@Value("${rabbitmq.username}")
private String userName;
@Value("${rabbitmq.password}")
private String password;
private final Jackson2JsonMessageConverter messageConverter;
private final String exchangeName = "exchange.command.sync";
private final String routingKey = "myroutingKey";
private final String queueName = "queue.sync";
@Bean
public TopicExchange topicExchange() {
return new TopicExchange(exchangeName);
}
@Bean
public Queue syncQueue() {
return new Queue(queueName, true, false, false);
}
@Bean
public Binding syncBinding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(routingKey);
}
@Bean
public ConnectionFactory connectionFactory() {
var connectionFactory = new CachingConnectionFactory(host, port);
connectionFactory.setUsername(userName);
connectionFactory.setPassword(password);
return connectionFactory;
}
@Bean
public RabbitTemplate rabbitTemplate() {
var rabbitTemplate = new RabbitTemplate(connectionFactory());
rabbitTemplate.setMessageConverter(messageConverter);
return rabbitTemplate;
}
@Bean
public RabbitListenerContainerFactory<?> rabbitListenerContainerFactory() {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setMessageConverter(null);
return factory;
}
}
마지막 bean 설정을 추가해주면 됩니다.