#ComponentScan on external library not working - java

In my spring boot project i have to use a external library which it has define beans in spring context. So in my Application class i have add below which are the base package for bothe my project and the external library,
#SpringBootApplication(exclude = SecurityAutoConfiguration.class)
#EnableHypermediaSupport(type = { EnableHypermediaSupport.HypermediaType.HAL })
#EnableSwagger2
#ComponentScan(basePackages = {"com.mylibrary.test", "com.otherlibrary.springtool"})
//#EnableDiscoveryClient
public class Application extends RepositoryRestMvcConfiguration {
}
But the beans in other library such as #Configuration are not initialize?

#ComponentScan works for the classes that are annotated with #Component, #Repository or #Service. Make sure classes in "com.otherlibrary.springtool" are annotated with above annotation to be found or else you have to declare them as Spring beans with #Bean annotation. Hope it helps.

I had something similar when I was trying to use open feign interfaces coming from an external lib and then I had to add the #EnableFeignClients(basePackages = {"lib.pckg"}), because the Feign had to create the beans for me, not the Spring IoC.
It would be good if you provide some log error.

Related

Spring Boot Application add external library component scan

I have a spring boot app, which has a library as a dependency. In this library I have several #Component and #Configuration classes, which are not scanned by Spring Boot app. I would like to add them to component scan, but I am not able to
How can this be achieved correctly? I think adding #ComponentScan to MainApp class, annotated with #SpringBootApplication will override the default config
Thanks!
#SpringBootApplication Annotation is the combination for #Configuration, #EnableAutoConfiguration and #ComponentScan
We can also use basePackages for scan based on requirement.
For example common package is com.example so directory will be com -> example and sub packages. So for the project there will be different packages for the different modules like controller, service, dto, repository etc...
If we want to use any package for the component scan then we can use like below script.
Hierarchy will be :
com.example.controller
com.example.service
com.example.repository
So basePackages will be look like this :
#ComponentScan(basePackages = "com.example")
Because com.example is only the path/package which is common for all other packages. So we can use like this.

#ComponentScan seens not to be working after migrate from Spring Boot 2.0 to 2.5

I have an application that was working in Spring Boot 1.5, than worked in 2.0.
Now I'm migrating to 2.5.7
This application uses a external lib. This lib also written using Spring Boot 2.5.7 and it users OpenFeign.
But now, when running, the main application seens not to be scanning the lib.
The error is:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field usersRestClient in my.library.package.infrastructure.acl.facade.user.UserFacade required a bean of type 'my.library.package.infrastructure.acl.restclient.user.UsersRestClient' that could not be found.
The injection point has the following annotations:
- #javax.inject.Inject()
Action:
Consider defining a bean of type 'my.library.package.acl.restclient.user.UsersRestClient' in your configuration.
I already tried to use ComponentScan at diferent places. I tried to Create a Configuration Class with ComponentScan at the lib and point in the main application using #Import.
Nothing worked.
I've edited the code leaving just whats matters.
In the lib:
The Service UserFacade uses the Component UsersRestClient
#Service
// I've already tried to put #ComponentScan here, didn't work.
public class UserFacade {
#Autowired
private UsersRestClient usersRestClient;
...
}
This is the component:
#RequestMapping("/users")
#Component("usersRestClient")
public interface UsersRestClient {
...
}
In the main App:
The main class
#SpringBootApplication
#ComponentScan(basePackages = {"my.library.package"})
#EnableAutoConfiguration
#EnableFeignClients({"my.library.package"})
public class ResourceAllocationServiceApplication {
...
}
Than, where I use the UseFacade Service:
#Component
public class RetrieveUserByIdUseCase {
#Autowired
private UserFacade userFacade;
...
}
Can anyone help? I found a similar issue here, but no answers worked.
#ComponentScan on external library not working

Inject bean from a different folder

I have a project structure that looks like this:
In My Groovy folder contains a class marked with #Component that I Want to inject in another class inside the java folder. However spring can't find the bean to inject, when I move the class marked with #Component to the java folder it works fine. How can I make spring aware of the groovy folder?
You can use #ComponentScan at your Spring application (annotated with #SpringBootApplication) to scan components from other packages.
#ComponentScan(basePackages = "com.stackoverflow.other.package")
See https://www.baeldung.com/spring-component-scanning.

What is the difference between #ComponentScan and #EnableAutoConfiguration in Spring Boot?

