Почему AmqpChannelFactoryBean с Jackson2JsonMessageConverter не является типом хранилища?
Я пытаюсь использовать интеграцию Spring с RabbitMQ, используя поддерживаемые RabbitMQ каналы интеграции Spring. (Что кажется почти не задокументированным по какой-то причине, это новое?).
Для этого, кажется, я могу использовать AmqpChannelFactoryBean для создания канала. Чтобы настроить преобразование сообщений, я использую Jackson2JsonMessageConverter.
Когда я использую GenericMessage с полезной нагрузкой POJO, он отказывается десериализовать его из Java, в основном потому, что не знает тип. Я бы ожидал, что тип будет автоматически помещен в заголовок, но в заголовке есть только __TypeId__=org.springframework.messaging.support.GenericMessage
,
При загрузке Spring мой класс конфигурации выглядит так:
@Configuration
public class IntegrationConfiguration {
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public AmqpChannelFactoryBean myActivateOutChannel(CachingConnectionFactory connectionFactory,
MessageConverter messageConverter) {
AmqpChannelFactoryBean factoryBean = new AmqpChannelFactoryBean(true);
factoryBean.setConnectionFactory(connectionFactory);
factoryBean.setQueueName("myActivateOut");
factoryBean.setPubSub(false);
factoryBean.setAcknowledgeMode(AcknowledgeMode.AUTO);
factoryBean.setDefaultDeliveryMode(MessageDeliveryMode.PERSISTENT);
factoryBean.setMessageConverter(messageConverter);
return factoryBean;
}
@Bean
@ServiceActivator(inputChannel = "bsnkActivateOutChannel", autoStartup="true")
public MessageHandler mqttOutbound() {
return m -> System.out.println(m);
}
}
Отправка производится так:
private final MessageChannel myActivateOutChannel;
@Autowired
public MySender(MessageChannel myActivateOutChannel) {
this.myActivateOutChannel = myActivateOutChannel;
}
@Override
public void run(ApplicationArguments args) throws Exception {
MyPojo pojo = new MyPojo();
Message<MyPojo> msg = new GenericMessage<>(pojo);
myActivateOutChannel.send(msg);
}
Если я установлю свой собственный класс, все будет работать как надо. Но мне пришлось бы использовать много MessageConverters, если бы я настраивал подобные вещи. Например
converter.setClassMapper(new ClassMapper() {
@Override
public void fromClass(Class< ? > clazz, MessageProperties properties) {
}
@Override
public Class< ? > toClass(MessageProperties properties) {
return MyPojo.class;
}
});
Я использую это неправильно? Я что-то пропустил? Любые другие предложения?
Спасибо!!:)
Примечание. Если взглянуть больше на вещи, я предполагаю, что "интеграция Spring" будет заключаться в добавлении преобразователя JSON интеграции Spring с каждой стороны, что означает также добавление двух дополнительных прямых каналов в очередь RabbitMQ? Мне кажется, что это неправильно, так как у меня есть тройные каналы (6! Для входа / выхода), но, может быть, именно так предполагается использовать фреймворк? Соедините все простые шаги с прямыми каналами? (Сохраняю ли я постоянство, которое предлагают каналы RabbitMQ в этом случае? Или мне нужен какой-нибудь механизм транзакций, если я этого хочу? Или это присуще тому, как работают прямые каналы?)
Я также заметил, что теперь есть SpringConverter MessageConverter и Spring-amqp MessageConverter. Последний, который я использовал. Будет ли другой работать так, как я хочу? Быстрый взгляд на код показывает, что он не хранит тип объекта в заголовке сообщения?
1 ответ
До версии 4.3 каналы с поддержкой amqp поддерживали только сериализуемые полезные нагрузки; обходной путь заключался в том, чтобы вместо этого использовать канальные адаптеры (которые поддерживают отображение).
INT-3975 представил новое свойство extractPayload
что приводит к тому, что заголовки сообщений сопоставляются с заголовками rabbitmq, а тело сообщения - это просто полезная нагрузка вместо сериализованного GenericMessage
,
настройка extractPayload
Истина должна решить вашу проблему.