Tiago Costa
Tiago Costa

Reputation: 1016

RabbitMQ not serialize message, error convert

I've seen some related questions here, but none worked for me, the rabbit will not serialize my message coming from another application.

Caused by: org.springframework.amqp.AmqpException: No method found for class [B

Below my configuration class to receive the messages.

@Configuration
public class RabbitConfiguration implements RabbitListenerConfigurer{

    public final static String EXCHANGE_NAME = "wallet-accounts"; 
    public final static String QUEUE_PAYMENT = "wallet-accounts.payment";
    public final static String QUEUE_RECHARGE = "wallet-accounts.recharge";

    @Bean
    public List<Declarable> ds() {
        return queues(QUEUE_PAYMENT, QUEUE_RECHARGE);
    }

    @Autowired
    private ConnectionFactory rabbitConnectionFactory;

    @Bean
    public AmqpAdmin amqpAdmin() {
        return new RabbitAdmin(rabbitConnectionFactory);
    }

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

    private List<Declarable> queues(String ... names){
        List<Declarable> result = new ArrayList<>();

        for (int i = 0; i < names.length; i++) {
            result.add(makeQueue(names[i]));
            result.add(makeBinding(names[i]));
        }
        return result;
    }

    private static Binding makeBinding(String queueName){
        return new Binding(queueName, DestinationType.QUEUE, EXCHANGE_NAME, queueName, null);
    }

    private static Queue makeQueue(String name){
        return new Queue(name);
    }

    @Bean
    public MappingJackson2MessageConverter jackson2Converter() {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        return converter;
    }

    @Bean
    public DefaultMessageHandlerMethodFactory myHandlerMethodFactory() {
        DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
        factory.setMessageConverter(jackson2Converter());
        return factory;
    }

    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
        registrar.setMessageHandlerMethodFactory(myHandlerMethodFactory());
    }
}

Using this other configuration, the error is almost the same:

Caused by: org.springframework.amqp.support.converter.MessageConversionException: failed to resolve class name. Class not found [br.com.beblue.wallet.payment.application.accounts.PaymentEntryCommand]

Configuration:

@Configuration
public class RabbitConfiguration {

    public final static String EXCHANGE_NAME = "wallet-accounts"; 

    public final static String QUEUE_PAYMENT = "wallet-accounts.payment";
    public final static String QUEUE_RECHARGE = "wallet-accounts.recharge";

    @Bean
    public List<Declarable> ds() {
        return queues(QUEUE_PAYMENT, QUEUE_RECHARGE);
    }

    @Autowired
    private ConnectionFactory rabbitConnectionFactory;

    @Bean
    public AmqpAdmin amqpAdmin() {
        return new RabbitAdmin(rabbitConnectionFactory);
    }

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

    @Bean
    public MessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    private List<Declarable> queues(String ... names){
        List<Declarable> result = new ArrayList<>();

        for (int i = 0; i < names.length; i++) {
            result.add(makeQueue(names[i]));
            result.add(makeBinding(names[i]));
        }
        return result;
    }

    private static Binding makeBinding(String queueName){
        return new Binding(queueName, DestinationType.QUEUE, EXCHANGE_NAME, queueName, null);
    }

    private static Queue makeQueue(String name){
        return new Queue(name);
    }
}

Can anyone tell me what's wrong with these settings, or what's missing?

Upvotes: 4

Views: 7833

Answers (1)

Artem Bilan
Artem Bilan

Reputation: 121177

No method found for class [B

Means there is a default SimpleMessageConverter which can't convert your incoming application/json. It is just not aware of that content-type and just falls back to the byte[] to return.

Class not found [br.com.beblue.wallet.payment.application.accounts.PaymentEntryCommand]

Means that Jackson2JsonMessageConverter can't convert your application/json because the incoming __TypeId__ header, representing class of the content, cannot be found in the local classpath.

Well, definitely your configuration for the DefaultMessageHandlerMethodFactory does not make sense for the AMQP conversion. You should consider to use SimpleRabbitListenerContainerFactory bean definition and its setMessageConverter. And yes, consider to inject the proper org.springframework.amqp.support.converter.MessageConverter implementation.

https://docs.spring.io/spring-amqp/docs/1.7.3.RELEASE/reference/html/_reference.html#async-annotation-conversion

From the Spring Boot perspective there is SimpleRabbitListenerContainerFactoryConfigurer to configure on the matter:

https://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/#boot-features-using-amqp-receiving

Upvotes: 4

Related Questions