What is the difference between the #ComponentScan and #EnableAutoConfiguration annotations in Spring Boot? Is it necessary to add these? My application works very well without these annotations. I just want to understand why we have to add them.
What is the difference between the #ComponentScan and
#EnableAutoConfiguration annotations in Spring Boot?
#EnableAutoConfiguration annotation tells Spring Boot to "guess" how you will want to configure Spring, based on the jar dependencies that you have added. For example, If HSQLDB is on your classpath, and you have not manually configured any database connection beans, then Spring will auto-configure an in-memory database.
#ComponentScan tells Spring to look for other components, configurations, and services in the specified package. Spring is able to auto scan, detect and register your beans or components from pre-defined project package. If no package is specified current class package is taken as the root package.
Is it necessary to add these?
If you need Spring boot to Auto configure every thing for you #EnableAutoConfiguration is required. You don't need to add it manually, spring will add it internally for you based on the annotation you provide.
Actually the #SpringBootApplication annotation is equivalent to using #Configuration, #EnableAutoConfiguration and #ComponentScan with their default attributes.
See also:
Using the #SpringBootApplication annotation
Auto-configuration
One of the main advantages of Spring Boot is its annotation driven versus traditional xml based configurations, #EnableAutoConfiguration automatically configures the Spring application based on its included jar files, it sets up defaults or helper based on dependencies in pom.xml.
Auto-configuration is usually applied based on the classpath and the defined beans. Therefore, we donot need to define any of the DataSource, EntityManagerFactory, TransactionManager etc and magically based on the classpath, Spring Boot automatically creates proper beans and registers them for us. For example when there is a tomcat-embedded.jar on your classpath you likely need a TomcatEmbeddedServletContainerFactory (unless you have defined your own EmbeddedServletContainerFactory bean). #EnableAutoConfiguration has a exclude attribute to disable an auto-configuration explicitly otherwise we can simply exclude it from the pom.xml, for example if we donot want Spring to configure the tomcat then exclude spring-bootstarter-tomcat from spring-boot-starter-web.
#ComponentScan provides scope for spring component scan, it simply goes though the provided base package and picks up dependencies required by #Bean or #Autowired etc, In a typical Spring application, #ComponentScan is used in a configuration classes, the ones annotated with #Configuration. Configuration classes contains methods annotated with #Bean. These #Bean annotated methods generate beans managed by Spring container. Those beans will be auto-detected by #ComponentScan annotation. There are some annotations which make beans auto-detectable like #Repository , #Service, #Controller, #Configuration, #Component.
In below code Spring starts scanning from the package including BeanA class.
#Configuration
#ComponentScan(basePackageClasses = BeanA.class)
#EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})
public class Config {
#Bean
public BeanA beanA(){
return new BeanA();
}
#Bean
public BeanB beanB{
return new BeanB();
}
}
#EnableAutoConfiguration in spring boot tells how you want to configure spring, based on the jars that you have added in your classpath.
For example, if you add spring-boot-starter-web dependency in your classpath, it automatically configures Tomcat and Spring MVC.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
You can use #EnableAutoConfiguration annotation along with #Configuration annotation.
It has two optional elements,
exclude : if you want to exclude the auto-configuration of a class.
excludeName : if you want to exclude the auto-configuration of a class using fully qualified name of class.
Examples:
#Configuration
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}
#EnableAutoConfiguration(excludeName = {"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#SpringBootApplication is a newer version of #EnableAutoConfiguration which was introduced in Spring Boot 1.2.
#SpringBootApplication is a combination of three annotations,
#Configuration - for java based configuration classes.
#ComponentScan - to enable component scanning, all the packages and
subpackages will be auto-scanned which are under the root package on
which #SpringBootApplication is applied.
#EnableAutoConfiguration - to enable auto-configuration of the
classes bases on the jars added in classpath.
#ComponentScan enables component scanning so that web controller classes and other components that you create will be automatically
discovered and registered as beans in spring's application context.
You can specify the base packages that will be scanned for auto-discovering and registering of beans.
One of the optional element is,
basePackages - can be used to state specific packages to scan.
Example,
#ComponentScan(basePackages = {"com.example.test"})
#Configuration
public class SpringConfiguration { }

Loading configuration classes present in Spring MVC

I have a Spring MVC application with multiple separate modules which all have their own JavaConfig #Configuration class. My goal is to load all spring configurations that are present in the war. Depending on options passed to the build command some modules and thus configurations may not be present and so #Import isn't an option as it would throw ClassDefNotFound.
In the spring documentation it says
#Configuration is meta-annotated with #Component, therefore #Configuration classes are candidates for component scanning (typically using Spring XML's element) and therefore may also take advantage of #Autowired/#Inject at the field and method level (but not at the constructor level).
#Configuration classes may not only be bootstrapped using component scanning, but may also themselves configure component scanning using the #ComponentScan annotation:
However the main application class entry point looks like this
#Configuration
#EnableWebMvc
#EnableAutoConfiguration
#ComponentScan(basePackages="com.svims.common.web.config")
public class Application extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And there is another class with the #Configuration annotation in the com.svims.common.web.config package that isn't found or the beans inside this configuration just aren't loaded.
I have tried adding this to the main application class
#ComponentScan(basePackages="com.svims.common.web.config",
includeFilters = {#ComponentScan.Filter( Configuration.class ) })
To ensure the scan is configured to find these types of classes but it still doesn't work.
I can only assume that Spring MVC bootstraps in a way as to ignore these configurations but I can't find any reference to this in the documentation.
Does anyone know what is going on or any suggestions on how I might do this?
Always check the packages being scanned again and again.

Categories