When working with messaging (Queue/Topic) applications based on AWS SQS, it is often desirable to run sandbox (local development machine) at parity with the real environment. Since it is operationally challenging to create AWS SQS resources from both costing and planning perspectives, what usually ends up happening is that local instances of applications (producers and consumers) start using the same queue as those by the deployed instances (usually dev). This leads to many problems including the most obvious one where messages are processed by random listeners.
This can easily be solved by declaring conditional beans in spring and swapping the JMS provider based on properties (e.g. spring profile)
Here's a before-
//App A (producer)
@Configuration
public class JMSConfig {
@Bean
public DefaultJmsListenerContainerFactory factory(){
//create SQSConnectionFactory
}
}
//App B (consumer
public class JMSConfig {
@Bean
public DefaultJmsListenerContainerFactory factory(){
//create SQSConnectionFactory
}
}After-
//App A (producer)
@Configuration
@Profile("!sanbox")
public class JMSConfig {
@Bean
public DefaultJmsListenerContainerFactory factory(){
//create SQSConnectionFactory
}
}
@Configuration
@Profile("sanbox")
public class JMSConfigActiveMQ {
@Bean
public DefaultJmsListenerContainerFactory factory(){
//create ActiveMQConnectionFactory
}
@Bean
public BrokerService broker() throws Exception {
BrokerService broker = new BrokerService();
broker.setPersistent(false);
broker.setUseJmx(true);
broker.addConnector("tcp://localhost:61616");
return broker;
}
}
}
//App B (consumer
public class JMSConfig {
@Bean
public DefaultJmsListenerContainerFactory factory(){
//create SQSConnectionFactory
}
}
@Configuration
@Profile("sanbox")
public class JMSConfigActiveMQ {
@Bean
public DefaultJmsListenerContainerFactory factory(){
//create ActiveMQConnectionFactory
}
}Note that BrokerService should be created in one of the applications (producer or consumer).