Create an instance of #EnableJpaRepositories repository for parameter - spring-boot

What should I pass as parameter to invoke Access.logLastName(?)? It's not clear to me how to put an instance of the implementation of UserRepository
com.company.app.persistence.test.Access
#Configuration
#EnableJpaRepositories({ "com.company.app.persistence.repository" })
public class Access {
static void logLastName( UserRepository repository ) {
for (User white: repository.findByLastName( "White" )) {
log.info( white.toString());
}
}
}
com.company.app.persistence.repository.UserRepository
public interface UserRepository extends CrudRepository<User, Long> {
List<User> findByLastName(String lastName);
}
Reference:
Inside the #SpringBootApplication annotated class of Getting Started Accessing Data with JPA, they have a method like
#Bean
public CommandLineRunner demo(UserRepository repository) {
return ( args ) -> {
repository.findByLastName( "White" );
};
}
it's not clear to me how the instance of UserRepository implementation is pass as the parameter.

From #dunni's comment:
Make sure com.company.app.persistence.test.Access.java is a spring
bean
It has #Configuration, which makes it qualify as a spring bean I think(?)
then in the class where I want to invoke logLastName(), you can simply #Autowired the interface:
class Invoker {
#Autowired UserRepository userRepo;
void invoke() {
Access.logLastName( userRepo );
}
}

Related

Object not initialized with autowire

I use spring boot 3
I created a object manually, FormGenerator, because everytime I use is in my advance search, some field need to be reset.
So I think the scope prototype is ok for that
#Repository
public class SchoolRepositoryCustomImpl extends SimpleJpaRepository<School, Long> implements SchoolRepositoryCustom {
#Override
public List<School> advanceSearch(SchoolSearch search) {
FormGenerator qg = new FormGenerator();
}
...
}
#Scope("prototype")
public class FormGenerator {
private int fieldCounter=0;
#Autowired
private EntityManager entityManager;
...
}
When I run application, entityManager is null?
It is null because you created the object manually by calling the constructor. You need to obtain it from the ApplicationContext. Something like this:
#Repository
public class SchoolRepositoryCustomImpl extends SimpleJpaRepository<School, Long> implements SchoolRepositoryCustom {
#Autowired
private ApplicationContext applicationContext;
#Override
public List<School> advanceSearch(SchoolSearch search) {
FormGenerator qg = applicationContext.getBean(FormGenerator.class);
}
...
}

JpaRepository mistakes custom interface as property

For general spring JpaRepository DAO (no spring-boot) , if the interface extends a custom interface , spring will mistake the interface methods as object's properties .
For example
interface ILocalDateTime {
fun getLocalDateTime() : LocalDateTime
}
interface UserDaoCustom : ILocalDateTime {
// query functions skipped
}
interface UserDao : JpaRepository<User, Long>, UserDaoCustom
class UserImpl : UserDaoCustom {
#PersistenceContext
private lateinit var em: EntityManager
override fun getLocalDateTime(): LocalDateTime {
return LocalDateTime.now()
}
// query functions skipped
}
This is a simplified UserDao. UserDaoCustom extends ILocalDateTime which contains a method getLocalDateTime .
Note : localDateTime is not a field of User.
At runtime, JpaRepository will mistake getLocalDateTime (or localDateTime ?) as User's field , and throws such exception :
Caused by: org.springframework.data.repository.query.QueryCreationException:
Could not create query for public abstract java.time.LocalDateTime foo.ILocalDateTime.getLocalDateTime()!
Reason: Failed to create query for method public abstract java.time.LocalDateTime foo.ILocalDateTime.getLocalDateTime()!
No property getLocalDateTime found for type User!;
nested exception is java.lang.IllegalArgumentException:
Failed to create query for method public abstract java.time.LocalDateTime foo.ILocalDateTime.getLocalDateTime()!
No property getLocalDateTime found for type User!
Environment :
Kotlin 1.6.20
Spring 5.3.19
spring-data-jpa 2.5.11
How to solve this problem ? (with able or unable to modify ILocalDateTime's code)
Thanks.
I think it is about naming and how Spring pick up implementations of repository extensions.
TLDR;
Change name of your implementation from UserImpl to UserDaoCustomImpl.
I have checked a similar setup and using your naming fails with the exact same error, but naming it "right" makes it work as expected
public interface ILocalDateTime {
LocalDateTime getLocalDateTime();
}
#Repository
public interface UserDao extends UserDaoCustom, JpaRepository<User, Long> {
}
public interface UserDaoCustom extends ILocalDateTime{
}
#Repository
public class UserDaoCustomImpl implements UserDaoCustom {
#Override
public LocalDateTime getLocalDateTime() {
return LocalDateTime.now();
}
}
and tests
#ExtendWith(SpringExtension.class)
#DataJpaTest
class UserRepositoryTest {
#Autowired
private UserDao userDao;
#Test
public void savesUser() {
userDao.save(new User());
}
#Test
public void bazzinga() {
assert userDao.getLocalDateTime() != null;
System.out.println("Bazzinga!"+userDao.getLocalDateTime());
}
}
yelds

Why can't #Autowired a JPA repository - Spring boot + JPA

I'm giving this error:
Parameter 0 of constructor in x.microservice.module.business.application.BusinessCreator required a bean of type 'x.microservice.module.business.infrastructure.HibernateJpaRepository' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=false)
Action:
Consider defining a bean of type 'x.microservice.module.business.infrastructure.HibernateJpaRepository' in your configuration.
The controller:
#Slf4j
#RestController
public final class BusinessPostController {
#Autowired
private BusinessCreator creator;
#PostMapping(value = "/business")
public ResponseEntity create(#RequestBody Request request){
BusinessCreatorDto businessCreatorDto = new BusinessCreatorDto(IdentifierEpoch.generate(),request.getName());
return ResponseEntity.ok(
creator.create(businessCreatorDto)
);
}
}
The Application Layer:
#AllArgsConstructor
#Service
public class BusinessCreator {
#Autowired
private HibernateJpaRepository repository;
public BusinessResponse create(BusinessCreatorDto dto){
Business business = new Business(dto.getId(), dto.getName());
repository.save(business);
return BusinessResponse.fromAggregate(business);
}
}
In the Infrastructure layer
#Repository
public abstract class HibernateJpaRepository implements JpaRepository<Business, Long> {
}
The boot Application:
#EnableJpaRepositories
#SpringBootApplication
public class MicroserviceApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceApplication.class, args);
}
}
All dependencies are resolved and the others classes I believe that are irrellevant.
Any suggestions? Thank you very much
Probably, the error cause is HibernateJpaRepository - it has to be an interface that extends JpaRepository.
You could write your own Repository in a interface:
#Repository
public interface HibernateJpaRepository extends JpaRepository < Business, Long > {
}
Then your Class:
#AllArgsConstructor
#Service
public class BusinessCreator {
#Autowired
private HibernateJpaRepository repository;
public BusinessResponse create(BusinessCreatorDto dto){
Business business = new Business(dto.getId(), dto.getName());
repository.save(business);
return BusinessResponse.fromAggregate(business);
}
}

