CommandLineRunner required a bean that could not be found - spring

I'm new to making APIs and Spring in general.
I'm trying to use CommandLineRunner in order to populate my repository but it says that it cannot find the required bean that I put in the parameter.
#SpringBootApplication
public class DemoApplication {
private static final Logger logger = LoggerFactory.getLogger(DemoApplication.class);
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public CommandLineRunner initializeDB(StudentRepository studentRepository){
return (args)->{
studentRepository.save(new Student("John1", "Doe1", "asdasda1","Comp Sci1",21));
studentRepository.save(new Student("John2", "Doe2", "asdasda2","Comp Sci2",22));
studentRepository.save(new Student("John3", "Doe3", "asdasda3","Comp Sci3",23));
studentRepository.save(new Student("John4", "Doe4", "asdasda4","Comp Sci4",24));
studentRepository.save(new Student("John5", "Doe5", "asdasda5","Comp Sci5",25));
studentRepository.save(new Student("John6", "Doe6", "asdasda6","Comp Sci6",26));
logger.info("The sample data has been generated");
};
}
}
That is my application class and below is my repository class.
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.model.Student;
public interface StudentRepository extends JpaRepository<Student, Integer> {
}
Is there a basic thing that I am missing?
Thanks in advance

Easiest and wise thing to do
DemoApplication (or whichever class annotated with #SpringBootApplication) should reside at the root of the package structure
That means, for any other classes for which you want spring to manage it's bean's lifecycle, move that to a (sub)package of DemoApplication.
In other words, if your DemoApplication is in a package src/main/java/com/yourorg then StudentRepository should be in a (sub)package of src/main/java/com/yourorg

If the application class is not in a super package as the other classes, you have to specify all packages in the SpringBootApplication, which should be scanned (for component scanning, Spring Data repositories etc.).
#SpringBootApplication(scanBasePackages= {"package1", "package2"})
or for a typesafe approach
#SpringBootApplication(scanBasePackageClasses = {ClassFromPackage1.class, ClassFromPackage2.class})
Alternatively move all packages to a subpackage of the application class package, so that all the default mechanisms take place.

Related

I am trying to push data into my db using JpaRepository but there was some error stopping me to do so

*************************** APPLICATION FAILED TO START ***************************
Description:
Field userRepository in com.Lex.Exercise.Service.RegistrationService required a bean of type 'com.Lex.Exercise.Repository.UserRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.Lex.Exercise.Repository.UserRepository' in your configuration.
//UserRepository
package com.Lex.Exercise.Repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.Lex.Exercise.Model.UserEntity;
public interface UserRepository extends JpaRepository<UserEntity, String>{
}
//RegistrationService
#ComponentScan(basePackages = "com.Lex.Exercise.Repository")
#Component
public class RegistrationService {
#Autowired
private UserRepository userRepository;
//business methods and other validations comes here
}
This is the main class
package com.Lex.Exercise.SpringBootDemo;
#SpringBootApplication
#PropertySource(value = { "classpath:configuration.properties" })
public class SpringBootDemoApplication implements CommandLineRunner {
#Autowired
private RegistrationService service;
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
Below is the project structure:
/SpringBootDemo/src/main/java/com/Lex/Exercise/Model/User.java
/SpringBootDemo/src/main/java/com/Lex/Exercise/Model/UserEntity.java
/SpringBootDemo/src/main/java/com/Lex/Exercise/Repository/UserRepository.java
/SpringBootDemo/src/main/java/com/Lex/Exercise/Service/RegistrationService.java
/SpringBootDemo/src/main/java/com/Lex/Exercise/SpringBootDemo/SpringBootDemoApplication.java
/SpringBootDemo/src/main/resources/application.properties
/SpringBootDemo/src/main/resources/configuration.properties
Please help me how I could resolve this
Remove #ComponentScan(scanBasePackages = "com.Lex.Exercise.Repository") on your RegistrationService.class
And your SpringBootDemoApplication.class should look like this. Than your components in subpackages of com.Lex.Exercise will be injected into the Application context.
#SpringBootApplication
#ComponentScan(basePackages = {"com.Lex.Exercise"})
public class SpringBootDemoApplication{
public static void main(String[] args) {
new SpringApplication(SpringBootDemoApplication.class).run(args);
}
}
In general it is a good idea to put the SpringApplication in the top level package (like in your case com.Lex.Exercise) because Spring Boot scans automatically all subpackages of that class. So you wouldn't need the extra #ComponentScan
The #ComponentScan(basePackages = "com.Lex.Exercise.Repository") belongs on your configuration, which might be your application class

Creating Bean inside Spring boot application using command line runner

#SpringBootApplication
public class ReactiveCouchbaseExample1Application {
#Bean
CommandLineRunner employees(ApplicationContext context) {
EmployeeRepository repository = context.getBean(EmployeeRepository.class);
return args -> {
repository
.deleteAll()
.subscribe(null,null,()->{
Stream.of(new Employees(UUID.randomUUID().toString(), "Nikhil", 23, 3000L),
new Employees(UUID.randomUUID().toString(), "Shubham", 23, 3000L),
new Employees(UUID.randomUUID().toString(), "Anshul", 23, 3000L))
.forEach(employee->{
repository.save(employee)
.subscribe(System.out::println);
});
});
};
}
public static void main(String[] args) {
SpringApplication.run(ReactiveCouchbaseExample1Application.class, args);
}
I wants to run this piece of logic as soon my application context get loaded but when i started my app it shows this error.
Method employees in com.reactive.reactivecouchbaseexample1.ReactiveCouchbaseExample1Application required a bean of type 'com.reactive.repository.EmployeeRepository' that could not be found.
Can someone tell me how can I create a repository bean inside CommandLineRunner.
I also googled it but could'nt find any answers.
This is my repository
#Repository
public interface EmployeeRepository extends
ReactiveCouchbaseRepository<Employees, String>{
}
Scanned component must be in the same package as #SpringBootApplication annotated class, or its subpackage. I can only assume it is ReactiveCouchbaseExample1Application.class.
Maybe your repo is in different package, or you didn't enable component scan with #SpringBootApplication or #ComponentScan.

Spring Boot: autowire beans from library project

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

Execute CommandLineRunner outside #SpringBootApplication

This is based on https://spring.io/guides/gs/accessing-data-jpa/
I tried to move demo() in a different class in a different package (Application still on top of the filesystem hierarchy)
How do I make demo() run when i boot the project?
Application.java
package com.company.app
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
CommandLineRunner.java
package com.company.app.runner
public class Test {
#Bean
public CommandLineRunner demo() {
System.out.print("Run 1");
return (args) -> {
System.out.print("Run 2");
};
}
}
Add #Configuration to the Test class so that it is picked up when the classpath is scanned.
I haven't seen a Lambda for the CommandLineRunner before. Very nifty and saves having to create a class that specifically implements the CommandLineRunner.
Otherwise, you could implement CommandLineRunner to test and annotate as #Component.
#Component
public class ApplicationLoader implements CommandLineRunner {
#Override
public void run(String... strings) throws Exception {
System.out.print("Run 2");
}
}
* Update *
Answering the question in the comment with this update as I have more room to type...
#SpringBootApplication composes those other annotations as you indicated but those annotations are only applied to the specific class that it is defined on. The #Configuration annotation is telling Spring that the class defines beans that should be managed by the application context. The #ComponentScan tells spring to look through the classpath for classes that have specific annotations (e.g. #Component, #Service, #Configuration) and then act on those classes based on the type of annotation. the #EnableAutoConfiguration is the magic that loads appropriate beans based on the project dependencies (e.g. if mongo driver is on the classpath then create a MongoTemplate).

getting #autowired intance null when try trying to do operation on it,throwing null pointer exception

I am trying to save data on gemfire using crud repository. I have created one operation class to call save method of repository but at autowired instance I am getting null pointer exception. Below is my code:
public interface GeodeRepository extends CrudRepository<KeyValueBean, String> {
#Override
public KeyValueBean findOne(String name);
#Override
public <S extends KeyValueBean> Iterable<S> save(Iterable<S> entities);
}
#EnableGemfireRepositories(basePackageClasses = GeodeRepository.class)
#EnableAutoConfiguration
#Configuration
public class Operations {
#Autowired
private GeodeRepository repository;
public void saveKeyValueData(KeyValueBean keyValueBean) {
System.out.println("Repository is : " + repository);
repository.save(Arrays.asList(keyValueBean)); // <--- i am getting
// repository as null so
// getting null pointer
// exception
}
}
When we #Autowired any class make sure, you have declared that class as a #Component.
for example:
#Component
public class Operations {
#Autowired
private GeodeRepository repository;
public void saveKeyValueData(KeyValueBean keyValueBean) {
System.out.println("Repository is : " + repository);
repository.save(Arrays.asList(keyValueBean));
}
}
and try using #Autowired to Operation class to your class
in which class your are calling your saveKeyValueData() method.
So, what is not apparent from your example is how you "bootstrap" your application and it's features (e.g. Repositories) into action.
It is not simply enough to add the Spring #Configuration, Spring Boot's #EnableAutoConfiguration and SD GemFire's #EnableGemfireRepositories annotations and expect everything to be auto-configured and wired up successfully. I.e. you need a bootstrapping mechanism, like Spring Boot, especially if you are using the #EnableAutoConfiguration annotation.
For example...
import org.springframework.boot.SpringApplication;
...
class MyApplication {
public static void main(String[] args) {
SpringApplication.run(Operations.class, args);
}
}
Now, you could remove the #EnableAutoConfiguration from your Operations class and add the #SpringBootApplication to the MyApplication class, like so...
#SpringBootApplication
class MyApplication {
...
}
#SpringBootAppliation combines together Spring's #Configuration with Spring Boot's #EnableAutoConfiguration, along with many other useful meta-annotations, like Spring's #ComponentScan, enabling all sorts of magic to happen.
But, if you are not using Spring Boot, you can always bootstrap you application with the AnnotationConfigApplicationContext, like so..
class MyApplication
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(Operations.class);
applicationContext.registerShutdownHook();
}
}
This is essentially what the Spring Boot, SpringApplication class does for you anyway.
If you are developing a Web application, then of course you can specify the type of ApplicationContext created since you are using Java config, for instance. See here for more details.
Hope this helps!
Cheers,
John

Resources