Spring multiple configuration classes: Loading beans, components, repositories, configurations from other packages

In the beginning, I had a hundred problems creating beans, and spent hours to understand how spring works. I produce a lot of modules and libraries and separate everything by features. So, my applications don’t have a simple model-view-controller folder-set as I have hundreds or even thousands of classes in enterprise solutions. And, I was facing issues with setting up my libraries which were not in the application package in spring. By application package I mean where the Spring Application class resides in and all the sub-packages.

So, what happens when packages are outside? – the beans are not created, the spring annotations do not work! The solution is pretty easy but hard to find unless you are already familiar with “spring keywords“. But, the only way to get familiar with spring terminology is to become a master of it first! Anyway, so my goal here is to write tutorials which would be easy to find with common keywords like “my beans are not working in spring”.

By default, spring only parses bean annotations existing in application package. So, it will not parse anything outside it. If you want to parse other packages, you need to specifically instruct spring to scan them. Here is how I do it:

  1. For every other package, I create a config file which has the instruction to parse all the files under that package, including its sub-packages, and load the beans by putting @Configuration and @ComponentScan annotation.
  2. Then I include this config file in the application class by another spring annotation – @import.

For example, lets say my application package is com.myGreatApp. I have a component to manage all my media and it has its own package – com.media. The media package has its own repository which we need to create a bean of. It also has a controller to serve media over http protocol. So, my project folder looked like this at the beginning:

src\
----com\
--------myGreatApp\
--------------------SpringbootApplication.class
--------media\
--------------Media.class
--------------MediaRepository.class
--------------public\
---------------------MediaPublicController.class

When you run the application the beans for MediaRepository and MediaPublicController are not actually created. This is because Spring does not scan any configuration class outside the application package. So, I create a configuration class in the application package and separate configuration classes in other packages. The application configuration class imports all other configuration classes. Most of the time the configuration classes are pretty simple like this

package com.myGreatApp;

@ComponentScan( basePackages = "com.myGreatApp" )
@Configuration
@Import({
        com.media.ConfigForApp.class //parse media package
        //and many more like this one seperated by comma
})
public class ConfigForApp {

    //It is indeed empty

}

This is my master configuration class. And the media package has its own configuration class – com.media.ConfigForApp.class

package com.media;

@ComponentScan( basePackages = "com.media" ) // now spring will parse it
@Configuration
public class ConfigForApp {

    //It is indeed empty

}

Final folder structure:

src\
----com\
--------myGreatApp\
--------------------ConfigForApp.class
--------------------SpringbootApplication.class
--------media\
--------------ConfigForApp.class
--------------Media.class
--------------MediaRepository.class
--------------public\
---------------------MediaPublicController.class

This is called “Aggregating @Configuration classes“. Common mistakes:

  1. wrongly typed basePackages names as they are in string.
  2. Forgetting the @ComponentScan altogether

Here is an official document which is found when you already know about it:

Aggregating @Configuration classes with @Import

Please, write me the keywords you have searched with before coming across this tutorial and I will update it so that other’s can find it easily.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s