Spring Boot spring.factories vs #Enable annotations - spring-boot

I have been using Spring Boot and Spring Cloud for a while, and Spring core for even longer, yet I cannot find a clear rule on which technique to use when creating a framework :
Spring Boot starter + spring.factories file
Spring Boot starter + #EnableXxx
both
For example :
the Eureka client starter requires users to import spring-cloud-starter-eureka-client AND to add #EnableEurekaClient on some configuration class
On the other hand, adding spring-boot-starter-jdbc on the classpath is enough to trigger data source auto configuration. There is no such thing as #EnableDataSourceAutoConfiguration
Somebody who wants to configure caching through configuration properties also needs to add #EnableCaching manually
Sometimes the #EnableXxx annotated class is included in the code brought by a starter, sometimes not.
I know #Enable... is the "pre Spring-Boot" method (technically a good-looking #Import), but the fact that #EnableEurekaClient exists is proof that it's not deprecated by any mean.
What's the rule there ? I can't find it in the docs.

There's no hard and fast rule (at least from the Spring Cloud perspective).
Dave Syer said:
A candidate rule of thumb is "if something is on the classpath but
provides multiple features, you need a way to switch on a subset"
I prefer to think of it as "revealing a conscious choice"
as opposed to "relying on magic"
I've kind of looked at as starting servers or doing work (like Discovery Client)

Related

What's the difference between Spring Boot's #Configuration and #AutoConfiguration?

