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
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.