简体   繁体   中英

Failed to Autowire @Repository annotated interface after upgrading Spring Boot

The below implementation is working with SpringBoot version 2.0.2.RELEASE. After some dependencies upgrade the code fails to autowire DataRecordDBItemRepository .

The upgrades were:

spring-boot-dependencies 2.2.6.RELEASE
io.github.boostchicken:spring-data-dynamodb 5.2.5 (instead of com.github.derjust)
aws-java-sdk 1.11.807
jsk-bom 2.8.0

I also tried to add @Entity annotation but then I received multiple other errors.

As this implementation is working with older Spring version, I would like to understand why the upgrade in SpringBoot triggered the failure.

The class MyApplication.java looks like this:

package com.company.app;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication(scanBasePackages = "com.company.app", exclude = {RedisAutoConfiguration.class, ValidationAutoConfiguration.class, CassandraAutoConfiguration.class, DataSourceAutoConfiguration.class})
@ComponentScan(basePackages={"com.company.app"})
@EntityScan(basePackages={"com.company.app.entities"})
@EnableJpaRepositories(basePackages={"com.company.app.repositories"})
public class MyApplication {

    public static void main(String[] args) {
        try {
            SpringApplication.run(MyApplication.class, args);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

The class DataRecordController.java looks like this:

package com.company.app.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotBlank;

@RestController
@RequestMapping("/v1/dataRecord")
public class DataRecordController {

    private DataRecordService dataRecordService;

    @Autowired
    public void setDataRecordService(DataRecordService dataRecordService){
        this.dataRecordService = dataRecordService;
    }

    @RequestMapping(value = "/{tid}", method = RequestMethod.GET)
    public List<DataRecordDbItem> retrieveDataRecord(final @NotBlank @PathVariable String tid){

        List<DataRecordDbItem> dataRecordDbItems = dataRecordService.retrieveDataRecord(tid);

        return dataRecordDbItems;
    }
}

The interface DataRecordService.java looks like this:

package com.company.app.service;

import com.company.app.entities.DataRecordDbItem;
import java.util.List;

public interface DataRecordService {
    List<DataRecordDbItem> retrieveDataRecord(String tid);
}

The class DataRecordServiceImpl.java looks like this:

package com.company.app.service;

import com.company.app.entities.DataRecordDbItem;
import com.company.app.repositories.DataRecordDBItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
public class DataRecordServiceImpl implements DataRecordService {

    private DataRecordDBItemRepository dataRecordDBItemRepository;

    @Autowired
    public void setDataRecordDBItemRepo(DataRecordDBItemRepository dataRecordDBItemRepo){
        this.dataRecordDBItemRepository = dataRecordDBItemRepo;
    }

    @Override
    public List<DataRecordDbItem> retrieveDataRecord(String tid) {
        List<DataRecordDbItem> dataRecordDbItems = dataRecordDBItemRepository.findDataRecordDbItemsByTid(tid);
        return dataRecordDbItems;
    }
}

The repository DataRecordDBItemRepository.java looks like this:

package com.company.app.repositories;

import com.company.app.entities.DataRecordDbItem;
import com.company.app.entities.DataRecordId;
import org.socialsignin.spring.data.dynamodb.repository.EnableScan;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import java.util.List;

@EnableScan
@Repository
public interface DataRecordDBItemRepository extends CrudRepository<DataRecordDbItem, DataRecordId> {

    List<DataRecordDbItem> findDataRecordDbItemsByTid(String tid);
}

The Entity DataRecordDbItem.java looks like this:

package com.company.app.entities;

import com.amazonaws.services.dynamodbv2.datamodeling.*;
import org.springframework.data.annotation.Id;
import java.io.Serializable;

@DynamoDBTable(tableName = "DataRecord")
public class DataRecordDbItem  implements Serializable {

    @Id
    private DataRecordId dataRecordId;
    private String originalRequestTime;
    private String tid;

    @DynamoDBRangeKey(attributeName = "originalRequestTime")
    public String getOriginalRequestTime() { return originalRequestTime; }

    public void setOriginalRequestTime(String originalRequestTime) {
        this.originalRequestTime = originalRequestTime;
        if (dataRecordId == null) {
            dataRecordId = new DataRecordId();
        }
        dataRecordId.setOriginalRequestTime(originalRequestTime);
    }

    @DynamoDBHashKey
    public String getTid() { return tid; }

    public void setTid(String tid) {
        this.tid = tid;
        if (dataRecordId == null) {
            dataRecordId = new DataRecordId();
        }
        dataRecordId.setTid(tid);
    }
 
}

The Entity DataRecordId.java looks like this:

package com.company.app.entities;

import com.amazonaws.services.dynamodbv2.datamodeling.*;
import java.io.Serializable;

public class DataRecordId implements Serializable {

    private static final long serialVersionUID = 1L;
    private String tid;
    private String originalRequestTime;

    @DynamoDBRangeKey
    public String getOriginalRequestTime() {
        return originalRequestTime;
    }

    public void setOriginalRequestTime(String originalRequestTime) {
        this.originalRequestTime = originalRequestTime;
    }

    @DynamoDBHashKey
    public String getTid() {
        return tid;
    }

    public void setTid(String tid) {
        this.tid = tid;
    }
}

The exception is:

{"level":"ERROR","thread":"main","msg":""
***************************
APPLICATION FAILED TO START
***************************

Description:

Field dataRecordDBItemRepository in com.company.app.service.DataRecordServiceImpl required a bean of type 'com.company.app.repositories.DataRecordDBItemRepository' that could not be found.
    
Action:

Consider defining a bean of type 'com.company.app.repositories.DataRecordDBItemRepository' in your configuration.
"}
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataRecordController': Unsatisfied dependency expressed through method 'setDataRecordService' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataRecordServiceImpl': Unsatisfied dependency expressed through field 'dataRecordDBItemRepository'; nested exception is 

org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.company.app.repositories.DataRecordDBItemRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataRecordController': Unsatisfied dependency expressed through method 'setDataRecordService' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataRecordServiceImpl' defined in file [/Users/myuser/workspace /app/target/classes/com/company/app/service/DataRecordServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.company.app.repositories.sDataRecordDBItemRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:723)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1422)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:882)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
    at com.company.app.MyApplication.main(MyApplication.java:89)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataRecordServiceImpl' defined in file [/Users/myuser/workspace /app/target/classes/com/company/app/service/DataRecordServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.company.app.repositories.DataRecordDBItemRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:798)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:228)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1358)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1290)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1210)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:715)
    ... 19 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com. company.app.repositories.DataRecordDBItemRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1700)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1256)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1210)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789)
    ... 32 more

    
