Autowiring of #Repository interface fails in concrete class - spring

I have a concrete class implementing an interface as below:
#Service
public class BaseImpl implements Base{
#Autowired
Details details;
...
public void doSomething(){
}
}
Code for the interface:
#Service
public interface Base{
void doSomething();
}
My configuration class:
#Configuration
public class AppConfig {
#Bean(name="samplebean")
public Base getImpl(){
return new BaseImpl();
}
}
And the Details interface (which is annotated with #Repository):
#Repository
public interface Details extends CrudRepository<..., ...>{
...
}
Finally, I call the BaseImpl class as below:
#RestController
#RequestMapping(value = "...")
public class Caller{
public void foo(){
Base b = (Base) context.getBean("samplebean");
b.doSomething();
}
}
I get the following error:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.model.Details com.pkg.BaseImpl.details; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.model.Details] 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:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 35 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.model.Details] 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.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1308)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 37 more
However, when I do the same auto-wiring in the Caller class (or for that matter any other class which is not implementing an interface), it seems to work fine. I'm new to Spring, so I might be missing something here.
Thanks.

You need to tell spring about the Details bean. Either declare it as a bean,
#Configuration
public class AppConfig {
#Bean(name="samplebean")
public Base getImpl(){
return new BaseImpl();
}
#Bean
public Details details() {
return new Details();
}
}
or annotate it with #Component (or some other more appropriate stereotype)
#Component
public class Details {
// ...
}

Since you are annotating your Details class with #Repository, you just need to add #ComponentScan annotation to your configuration class with the correct base package names.
#ComponentScan(basePackages = { "<yourBasePackage>" })

Related

How do I create and use a spring boot testing utility class?

I want to create a utility class just for my tests that have some methods that all tests will use to reduce code duplication.
Where do I create this class and how do I import it in my tests?
Errors
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'FooTest': Unsatisfied dependency
expressed through field 'myTestUtils'; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'com.utils.MyTestUtils' available: expected
at least 1 bean which qualifies as autowire candidate. Dependency
annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Files
// src/test/com/example/utils/MyTestUtils.java
public class MyTestUtils {
public String foo = "bar";
}
// src/test/com/example/services/FooTest.java
import com.example.utils.TestUtils;
#SpringBootTest
public class FooTest {
// If I remove this decorator I get that this.testUtils is null
#Autowired
MyTestUtils myTestUtils
#Test
public void testFoo() throws Exception {}
Asserthat(myTestUtils.foo).equals("bar")
}
Update
I solved the problem above with annotating the myTestUtils class with #Service
This works.
// src/test/com/example/utils/MyTestUtils.java
#Service
public class MyTestUtils {
public String foo = "bar";
}

How to obtain bean from context?

I have two services A and B, and A has in its pom file the dependency from B.
In service B I am creating a bean of a class named ClassB, and in service A I have a class called ClassA that receives in the constructor as parameter an instance of the ClassB from the other service.
Even I specify in the import section that is from the other service when I run both services I get the error:
Error creating bean with name 'classA' defined in file
[something/ClassA.class]: Unsatisfied dependency expressed through
constructor parameter 0; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'something.something.something.something.something.ClassB' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {}
I don't know how to specify to autowire the class with the bean of the other service.
package .....;
import something.something.something.something.something.ClassB;
public class ClassA {
private ClassB classB;
#Autowired
public ClassA(ClassB classB) {
this.classB = classB;
}
//More methods not relevant
}
Thank you for your help!
Inn your #Configuration class create a a method anotated with #Bean that returns the ClassB instance named classB as below
#Configuration
public class YourConfigClass {
...
.
.
#Bean
public ClassB classB() {
return new ClassB();
}
.
.
...
}

UnsatisfiedDependencyException during test

I use psring boot 2, postgres and Jpa with hibernate.
I would like to test one of my class
#Component
public class ExportsFacade {
private SamplesService sampleService;
private SamplesRepository sampleRepository;
#Autowired
public ExportsFacade(SamplesService sampleService, SamplesRepository sampleRepository) {
this.sampleService = sampleService;
this.sampleRepository=sampleRepository;
}
...
}
I created this test
#RunWith(SpringRunner.class)
#DataJpaTest
#AutoConfigureTestDatabase(replace=Replace.NONE)
public class ExportsFacadeTest {
#Autowired
private ExportsFacade exportsFacade;
#Test
public void export() throws IOException {
exportsFacade.generateExport();
}
}
I get this error
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'com.lcm.facade.ExportsFacadeTest':
Unsatisfied dependency expressed through field 'exportsFacade'; nested
exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'com.lcm.facade.ExportsFacade' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}

BeanCreationException for Spring-data-jpa repository in controller

I have spring-boot-starter-data-jpa and spring-boot-starter-web. I try load List<Project> from mysql using Spring jpa but get bellow BeanCreationException in controller.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'controller': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.project.data.spring_jpa.ProjectRepository com.project.application.Controller.repository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.project.data.spring_jpa.ProjectRepository] 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)}
Controller.java:
...
#RestController
public class Controller {
...
#Autowired
private ProjectRepository repository;
private ProjectAccessor projectAccessor = manager.createAccessor(ProjectAccessor.class);
public void setRepository(ProjectRepository repository){
this.repository = repository;
}
#RequestMapping("/test")
#ResponseBody
public List<Project> test() {
System.out.println("mysql test");
return repository.findAll();
}
...
ProjectRepository.java:
public interface ProjectRepository extends CrudRepository<Project, Long>{
List<Project> findAll();
}
Did you write #Repository annotation on ProjectRepository
#Repository
public interface ProjectRepository extends CrudRepository<Project, Long>{
List<Project> findAll();
}
Do make sure you enabled JpaRepository on your configuration using #EnableJpaRepositories
We get this exception usually when we don't specify where to look for the JPA repositories.
So mention #EnableJpaRepositories("your repository package") where you specify #Configuration or #SpringBootApplication.
It will work fine.

Spring Injecting implementation instead of interface

Here my class structure :
public interface CertificatService
{
}
The only one implementation
#Service
#Transactional
public class CertificatServiceImpl extends GestionCertificat implements CertificatService
{
}
And the injection :
#Service
#Transactional
public class ConnexionEbicsServiceImpl extends GestionConnexion implements ConnexionEbicsService
{
#Inject
private CertificatServiceImpl certificatService;
}
}
Injection the implementation causes injection failure :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'connexionEbicsServiceImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tess2i.service.impl.CertificatServiceImpl com.tess2i.service.impl.ConnexionEbicsServiceImpl.certificatService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.tess2i.service.impl.CertificatServiceImpl] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#javax.inject.Inject()}
But if I inject the interface, it works :
#Service
#Transactional
public class ConnexionEbicsServiceImpl extends GestionConnexion implements ConnexionEbicsService
{
#Inject
private CertificatService certificatService;
}
}
But I need to inject the implementation so to benefit methods inherited from GestionCertificat
Can you help me to autowired the implementation. I understand that the real type is a proxy and not the implementation class CertificatServiceImpl as I would like. But what is the solution so ?
Thanks.
Perfect.
Just using proxy via CGLIB it is OK setting proxyTargetClass = true :
#EnableTransactionManagement(proxyTargetClass = true)
Thanks for the answer here : Spring - how to inject concrete interface implementation?

Resources