conquester
conquester

Reputation: 1132

Spring Boot load beans from a different module before

I have two maven modules:

api-module
commons-module

The api-module contains the package com.example.api and the commons-module contains the package com.example.commons.

When I run the main app com.example.api.ApiMain, the execution fails. It is because I have Mongo Repository classes defined in the commons package. The API controllers depends on them and since they are not instantiated before the api beans, the execution fails.

Here is the main api app:

package com.example.api;

@SpringBootApplication
@ComponentScan({"com.example.commons", "com.example.api"})
public class ApiMain {
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

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

How do I make sure that com.example.commons components are scanned before the beans in com.example.api are loaded?

I can use @DependsOn annoation on every bean in com.example.api but there are several classes and several more will be added in future and it will make the code ugly.

This problem can be solved if there is a way to instruct spring to load components from the commons-module first.

You may instruct me on how to perform this.

Upvotes: 0

Views: 4075

Answers (2)

Akshay Thorve
Akshay Thorve

Reputation: 718

I was facing the same issue. I used below code for Rest API controller

@RestController
@EnableOAuth2Sso
@EnableResourceServer
@SpringBootApplication
public class SpringBootWebApplication extends WebSecurityConfigurerAdapter {

    //Dependancy injection using autowire
    @Autowired
    OAuth2ClientContext oauth2ClientContext;
    public static void main(String[] args) throws Exception {
        SpringApplication.run(SpringBootWebApplication.class, args);
    }

Using this code for the normal controller which is rendering my HTML page

@Configuration
@EnableAutoConfiguration
@Controller
public class WelcomeController {

Try this and let me know if this works or you still have some issue.

Upvotes: 0

Derrops
Derrops

Reputation: 8117

Whatever package is scanned first should not matter, as Spring will build a dependency graph and figure out the order in which beans are instantiated. If you want certain beans to be instantiated before others, as in lets say BeanA depends on BeanB, then BeanA will have a constructor @Autowired BeanA(BeanB b).

Figuring out the order of instantiating is a fundamental aspect of Spring Dependency Injection, I would suggest you read up a bit more on Spring DI because I don't think you are grasping the concept of inversion of control and what Spring DI does.

But what it sounds like to me is you have something like:

public class BeanA {
    @Autowired
    BeanB b;
    public BeanA() {
        b.doSomething();
    }
}

But b is still null when BeanA's constructor is called. Because you are performing some sort of instantiation in BeanA with BeanB you get a NullPointerException, instead you have to have: BeanA(BeanB b).

Upvotes: 1

Related Questions