Consider defining a bean for jpa repository - spring-boot

My project structure is as follows:
java/com.company.foo/container/configuration/
This folder contains
#ComponentScan({"com.company.foo.module.project",
"com.company.foo.module.user"})
#Configuration
#EnableScheduling
#Import(value = {
SecurityConfiguration.class})
public class ApplicationContextConfiguration {
}
My ResourcePlannerApplication is in this folder:
java/com.company.foo/container/
and has following annotations:
#Import({ApplicationContextConfiguration.class})
#SpringBootApplication
Now I have two modules project and user with both the same structure:
java/com.company.foo/module/user/dao/
This folder contains:
public interface UserRepository extends JpaRepository<UserEntity, Long> {
UserEntity findByUsername(String username);
}
now when I start the app it tells me:
Consider defining a bean of type 'com.company.foo.module.user.dao.UserRepository' in your configuration.
I'm not seeing the problem because the ComponentScan is scanning all the folders?

JPA repositories are not picked up by component scans since they are just interfaces whos concrete classes are created dynamically as beans by Spring Data provided you have included the #EnableJpaRepositories annotation in your configuration:
#ComponentScan({"com.company.foo.module.project",
"com.company.foo.module.user"})
#Configuration
#EnableScheduling
#EnableJpaRepositories("com.company.foo.module.user")
#Import(value = {
SecurityConfiguration.class})
public class ApplicationContextConfiguration {
}

Plog's answer is correct.
I just want to add that, similar solution is applicable for Mongo Repositories as well (where we have interface as a repository).
Suppose, repository package is:
package com.example.respository;
Enable mongo repositories in spring application code, like below:
#EnableMongoRepositories("com.example.repsoitory")

Related

SpringBoot 3 native compilation not generating bean definition for second JpaRepository and failing to start with -Dspring.aot.enabled=true

I am facing an issue with Spring Boot 3 native compilation where the project contains two JpaRepository connecting to two different datasources. The creation of the second datasource configuration depends on the first datasource and JpaRepository as it contains the details about the databases to connect.
The problem is that the Spring Boot Maven plugin process-aot goal does not generate bean definition for repositories which are processed later on. As a result, the application fails to start with the -Dspring.aot.enabled=true property enabled.
I have tried several solutions, including:
Adding the #DependsOn annotation to the second datasource configuration class, but it didn't work.
Adding the #DependsOn annotation to the second JpaRepository, but it also didn't work.
Adding a #Configuration class that contains both datasource configurations, but it also didn't work.
Here is a simplified version of my code:
package com.company.multidatabases.config
#Configuration
public class DataSource1Config {
// datasource1 configuration
#Autowired
private MyEntity1Repository repo;
private Map<Object,Object> dataSources;
}
package com.company.config
#Configuration
public class DataSource2Config {
#Autowired
private DataSource1Config dataSource1Config;
#Bean
public DataSource dataSource(){
return // AbstractDataSourceRouting with datasources map from DataSource1Config
}
// datasource2 configuration that depends on dataSource1Config
}
package com.company.multidatabases.repository
#Repository
public interface MyEntity1Repository extends JpaRepository<MyEntity1, Long> {
// MyEntity1Repository definition
}
package com.company.repository
#Repository
public interface MyEntity2Repository extends JpaRepository<MyEntity2, Long> {
// MyEntity2Repository definition that depends on DataSource2Config
}
And here is the error message I get:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'myEntity1Repository' available
Any help or suggestion is highly appreciated. Thank you in advance.

application.properties not read with #EnableAutoConfiguration and custom spring boot starter

I try to create a simple custom spring boot starter that read property in application.properties :
#EnableConfigurationProperties({ CustomStarterProperties.class })
#Configuration
public class CustomStarterAutoConfiguration {
#Autowired
private CustomStarterProperties properties;
#Bean
public String customStarterMessage() {
return properties.getMessage();
}
}
with its ConfigurationProperties :
#ConfigurationProperties(prefix = "custom.starter")
public class CustomStarterProperties {
private String message;
/* getter and setter */
...
}
There is also the corresponding application.properties and META-INF/spring.factories to enable the autoconfiguration.
I have another project that declares this starter as a dependency and in which I write a test to see if the customStarterMessage Bean is created :
#RunWith(SpringRunner.class)
#EnableAutoConfiguration
public class TotoTest {
#Autowired
String customStarterMessage;
#Test
public void loadContext() {
assertThat(customStarterMessage).isNotNull();
}
}
This test fails (even with the appropriate application.properties file in the project) because the application.properties seems to not be read.
It works well with a #SpringBootTest annotation instead of the #EnableAutoConfiguration but I would like to understand why EnableAutoConfiguration is not using my application.properties file whereas from my understanding all the Spring AutoConfiguration are based on properties.
Thanks
#EnableAutoConfiguration on test classes don't prepare required test context for you.
Whereas #SpringBootTest does default test context setup for you based on default specification like scanning from root package, loading from default resources. To load from custom packages which are not part of root package hierarchy, loading from custom resource directories you have define that even in test context configuration. All your configurations will be automatically done in your actual starter project based on #EnableAutoConfiguration you defined.

