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
Related
I am new to the Springboot framework, and I have some questions about the defualt run() function in the application.java file of the springboot maven project.
I'm trying to build a REST api with spring maven project. In specific, if I have a #Restcontroller class, when and how does the default run() function call an instantiated object of it? And how are the annotated classes like #Service, #RestController and #SpringBootApplication linked together when running the application? (like, what is the process of execution of all these components at runtime?) I know the controller class is used to host APIs, but what should I put in the #Service classes?
Thanks!
#SpringBootApplication annotation in the main application class combines the #EnableAutoConfiguration, #Configuration and the #ComponentScan annotations.
When run, the static run() method starts the Spring Boot application:
#ComponentScan scans the main class package and subpackages for different #Component classes such as controllers, services and repos and registers them as beans in the ApplicationContext.
#EnableAutoConfiguration auto configures your application based on the included jars in classpath.
As far as components go:
#RestController as you said exposes the application's endpoints using #RequestMapping method annotations.
#Service holds the business logic and calls repository methods.
#Repository is data access object that connects to the databases.
'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
I want my spring boot server to be up even if my redis cache isnt up.
I am using #EnableCachingannotation , but my server startup fails if redis is down giving me BeanCreationException. Because BeanCreationException cannot be handled , the only option I have is to lazy load my #EnableCaching class.
I tried annotating that class as under:
#Configuration
#EnableCaching
#Lazy
#Profile("dev")
public class RedisCache extends CachingConfigurerSupport {}
But still this bean is getting loaded at server startup and startup therefore fails.
How do I lazy load the above mentioned class
As far as I know Spring configuration is alwasy loaded on application startup, because that is when the ApplicationContext is created.
In order to do what you want you'd either have to create some sort of custom implementation of ApplicationContext (although I honestly cannot think of how it should work regarding the dependency resolution for dependency injection) or create custom wrapper for caching which would not try to establish connection to Redis until the cache is used.
It may also be possible to configure Spring Boot to skip this particular #Configuration class (Using Boot configuration classes) and then to manually create AnnotationConfigApplicationContext and then retrieve Redis connection Beans from this context manually rather than autowiring them.
I am using Spring Boot embedded tomcat.
In my application I have three configuration classes and I have used the #Order annotation to control the loading order of classes. When I run the application in embedded Tomcat it's working fine, but in standalone Tomcat (WAR) it's not loading in the correct order.
My classes are like below :
#Order(1) public Class WebConfig
#Order(2) public Class SwaggerConfig
#Order(3) public Class PlanoutConfig
#Order defines the sort order for annotated components, not for configuration classes.
I suppose that in embedded Tomcat mode, you benefit from a side effect.
If your classes are configuration classes, that is, classes
annotated with #Configuration, the spring boot documentation states that
you should favor #AutoconfigureOrder over #Order.
44.1 Understanding auto-configured beans
If you want to order certain auto-configurations that shouldn’t have
any direct knowledge of each other, you can also use
#AutoconfigureOrder. That annotation has the same semantic as the
regular #Order annotation but provides a dedicated order for
auto-configuration classes.
AutoConfigureOrder
public #interface AutoConfigureOrder
Auto-configuration specific variant of Spring Framework's Order
annotation. Allows auto-configuration classes to be ordered among
themselves without affecting the order of configuration classes passed
to AnnotationConfigApplicationContext.register(Class...).
You could so write :
#AutoConfigureOrder(0) public Class WebConfig {...}
#AutoConfigureOrder(1) public Class SwaggerConfig {...}
#AutoConfigureOrder(2) public Class PlanoutConfig {...}
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