NoSuchBeanDefinitionException for deep inheritance - java

I have a Spring boot application. My repository is written in the following way:
An interface:
#NoRepositoryBean
public interface MyQueryRepository {
int checkThis(String this);
int checkThisAndThat(String this, String that);
}
An abstract Class:
public abstract class AbstractMyQueryRepository implements MyQueryRepository {
#Override
public int checkThis(String this) {...}
#Override
public int checkThisAndThat(String this, String that) {...}
}
then the implementation:
#Transactional(TVServiceDbConfigAtlanta.TV_TRANSACTION_MANAGER_NAME_ATLANTA)
#Repository
public class MyQueryRepositoryAtlanta extends AbstractMyQueryRepository {
#Autowired
public MyQueryRepositoryAtlanta (
#Qualifier(TVServiceDbConfigAtlanta.TV_DATA_SOURCE_BEAN_NAME_ATLANTA) final DataSource dataSource) {
super(dataSource);
}
}
When I try to autowire MyQueryRepositoryAtlanta in my UT in the following way:
#ExtendWith(SpringExtension.class)
#DataJpaTest
#ActiveProfiles("test")
class MyQueryRepositoryAtlantaTest{
#Autowired
private MyQueryRepositoryAtlanta myQueryRepositoryAtlanta ;
#Test
void checkThisTest() {
assertThat(myQueryRepositoryAtlanta.checkThis("ABC")).isEqualTo(1);
}
#TestConfiguration
#Profile("test")
#Import(TVServiceDbConfigAtlanta.class)
public static class Config {
}
}
I get the following error:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
'com.myapp.MyQueryRepositoryAtlantaTest': Unsatisfied dependency
expressed through field 'myQueryRepositoryAtlanta '; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'com.myapp.AbstractMyQueryRepository '
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586)
~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at
org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372)
~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1341)
~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:393)
~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at
org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
~[spring-test-5.0.8.RELEASE.jar:5.0.8.RELEASE] [...]
I am not sure I understand why, since:
The bean that I am testing is annotated as #Repository and
There is no other bean called in the same way
I also checked similar answers in SOF but they are not applicable because of the particular structure that I use. Any idea about how to solve the issue?

Related

UnsatisfiedDependencyException: Error creating bean with name in 2.4.1 Spring Boot

main Class:
package *.*.*;
#SpringBootApplication
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class, args);
}
}
DBUtils.java
package *.*.*.dataaccess.dbutils;
#Service
public class DBUtils {
#Autowired
UserRepository userRepository;
public UserEntity getUserEntityById(String id) {
return userRepository.findById(id);
}
}
Repository Class:
package *.*.*.dataaccess.repository;
#Repository
public interface UserRepository extends JpaRepository<UserEntity, UserIdentity> {
UserEntity findById(String id);
}
and also UserEntity java class is in package *.*.*.dataaccess.dao;
Test Class:
#SpringBootTest
class UserApplicationTests {
#Autowired
DBUtils utils; // issue is with this
#Test
void contextLoads() {
}
}
While doing maven test for entire project and getting the below error:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DBUtils': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '...dataaccess.repository.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '...dataaccess.repository.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I have used #Service on DBUtils and #Repository on JpaRepository but still getting the above error and using springboot is 2.4.1.
Can anyone please help here?

Unsatisfied Dependency Exception in creating beans using Spring

I'm trying to use JPA for my spring application. I have integrated the JPATransactionManager & LocalEntityManagerFactoryBean into AppConfig class. Now, when I try to call one of the method which is in DaoImpl, the AppConfig is not able to Autowire the classes. Here is my code
Test Class
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
BbDao personService = context.getBean(BbDao.class);
personService.getDealByDealId("0194541605021NJMAPFU");
context.close();
}
}
AppConfig
#Configuration
#EnableWebMvc
#EnableTransactionManagement
#ComponentScan(basePackages = "net.bb.spring")
public class AppConfig{
#Bean
public LocalEntityManagerFactoryBean getEntityManagerFactoryBean() {
LocalEntityManagerFactoryBean factoryBean = new LocalEntityManagerFactoryBean();
factoryBean.setPersistenceUnitName("MyPersistence");
return factoryBean;
}
#Bean
public JpaTransactionManager geJpaTransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(getEntityManagerFactoryBean().getObject());
return transactionManager;
}
}
ConfirmPurchaseController
#RestController
public class ConfirmPurchaseController {
private Logger logger = Logger.getLogger(ConfirmPurchaseController.class);
#Autowired
private MyService myService;
#GetMapping("/purchase")
public ResultDto confirmpurchase(HttpServletResponse response) throws ClassNotFoundException, IOException {
// Business Logic
}
}
MyService
#Component
public interface MyService {
// Methods defined
}
MyServiceImpl
#Service
public class MyServiceImpl implements MyService, ServletContextAware {
private ServletContext servletContext;
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
public ServletContext getServletContext() {
return servletContext;
}
// Added the implemented methods of the MyService Interface
}
The exception it throws is
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myServiceImpl': Unsatisfied dependency expressed through field 'servletContext'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.servlet.ServletContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
and the error log is
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'confirmPurchaseController': Unsatisfied dependency expressed through field 'myService'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myServiceImpl': Unsatisfied dependency expressed through field 'servletContext'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.servlet.ServletContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:84)
at net.bb.spring.controller.Test.main(Test.java:14)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myServiceImpl': Unsatisfied dependency expressed through field 'servletContext'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.servlet.ServletContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:588)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 14 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.servlet.ServletContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 27 more
Any ideas would be very helpful for me.
P.S : Im using configuration as annotations, no XML
It is not an answer, however I cannot add a comment yet.
Did you try to autowire a ServletContext via setter method?
- remove #Autowired from property
- remove one of your setters for context (unnecessary duplication)
- mark a setter as #Autowired
Moreover remove #Component annotation from MyService, it is unnecessary if you are using #Service annotation in its implementation.
As per Apache Tomcat documentation, a ServletContext
Defines a set of methods that a servlet uses to communicate with its
servlet container.
There is one context per "web application" per Java Virtual Machine.
(A "web application" is a collection of servlets and content installed
under a specific subset of the server's URL namespace such as /catalog
and possibly installed via a .war file.)
Which means that a ServletContext is only valid within a Servlet Container like Apache Tomcat. But as I can see, you are trying to run a normal Java application by creating beans in a main method, which makes the existence of ServletContext invalid.
So what you have to do is:
STEP 1: Build your AppConfig and override required methods.
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"net.bb.spring"})
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/WEB-INF/");
}
//....
}
STEP 2: Create WebInitializer to initialize Dispatcher Servlet
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] {AppConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
}
STEP 3: Create your Service layer to autowire ServletContext
#Service
public class MyServiceImpl implements MyService {
private ServletContext servletContext;
#Autowire
public MyServiceImpl(ServletContext servletContext) {
this.servletContext = servletContext;
}
public ServletContext getServletContext() {
return servletContext;
}
//...
}
STEP 4: Build your application to a WAR file
STEP 5: Deploy your WAR file to webapp folder of Tomcat (If you are using Tomcat)
STEP 6: Start Tomcat
Here is what you need to change:
1) You don't need to annotate the interface with #Component, annotation is required only on the implementation class
MyService
public interface MyService {
// Methods defined
}
2) Use constructor injection to obtain an instance of ServeletContext.
#Service
public class MyServiceImpl implements MyService, ServletContextAware {
private ServletContext servletContext;
#Autowire
public MyServiceImpl(ServletContext servletContext) {
this.servletContext = servletContext;
}
//TODO: other methods goes here...
}
pay attention that ServletContext is not a Spring bean and it can, therefore, not be injected unless you implement ServletContextAware. keep your implementation class implements ServletContextAware