How to autowire an Inteface which extends JpaRepository in an another class

#Repository
public interface Userrepo extends JpaRepository<Users, String> {
}
I want the above interface to be autowired in the below class
#Component
public class Userauth {
#Autowired
Userrepo urepo;
public boolean check(String name,String password) {
Application a=new Application();
Optional<Users> u=urepo.findById(name);
if(!u.isEmpty()) {
Users ud=u.get();
if(ud.getPassword().equals(password))
return true;
}
return false;
}
}
but its giving an error "urepo" is null
in the log getting this.
Ignored because not a concrete top-level class: file [C:\Users\Documents\workspace-spring-tool-suite-4-4.9.0.RELEASE\1Sampleproject\target\classes\com\example\demo\repos\Userrepo.class]

#Qualifier & #Autowired object coming as null

I am having following code below.
#Builder(toBuilder = true)
#AllArgsConstructor(access = AccessLevel.PRIVATE)
#NoArgsConstructor(access = AccessLevel.PRIVATE)
#ToString
#EqualsAndHashCode
#Configurable
public class Employee {
#Autowired
#Qualifier("findEmpByDepartment")
private Function<Long, Long> empByDepartment;
private void save() {
this.empByDepartment.getList();
}
}
and FindEmpByDepartment class below.
#Component("findEmpByDepartment")
public class FindEmpByDepartment implements Function<Long, Long> {
public void getList() {
}
....
}
My problem is I am always getting null when invoke
this.empByDepartment.getList();
line. Here this.empByDepartment is coming as null. Any idea why it is like this?
Thanks
May be you would have missed annotating any class in the flow hierarchy .
#Service, #Repository and #Controller are all specializations of #Component, so any class you want to auto-wire needs to be annotated with one of them.
IoC is like the cool kid on the block and if you are using Spring then you need to be using it all the time .
So make sure you do not have any object created with new operator in the entire flow .
#Controller
public class Controller {
#GetMapping("/example")
public String example() {
MyService my = new MyService();
my.doStuff();
}
}
#Service
public class MyService() {
#Autowired
MyRepository repo;
public void doStuff() {
repo.findByName( "steve" );
}
}
#Repository
public interface MyRepository extends CrudRepository<My, Long> {
List<My> findByName( String name );
}
This will throw a NullPointerException in the service class when it tries to access the MyRepository auto-wired Repository, not because there is anything wrong with the wiring of the Repository but because you instantiated MyService() manually with MyService my = new MyService().
For more details , you can check
https://www.moreofless.co.uk/spring-mvc-java-autowired-component-null-repository-service/

Resources