Why is only one DatabaseConfig being called in Spring? - spring

I have two DatabaseConfig.java, one in the model1.config package and the other in the model2.config package. Each have the annotations #Configuration, #EnableTransactionManagement, #EntityScan, #EnableJPARepositories with their respective properties set. Both configs have DataSource #Bean. However, when the Spring service is started, only one of the DatabaseConfigs is ever called at a time.

Related

Spring Boot external DataSource bean

I am trying to create a common library that includes several stuff needed by my microservices. One of those things is the ACL functionality provided with spring-security. My initial thought was to initialize all ACL-related beans from a #Configuration file in the common library and each time a microservice needs this functionality i could use the #Import annotation(to my microservice project) to "enable" it.
Some of these beans require the famous javax.sql.DataSource to work, so in my common library i autowired it as follows:
#Configuration
public class AclConfiguration {
#Autowired
DataSource dataSource
When i decide that i want this configuration to take place i go to my microservice project (let's say RulesApplication) and on the main class (annotated with #SpringBootApplication) i do the following
#SpringBootApplication
#EnableJpaRepositories
#EnableJpaAuditing
#EnableCaching
#Import(AclConfiguration.class)
public class RulesApplication {
.
.
.
The problem is that the DataSource bean cannot be seen from the common library, although it is being created as expected (validated just by removing the #Import).
Everytime i import the configuration from the common library i get a :
Caused by: java.lang.IllegalArgumentException: DataSource required
at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
Indicating that the DataSource bean is null.
What am i missing here?
Coming up from some digging.. There was never a real problem with the DataSource bean. All the frustration was created by double-defining another Bean in the same class, which led to all the #Autowired beans failure to initialize.
As a result from this research(as other posts mentioned) the bean initialization is working smoothly between shared projects, so most of the times this error will occur from double-defining/badly-defining other beans.

How SpringBoot dependency injection works with different type of annotations

I recently started exploring Spring Boot. I see that there are 2 ways to define Beans in Spring Boot.
Define #Bean in the class annotated with #SprinBootApplication
Define #Bean in a class annotated with #Configuration
I am also confused about stereo-type annotation #Repository #Service #Controller etc.
Can someone please explain how dependency-injection works with these annotations?
Yes it is possible.
Either you use #Bean in any of your #Configuration or #SpringBootApplication class or mark the bean classes explicitly with annotations like #Service, #Component #Repository etc.
#Service or #Component
When you mark a class with #Service or #Compoenent and if spring's annotation scanning scope allows it to reach to the package, spring will register the instances of those classes as spring beans.
You can provide the packages to be included/excluded during scan with #ComponentScan
#Bean
#Beans are marked on factory methods which can create an instance of a particular class.
#Bean
public Account getAccount(){
return new DailyAccount();
}
Now in you application you can simply #Autowire Account and spring will internally call its factory method getAccount, which in turn returns an instance of DailyAccount.
There is a simple difference of using #Bean vs #Service or #Compoenent.
The first one makes your beans loosely coupled to each other.
In the #Bean, you have flexibility to change the account implementation without even changing any of the account classes.
Consider if your classes instantiation is a multi-step operation like read properties values etc then you can easily do it in your #Bean method.
#Bean also helps if you don't have source code access to the class you are trying to instantiate.
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added.
You need to opt-in to auto-configuration by adding the #EnableAutoConfiguration or #SpringBootApplication annotations to one of your #Configuration classes.
You are free to use any of the standard Spring Framework techniques to define your beans and their injected dependencies. For simplicity, we often find that using #ComponentScan (to find your beans) and using #Autowired (to do constructor injection) works well.
One way is to define #Bean in the class annotated with
#SprinBootApplication
If you see #SprinBootApplication it is combination of many annotation, and one of them is #Configuration. So when you define #Bean in the Main class, it means it's inside #Configuration class.
According to Configuration docs :
Indicates that a class declares one or more #Bean methods and may be
processed by the Spring container to generate bean definitions and
service requests for those beans at runtime.
class annotated with #Configuration
When you define #Bean is a class annotated with #Configuration class, it means it is the part of spring configuration all the Beans define in it all available for Dependency-Injection.
I have also seen some code where neither of the 2 above approaches
have been used and yet dependency injection works fine. I have tried
to research a lot on this but could not find any concrete answer to
this. Is this possible?
I am assuming you are talking about Sterio-type annotation. Every sterio type annotation has #Component, according to docs :
Indicates that an annotated class is a "component". Such classes are
considered as candidates for auto-detection when using
annotation-based configuration and classpath scanning.

why do we need componentScan in spring

This question might be trivial but still i'm unable to find a good reason or best practice towards #ComponentScan in Spring
DI works just by self annotating the class then why do we need #ComponentScan
What is the best practice towards this?
#ComponentScan tells Spring in which packages you have annotated classes which should be managed by Spring.
Spring needs to know which packages contain spring beans, otherwise you would have to register each bean individually in(xml file). This is the use of #ComponentScan.
Take a simple example, you have a class and annotated with #Controller in a package package com.abc.xyz; , you have to tell the spring to scan this package for Controller class, if spring didn't scan this package, then spring will not identifies it as a controller class.
Suppose if your dealing with configuration file,
<context:component-scan base-package="com.abc.xyz">
like this,
When spring loads the xml file, this tag will search the all the classes present in the package com.abc.xyz, so any of the class containing #controller, #Repository #Service etc.., if it found then spring will register these annotated class in the bean factory.
Suppose if your using spring boot application,
Then your spring-boot application is annotated with The#SpringBootApplication.
#SpringBootApplication annotation is equivalent to using #Configuration, #EnableAutoConfiguration and #ComponentScan with their default attributes.
One more point if you didn;t specify the base package name in #ComponentScan,
it will scan from the package, where the #Springbootapplication present

Why AutoConfigurationPackages not consider #ComponentScan?

Spring Boot's support for Spring data configuration is generally by org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport, and this class use the follow code to determine what packages to scan for repositories:
AutoConfigurationPackages.get(this.beanFactory)
So, basically Spring Data with Spring Boot only scan the package which contains the #EnableAutoConfiguration or #ImportAutoConfiguration, but not consider the #ComponentScan, Is this correct ?
The #ComponentScan annotation is a core Spring Framework feature to search for classes annotated with #Component. Since Spring Data repositories are interfaces (and not annotated), the #ComponentScan annotation won't pick them up.
If you are using Spring Data outside of Spring Boot, you can scan for Spring Data repositories using #EnableJpaRepositories with the basePackages attribute set.
When it comes to Spring Boot, there's usually no need to use either #ComponentScan or #EnableJpaRepositories. If you structure your code as suggested, both components and repositories will be picked up.
To get back to your original question about AbstractRepositoryConfigurationSourceSupport. If you look at the source of #SpringBootApplication you'll see it's annotated with #ComponentScan (to find #Components) and #AutoConfigurationPackage (via #EnableAutoConfiguration). The #AutoConfigurationPackage sets up AutoConfigurationPackages with the value that's later retrieved.
If you want to override the packages the Spring Data searches for repositories (for example in tests) you'll need to use #EnableJpaRepositories to completely override auto-configuration. I usually don't do this, but instead use #DataJpaTest and pick up my main configuration.

Spring order of #component creation

In what order the #Component classes will be created in spring. is it #configuration annotated class that will be created first ?? Can we specify the order of creation ??
#Component and #Configuration are different types of annotations.
#Component and similar annotations (#Service, #Repository, etc. ) and its JSR-330 counterpart and allow you to declare beans that are to be picked up by autoscanning with <context:component-scan/> or #ComponentScan they register the bean definition for the classes, so they are roughly equivalent to declaring the specified beans with the <bean ... /> tag in XML. This bean types will adhere to the standard proxy creation policies.
#Configuration annotation was designed as the replacement of the XML configuration file. To create #Configuration annotated beans, Spring will always use CGLIB to subclass the #Configuration annotated class, overriding its #Bean annotated method to replace it with the bean lookup method to make singleton beans to be created only once. Despite that, #Configuration annotated classes are still able to use annotated(#Autowired, #Inject etc.) fields and properties to request beans (and even other #Configuration annotated beans too) from the container.
Now answer to your question, you have to annotate the class with #Configuration and then with #ComponentScan(basePackages = { "com.test.*" }) and you can't specify the order of creation.

Resources