bradden_gross
bradden_gross

Reputation: 678

Spring Autowire inside of SpringBootApplication class is behaving differently between nearly identical applications

I have two SpringBoot applications where I'm using RabbitMQ to communicate messages across a queue. One application is built to send messages and the other listens for the sent messages. Each application consists of an @SpringBootApplication file which has one @Autowired dependency at the attribute level (one application has the sender the other has the listener) and each application has a separate Spring @Configuration file which declares one bean each (one has the sender and one has the receiver).

For some reason, the Sender application has no issue with the injection, however, the Receiver application is not injecting at the @Autowire even though the bean is in my application context. I'm using the sample app as a means of demonstrating RabbitMQ/SpringAMQP with SpringBoot and microservices to our company. Below is the code of the Sender Application followed by the Receiver Application. If I change the Receiver application to use Setter injection it works just fine, I'm just very curious as to why one of these works and the other doesn't. The Receiver application blows up on receiver.receive() call in its main method like so:

Exception in thread "main" java.lang.NullPointerException at com.bettercloud.SpringAmqpApplication.main(SpringAmqpApplication.java:17)

Receiver application:

@SpringBootApplication
public class SpringAmqpApplication {

@Autowired
static Recv receiver;
public static void main(String[] args) throws IOException,InterruptedException {
    SpringApplication.run(SpringAmqpApplication.class, args);
    receiver.receive();
  }
 }

@Configuration
public class Config {

@Bean
public Recv recv(){
    return new Recv();
 }
 }


 public class Recv {

 private final static String QUEUE_NAME = "task_queue";
 public void receive()
        throws java.io.IOException,
        InterruptedException {

    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

    channel.queueDeclare(QUEUE_NAME, true, false, false, null);
    System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

    channel.basicQos(1);

    QueueingConsumer consumer = new QueueingConsumer(channel);
    channel.basicConsume(QUEUE_NAME, false, consumer);

    while (true) {
        QueueingConsumer.Delivery delivery = consumer.nextDelivery();
        String message = new String(delivery.getBody());

        System.out.println(" [x] Received '" + message + "'");
        doWork(message);
        System.out.println(" [x] Done");
        channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
    }
  }

private static void doWork(String task) throws InterruptedException {
    for (char ch: task.toCharArray()) {
        if (ch == '.') Thread.sleep(1000);
    }
  }
}

Sender Application:

@SpringBootApplication
public class SpringAmqpProducerApplication {

@Autowired
static Send sender;

public static void main(String[] args) throws IOException {
    SpringApplication.run(SpringAmqpProducerApplication.class, args);
    sender.send(null);
   }
 }


@Configuration
public class Config {

@Bean
public Send send(){
    return new Send();
    }
 }

public class Send {

private final static String QUEUE_NAME = "task_queue";

public static void send(String[] argv)
        throws java.io.IOException {
    Connection connection = null;
    Channel channel = null;
    try {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        connection = factory.newConnection();
        channel = connection.createChannel();

        channel.queueDeclare(QUEUE_NAME, true, false, false, null);
        String message = getMessage(argv);
        channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
        System.out.println(" [x] Sent '" + message + "'");
    } finally {
        channel.close();
        connection.close();
     }
  }

private static String getMessage(String[] strings){
    if (strings == null || strings.length < 1)
        return "Hello World!";
    return joinStrings(strings, " ");
}

private static String joinStrings(String[] strings, String delimiter) {
    int length = strings.length;
    if (length == 0) return "";
    StringBuilder words = new StringBuilder(strings[0]);
    for (int i = 1; i < length; i++) {
        words.append(delimiter).append(strings[i]);
    }
    return words.toString();
 }
}

Upvotes: 1

Views: 790

Answers (2)

Sean Crews
Sean Crews

Reputation: 11

Not sure if this will help, but the send() method in your Send class is static while the receive() method of the Receive class is not.

Upvotes: 1

dunni
dunni

Reputation: 44535

I don't think the injection works at all, since your trying to inject static fields, which doesn't work with Spring. Remove the static identifier from your fields (and from your methods, because there is no reason they're static too) and your application should work fine.

The sender works, because the send method is static, so you don't need an object to call the method.

Upvotes: 1

Related Questions