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.
Related
I know that #ComponentScan with #Configuration tell Spring where to look for beans.
#ComponentScan
#Configuration
public class MyApp{
...
}
What I do not understand is on which class I have to put these two annotations. Should they stay on the class containing the main method?
Like this
#ComponentScan
#Configuration
public class MyApp{
public static void main(String[] args) {
...
}
}
Or they can stay on whatever class of the application?
The question comes from the fact that Spring has to know the location of #ComponentScan... or is there an automatic way of detection of the #ComponentScan annotation which Spring is performing under the hood?
Hope to have explained myself!
You can put it wherever you want (I usually put mine in com.domain.project-name.config) and just specify the directories it should scan, for example if you want it to scan everything in project use
#ComponentScan("com.domain.project-name")
#Configuration
public class Config {
...
By default, ComponentScan scans all the annotated classes at the current directory level and below.
#Configuration annotation tells the Spring container that the class contains Spring bean configuration.
#ComponentScan annotation tells the Spring container that the annotated class to scan/searches for other annotations and components. You can also define package name to scan with the annotation like #ComponentScan("your.package.name") or you can give package/class names that need not be scanned.
Hence, you can put these annotations on any class that defines your bean configuration and could be required by spring container to parse and create objects for your entities/POJOs, services and DAOs.
To conclude, I would like to add #ComponentScan and other annotations are there for automatic detection. Else, you would need to define XMLs (that's what happens under the hood with annotations) for spring to read and perform these actions.
Using simple example. You can place #ComponentScan with #Configuration in any class which main method can scan.
Main class scans MyScan class which then scan for bean class.
package com.boot.spring;
#SpringBootApplication
#ComponentScan(basePackages = "com.boot.scan")
public class BootApplication {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = SpringApplication.run(BootApplication.class, args);
System.out.println(ctx.getBean("demoBean"));
}
}
Bean class is in different package
package com.boot.bean;
#Service
public class DemoBean {
}
Now, bean class is discovered through DemoScan class
package com.boot.scan;
#ComponentScan(basePackages = "com.boot.bean")
#Configuration
public class DemoScan {
}
I have the below Main App:-
Both packages are in different module and i have "com.app.api is included in the pom.xml of com.app.batch
//commented #SpringBootApplication(scanBasePackages={"com.app.batch", "com.app.api"})
public class App
{
public static void main( String[] args )
{
SpringApplication.run(App.class, args);
}
}
In com.app.api i have class ApiClass
#Service
public class ApiClass {}
in `com.app.batch i have
#Component
public class JobRunner implements CommandLineRunner {
#Override
public void run(String... args) throws Exception {
// TODO Auto-generated method stub
apiClass.getData(1111);
}
}
When i comment #SpringBootApplication(scanBasePackages={"com.app.batch", "com.app.api"}) i get the following error
Field apiClass in com.app.batch.config.JobRunner required a bean of
type 'com.com.api.ApiClass' that could not be found.
How can i resolve the issue without using scanBasePackages .I don't want to use scanBasePackages as the module can get added in future and it can get cumberson
If your not interested to use
#SpringBootApplication(scanBasePackages={"com.app.batch", "com.app.api"})
you need to change the package hierarchy so that spring scans the beans easily.
Your main SpringBootApplication class should be in com.app package
and remaining classes should be in sub-packages.
Like com.app.batch and com.app.api are sub-package of com.app
By using this kinda package hierarchy you no need scanBasePackages.
What is the package of the App class?
It needs to be in the base package so that Spring Boot Application scans all the packages inside it.
#SpringBootApplication annotation enables the following annotations/features on its own:
#EnableAutoConfiguration: enable Spring Boot’s auto-configuration mechanism
#ComponentScan: enable #Component scan on the package where the application is located
#Configuration: allow to register extra beans in the context or import additional configuration classes
For further details, you can read here
I'm struggling to autowire beans from my custom library, imported with gradle.
after reading couple of similar topics I am still unable to find solution.
I have a Spring Boot project that depends on another project (my custom library with Components, Repositories etc...). This library is a Spring non-runnable jar, that consists primarily of domain Entities and Repositories. It doesn't have runnable Application.class and any properties...
When I start the application I can see that My 'CustomUserService' bean (from the library) is trying to be initialized, but the bean autowired in it failed to load (interface UserRepository)...
Error:
Parameter 0 of constructor in
com.myProject.customLibrary.configuration.CustomUserDetailsService
required a bean of type
'com.myProject.customLibrary.configuration.UserRepository' that could not
be found.
I've even tried to set 'Order', to load it explicitly (with scanBasePackageClasses), scan with packages and marker classes, add additional EnableJPARepository annotation but nothing works...
Code example (packages names were changed for simplicity)
package runnableProject.application;
import runnableProject.application.configuration.ServerConfigurationReference.class
import com.myProject.customLibrary.SharedReference.class
//#SpringBootApplication(scanBasePackages = {"com.myProject.customLibrary", "runnableProject.configuration"})
//#EnableJpaRepositories("com.myProject.customLibrary")
#SpringBootApplication(scanBasePackageClasses = {SharedReference.class, ServerConfigurationReference.class})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Classes from the library:
package com.myProject.customLibrary.configuration;
import com.myProject.customLibrary.configuration.UserRepository.class;
#Service
public class CustomUserDetailsService implements UserDetailsService {
private UserRepository userRepository;
#Autowired
public CustomUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
...
package myProject.customLibrary.configuration;
#Repository
public interface UserRepository extends CustomRepository<User> {
User findByLoginAndStatus(String var1, Status var2);
...
}
Just found the solution.
Instead of defining base packages to scan from separate library, I've just created configuration class inside this library with whole bunch of annotation and imported it to my main MyApplication.class:
package runnableProject.application;
import com.myProject.customLibrary.configuration.SharedConfigurationReference.class
#SpringBootApplication
#Import(SharedConfigurationReference.class)
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
package com.myProject.customLibrary.configuration;
#Configuration
#ComponentScan("com.myProject.customLibrary.configuration")
#EnableJpaRepositories("com.myProject.customLibrary.configuration.repository")
#EntityScan("com.myProject.customLibrary.configuration.domain")
public class SharedConfigurationReference {}
You can create a folder called 'META-INF' in the 'resources' folder of your library and add a file called 'spring.factories' with the content org.springframework.boot.autoconfigure.EnableAutoConfiguration=<fully_qualified_name_of_configuration_file>. This will autoconfigure your library.
The accepted answer is too cumbersome. What you would need to do is implement your own custom auto-configuration in your library jar so that it is picked up in the classpath scan in the main application. More details here
I need to publish a Spring boot based jar which should be consumed in other Spring/Spring boot based applications.
In my reuse jar I have a class(BusinessConfig) annotated with #Configuration and it gives out two beans. This class is in the base package of the reuse jar.
#Configuration
public class BusinessConfig {
#Bean(name = "BusinessRepoManager")
public BusinessRepoManager businessRepoManager(){
return BusinessRepoManager.getInstance();
}
#Autowired
#Bean(name = "CustomerManager")
#Scope("request")
public CustomerManager customerManager(BusinessRepoManager busrepoManager){
return CustomerManager.getInstance();
}
}
In the second application, I have added the dependency and in the application class I have the statement
#ComponentScan(basePackageClasses = {BusinessConfig.class})
to inform Spring context to look for beans provided in BusinessConfig class as well.
This works well, as I could see the beans getting created.
Is there any possibility to simplify this, should all consuming applications know the class name in which my configuration exists/package name.
I tried creating a custom annotation in the jar project and used that in the consuming application.
#ComponentScan(basePackageClasses = {BusinessConfig.class})
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
#Component
public #interface EnableDemoBusiness {
}
Then in my consuming application I just added
#EnableDemoBusiness
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Is there any way to get this work ?
Thanks in advance !
You have a couple of options:
Option 1
You can turn your class into "auto-configuration", by creating a META-INF/spring.factories file in your jar with the following content:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.your.package.BusinessConfig
Now in applications using your jar if #EnableAutoConfiguration or #SpringBootApplication annotations are used, your configuration will be processed and the beans created.
You might want to annotate your configuration with some #ConditionalXXX annotations if required to give applications that use your jar more control.
Refer to the documentation for more information.
Options 2
You can create a custom #EnableXXX annotation like you attempted.
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
#Import(com.your.package.BusinessConfig.class)
public #interface EnableDemoBusiness {
}
I followed the example that the Spring organization provides here for Spring Data JPA.
This is my repository interface:
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
And this is a snippet of my Application class:
#Configuration
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class);
CustomerRepository repository = context.getBean(CustomerRepository.class);
I get the following error :
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [hello.CustomerRepository] is defined
I tried adding a #Repository annotation to CustimerRespository and the #ComponentScan annotation to the Application class, but result is the same.
I had the same problem and #EnableAutoConfiguration solved it.
If it doesn't work automatically, try disabling JpaRepositoriesAutoConfiguration and explicitly specify the repositories base package:
#EnableAutoConfiguration(exclude = {
JpaRepositoriesAutoConfiguration.class
}
#EnableJpaRepositories(basePackages = {"com.project.app.repositories"})
Good luck.
Maybe try adding on your configuration class
#EnableJpaRepositories
#EnableConfigurationProperties()
#EntityScan({"com.project.app.entities" })
try to add #EnableJpaRepositories and #ComponentScan annotations in Application class to see if adding them solve your problem.
If still it doesn't work, add #Configuration in your CustomerRepository interface and then in Application class add #Import(CustomerRepository .class).
let me know if works.