package org.springframework.amqp.samples.json;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.AnonymousQueue;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessagePropertiesBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
import org.springframework.amqp.support.converter.DefaultClassMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ParameterizedTypeReference;
@SpringBootApplication
public class Application {
private static final String INFERRED_FOO_QUEUE = "sample.inferred.foo";
private static final String INFERRED_BAR_QUEUE = "sample.inferred.bar";
private static final String RECEIVE_AND_CONVERT_QUEUE = "sample.receive.and.convert";
private static final String MAPPED_QUEUE = "sample.mapped";
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);
ctx.getBean(Application.class).runDemo();
ctx.close();
}
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private RabbitTemplate jsonRabbitTemplate;
@Autowired
private AmqpAdmin rabbitAdmin;
private volatile CountDownLatch latch = new CountDownLatch(2);
public void runDemo() throws Exception {
String json = "{\"foo\" : \"value\" }";
Message jsonMessage = MessageBuilder.withBody(json.getBytes())
.andProperties(MessagePropertiesBuilder.newInstance().setContentType("application/json")
.build()).build();
// inferred type
this.rabbitTemplate.send(INFERRED_FOO_QUEUE, jsonMessage);
this.rabbitTemplate.send(INFERRED_BAR_QUEUE, jsonMessage);
this.latch.await(10, TimeUnit.SECONDS);
// convertAndReceive with type
this.rabbitTemplate.send(RECEIVE_AND_CONVERT_QUEUE, jsonMessage);
this.rabbitTemplate.send(RECEIVE_AND_CONVERT_QUEUE, jsonMessage);
Foo foo = this.jsonRabbitTemplate.receiveAndConvert(RECEIVE_AND_CONVERT_QUEUE, 10_000,
new ParameterizedTypeReference<Foo>() { });
System.out.println("Expected a Foo, got a " + foo);
Bar bar = this.jsonRabbitTemplate.receiveAndConvert(RECEIVE_AND_CONVERT_QUEUE, 10_000,
new ParameterizedTypeReference<Bar>() { });
System.out.println("Expected a Bar, got a " + bar);
// Mapped type information with legacy POJO listener
this.latch = new CountDownLatch(2);
jsonMessage.getMessageProperties().setHeader("__TypeId__", "foo");
this.rabbitTemplate.send(MAPPED_QUEUE, jsonMessage);
jsonMessage.getMessageProperties().setHeader("__TypeId__", "bar");
this.rabbitTemplate.send(MAPPED_QUEUE, jsonMessage);
this.latch.await(10, TimeUnit.SECONDS);
this.rabbitAdmin.deleteQueue(RECEIVE_AND_CONVERT_QUEUE);
}
@RabbitListener(queues = INFERRED_FOO_QUEUE)
public void listenForAFoo(Foo foo) {
System.out.println("Expected a Foo, got a " + foo);
this.latch.countDown();
}
@RabbitListener(queues = INFERRED_BAR_QUEUE)
public void listenForAFoo(Bar bar) {
System.out.println("Expected a Bar, got a " + bar);
this.latch.countDown();
}
@Bean
public SimpleMessageListenerContainer legacyPojoListener(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setQueueNames(MAPPED_QUEUE);
MessageListenerAdapter messageListener = new MessageListenerAdapter(new Object() {
@SuppressWarnings("unused")
public void handleMessage(Object object) {
System.out.println("Got a " + object);
Application.this.latch.countDown();
}
});
Jackson2JsonMessageConverter jsonConverter = new Jackson2JsonMessageConverter();
jsonConverter.setClassMapper(classMapper());
messageListener.setMessageConverter(jsonConverter);
container.setMessageListener(messageListener);
return container;
}
@Bean
public DefaultClassMapper classMapper() {
DefaultClassMapper classMapper = new DefaultClassMapper();
Map<String, Class<?>> idClassMapping = new HashMap<>();
idClassMapping.put("foo", Foo.class);
idClassMapping.put("bar", Bar.class);
classMapper.setIdClassMapping(idClassMapping);
return classMapper;
}
@Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
return new RabbitTemplate(connectionFactory);
}
@Bean
public RabbitTemplate jsonRabbitTemplate(ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setMessageConverter(jsonConverter());
return template;
}
@Bean
public MessageConverter jsonConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public Queue inferredFoo() {
return new AnonymousQueue(() -> INFERRED_FOO_QUEUE);
}
@Bean
public Queue inferredBar() {
return new AnonymousQueue(() -> INFERRED_BAR_QUEUE);
}
@Bean
public Queue convertAndReceive() {
return new Queue(RECEIVE_AND_CONVERT_QUEUE);
}
@Bean
public Queue mapped() {
return new AnonymousQueue(() -> MAPPED_QUEUE);
}
public static class Foo {
private String foo;
public Foo() {
super();
}
public Foo(String foo) {
this.foo = foo;
}
public String getFoo() {
return this.foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
@Override
public String toString() {
return getClass().getSimpleName() + " [foo=" + this.foo + "]";
}
}
public static class Bar extends Foo {
public Bar() {
super();
}
public Bar(String foo) {
super(foo);
}
}
}