'ABCService' is not reachable by #ComponentsScan or #SpringBootApplication. Either move it to a package configured in #ComponentsScan or update your #ComponentsScan configuration.
This the error message I get in 9 critical bugs in Sonarqube analysis, one for each Service and Controller.
Though #Autowire and dependency injection is working fine but still Sonar seems to be complaining.
The rule in question causing the issue is:
Spring beans should be considered by "#ComponentScan"
Spring beans belonging to packages that are not included in a
#ComponentScan configuration will not be accessible in the Spring
Application Context. Therefore, it's likely to be a configuration
mistake that will be detected by this rule. Note: the #ComponentScan
is implicit in the #SpringBootApplication annotation, case in which
Spring Boot will auto scan for components in the package containing
the Spring Boot main class and its sub-packages.
Since #SpringBootApplication is has component scan which scans main class package and all it's sub packages as well this issue shouldn't come.
This is a SonarQube bug, it doesn't handle SpringBootApplication properly. You should report it here : https://community.sonarsource.com/c/bug
To quote from Rules from Sonar,
#ComponentScan is used to determine which Spring Beans are available
in the application context. The packages to scan can be configured
thanks to the basePackageClasses or basePackages (or its alias value)
parameters. If neither parameter is configured, #ComponentScan will
consider only the package of the class annotated with it. When
#ComponentScan is used on a class belonging to the default package,
the entire classpath will be scanned.
This will slow-down the start-up of the application and it is likely
the application will fail to start with an
BeanDefinitionStoreException because you ended up scanning the Spring
Framework package itself.
Find below the link and tehy have also mentioned how to write compliant code.
https://rules.sonarsource.com/java/RSPEC-4602
Related
My application looks as follows:
AContext.java containing Beans that define the application. It has #Configuration and #Import(RabbitMQContext.class) to import a class defining Beans for RabbitMQ communication.
This works fine for dev/prod, but I have got an issue with related tests.
I have a TestContext.java defining the base context for the tests. It has
#ComponentScan(basePackageClasses = {AContext.class,...})
Now, I don't want spring to instantiate the beans in RabbitMQContext.class because I don't have a RabbitMQ environment during tests.
So I thought, the easiest way would be to define excludeFilters in my TestContext.java to exclude classes having #EnableRabbit annotation:
#ComponentScan(basePackageClasses = {AContext.class,...},
excludeFilters=Filter(EnableRabbit.class))
But: it doesn't work as expected. When starting the test, I get errors because Spring tries to instantiate beans defined in RabbitMQContext.class.
I also read some similar questons on stackoverflow but found none that really helped, apart from the fact that non-working exclusion seems to be a problem that occurs more often.
Any hints?
Use this:
#EnableAutoConfiguration(exclude=AContext.class)
How does Spring boot application works without #SpringBootApplication?
In our project, we used #Component, #Configuration and bean configuration with #Bean annotation. Later we have commented both the spring-boot-maven-plugin dependency and #SpringBootApplication, but application is built successfully without #SpringBootApplication annotation. I don't understand how its working?
#SpringBootApplication annotation is a combination of #ComponentScan, #Configuration and #EnableAutoConfiguration.
If you comment out #SpringBootApplication but still include #Configuration and #Component you are still allowing your application to be scanned for components and allowing additional components to be added to the applicationContext.The only difference is that Spring's auto configuration mechanism is not included.
https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-using-springbootapplication-annotation.html
I'm looking for a generic/clean solution to import a spring boot jar application into another spring boot application without doing #ComponentScan(package name of the application), without the xml configuration.
If I didn't say #Componentscan in the base application, #Autowired is not working, which is quite understandable.
So in general writing libraries with spring boot is not a ideal way?
Finally, I went with #Import(ApplicationConfiguration)which I find it quite neat.
I had a multi-level project structure so on each of the sub-module created a configuration file which initiate the required beans and then in the parent module, I have used #Import.
I am trying to avoid component scanning to reduce start up time in our module tests, and in our web app in general.
When I replace #SpringBootApplication with #SpringBootConfiguration #EnableAutoConfiguration, I get the following error:
Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean
Can I manually import the EmbeddedServletContainerFactory somehow?
My suggestion is to first run your application with the debug flag on and write down all the activated auto-configurations. Then, disable auto-configuration and import those configurations by using #Import on your application class.
Alternatively, you can look at each of those configuration classes and see what Spring Boot configures for you and decide if you want to provide your own configurations instead - you can just mimic the auto-configuration classes and everything should work the same way.
Miloš and Pieter provided the means to find the answer. A minimal Spring Boot Web Application can be started with the following:
#SpringBootConfiguration
#Import({EmbeddedServletContainerAutoConfiguration.class})
public class Application extends SpringBootServletInitializer {
...
}
ServerPropertiesAutoConfiguration.class might also be handy to pick up things like port number for the application.
I have spring boot application (1.1.5.RELEASE) and enabling my profiles via the configuration protperty spring.profiles.active=MyProfile
The profile gets activated correctly which I can see by beans from that profile being created.
Then I have a #Controller used as follows:
#Controller
#RequestMapping("/someUrl")
#Profile("MyProfile")
public class MyController {
...
}
This controller is not instantiated and URL used in the controller are not mapped. In the same package I have another controllers which are not limited by #Profile and these get instsantiated and mapped as expected.
So is using #Profile annotation on controller something which is not compatible with spring boot? Is there other approach I should be using?
Edit: It seems to be a bug after all as if I include -Dspring.profiles.active=MyProfile as JVM property the controller gets instantiated :'(
Edit2: So here comes the interesting part:
If you define spring.profiles.active in application.properties which is loaded by default from classpath thne it works
when you rename the file to test.properties and include it via #PropertySource("classpath:test.properties") it stops working. Will raise a bug against it.
Edit 3: As promised: https://github.com/spring-projects/spring-boot/issues/1417
Thanks!
I've tracked this down to what I believe to be a bug in Spring. See SPR-12111 for more details.
You can definitely annotate a controller with #Profile in Spring Boot, just as you are doing above. MyController gets instantiated if MyProfile is active. Are you sure that "MyProfile" is the active profile? Are you setting the spring.profiles property?
http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/context/annotation/Profile.html
The #Profile annotation may be used in any of the following ways:
as a type-level annotation on any class directly or indirectly annotated with #Component, including #Configuration classes
as a meta-annotation, for the purpose of composing custom stereotype annotations