Spring componentscan for multiple packages - spring

I want Spring to perform dependency injection from 2 different projects and have a main #Configuration annotated class as below -
#Configuration
#EnableWebMvc
#ComponentScan(value = { "com.x.y", "com.a.b" })
public class AppConfig {
}
Classes under com.x.y is part of packages which contains AppConfig class but classes under com.a.b are part of different jar which is packaged under war file containing AppConfig class.
When i am deploying war file i am getting error as -
Unsatisfied dependency expressed through constructor argument with index 0 of
type [com.a.b.c.d.ClassA]: No qualifying bean of type [com.a.b.c.d.ClassA]
found for dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations: {}; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException:
I am not sure what is wrong in my way of using #ComponentScan. Looking for inputs from Spring experts.
Thanks

Related

How to autowire a spring DAO repository in its unit test?

I am experimenting Spring's reactive support for DB operations. So I have created a repository as:
public interface FeatureRepository extends ReactiveCrudRepository<Feature, UUID> {}
Now I want to test it through a unit test.
So my test is:
#ExtendWith(SpringExtension.class)
#SpringBootTest
public class FeatureRepositoryTest {
#Autowired
FeatureRepository featureRepository;
.....
}
But I get error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of
type 'x.y.z.FeatureRepository' available: expected at least 1 bean which
qualifies as autowire candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
How can I solve this issue?
Your DAO is managed as any other tested class, so without defining a specific ApplicationContext in your test runtime, Spring do nothing and the FeatureRepository bean is not known.
2 approaches :
Your test is more about integration test, so your test runtime need to be specify.
Your test is more about unit test, I suggest you to mock your repository (pragrammatically or using framework like Mockito)
Regards.

NoSuchBeanDefinitionException for bean defined in JavaConfig

I was using XML configuration on my project earlier, and everything was working.
We're moving gradually to java config, so right now I'm at a stage where I'm using a mix of Java and XML configs.
Here's the problem, there is a bean defined in my XML config : beanA.
<bean id="beanA" class="BeanA" />
The class BeanA has an autowired dependency on BeanB.
class BeanA {
#Autowired
BeanB beanB;
}
Earlier, this beanB was also in XML config, and it ran correctly.
Now, I have made this change, and it is no longer working :
#Configuration
class MyConfig {
#Bean
public BeanB beanB() {
return new BeanB();
}
}
Apart from adding #Configuration and #Bean annotations, is there something else required to do that I am missing?
I'm getting the following error :
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'beanB': Unsatisfied dependency expressed through field 'beanA';
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xxxxxx.yyy.zzzzzzzzzzzz.abc.beanA' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Please note,
I have only moved beanB to be created via java config.
BeanA actually has more dependencies, so I cannot move it to java config at this stage (will be doing proper migration later).
you need to add configuration for BeanB as well in the xml configuration. as when the program is run it loads all the bean definition from xml configuration file. So it looks like BeanB definition is missing in configuraion file.
Spring does not load the beans from the classes annotated with #Configuration unless it has been told to look for classes with this annotation.
To make spring look for these classes, the following must be added in your xml configuration :
<context:component-scan base-package="com.xxxxx.yyy.zzzz">
It will then recursively find and initialize all the beans in the package com.xxxxx.yyy.zzzz.

Unable to Autowire brave.Tracer inside Spring boot Application

I am working on Spring boot application and I tried to Autowire Tracer object to get the traceId, but its raised the following exception. why??
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'brave.Tracer' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I used the Tracer in a lot of projects and its always working with no issues!!
Spring boot container is not able to resolve the implementation of your autowired interface in this case. Please annotate your implementation class with spring stereotype annotations.
For e.g We provide #Reposiory for dao classes, #Service for service classes & #Component as a generic one. This will solve your problem. If you still face any issues, Just share your code snippet.

Spring initialization done outside the project

I have a java spring project . I see that one way of initialing the spring project is using this code in the main method.
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(Config.class);
ctx.scan("com.example.db.app");
ctx.refresh();
Is it possible to keep this outside a main method and then make a jar of this project. Add it as a dependency in pom.xml in other project and call the method which initializes the spring artifacts from there.
I tried doing it. I am getting an error.
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'itemInformationRepositoryService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.example.db.app.service.ItemInformationRepositoryService.setItemInformationRepositoryService(com.example.db.app.repository.ItemInformationRepository); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.db.app.repository.ItemInformationRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
The exception message states:
No qualifying bean of type [com.example.db.app.repository.ItemInformationRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
This means that the class com.example.db.app.repository.ItemInformationRepository is not in the Spring context. Perhaps you were expecting Spring to discover this class as a result of your instruction to Spring to scan com.example.db.app? According to the Javadocs for AnnotationConfigApplicationContext.scan() ...
Perform a scan within the specified base packages.
#param basePackages the packages to check for annotated classes
So, in order for Spring to discover com.example.db.app.repository.ItemInformationRepository you must either:
Annotate it with org.springframework.stereotype.Component so that it is discovered by scan()
Register it in the same way as you are registering Config.class e.g. ctx.register(ItemInformationRepository.class);

how Spring boot explicitly not load a class if it's not a web project?

An independent common project A which supply common configuration, inside it there is a class
#RestController
public class CustomErrorController implements ErrorController {
#Autowired
private ErrorAttributes errorAttributes;
//...
}
Now there is another project B which depend on above project A, but this is not a web project only execute some business logic then exit. So in application.properties I have this configuration:
spring.main.web_environment=false
but when run project B, it failed because this exception:
No qualifying bean of type [org.springframework.boot.autoconfigure.web.ErrorAttributes] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
So how to solve this problem? Could exclude CustomErrorController in B's pom.xml or if it's not a web project could not load CustomErrorController?
spring.main.web_environment=false disable the embedded container even if it is present in your project. It does not perform black magic to prevent your classes to be instantiated.
If you are using component scan and you provide classes that require a web environment it will fail (as you just saw). Maybe you need to refactor your project in several modules and isolate the web part in a separate project?
exclude CustomErrorController class
#ComponentScan(basePackages = "com.foo",
excludeFilters = {#ComponentScan.Filter(value = ProjectAApplication.class,type = FilterType.ASSIGNABLE_TYPE),
#ComponentScan.Filter(value = CustomErrorController.class, type = FilterType.ASSIGNABLE_TYPE)})
#SpringBootApplication
public class ProjectBApplication implements CommandLineRunner {

Resources