Cannot autowire bean that overrides a method that is overriden in parent

In our project we have a structure similiar to code below. If I uncomment the specified block Spring will fail to autowire PrintService in the PrintController
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'PrintController': Injection of autowired dependencies failed;
nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private printService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [MyPrintService] 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)}
Why is Spring having issues with it?
#Controller
public class PrintController {
#Autowired
private MyPrintService printService;
}
#Service
public class MyPrintService extends AbstractPrintService<MyModel> {
/* uncomment this block to get error
#Override
public void print(MyModel model){
//do stuff
}*/
}
public abstract class AbstractPrintService<M> extends CommonAbstractPrintService<M> {
}
public abstract class CommonAbstractPrintService<M> implements PrintService<M> {
#Override
public void print(M model){
//do common stuff
}
}
public interface PrintService<M> {
void print(M model);
}
The solution was to autowire the bean using interface. So instead of:
#Autowired
private MyPrintService printService;
I used
#Autowired
private PrintService printService;
And it suddenly worked. But I have no Idea why Spring was offended by that override. Would be glad if anyone could explain that! Thanks!

MongoDB autowire is throwing exception

I have below class files and it looks everything fine but i am not understanding why i am getting autowire failure. Can anyone please help me to find the issue?
updated with package details
package com.ui.controller;
#RestController
#RequestMapping(value = "/Person")
public class PersonController {
#Autowired
#Lazy
private RepoService repoService;
}
package com.messaging.service.impl;
#Component
#Lazy
public class RepoServiceImpl implements RepoService {
#Autowired
#Qualifier("personRepository")
private PersonRepository personRepo;
}
package com.messaging.service;
public interface RepoService {
}
package com.da.repository;
#Repository("personRepository")
public interface PersonRepository extends MongoRepository<SomeType, String> {
}
package com.conf;
#Configuration
#EnableMongoRepositories(basePackages = "com.da.repository")
#EnableMongoAuditing
#Profile("mongo")
public class MongoConfig extends AbstractMongoConfiguration {
}
I am getting following error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.da.repository.PersonRepository] 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), #org.springframework.beans.factory.annotation.Qualifier(value=personRepository)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 52 more
Its my bad. The issue was not with the above coding but with the mongodb connection. There was a connection issue which resulted the above error.

Spring: No matching bean found which qualifies as autowire

Application-Context is correctly setup!
Heres my class scenario
public interface IManager
{
public void doStuff();
}
#Component
public abstract class ManagerAction implements IManager
{
#Async
#Override
public void doStuff()
{
//doing stuff
}
public abstract manageWorker();
}
#Component
public class Working extends ManagerAction
{
#Override
public manageWorker()
{
//some busy code
}
}
#Component
public class NotWorking extends ManagerAction
{
#Override
public manageWorker()
{
//some busy code
}
}
#Service
public class BusinessWorker
{
#Autowire
private IManager manager_;
public void preformTasks()
{
manager_.doStuff();
}
}
Heres my error
ERROR [main] (ContextLoader.java:307) - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'BusinessWorker': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.B
eanCreationException: Could not autowire field: private com.background.IManager com.background.BusinessWorker.manager_; nested exception is org.springframework.beans.
factory.NoSuchBeanDefinitionException: No matching bean of type [com.background.IManager] 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)}
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.background.IManager com.background.BusinessWorker.manager_;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.background.IManager] 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)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:506)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
... 28 more
Application-Context
<mvc:annotation-driven />
<task:annotation-driven />
<context:annotation-config />
<context:component-scan base-package="com.background" />
The error message says it all: you try to autowire an instance of IManager, but two different Spring components implement this interface, so Spring doesn't know which one to autowire. You need to use the #Qualifier annotation to specify which one you want Spring to autowire.

Categories

Resources