How to get #Configuration files in Spring to run

I'm writing a micro service using dependency injection, and I have a Java class annotated with #Configuration which creates all my beans. However, my autowired fields are not detecting the beans. How do I get my #Configuration class to run before the application starts?
I tried annotating the classes with the Autowired fields as #ContextConfiguration(classes = Config.class), but this didn't work.
My spring configuration file:
#Configuration
public class Config {
#Bean
public AmazonDynamoDB amazonDynamoDB() {
return ...
}
#Bean
public DynamoDBMapper dynamoDBMapper(AmazonDynamoDB amazonDynamoDB) {
return ...
}
}
I expect the Configuration file to be run and the beans injected, but the beans are not being detected.
There's no main method, since I'm writing this in a service which is created using dependency injection in another service. I'm not sure where I'd tell my application to use my Config file.
probably place a #EnableConfigurationProperties( {Config.class}) above your #SpringBootApplication main class.

Inject CRUD Repository in Spring

I can't Inject CRUD Repository in Spring.
Repository
#Repository
public interface EntityRepository extends CrudRepository<entity,Long>{
}
#Autowired EntityRepository eR
Error:
.. Required a Bean of Type EntityRepository that could not be found
Consider defining a bean of type 'EntityRepository' in your configuration.
My main
#SpringBootApplication
#ComponentScan({"de.xyz.*"})
#EntityScan("de.xyz.entities")
#EnableJpaRepositories("de.xyz.*")
//#EnableEurekaClient
public class Application extends SpringBootServletInitializer {
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
Another way of doing this is using the basePackages field; which is a field inside ComponentScan annotation.
#ComponentScan(basePackages = {"de.xyz.repository"})
public class Application extends SpringBootServletInitializer {
//
}
Step1 :
Try to include both the classes in the same package. This way you can narrow down the issue of component scanning. Remove all other annotations and keep only #SpringBootApplication
Note :
By default spring loads all the classes under the package of Application Class.
Step2 : See your dependencies, verify you have included the dependencies for JPA repositories.
Step3 : Post the GIT Hub link of the code, so that it can be looked further.
Otherwise add all the packages inside the component scan annotation , Like below.
#ComponentScan({ "a.b.c", "a.b.c.dao" })
As you have mentioned there is a configuration class which is creating the beans, try to include that class package in the same package or include it in component scan.
Hope this help.

How can I register an auto-implemented repository located in a dependency as bean?

I have a module A with a project dependency of module B:
A's build.gradle
dependencies {
....
compile project(":B")
}
In module B, I have this interface:
#Repository
public interface MyRepo extends CrudRepository<User, String> {
//some methods
}
In module A, I have this configuration class:
#Configuration
public class MyConfig {
#Bean
public MyRepo provideMyRepo() {
//???
}
}
How can I export MyRepo bean in module A?
I have tried using #ComponentScan and #EnableJpaRepositories:
#Configuration
#EnableJpaRepositories(basePackageClasses = MyRepo.class)
public class MyConfig {
#Autowired
public MyRepo myRepo;
}
But bean cannot be found:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean found for dependency
You can either #EnableJpaRepositories the package that MyRepo is contained in.
Or add a configuration is in Module B which will scan the required pacakges for the Repository for you and use the Import to pull the Configuration into A.
If it's a Spring Boot project you have the added functionality of Auto-configurations, https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-auto-configuration.html
Finally, If the repository is already registered you can just use it as normal.
You don't need a new configuration for that repository since it is already registered with Spring. You can just inject it directly in your client classes in A module:
#Component
public class MyComponent {
#Inject
private MyRepo myRepo;
// your code using myRepo
}
If Spring says it can't find the bean, you need to check the autowiring configuration you have, so check that your scan path contain the repository class in B (change that using #ComponentScan or )
See this example

Resources