Spring-boot repository not being registered as a valid bean - spring

Spring-boot does not seem to want to register my repository as a valid bean :( Here is the error I am seeing:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.frustrated.stats.MyRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
The underlying cause seems to be:
o.s.c.a.ClassPathBeanDefinitionScanner : Ignored because not a concrete top-level class: file [/Users/me/Code/my_app/my_service/build/classes/java/main/com/frustrated/stats/MyRepository.class]
Have I configured my application improperly somewhere?
Here are my files:
MyRepository.java:
package com.frustrated.stats;
#Repository
public interface MyRepository extends JpaRepository<StatsEvent, Long> {}
StatsEvent.java:
package com.frustrated.stats;
#Entity
public class StatsEvent { ... }
Application.java:
#SpringBootApplication
#ComponentScan(basePackages = { "com.frustrated" })
#EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class })
#EnableSpringDataWebSupport
public class Application extends SpringBootServletInitializer {
Here is my package structure:
com:
frustrated:
- Application.java
stats:
- MyRepository.java
- StatsEvent.java
Attempts to Debug
After trying a lot of different annotations, I thought it may be more productive to simply step through the registration process. I have traced the code, and it seems to be failing here:
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
AnnotationMetadata metadata = beanDefinition.getMetadata();
return (metadata.isIndependent() && (metadata.isConcrete() ||
(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
}
It is the metadata.hasAnnotatedMethods(Lookup.class.getName()) that is false and causing my repository to not be instantiated as such.
It may also be of note that my StatsEvent is also ignored because:
o.s.c.a.ClassPathBeanDefinitionScanner : Ignored because not matching any filter: file [/Users/me/Code/my_app/my_service/build/classes/java/main/com/frustrated/stats/StatsEvent.class]
Any help would be greatly appreciated!

Judging by MyRepository extending JpaRepository, you are trying to use Spring Data JPA but your have excluded the auto-configuration for Hibernate and a DataSource. Unless you have some manual configuration for Hibernate or another JPA provider that you haven't shown, the support for JpaRepository will be disabled as it requires a JPA provider and a data source.

Try to add this on top of your Application.class
#EnableJpaRepositories(basePackages = "com.frustrated.stats.MyRepository")
#ComponentScan("com.frustrated.stats.service") // if you have it
#EntityScan("com.frustrated.stats.entity") // of your entities

Related

#ConditionalOnBean not work for spring boot test

Hy everyone! I'm trying to solve the problem for a very long time.
There is very simple spring boot test
public class ApplicationTest {
#Test
void testContext() {
SpringApplication.run(Application.class);
}
}
And several beans...
#Service
#ConditionalOnBean(CommonService.class)
#RequiredArgsConstructor
public class SimpleHelper {
...
#Service
#RequiredArgsConstructor
#ConditionalOnBean(CommonFeignClient.class)
public class CommonService {
...
#FeignClient(
name = "CommonClient",
url = "localhost:8080"
)
public interface CommonFeignClient {
And the main class look as
#SpringBootApplication
#EnableFeignClients(clients = AnotherFeignClient.class)
public class Application {
When the spring application starts everything works ok. SimpleHelper does not created.
But in the spring boot test throw the exception:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'simpleHelper' defined in URL [...]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'foo.bar.CommonService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Please help, I don't understand what's going on anymore =)
Spring boot version is 2.3.0.RELEASE.
To use #ConditionalOnBean correctly, CommonService needs to be an auto-configuration class or defined as a bean by an auto-configured class rather than a service that's found by component scanning. This ensures that the bean on which CommonService is conditional has been defined before the condition is evaluated. The need for this is described in the annotation's javadoc:
The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.

Spring Data JDBC UnsatisfiedDependencyException

I wanted to move from JdbcTemplate to Spring Data JDBC. However I seem to have some misconfiguration but I cannot figure out where. The errors are "expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}" and "Parameter 0 of constructor ... required a bean ... that could not be found."
I put #Repository on the public repository interfaces extending PagingAndSortingRepository (as I did with the DAO classes extending from JdbcDaoSupport) without success. Then I added #EnableJdbcRepositories with and without package name to the database config class, also no success. I also tried the database config to inherit from AbstractJdbcConfiguration, still the same errors ...
Unfortunately I couldn't find a working example and I now gave up after some trial and error. I still would love to get this working, the version I used is spring-boot-starter-data-jdbc:2.4.0
Code fragments:
DatabaseConfiguration.java
#Configuration
#EnableJdbcRepositories("<basepackage>.repository.jdbc")
#EnableJdbcAuditing(auditorAwareRef = "springSecurityAuditorAware")
#EnableJpaRepositories("<basepackage>.repository")
#EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
#EnableTransactionManagement
#EnableElasticsearchRepositories("<basepackage>.repository.search")
public class DatabaseConfiguration extends AbstractJdbcConfiguration {
}
UserRepository.java
#Repository
public interface UserRepository extends PagingAndSortingRepository<User, String> {
}
QualityResource.java (REST Controller)
public QualityResource(UserRepository userRepository) {
this.userRepository = userRepository;
}
Error messages:
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'qualityResource' defined in file [.../backend/build/classes/java/main/.../web/rest/QualityResource.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type '....repository.jdbc.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Application failed to start: Description: Parameter 0 of constructor in <basepackage>.web.rest.QualityResource required a bean of type '<basepackage>.repository.jdbc.UserRepository' that could not be found.

Spring Data: Can't Autowire #Repository JpaRepository Interface: "expected at least 1 bean which qualifies as autowire candidate"

My question is almost identical to this one but not the same, because I'm NOT using Spring Boot.
Can't Autowire #Repository annotated interface in Spring Boot
So I can't do #EnableJpaRepositories there's no Spring Boot Runner in my case. I have SpringMVC Controllers inside a Web app.
I'm using Spring Data independently, in a regular old-school SpringMVC application.
I'm getting the error
Caused by: No qualifying bean of type 'com.myapp.dao.QuestionsDAO' available:
expected at least 1 bean which qualifies as autowire candidate.
DAO Interface for Spring Data, note #Repository:
#Repository
public interface QuestionsDAO extends JpaRepository<Question, Long> {
public String findById(Long id);
}
A Service should then use this DAO, autowired:
Component
public class SchedulingService {
#Autowired
QuestionsDAO questionsDAO;
public String findLabelById(Long id) {
return questionsDAO.findById(id);
}
}
Component Scan is enabled, works for everything else.
<context:component-scan base-package="com.myapp" />
Is Spring Data only allowed with Spring Boot?
The annotation #EnableJpaRepositories comes from Spring Data, it has nothing to do with Spring Boot. So it would be enough, to have one class annotated with #Configuration and #EnableJpaRepositories.
If you want to do it in XML, you have to add
<jpa:repositories base-package="com.acme.repositories" />
You also don't need the #Repository annotation on your interfaces, that annotation has another purpose.

Spring Boot ConfigurationProperties fail to initialize for integration testing

Using gradle (3.4.1) with an integrationTest configuration, the tests using the ConfigurationProperties of Spring Boot (1.5.1.RELEASE) is failing to initialize even though the application initializes correctly (./gradlew bootRun). The class annotated with ConfigurationProperties is similar to the following
#Component
#ConfigurationProperties(prefix = "foo")
#Validated
public class AppConfiguration {
#NonNull
private URL serviceUrl;
...
The configuration file does have getters and setters. The error that is generated is similar to the following
java.lang.IllegalStateException: Failed to load ApplicationContext
....
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'AppConfiguration': Could not bind properties to AppConfiguration
....
Caused by: org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult
Field error in object 'foo' on field 'serviceUrl': rejected value [null]; codes ...
The configuration class of the integration test is annotated as follows
#Configuration
#ComponentScan(...)
#EnableConfigurationProperties
#EnableIntegration
public static class ContextConfiguration {}
The test class had the following annotations
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration
public class ReleaseTest {
...
After looking at the Spring Boot code for the ConfigurationPropertiesBindingPostProcessor#postProcessBeforeInitialization() it suggested that the property source was not being discovered. Adding the org.springframework.boot:spring-boot-starter-test artifact as a compile-time dependency and modifying the context configuration of the test class to
#ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
the AppConfiguration class was initialized properly using a YAML-based properties file.
An alternative is to add
#TestPropertySource("classpath:/application.properties")
This approach doesn't require the spring-boot-starter-test dependency and requires that a "traditional" properties file is used (a YAML file will not work with this approach).

Spring JPA not implementing/autowiring repository despite #EnableJpaRepositories annotation

I'm getting an exception when I start my application, where Spring complain about UnsatisfiedDependencyException:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'applicationConfig': Unsatisfied dependency expressed through field 'controlRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean found for dependency [com.oak.api.finance.repository.ControlRepository]: 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:569)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
My application is organized in this format:
I declared my repository interfaces, with the proper Spring JPA annotations:
#RepositoryRestResource(collectionResourceRel = "exchange", path = "exchanges")
public interface ControlRepository extends PagingAndSortingRepository<Control, Long> {
}
I annotated the EntryPoint class that contains the main method
#SpringBootApplication
#EntityScan(basePackages = {"com.oak.api.finance.model.dto"})
#EnableJpaRepositories(basePackages = {"com.oak.api.finance.repository"})
public class EntryPoint {
public static void main(String[] args) {
Logger logger = LogManager.getLogger(EntryPoint.class);
logger.info("Starting application");
ApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationConfig.class);
// SpringApplication.run(EntryPoint.class, args);
ctx.getBean(ApplicationServer.class).start();
}
I used #Autowired to inject my repository into my spring config (java based) ApplicationConfig class:
#Autowired
private ControlRepository controlRepository;
#Autowired
private CompanyRepository companyRepository;
#Autowired
private SectorRepository sectorRepository;
Essentially I want to control the dependency on Spring and limit it to a couple of packages, (the repositories, the java config, and the program entry point - EntryPoint)
I assumed that, by specifying #EnableJpaRepositories with the package where my repositories are located, spring would create a proxy for my repository and instantiate an instance of that, and that by the time I call :
ApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationConfig.class)
The repositories instances would be present in the beans poole and would be possible to autowire them into my ApplicationConfig context, and then inject them into my controller.
This is clearly not happening, and Spring is complaining about the missing Bean to autowire, but I'm not sure what am I missing.
Below a snapshot of my packages:
any ideas?
My guess is your repositories are not being scanned, so as a result beans are not getting created. Can you try removing these 2 annotations
#EntityScan(basePackages = {"com.oak.api.finance.model.dto"})
#EnableJpaRepositories(basePackages = {"com.oak.api.finance.repository"})
And keep only #SpringBootApplication. If this is not working, you might need to check the package structure (if possible paste a screenshot here)
Edit 1
replace #SpringBootApplication with
#Configuration
#EnableAutoConfiguration
#ComponentScan("com.oak")
Edit2
Use
new SpringApplicationBuilder()
.sources(SpringBootApp.class)
.web(false)
.run(args);
Or use CommandLineRunner after changing ComponentScan path to "com.oak" as mh-dev suggested

Resources