Process finished with exit code 0

For setter injection to work, the setter method needs to follow Java bean conventions ie, there should be setter method called set , here it should be setDataRecordDBItemRepository . Corrected the code and please have a try?

package com.company.app.service;

import com.company.app.entities.DataRecordDbItem;
import com.company.app.repositories.DataRecordDBItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;

@Component
public class DataRecordServiceImpl implements DataRecordService {

    private DataRecordDBItemRepository dataRecordDBItemRepository;

    @Autowired
    public void setDataRecordDBItemRepository(DataRecordDBItemRepository dataRecordDBItemRepo){
        this.dataRecordDBItemRepository = dataRecordDBItemRepo;
    }

    @Override
    public List<DataRecordDbItem> retrieveDataRecord(String tid) {
        List<DataRecordDbItem> dataRecordDbItems = dataRecordDBItemRepository.findDataRecordDbItemsByTid(tid);
        return dataRecordDbItems;
    }
}

One of the pom.xml upgrades were

io.github.boostchicken:spring-data-dynamodb version 5.2.5 which replaced com.github.derjust:spring-data-dynamodb version 5.0.4

I had another dependency that also imported the com.github.derjust .

The impact was that I actually had dependencies to both io.github.boostchicken and com.github.derjust . Spring didn't know which lib to use for the required @Bean .

Excluding the com.github.derjust lib from the other dependency solved the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM