rabbitmq is not creating queue automatically when spring boot publisher send msg ...
i did it this way so it is without manual configuration
and this is my configuration ///////rabbitmq is not creating queue automatically when spring boot publisher send msg ...
i did it this way so it is without manual configuration
and this is my configuration
package com.hariri_stocks.MQ;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
public class msgConfiguration {
public static final String ROUTING_KEY1 = "routingKey1";
public static final String STOCKS_EXCHANGE = "stocks_exchange";
public static final String STOCKS_QUEUE = "stocks_queue";
#Bean
public Queue queue() {
return new Queue(STOCKS_QUEUE , false);
}
#Bean
public TopicExchange exchange() {
return new TopicExchange(STOCKS_EXCHANGE );
}
#Bean
public Binding binding()
{
return BindingBuilder.bind(queue()).to(exchange()).with(ROUTING_KEY1);
}
#Bean
public MessageConverter converter()
{
return new Jackson2JsonMessageConverter();
}
#Bean
public AmqpTemplate template(ConnectionFactory cf) {
final RabbitTemplate rt = new RabbitTemplate(cf);
rt.setMessageConverter(converter());
return rt;
}
}
package com.hariri_stocks.MQ;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class Givver {
#Autowired
private RabbitTemplate template;
#GetMapping("/msg")
public String send() {
msgStatus m = new msgStatus("ok","damn");
template.convertSendAndReceive(msgConfiguration.STOCKS_EXCHANGE, msgConfiguration.ROUTING_KEY1,m);
return "ok";
}
}
enter image description here
spring.datasource.url=jdbc:mysql://localhost:3306/hariri_stocks
spring.datasource.username=root
spring.datasource.password=
spring.thymeleaf.enabled=true
spring.thymeleaf.check-template-location=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
server.port=9091
spring.application.name=hariri
Class msgConfiguration needs to be annotated with #Configuration for those beans to be added to the application context.
Also you don't need the template bean - Spring Boot will auto wire the converter bean into its auto-configured RabbitTemplate.
Related
I'm having a few issues with Spring Integration and the control bus. I need to turn auto-start off on an InboundChannelAdapter. However when I do this I can't get the ControlBus to start the channel adapter.
I've searched for an answer online, but most of the examples use XML configuration.
Here is the entirety of my code:
package com.example.springintegrationdemo;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.integration.annotation.InboundChannelAdapter;
import org.springframework.integration.annotation.Poller;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.config.ExpressionControlBusFactoryBean;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.file.FileReadingMessageSource;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.support.GenericMessage;
import java.io.File;
#SpringBootApplication
#EnableIntegration
public class SpringIntegrationDemoApplication {
#Bean
public MessageChannel fileChannel() {
return new DirectChannel();
}
#Bean(name = "fileMessageSource")
#InboundChannelAdapter(channel = "fileChannel", poller = #Poller(fixedDelay = "1000"),autoStartup = "false")
public MessageSource<File> fileMessageSource() {
FileReadingMessageSource fileReadingMessageSource = new FileReadingMessageSource();
fileReadingMessageSource.setDirectory(new File("lz"));
return fileReadingMessageSource;
}
#Bean
#ServiceActivator(inputChannel = "fileChannel")
public MessageHandler messageHandler() {
MessageHandler messageHandler = message -> {
File f = (File) message.getPayload();
System.out.println(f.getAbsolutePath());
};
return messageHandler;
}
#Bean
MessageChannel controlChannel() {
return new DirectChannel();
}
#Bean
#ServiceActivator(inputChannel = "controlChannel")
ExpressionControlBusFactoryBean controlBus() {
ExpressionControlBusFactoryBean expressionControlBusFactoryBean = new ExpressionControlBusFactoryBean();
return expressionControlBusFactoryBean;
}
#Bean
CommandLineRunner commandLineRunner(#Qualifier("controlChannel") MessageChannel controlChannel) {
return (String[] args)-> {
System.out.println("Starting incoming file adapter: ");
boolean sent = controlChannel.send(new GenericMessage<>("#fileMessageSource.start()"));
System.out.println("Sent control message successfully? " + sent);
while(System.in.available() == 0) {
Thread.sleep(50);
}
};
}
public static void main(String[] args) {
SpringApplication.run(SpringIntegrationDemoApplication.class, args);
}
}
The message is sent to the control bus component successfully, but the inbound channel adapter never starts.
I would appreciate any help.
Thanks,
Dave
See here: https://docs.spring.io/spring-integration/docs/current/reference/html/configuration.html#annotations_on_beans
The fileMessageSource bean name is exactly for the FileReadingMessageSource. A SourcePollingChannelAdapter created from the InboundChannelAdapter has this bean name: springIntegrationDemoApplication.fileMessageSource.inboundChannelAdapter.
The #EndpointId can help you to simplify it.
In other words: everything is OK with your config, only the problem that you don't use the proper endpoint id to start the SourcePollingChannelAdapter.
We were using Spring Boot 2.1.6.RELEASE.
after that we updated spring version to 2.2.2.RELEASE. When we change the version we noticed our quartz jobs not working. We have multiple jobs and we configured them like below. After some reasearch i found some differences between in QuartzAutoConfiguration class.
How can i inject my triggers in spring 2.2.2.RELEASE. Is there any easy way? I dont want to write to many triggers and trigger details.
MyConfig
import io.rkpc.commons.util.ApplicationReflectionUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
#Slf4j
#Configuration
#ConfigurationProperties(prefix = "quartz")
#Profile("quartz")
#Data
public class JobConfig {
private List<Job> jobs;
#Bean
public JobDetail[] jobDetail() throws SchedulerConfigException {
Set<Class<QuartzJobBean>> subClasses = ApplicationReflectionUtil.getSubClasses(QuartzJobBean.class, "io.rkpc");
List<JobDetail> jobDetails = new ArrayList<>();
for (Class<QuartzJobBean> quartzJobBeanClass : subClasses) {
Job job = getJob(quartzJobBeanClass.getSimpleName());
if (job.isEnabled()) {
JobDetail jobDetail = JobBuilder.newJob(quartzJobBeanClass)
.withIdentity(quartzJobBeanClass.getSimpleName())
.storeDurably()
.build();
jobDetails.add(jobDetail);
}
}
return jobDetails.toArray(new JobDetail[0]);
}
#Bean
public Trigger[] jobATrigger(JobDetail[] jobADetails) throws SchedulerConfigException {
List<Trigger> triggers = new ArrayList<>();
for (JobDetail jobDetail : jobADetails) {
Job job = getJob(jobDetail.getKey().getName());
CronTrigger trigger = TriggerBuilder.newTrigger().forJob(jobDetail)
.withIdentity(jobDetail.getKey().getName().concat("Trigger"))
.withSchedule(CronScheduleBuilder.cronSchedule(job.getCron()))
.build();
triggers.add(trigger);
}
return triggers.toArray(new Trigger[0]);
}
private Job getJob(String name) throws SchedulerConfigException {
List<Job> filteredJobs = jobs.stream().filter(job -> job.getName().equals(name)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(filteredJobs) || filteredJobs.size() > 1) {
log.error("{} is not configured", name);
throw new SchedulerConfigException("Job is not configured");
}
return filteredJobs.get(0);
}
#Data
public static class Job {
private String name;
private String cron;
private boolean enabled;
}
}
QuartzAutoConfiguration.java Spring version 2.1.6 github url ; https://github.com/spring-projects/spring-boot/blob/v2.1.6.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java
QuartzAutoConfiguration.java Spring version 2.2.2 github url https://github.com/spring-projects/spring-boot/blob/v2.2.2.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/quartz/QuartzAutoConfiguration.java
Main difference i notice is ; in 2.1.6 version Quartz AutoConfiguration was "Trigger" array but 2.2.2 doesn't have "Trigger" array.
Spring has always some magic :)
import io.rkpc.commons.util.ApplicationReflectionUtil;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.JobDetailImpl;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import javax.validation.constraints.NotNull;
import java.text.ParseException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
#Slf4j
#Configuration
#ConfigurationProperties(prefix = "quartz")
#Profile("quartz")
#Data
#AutoConfigureBefore({QuartzAutoConfiguration.class})
#RequiredArgsConstructor(onConstructor = #__({#Autowired, #NotNull}))
public class JobConfig {
private final List<Job> jobs;
private final DefaultListableBeanFactory beanFactory;
#PostConstruct
public void init() throws SchedulerConfigException, ParseException {
Set<Class<QuartzJobBean>> subClasses = ApplicationReflectionUtil.getSubClasses(QuartzJobBean.class, "io.rkpc");
for (Class<QuartzJobBean> quartzJobBeanClass : subClasses) {
Job job = getJob(quartzJobBeanClass.getSimpleName(), jobs);
if (job.isEnabled()) {
JobDetailImpl jobDetail = (JobDetailImpl) JobBuilder.newJob(quartzJobBeanClass)
.withIdentity(quartzJobBeanClass.getSimpleName())
.storeDurably()
.build();
CronTriggerImpl trigger = (CronTriggerImpl) TriggerBuilder.newTrigger().forJob(jobDetail)
.withIdentity(jobDetail.getKey().getName().concat("Trigger"))
.withSchedule(CronScheduleBuilder.cronSchedule(job.getCron()))
.build();
GenericBeanDefinition jobBeanDefinition = new GenericBeanDefinition();
jobBeanDefinition.setBeanClass(JobDetailImpl.class);
jobBeanDefinition.getPropertyValues().addPropertyValue("jobClass", quartzJobBeanClass);
jobBeanDefinition.getPropertyValues().addPropertyValue("key", jobDetail.getKey());
jobBeanDefinition.getPropertyValues().addPropertyValue("durability", jobDetail.isDurable());
beanFactory.registerBeanDefinition(quartzJobBeanClass.getSimpleName(), jobBeanDefinition);
GenericBeanDefinition triggerBeanDefinition = new GenericBeanDefinition();
triggerBeanDefinition.setBeanClass(CronTriggerImpl.class);
triggerBeanDefinition.getPropertyValues().addPropertyValue("jobKey", trigger.getJobKey());
triggerBeanDefinition.getPropertyValues().addPropertyValue("key", trigger.getKey());
triggerBeanDefinition.getPropertyValues().addPropertyValue("cronExpression", new CronExpression(trigger.getCronExpression()));
beanFactory.registerBeanDefinition(trigger.getName(), triggerBeanDefinition);
}
}
}
public Job getJob(String name, List<Job> jobs) throws SchedulerConfigException {
List<Job> filteredJobs = jobs.stream().filter(job -> job.getName().equals(name)).collect(Collectors.toList());
if (CollectionUtils.isEmpty(filteredJobs) || filteredJobs.size() > 1) {
log.error("{} is not configured", name);
throw new SchedulerConfigException("Job is not configured");
}
return filteredJobs.get(0);
}
#Data
public static class Job {
private String name;
private String cron;
private boolean enabled;
}
}
You are exposing a single Trigger[] bean rather than multiple Trigger beans. You should define one bean per Trigger. You should also do the same for each JobDetail. This was working by accident with Spring Boot 2.1.x as you were relying on the auto-configuration using ObjectProvider<Trigger[]>. The intent of the auto-configuration was to consume all Trigger beans, with the application context turning those beans into an array before injecting them.
If you don't want to define multiple Trigger and JobDetail beans, you may be better configuring the SchedulerFactoryBean yourself rather than relying on the auto-configuration.
I am trying to configure inbound and outbound adaptors as provided in the spring batch remote partitioning samples for Manager and worker beans. Having difficulty since they are configured in context of AMQPConnectionFactory.
However when I follow spring integration samples, there is no class which can provide Connection Factory. Help appreciated.
Below is sample code:-
import com.microsoft.azure.spring.integration.core.DefaultMessageHandler;
import com.microsoft.azure.spring.integration.core.api.CheckpointConfig;
import com.microsoft.azure.spring.integration.core.api.CheckpointMode;
import com.microsoft.azure.spring.integration.servicebus.inbound.ServiceBusQueueInboundChannelAdapter;
import com.microsoft.azure.spring.integration.servicebus.queue.ServiceBusQueueOperation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.integration.partition.RemotePartitioningManagerStepBuilderFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.util.concurrent.ListenableFutureCallback;
#Configuration
#IntegrationComponentScan
public class ManagerConfiguration {
private static final int GRID_SIZE = 3;
private static final String REQUEST_QUEUE_NAME = "digital.intg.batch.cm.request";
private static final String REPLY_QUEUE_NAME = "digital.intg.batch.cm.reply";
private static final String MANAGER_INPUT_CHANNEL = "manager.input";
private static final String MANGER_OUTPUT_CHANNEL = "manager.output";
private static final Log LOGGER = LogFactory.getLog(ManagerConfiguration.class);
private final JobBuilderFactory jobBuilderFactory;
private final RemotePartitioningManagerStepBuilderFactory managerStepBuilderFactory;
public ManagerConfiguration(JobBuilderFactory jobBuilderFactory,
RemotePartitioningManagerStepBuilderFactory managerStepBuilderFactory
) {
this.jobBuilderFactory = jobBuilderFactory;
this.managerStepBuilderFactory = managerStepBuilderFactory;
}
/*
* Configure outbound flow (requests going to workers)
*/
#Bean( name = MANGER_OUTPUT_CHANNEL )
public DirectChannel managerRequests() {
return new DirectChannel();
}
/*
* Configure inbound flow (replies coming from workers)
*/
#Bean( name = MANAGER_INPUT_CHANNEL )
public DirectChannel managerReplies() {
return new DirectChannel();
}
#Bean
public ServiceBusQueueInboundChannelAdapter managerQueueMessageChannelAdapter(
#Qualifier( MANAGER_INPUT_CHANNEL ) MessageChannel inputChannel, ServiceBusQueueOperation queueOperation) {
queueOperation.setCheckpointConfig(CheckpointConfig.builder().checkpointMode(CheckpointMode.MANUAL).build());
ServiceBusQueueInboundChannelAdapter adapter = new ServiceBusQueueInboundChannelAdapter(REPLY_QUEUE_NAME,
queueOperation);
adapter.setOutputChannel(inputChannel);
return adapter;
}
#Bean
#ServiceActivator( inputChannel = MANGER_OUTPUT_CHANNEL )
public MessageHandler managerQueueMessageSender(ServiceBusQueueOperation queueOperation) {
DefaultMessageHandler handler = new DefaultMessageHandler(REQUEST_QUEUE_NAME, queueOperation);
handler.setSendCallback(new ListenableFutureCallback<Void>() {
#Override
public void onSuccess(Void result) {
LOGGER.info("Manager Request Message was sent successfully.");
}
#Override
public void onFailure(Throwable ex) {
LOGGER.info("There was an error sending request message to worker.");
}
});
return handler;
}
#Bean
public IntegrationFlow managerOutboundFlow(MessageHandler managerQueueMessageSender) {
return IntegrationFlows
.from(managerRequests())
.handle(managerQueueMessageSender)
.get();
}
#Bean
public IntegrationFlow managerInboundFlow(ServiceBusQueueInboundChannelAdapter managerQueueMessageChannelAdapter) {
return IntegrationFlows
.from(managerQueueMessageChannelAdapter)
.channel(managerReplies())
.get();
}
/*
* Configure the manager step
*/
#Bean
public Step managerStep() {
return this.managerStepBuilderFactory.get("managerStep")
.partitioner("workerStep", new BasicPartitioner())
.gridSize(GRID_SIZE)
.outputChannel(managerRequests())
.inputChannel(managerReplies())
//.aggregator()
.build();
}
#Bean
public Job remotePartitioningJob() {
return this.jobBuilderFactory.get("remotePartitioningJob")
.start(managerStep())
.build();
}
}
The sample uses ActiveMQ because it is easily embeddable in a JVM for our tests and samples. But you can use any other broker that you want.
?? what should I inject here?
You should inject any dependency required by the queueMessageChannelAdapter handler:
.handle(queueMessageChannelAdapter)
My property file is location in src/main/resources in eclipse checked its in the classpath - however the following class is unable to initialize the env variable. Any help?
import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.HttpSolrClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.solr.core.SolrTemplate;
#Configuration
#PropertySource(value = { "classpath:solr.properties" })
public class SolrConfig {
#Autowired
private Environment env;
private final static Logger logger = LoggerFactory.getLogger(SolrConfig.class);
#Bean
public SolrClient solrClient() {
if(env == null )
{
logger.error("Property file not loaded!!!");
System.exit(1);
}
String servername = env.getProperty("solr.server");
return new HttpSolrClient.Builder(servername)
.build();
}
#Bean
public SolrTemplate solrTemplate(SolrClient client) throws Exception {
return new SolrTemplate(client);
}
}
You class annotation is correct, but try the following within your method:
Properties _properties = new Properties();
_properties.load(getClass().getClassLoader().getResourceAsStream("solr.properties"));
String servername = _properties.getProperty("solr.server");
I believe you're missing a PropertySourcesPlaceholderConfigurer registered.
From Spring documentation of #PropertySource:
In order to resolve ${...} placeholders in definitions or
#Value annotations using properties from a PropertySource, one must
register a PropertySourcesPlaceholderConfigurer. This happens
automatically when using in XML, but
must be explicitly registered using a static #Bean method when using
#Configuration classes.
So consider registering this bean:
#Bean
public static PropertySourcesPlaceholderConfigurer
propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
In my project created by SpringBoot,
I have added 2 main classes with #SpringBootApplication.
Because if I use STS I can choose one main application when start to debug.
But I found that while SpringDemoApplication is up ,RabbitMQApplication is also running.
Is this specification ? working appropriately?
Here this is sample to reproduce
https://github.com/MariMurotani/SpringDemo/tree/6_rabbitMQ
SpringDemoApplication
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
#SpringBootApplication
public class SpringDemoApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SpringDemoApplication.class);
ApplicationContext context = application.run(args);
}
}
RabbitMQApplication
package demo;
import java.util.Date;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import demo.configs.Const;
import demo.dto.Mail;
#SpringBootApplication
public class RabbitMQApplication implements CommandLineRunner {
#Autowired
ApplicationContext context;
#Autowired
RabbitTemplate rabbitTemplate;
#Bean
Queue queue() {
return new Queue(Const.RabbitMQMessageQue, false);
}
#Bean
TopicExchange exchange() {
return new TopicExchange("spring-boot-exchange");
}
#Bean
Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(Const.RabbitMQMessageQue);
}
#Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(Const.RabbitMQMessageQue);
//container.setMessageListener(listenerAdapter);
return container;
}
/*
For asyncronized receiving
#Bean
Receiver receiver() {
return new Receiver();
}
#Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver, "receiveMessage");
}*/
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(RabbitMQApplication.class, args);
}
#Override
public void run(String... args) throws Exception {
System.out.println("Waiting five seconds...");
while(0 < 1){
for(int i = 0 ; i < 5 ; i++){
String object = (String)rabbitTemplate.receiveAndConvert(Const.RabbitMQMessageQue);
if(object != null){
try{
System.out.println(new Date().toGMTString() + ": " + object);
ObjectMapper mapper = new ObjectMapper();
Mail mail = mapper.readValue(object, Mail.class);
System.out.println(mail.getToAddress() + " , " + mail.getStrContent());
}catch(Exception e){
System.out.println(e.getMessage());
}
}
}
Thread.sleep(10000);
}
}
}
The #SpringBootApplication annotation is a shortcut annotation for #Configuration, #EnableAutoConfiguration, and #ComponentScan.
http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-using-springbootapplication-annotation.html
The default behavior of #ComponentScan is to look for #Configuration and #Component classes within the same package and all sub-packages of the annotated class. Since all your classes are in the same package, when you start any one of them Spring will find the others and treat them like #Configuration classes, and register their beans, etc.
So yes, this is expected behavior given your project setup. Put each #SpringBootApplication class in a separate subpackage if you don't want this to happen for local testing. If this moves beyond a demo at some point you'll probably want to come up with a better setup (subprojects for each #SpringBootApplication perhaps).
I recently faced the same scenario here and I solved with a simple solution.
My projected uses Maven and is configured with sub-modules like this:
my-parent
|__ my-main (depends on my-other module)
|__ my-other
Each module has its own main App class annotated with #SpringBootApplication. The problem is that both classes reside in the same package even though they are in different modules.
Once I start MyMainApp it also starts MyOtherApp. To avoid this I just had to do the following.
In the my-main module I have:
#SpringBootApplication
public class MyMainApp ... { ... }
and in the my-other module I have:
#SpringBootApplication
#ConditionalOnProperty(name = "my.other.active", havingValue = "true", matchIfMissing = false)
public class MyOtherApp ... { ... }
with application.properties with:
my.other.active=true
It works as expected.