1

I'm trying to write an access layer class that gets data from MongoDB using Spring Data, but I have the following problem: I have the following interface:

public interface BlogDataRepository extends MongoRepository<Article, String> {
    public Article findArticleByName(String name);
}

and the access layer class:

@EnableAutoConfiguration
public class BlogDataAccessLayer {

    @Autowired
    private BlogDataRepository dataRepository;
    ...
}

And finally a main class:

@EnableAutoConfiguration
public class Test implements CommandLineRunner {

    public static void main(String[] args) {
        SpringApplication.run(Test.class, args);
    }

    public void run(String... args) throws Exception {
        BlogDataAccessLayer layer = new BlogDataAccessLayer();

        Article article = new Article("test", "first article");
        layer.addArticle(article);
    }
}

Each time I'm trying to run the app I get a NullPointerExeption from dataRepository located in BlogDataAccessLayer.

I don't understand why dataRepository is not autowired. If I move dataRepository in Test it works.

Can somebody explain why I get this behavior?

Hamid Samani
  • 445
  • 5
  • 15
djWann
  • 2,017
  • 4
  • 31
  • 36

2 Answers2

5

I'll review your code from top to bottom,first thing to consider is using @Repository annotation in your data access layer, in this case BlogDataRepository interface should be annotated with this stereotype annotation.

In the sense of Domain Driven Design we should access repository layer through the service layer. so in your case BlogDataAccessLayer is act as Service layer and in this case @EnableAutoConfiguration is redundant and in Spring echo system service layer beans should annotated with @Service annotation.

Last and most important part of your code, spring boot @EnableAutoConfiguration doesn't scan for beans in your class path and you should add @ComponentScan to your main class, in your case Test class.

notice that in Spring Boot it's a good practice to place your main class in root package and other classes in their specific package. for example it's a good practice:

org->Application.java //Test
org.service->FooService.java // BlogDataAccessLayer
org.repository->FooRepository // BlogDataRepository

if you want to use beans into your client classes you should inject them. so in your case instantiating BlogDataAccessLayer with new keyword should be replaced with spring @Autowired annotation. and also your Test class should has @Configuration annotation.

Hamid Samani
  • 445
  • 5
  • 15
2

You need to autowire BlogDataAccessLayer instead of instantiating. Then only the BlogDataRepository within that class gets autowired.

Dinal
  • 661
  • 4
  • 9