I have two queues and they each have messages on them. Queue one has bird objects and queue two has birdspotting object. I'm using a defaultclassmapper to convert the messages back into objects. Is there a way for me to add different configurations on both my rabbitlisteners.
My listeners.
@Qualifier("bird")
@RabbitListener(queues = "vogels")
public void receiveBird(Bird in)
BirdSpotting birdSpotting = new BirdSpotting();
birdSpotting.setBird(in);
rabbitTemplate.convertAndSend("vogelspottings",birdSpotting);
}
@Qualifier("birdspotting")
@RabbitListener(queues = "vogelspottingmetlocatie")
public void receiveBirdWithLocation(BirdSpotting birdSpotting){
service.saveBirdSpotting(birdSpotting);
}
My configuration class.
@Configuration
@EnableRabbit
public class RabbitConf2 implements RabbitListenerConfigurer {
@Autowired
DefaultClassMapper mapper;
@Bean
public MappingJackson2MessageConverter consumerJackson2MessageConverter() {
return new MappingJackson2MessageConverter();
}
@Bean
public DefaultMessageHandlerMethodFactory messageHandlerMethodFactory() {
DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
factory.setMessageConverter(consumerJackson2MessageConverter());
return factory;
}
@Override
public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
registrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory());
}
@Bean
public RabbitTemplate rabbitTemplateService2(final ConnectionFactory connectionFactory) {
final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(producerJackson2MessageConverterService2());
return rabbitTemplate;
}
@Bean
public Jackson2JsonMessageConverter producerJackson2MessageConverterService2() {
final Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
jackson2JsonMessageConverter.setClassMapper(mapper);
return jackson2JsonMessageConverter;
}
My two defaultclassmappers for both queues:
@Bean(value = "bird")
public DefaultClassMapper classMapperService2() {
DefaultClassMapper classMapper = new DefaultClassMapper();
Map<String, Class<?>> idClassMapping = new HashMap<>();
idClassMapping.put("be.kdg.birdgeneratorservice.Bird", Bird.class);
classMapper.setIdClassMapping(idClassMapping);
return classMapper;
}
@Bean(value = "birdspotting")
public DefaultClassMapper classMapperService3() {
DefaultClassMapper classMapper = new DefaultClassMapper();
Map<String, Class<?>> idClassMapping = new HashMap<>();
idClassMapping.put("be.kdg.locationservice.BirdSpotting", BirdSpotting.class);
classMapper.setIdClassMapping(idClassMapping);
return classMapper;
}
You need to introduce one more RabbitListenerContainerFactory
bean with an appropriate configuration and use its name from the second @RabbitListener
:
/**
* The bean name of the {@link org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory}
* to use to create the message listener container responsible to serve this endpoint.
* <p>If not specified, the default container factory is used, if any.
* @return the {@link org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory}
* bean name.
*/
String containerFactory() default "";
This way you will distinguish a default one provided by the Spring Boot and will have your own custom for another use-case.
See more info in the Docs: https://docs.spring.io/spring-amqp/docs/2.1.4.RELEASE/reference/#async-annotation-driven