2

I am learning spring boot. This is my spring boot project structure. I do intentionally keep my application.java in a different package to learn about @ComponentScan

Project source - https://github.com/kitkars/spring-boot

project structure

Error :

The application failed to start due to below error.

***************************
APPLICATION FAILED TO START
***************************

Description:

Field productRepository in com.test.service.ProductService required a bean of type 'com.test.repository.ProductRepository' that could not be found.

The injection point has the following annotations:
  - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.test.repository.ProductRepository' in your configuration.


Process finished with exit code 1

This is my Application.java

@SpringBootApplication
@ComponentScan(basePackages = "com.test")
public class Application {

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

}

Now If I move my Application.java under com.test, everything works just great.

What If my Application.java is not under com.test - can it not use the ComponentScan packages and start from there? All the controller, services, repositories etc are present under com.test.

Andronicus
  • 25,419
  • 17
  • 47
  • 88
RamPrakash
  • 2,218
  • 3
  • 25
  • 54

6 Answers6

6

The class annotated with @SpringBootApplication should be in your root package (by default all classes in this package and subpackages are scanned) or you need to specify other packages (controller, entity and others) in @ComponentScan.

Official documentation states:

We generally recommend that you locate your main application class in a root package above other classes.

Andronicus
  • 25,419
  • 17
  • 47
  • 88
  • more info [here](https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-structuring-your-code.html) – nortontgueno Apr 18 '19 at 17:24
  • @ngueno thank you, just found same source for citing;) – Andronicus Apr 18 '19 at 17:25
  • @Andronicus, I can see that it works if I move application. but my question is - should i follow this structure to make this work? Otherwise spring boot wont even start? – RamPrakash Apr 18 '19 at 17:29
  • Everything is in the answer... It's recommended to move the class and there is a workaround - `@ComponentScan` – Andronicus Apr 18 '19 at 17:30
  • What's there? I can see the main class is not in root package – Andronicus Apr 18 '19 at 17:33
  • @Andronicus so you are not seeing the componentscan which you say that as a workaorund? thats werid – RamPrakash Apr 18 '19 at 17:34
  • @RamPrakash can you try with `@EnableJpaRepositories`? – Andronicus Apr 18 '19 at 17:47
  • @Andronicus, thanks for helping. but it does not work. I have updated my question with little bit more info - also updated the screenshot with more clear structure in case if it could help. – RamPrakash Apr 18 '19 at 17:55
  • 2
    @RamPrakash, let me put my two cents here - *should i follow this structure to make this work?* The main advantage of following this structure is not being worried about making extra configurations to make things work, and also to make it simple in case you need to change something, I would say you should consider building in the standard structure present in the docs and avoid a lot of issues – nortontgueno Apr 18 '19 at 17:55
  • @ngueno, I totally get it & ofcourse i am going to follow the recommended strcuture . I am trying to understand the use of ComponentScan. Just for learning purposes. Not for an application which going to production ofcourse. I really appreciate both of your time and effort here. – RamPrakash Apr 18 '19 at 18:02
  • @RamPrakash is `ProductRepository` annotated with `@Repository`? – Andronicus Apr 18 '19 at 18:11
  • 1
    Bravo @Andronicus in my case `@SpringBootApplication` annotated class is not in my root package. once i changed it to root. works charm – anand krish Jul 22 '21 at 14:07
4

Spring Boot relies heavily on default configuration. Consider this excerpt from @EnableAutoConfiguration annotation.

The package of the class that is annotated with @EnableAutoConfiguration, usually via @SpringBootApplication, has specific significance and is often used as a 'default'. For example, it will be used when scanning for @Entity classes. It is generally recommended that you place @EnableAutoConfiguration (if you're not using @SpringBootApplication) in a root package so that all sub-packages and classes can be searched.

The same logic implies to @ComponentScan, @EnableJpaRepositories and the above mentioned @EntityScan annotations. So, if you want to take control of component scanning, you should specify base packages explicitly for all of those annotations.

@SpringBootApplication(scanBasePackages = "com.test")
@EnableJpaRepositories(basePackages = "com.test")
@EntityScan(basePackages = "com.test")
public class Application {
  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

Also note that in your case there is no need to use another @ComponentScan as you can provide arguments to Spring Boot's @ComponentScan via scanBasePackages attribute.

Yevgen
  • 1,576
  • 1
  • 15
  • 17
1

Please check the dependency 'org.springframework:spring-context-indexer if you have one, of course. In my case, this library has caused problems with submodules. The problem was that only beans of the current gradle project were included in the index.

0

resolving do this in my application class.

@Configuration
@SpringBootApplication
@ComponentScan(basePackages = "{lamc.bar.*}")
0

For me, removing the @ComponentScan did the job.

SpringBoot should pick up all your components automatically, so long as your application structure is like this:

|-->package1
|-->package2
|Main.java
PowerAktar
  • 2,341
  • 1
  • 21
  • 17
-2

You should remove @Repository in com/test/repository/ProductRepository.java.

TranNgocKhoa
  • 423
  • 1
  • 6
  • 20
  • Having that annotation on an interface doesn't matter, it is ignored anyway. So removing it won't change a thing. – M. Deinum Apr 23 '19 at 17:28
  • 1
    I think we should remove the annotation on interface because Spring will create a bean with type of `@Repository`. But It can't, because `ProductRepository` is an interface. – TranNgocKhoa Apr 24 '19 at 03:25
  • It won't as it won't try to detect interfaces annotated with `@Repository`. – M. Deinum Apr 24 '19 at 05:25