Java – scan components of different Maven modules / jars in spring boot applications
I have two Maven modules
package org.example.application; @SpringBootApplication @ComponentScan({"org.example.model","org.example"}) public class Application { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(Application.class,args); } }
In the same Maven module and package org example. In application, I have a restcontroller using component, and component uses another component of Maven module described below
Another Maven module called "model" contains spring boot components (crud repositories, entities, etc.) All of these classes are under the same package structure as the first Maven module (org. Example), but in its sub packages, such as org example. model. entities,org. example. model. Repositories, etc
Therefore, the process is as follows:
Package org Maven module application in example: springbootapplication – > restcontroller – > is mycomponent
The component that should be automatically assembled in mycomponent is package org example. The model under model is the component in Maven module
But when I start the application, I just get an error:
*************************** APPLICATION Failed TO START *************************** Description: Field myRepository in org.example.MyComponent required a bean of type 'org.example.model.repositories.MyRepository' that Could not be found. Action: Consider defining a bean of type 'org.example.model.repositories.MyRepository' in your configuration.
org. example. model. repositories. Myrepository does exist in Maven module "model", but the springbootapplication class cannot find it!
As you can see, I tried to explicitly define the scanning component as: @ componentscan ({"org. Example. Model", "org. Example"}), but it doesn't seem to help
What did I do wrong?
Solution
The first thing you should want to know is: why do you declare @ componentscan and one of the goals of @ springbootapplication is (among other things) to enable component scanning?
Please note that on the class of spring boot application, declare @ componentscan and specify the value as basepackages, which will overwrite the basepackages used by @ springboot application by default, which is the current package of the class Therefore, to use the package of spring boot application class and other missing packages as the base package, you must explicitly set them
Except that basepackages are recursive Therefore, to enable scanning for classes located in the "org. Example" and "org. Example. Model" packages, specifying "org. Example" is sufficient because "org. Example. Model" is its sub package
have a try:
@SpringBootApplication(scanBasePackages={"org.example"})
Or:
@SpringBootApplication @ComponentScan("org.example")
Specify @ enablejparepositories / @ componentscan / scanbasepackages in the spring boot application?
When designing the spring boot application layout, you have two situations:
1) Case: you use a package layout, which provides zero configuration and automatic configuration of spring boot
To sum up: if your class uses spring bean stereotype annotation: @ component, @ storage, @ repositories,... Is located in the same package or sub package of spring boot application class, only declaring @ springbootapplication is what you need
2) Case (avoid) the package layout you don't use provides spring guided zero configuration and automatic configuration
It usually means that you have candidate classes to scan, which are not in the package (or sub package) of the class annotated with @ springbootapplication In this case, you can add the scanbasepackages property or add @ componentscan to specify the packages to scan In addition, if your repository is not in a package or sub package of a class annotated with @ springbootapplication, you must declare something else, such as @ enablejparepositories (= "packagewhere myrepoarelocated")
Here is the documentation:
example
1) Case: you use a package layout, which provides zero configuration and automatic configuration of spring boot
Use at org The spring boot application declared in the example package, and in the same package or org For all bean classes declared in the sub package of example (including the repository), the following declaration is sufficient for spring boot applications:
package org.example; @SpringBootApplication public class Application { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(Application.class,args); } }
The repository can be located at org example. In the repository package, for example:
package org.example.repository; @Repository public interface FooRepository extends JpaRepository<Foo,Long>,{ }
and
package org.example.repository; @Repository public interface BarRepository extends JpaRepository<Bar,{ }
The controller can be located at org example. In the controller package:
package org.example.controller; @RestController @RequestMapping("/api/foos") public class FooController {...}
Wait
2) Case (avoid) the package layout you don't use provides spring guided zero configuration and automatic configuration
Use org example. The spring boot application declared in the application package, not in the same package or org example. For all bean classes declared in the sub package of application (including the repository), spring will need the following Declaration: start the application:
package org.example.application; @SpringBootApplication(scanBasePackages= { "org.example","org.thirdparty.repository"}) @EnableJpaRepositories("org.thirdparty.repository") public class Application { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(Application.class,args); } }
Bean classes can be as follows
A repository that might come from an external jar can be located at org. Jar thirdparty. In the repository package, for example:
package org.thirdparty.repository; @Repository public interface FooRepository extends JpaRepository<Foo,{ }
and
package org.thirdparty.repository; @Repository public interface BarRepository extends JpaRepository<Bar,{ }
The controller can be located at org example. In the controller package:
package org.example.controller @RestController @RequestMapping("/api/foos") public class FooController {...}
Wait
Conclusion: we encourage defining spring boot applications in the namespace base package to make spring boot configuration as simple as possible