And most important, what's the reason behind the "Auto" prefix? Classes annotated with #Configuration rather than #AutoConfiguration are less automatic or something?
#Configuration is a spring framework annotation and not strictly bound to spring-boot. It was introduced when spring started to allow programmatic creation of spring-beans as to move forward from xml definitions of beans.
#AutoConfiguration is a spring-boot specific annotation not commonly available in spring framework. The reason it exists, is for external providers that cooperate with spring-boot to be able to mark some classes in some libraries they provide with this annotation as to inform spring-boot that those classes could be parsed and make some initializations during start up of spring application automatically.
So if some regular programmer that develops some application happens to have kafka in dependencies then some beans will automatically be created and added in application context and will be ready for the programmer to use, although he has not defined any configuration for them. Spring-boot already knows this as the kafka provider has already informed by marking some class in the jar they provide with the annotation #AutoConfiguration.
For this reason #AutoConfiguration has some more powerful configurations available as before, after, beforeName, afterName as to allow the provider to specify when the configuration is applied during application startup if some order is necessary.
So this annotation is not to be used from some regular programmer that develops an application using spring-boot. It is for someone that develops a library that other users might use with spring-boot. One such example is kafka library.
For this to work in a spring-boot project #EnableAutoConfiguration is needed as well, to enable auto configuration.
From spring documentation
Spring Boot auto-configuration attempts to automatically configure
your Spring application 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 Boot
auto-configures an in-memory database.
#Configuration instead is to be used from some regular programmer that develops an application using spring-boot or spring-framework as to inform the framework for which beans should be created and how.
#AutoConfiguration was introduced in 2.7 with the idea to mark all auto-configurations with its dedicated annotation and move away from spring.factories for auto-configuration imports in 3.0 as described in Github issue.
According to Spring documentation:
[#AutoConfiguration] indicates that a class provides configuration that can be
automatically applied by Spring Boot. Auto-configuration classes are
regular #Configuration with the exception that
Configuration#proxyBeanMethods() proxyBeanMethods is always false.
Usually, #AutoConfiguration classes automatically configure an application based on the dependencies that are present on the classpath. Those classes are generally marked as #ConditionalOnClass and #ConditionalOnMissingBean annotations that detect the presence or absence of specific classes.
Additionally, if a configuration needs to be applied in a specific order, you can use the before, beforeName, after, and afterName attributes on the #AutoConfiguration, unlike #Configuration which doesn't provide those attributes.

what does "spring-kafka without springboot" mean

I'm totally new to Kafka and terribly confused by this:
https://docs.spring.io/spring-kafka/reference/html/#with-java-configuration-no-spring-boot
I don't understand what that even means. What does "no spring boot mean" because that example sure as hell uses spring boot. I'm so confused....
EDIT
if I'm using SpringBoot and spring-kafka, should I have to manually create #Bean ConcurrentKafkaListenerContainerFactory as shown here. Most of the examples in the docs for setting up filtering / config / etc seem to use the "manual" configuration using #Bean. Is that "normal"? The docs are very confusing to me...especially this warning:
Spring for Apache Kafka is designed to be used in a Spring Application Context. For example, if you create the listener container yourself outside of a Spring context, not all functions will work unless you satisfy all of the …​Aware interfaces that the container implements.
It's referring to the autowired configuration, as compared to putting each property in the config via HashMap/Properties in-code.
Also, it does not use #SpringBootApplication or SpringApplication.run, it just calls a regular main method using a hard-coded Config class.
Spring boot contains the functionality of AutoConfiguration
What this means is that spring boot when discovers some specific jar dependencies it knows, in the project, it automatically configures them to work on a basic level. This does not exist in simple Spring project where even if you add the dependency you have to also provide the configuration as to how it should work in your application.
This is also happening here with dependencies of Kafka. Therefore the documentation explains what more you have to configure if you don't have spring-boot with auto-configuration to make kafka work in a spring project.
Another question asked in comment is what happens in case you want some complex custom configuration instead of the automatic configuration provided while you are in a spring-boot app.
As documented
Auto-configuration tries to be as intelligent as possible and will
back-away as you define more of your own configuration. You can always
manually exclude() any configuration that you never want to apply (use
excludeName() if you don't have access to them). You can also exclude
them via the spring.autoconfigure.exclude property.
So if you want to have some complex configuration which is not automatically provided by spring-boot through some other mechanism like a spring-boot specific application property, then you can make your own configuration with your custom bean and then either automatic configuration from spring-boot for that class will back of as spring does several intelligent checks during application context set up or you will have to exclude the class from auto configuration manually.
In that case you could probably take as an example reference of how to register manually your complex configurations in spring boot what is documented on how to be done in non spring boot app. doc

What is meant by Spring boot follows “Opinionated Defaults Configuration” Approach?

I have just started learning spring boot . In its official page I found out this term and I did not understand that what actually it meant in Spring boot context.
Spring Boot just decides on a set of default configured beans which you can override if you want.
For example if you include the spring boot starter pom for jpa, you'll get autoconfigured for you an in memory database, a hibernate entity manager, and a simple datasource. This is an example of an opinionated (Spring's opinion that it's a good starting point) default configuration that you can override.
See https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#using-boot-replacing-auto-configuration
Spring Boot, is Spring on steroids if you will. It's a great way to get started very quickly with almost the entire Spring stack. I'll try to summarize as what "Opinionated Defaults Configuration" would mean in practice from a programmer's perspective below:
Helps you to setup a fully working application(web app or otherwise) very quickly by providing you intelligent default configurations that you are most likely to be satisfied to start with.
It does so by something called "AutoConfiguration", where capabilities from the Spring ecosystem of products are "auto-magically" enabled in your application by adding certain dependencies to your classpath; adding such dependencies via maven or gradle is super easy.
Most auto-configuration respects your own configuration, and backs off silently if you have provided your own configuration via your own beans.
You would benefit most if you take the java config approach of configuring your Spring application.
Super silky integration of new capabilities in your application by developing your own auto-configuration components (via annotations!).
Tons of auto-configaration components available ranging from Databases(h2, derby etc.), servlet containers(tomact, jetty etc.) to email and websockets are available. It is easy to develop your own. The important thing is that others can use those technology enablements in their own components. Please feel free to contribute.
Helps write very clean code with all the heavy lifting taken care of you, so that you can focus more on your business logic.
Hope you have fun with Spring Boot; its absolutely among the very best of frameworks to have hit the market in the last decade or so.
It follows opinionated default configuration so it reduces the developer efforts. Spring boot always uses sensible opinions, mostly based on the class path contents. So it overrides the default configuration.

SpringBoot Multiple AutoConfiguration exclusions defined at startup

I work on a corporate Spring Boot extension that autoconfigures its own RabbitMQ clients. This extension (a starter) replaces the Spring Boot RabbitAutoConfiguration.
I know there are many ways to disable the RabbitAutoConfiguration :
in each Application (main) class with #EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class) or #SpringBootApplication(exclude = RabbitAutoConfiguration.class)
in the application.properties or yml file (externalized or within the jar), with spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
I wonder if there is a way that the presence of my new starter disables the Spring Boot RabbitAutoConfiguration.
I tried some dirty things, such as putting an application.properties with the exclude property in the corporate starter module, but as Spring Boot only reads one in the classpath, it can be easily overriden by one used in a client application. I do not want to impose some restrictions.
I do not like the idea of each application adding the same exclusion one way or the other (properties or annotation).
Any ideas ?
EDIT
I need to configure several RabbitMQ ConnectionFactory and RestTemplate within the same application.
If you want to truly replace the standard RabbitAutoConfiguration by yours, you just need to add #AutoconfigureBefore(RabbitAutoConfiguration.class) on your own auto-configuration to teach Spring Boot to process yours before the standard one.
If it is a replacement, yours will register beans that the standard auto-configuration will detect and it will back-off the same way as if you would have defined them manually.
Having said that, why are you doing this? I'd rather complement the existing auto-configuration rather than replacing the standard one. Is there a problem with the standard one? If so, we'd love to hear about it and adapt the code so that you don't have to fully replace it.

Difference between Spring and Spring Boot

There are many people who advised me to use Spring Boot instead of Spring to develop REST web services.
I want to know what exactly the difference between the two is?
In short
Spring Boot reduces the need to write a lot of configuration and boilerplate code.
It has an opinionated view on Spring Platform and third-party libraries so you can get started with minimum effort.
Easy to create standalone applications with embedded Tomcat/Jetty/Undertow.
Provides metrics, health checks, and externalized configuration.
You can read more here http://projects.spring.io/spring-boot/
Unfortunately and I mean this out of personal frustration with Spring boot, I have yet to see any real quantified list, where the differences are explicitly outlined.
There is only qualifications such as the rubbish sentence "...opinionated view..." which are bandied about.
What is clear, is that SpringBoot has wrapped up groups of Spring annotations into its own set of annotations, implicitly.
Further obfuscating, and making the need for anyone starting out in SpringBoot to have to commit to memory what a particular SpringBoot annotation represents.
My reply therefore is of no quantifiable benefit to the original question, which is analogous to that of the SpringBoot authors.
Those behind Spring IMO deliberately set-out to obfuscate, which reflects the obtuseness of their JavaDoc and API's (see SpringBatch API's as an example, if you think I am flaming) that makes one wonder the value of their open-source ethos.
My quest for figuring out SpringBoot continues.
Update. 22-08-2022
Read this (https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.auto-configuration) and you will figure out for yourself what "opinionated" means.
There are over 140 Config classes that Springboot can use for this opinionated view, depending on what is on your classpath.
yes, on your classpath.
Finally and bizzarely, the annotation #SpringBootApplication is a configuration annotation as it includes it.
Go figure :=)
Basically, Spring Boot is an opinionated instance of a Spring application.
Spring Boot is a rapid application development platform. It uses various components of Spring, but has additional niceties like the ability to package your application as a runnable jar, which includes an embedded tomcat (or jetty) server. Additionally, Spring Boot contains a LOT of auto-configuration for you (the opinionated part), where it will pick and choose what to create based on what classes/beans are available or missing.
I would echo their sentiment that if you are going to use Spring I can't think of any reasons to do it without Spring Boot.
Spring Boot is opinionated view of Spring Framework projects.Let's analyse it through one program taken from Spring Boot Documentation.
#RestController
#EnableAutoConfiguration
public class Example {
#RequestMapping("/")
String home() {
return "Hello World!";
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Example.class, args);
}
}
It's a very basic REST API and you need to add Spring-boot-starter-web in your POM.xml for the same. Since you have added starter-web dependency, the annotation
#EnableAutoConfiguration guesses that you want to develop a web application and sets up Spring accordingly.
Spring Boot auto-configuration attempts to automatically configure your Spring application 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 Boot auto-configures an in-memory database.
It's opinionated like maven. Maven creates a project structure for you which it thinks is the general pattern of projects like it adds src/main/java folder or resource folder for you.
Spring boot helps in faster development. It has many starter projects that helps you get going quite faster. It also includes many non functional features like: embedded servers, security, metrics, health checks etc. In short, it makes, spring based application development easier with minimally invading code(Less configuration files, less no of annotations).
Reference: https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-documentation-about
For developing common Spring applications or starting to learn Spring, I think using Spring Boot would be recommended. It considerably eases the job, is production ready and is rapidly being widely adopted.
Spring Boot is supposedly opinionated, i.e. it heavily advocates a certain style of rapid development, but it is designed well enough to accommodate exceptions to the rule, if you will. In short, it is a convention over configuration methodology that is willing to understand your need to break convention when warranted
For Spring Framework, you need to configure your project using XML configuration or Java configuration.
But for Spring Boot, these are preconfigured according to Spring team's view for rapid development. That is why Spring Boot is said to be an "opinionated view" of Spring Framework. It follows Convention over Configuration design paradigm.
Note: These configurations include view resolvers for MVC, transaction managers, way of locating container managed beans (Spring beans) and many more. And of course you can override any of these preconfigurations according to your need.
Spring Boot supports embedded servlet containers like Tomcat, Jetty or Undertow to create standalone applications, which Spring Framework doesn't.
Spring eliminate boilerplate code.
Spring-boot eliminates boilerplate configurations.
more

Resources