-3

I've started playing with spring data elasticsearch and have been looking at the example here.

I am having trouble understanding how @Autowired works. Consider the following:

IMessageProcessor.java:

package message.processor;

public interface IMessageProcessor {
    void processMessage();
}

MyMessageProcessor.java

package message.processor;

@Component
public class MyMessageProcessor implements IMessageProcessor {

    @Autowired
    private ArticleServiceImpl articleService;

    private final Author johnSmith = new Author("John Smith");
    private final Author johnDoe = new Author("John Doe");

    @Override
    public void processMessage() {
        Article article = new Article("Spring Data Elasticsearch");
        article.setAuthors(asList(johnSmith, johnDoe));
        article.setTags("elasticsearch", "spring data");
        articleService.save(article);       
    }   
}

MyMessageProcessorIT.java

package message.processor;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class MyMessageProcessorIT {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Before
    public void before() {
        elasticsearchTemplate.deleteIndex(Article.class);
        elasticsearchTemplate.createIndex(Article.class);
    }

    @Test
    void testProcessMessage() {
        MyMessageProcessor msgProcessor = new MyMessageProcessor();
        msgProcessor.processMessage();
    }
}

Whenever I run the unit test, articleService in MyMessageProcessor is always null. Do I need extra configuration for the autowiring to work? All other code is the same as what is in the github repo linked above.

How do I ensure that wherever in my project I need to use ArticleServiceImpl, it is autowired correctly?

I have seem other posts with the same issue but none of the solutions seem to work for my example below.

PCL
  • 421
  • 2
  • 7
  • 15
  • This is because you are creating an instance of `MyMessageProcessor` manually using `new` keyword. In this case the spring container didn't create the `msgProcessor` instance object, so it didn't have chance to inject an instance of `ArticleServiceImpl` to this object. You should not create this instance manually. Try to `autowire` it. – STaefi Mar 06 '19 at 12:12
  • because of you don't allow to create MyMessageProcessor with spring framework,that because spring doesnt inject your ArticleServiceImpl – Mithat Konuk Mar 06 '19 at 12:14

3 Answers3

1

You are not using the spring created instance of MyMessageProcessor and creating your own on this line.

MyMessageProcessor msgProcessor = new MyMessageProcessor();

You should autowire MyMessageProcessor in your test class instead.

Aditya Narayan Dixit
  • 2,105
  • 11
  • 23
0

because of you don't allow to create MyMessageProcessor with spring framework,that because spring doesnt inject your ArticleServiceImpl

@Configuration
public class Configuration { 

@Bean
public MyMessageProcessor mymessageProcessor() {
 return new MyMessageProcessor();
}
}

then @Autowire MyMessageProcessor in your test class

Mithat Konuk
  • 447
  • 5
  • 19
0

@PCL, the first comment link in your post provides the complete answer, but in your code you have 2 choices: 1 - Put MyMessageProcessor msgProcessor autowired:

package message.processor;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Config.class)
public class MyMessageProcessorIT {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    private MyMessageProcessor msgProcessor;
    ...
    @Test
    void testProcessMessage() {
       msgProcessor.processMessage();
    }
}

Or, you get the application context and manually autowire the bean, in the link that was provided by @Tom you can see thus referred to has Manual bean lookup. If you want to create a new bean then the applicationContext also has a autowire method.

Best regards, David

Deceiver
  • 324
  • 1
  • 2
  • 12
  • I've made this change into my project, but now it fails with a `NullPointerException` at `msgProcessor.processMessage()` as `msgProcessor` is `null`. Is there any other configuration/annotations required on the other classes to get this to work? – PCL Mar 06 '19 at 14:14
  • I've also tried adding the `@Configurable` annotation to `MyMessageProcessor` in place of `@Component` and creating my own instance via `new` as suggested in link provided by @Tom, but it gets me back to my original issue: `articleService` in `MyMessageProcessor` is `null`. – PCL Mar 06 '19 at 14:23
  • @PCL, you have a `@ContextConfiguration(classes = Config.class)`, what does the `Config.class` contain. Try adding to the config class `@ComponentScan("message.processor")`. It seems that the path is not being scanned. – Deceiver Mar 06 '19 at 15:55