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.
Related
In my library I have some Entities and Repositories which I want include in my spring-boot project.
This is an example of #Confituration class from library
package com.mylibrary.config
#Configuration
#ComponentScan("com.mylibrary.service")
#EntityScan("com.mylibrary.repo")
#EnableJpaRepositories("com.mylibrary.repo")
#ConditionalOnClass(value = [DataSource::class])
open class MyCustomConfigFromLibrary
This way I try include MyCustomConfigFromLibrary in my spring-boot project
package com.mainapp
#SpringBootApplication
#Import(value = [MyCustomConfigFromLibrary::class])
class Application
But when I run my spring-boot application it does not want scan Repositories and Entities from my spring-boot project itself. It scans its Components but not its Repositories and Entities. Repositories and Entities it scans are only from my library.
So, to fix it I found the solution which I do not like! I just explicitly add #EntityScan and #EnableJpaRepositories to my Application class.
package com.mainapp
#SpringBootApplication
#Import(value = [MyCustomConfigFromLibrary::class])
#EntityScan
#EnableJpaRepositories
class Application
As far as I know, if you are using your own custom schema.sql and/or data.sql then Spring Boot does not detect JPA Repos or Entities. If you want your application to scan those classes then try removing the custom schema.sql/data.sql from the resources folder.
In the JPA based app, You should not use both spring.jpa.hibernate.ddl-auto and schema.sql. Make sure to disable spring.jpa.hibernate.ddl-auto if you use schema.sql.
Reference - https://walkingtechie.blogspot.com/2018/12/execute-schema-and-data-sql-on-startup-spring-boot.html
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 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 { }
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.
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.