So I have tried searching all over for this blocker and tried many different ways of finding a solution but I cannot wrap my head around it. I am a beginner in Spring and I have created a generic DAO that takes in any T which extends BaseEntity. I have the following code:
private Class<T> clazz;
@Autowired
public void setClazz(Class<T> clazz){
System.out.println("In class Autowired Setter");
this.clazz = clazz;
}
@Bean
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public Class<T> getClazz(){
return clazz;
}
Which I have put inside my BaseDAOImpl . Then I use this constructor:
public BaseDAOImpl() {
this.collection = MongoDbUtil.getCollection(mongoConnection.mongoDb(), clazz);
}
to create a JacksonDbCollection for MongoDB. In my CustomerServiceImpl I Autowire my BaseDAO bean so that I can use my DAO for persistance.
@Autowired
public void setBaseDAO(BaseDAO<CustomerEntity> baseDAO) {
this.baseDAO = baseDAO;
}
So when I run a method that uses my BaseDAOImpl, I get a NullPointerException and I am pretty sure it is because of the Class that is not picking up my CustomerEntity. My question is how can I get Class to pick up CustomerEntity when I Autowire my baseDao bean? Or what suggestions do you have for me to solve my problem? I just need a different point of view and thought I would ask for it here.
Thank you in advanced for you assistance.
Update
BaseDAOImpl
package za.co.thekeeper.dao;
import org.mongojack.DBCursor;
import org.mongojack.DBQuery;
import org.mongojack.JacksonDBCollection;
import org.mongojack.WriteResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import za.co.thekeeper.entities.BaseEntity;
import za.co.thekeeper.mongo.MongoConnection;
import za.co.thekeeper.mongo.MongoDbUtil;
import java.util.ArrayList;
import java.util.List;
@Repository
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class BaseDAOImpl<T extends BaseEntity> implements BaseDAO<T> {
private JacksonDBCollection<T, String> collection;
/**Dependency Injections**/
private MongoConnection mongoConnection;
@Autowired
public void setMongoConnection(MongoConnection mongoConnection) {
System.out.println("In autowired setter");
this.mongoConnection = mongoConnection;
}
private Class<T> clazz;
@Autowired
public void setClazz(Class<T> clazz){
System.out.println("In class Autowired Setter");
this.clazz = clazz;
}
@Bean
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public Class<T> getClazz(){
return clazz;
}
public BaseDAOImpl() {
this.collection = MongoDbUtil.getCollection(mongoConnection.mongoDb(), clazz);
}
@Override
public T create(T entity) {
entity.activate();
entity.beforePersist();
WriteResult<T, String> inserted = this.collection.insert(entity);
return inserted.getSavedObject();
}
@Override
public void delete(T entity) {
deactivate(entity);
}
@Override
public T activate(T entity) {
entity.activate();
return update(entity);
}
@Override
public T deactivate(T entity) {
entity.deactivate();
return update(entity);
}
@Override
public void activate(String id) {
T entity = getById(id);
if (entity == null) {
throw new NullPointerException("Entity not found with id: " + id);
}
activate(entity);
}
@Override
public void deactivate(String id) {
T entity = getById(id);
if (entity == null) {
throw new NullPointerException("Entity not found with id: " + id);
}
deactivate(entity);
}
@Override
public T update(T entity) {
entity.beforePersist();
WriteResult<T, String> saved = this.collection.save(entity);
return saved.getSavedObject();
}
@Override
public void deleteById(String id) {
deactivate(id);
update(getById(id));
}
@Override
public T getById(String id) {
return this.collection.findOneById(id);
}
@Override
public List<T> findByField(String field, Object o) {
DBQuery.Query query = DBQuery.is(field, o);
DBCursor<T> cursor = this.collection.find(query);
return readCursor(cursor);
}
@Override
public void createDBRef(String databaseName, String collectionName, String id) {
}
@Override
public List<T> findAll() {
return findByField("activate", Boolean.TRUE);
}
/**
* Cursor
**/
private List<T> readCursor(DBCursor<T> cursor) {
if (cursor.size() > 0) {
List<T> found = new ArrayList<>();
while (cursor.hasNext()) {
found.add(cursor.next());
}
return found;
}
return null;
}
}
CustomerServiceImpl
package za.co.thekeeper.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import za.co.thekeeper.dao.BaseDAO;
import za.co.thekeeper.dao.BaseDAOImpl;
import za.co.thekeeper.entities.CustomerEntity;
import za.co.thekeeper.entities.MerchantEntity;
import za.co.thekeeper.entities.ReceiptEntity;
import za.co.thekeeper.mongo.MongoConnection;
import java.util.List;
import java.util.UUID;
@Service
public class CustomerServiceImpl implements CustomerService {
private BaseDAO<CustomerEntity> baseDAO;
@Autowired
public void setBaseDAO(BaseDAO<CustomerEntity> baseDAO) {
this.baseDAO = baseDAO;
}
@Override
public CustomerEntity registerNewCustomer(CustomerEntity customer) {
if (customer.getId() == null) {
customer.setId(UUID.randomUUID().toString());
}
CustomerEntity entity = baseDAO.create(customer);
System.out.println(entity.toString());
return entity;
}
@Override
public CustomerEntity getCustomer(String cellNumber) {
List<CustomerEntity> entities = baseDAO.findByField("cellNumber", cellNumber);
return entities.get(0);
}
@Override
public CustomerEntity updateCustomerDetails(CustomerEntity customer) {
return baseDAO.update(customer);
}
@Override
public void deleteCustomer(CustomerEntity customer) {
baseDAO.delete(customer);
}
}
Application Context
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="za.co.thekeeper"/>
As requested.
New Update
BaseDAO
package za.co.thekeeper.dao;
import za.co.thekeeper.entities.BaseEntity;
import za.co.thekeeper.mongo.MongoConnection;
import java.util.List;
public interface BaseDAO<T extends BaseEntity> {
T create(T entity);
void delete(T entity);
T activate(T entity);
T deactivate(T entity);
void activate(String id);
void deactivate(String id);
T update(T entity);
void deleteById(String id);
T getById(String id);
List<T> findByField(String id, Object o);
void createDBRef(String databaseName, String collectionName, String id);
List<T> findAll();
}
private BaseDAO<CustomerEntity> baseDAO;
@Autowired
public void setBaseDAO(BaseDAO<CustomerEntity> baseDAO) {
this.baseDAO = baseDAO;
}
Try using constructor-injection
instead. Check if it helps
private BaseDAO<CustomerEntity> baseDAO;
@Autowired
public CustomerServiceImpl(BaseDAO<CustomerEntity> baseDAO) {
this.baseDAO = baseDAO;
}
You existing BaseDAOImpl:
private MongoConnection mongoConnection;
@Autowired
public void setMongoConnection(MongoConnection mongoConnection) {
System.out.println("In autowired setter");
this.mongoConnection = mongoConnection;
}
private Class<T> clazz;
@Autowired
public void setClazz(Class<T> clazz){
System.out.println("In class Autowired Setter");
this.clazz = clazz;
}
@Bean
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public Class<T> getClazz(){
return clazz;
}
public BaseDAOImpl() {
this.collection = MongoDbUtil.getCollection(mongoConnection.mongoDb(), clazz);
}
This is not the right way to initialize this bean.
mongoConnection
and accessing that in the default constructor. MongoDbUtil.getCollection(mongoConnection.mongoDb(), clazz);
The constructor gets called before the setter is invoked. This is going to result in NPE. @Autowired
on a setter and @Bean
on a getter is meaningless. @Repository
annotation is not required. You can use @Component
The right way to do things would be this.
BaseDAOImpl class - Including only a part of the class for brevity
package za.co.thekeeper.dao;
import org.mongojack.DBCursor;
import org.mongojack.DBQuery;
import org.mongojack.JacksonDBCollection;
import org.mongojack.WriteResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
import za.co.thekeeper.entities.BaseEntity;
import za.co.thekeeper.mongo.MongoConnection;
import za.co.thekeeper.mongo.MongoDbUtil;
import java.util.ArrayList;
import java.util.List;
public class BaseDAOImpl<T extends BaseEntity> implements BaseDAO<T> {
private JacksonDBCollection<T, String> collection;
/**Dependency Injections**/
private MongoConnection mongoConnection;
public void setMongoConnection(MongoConnection mongoConnection) {
System.out.println("In autowired setter");
this.mongoConnection = mongoConnection;
}
private Class<T> clazz;
public void setClazz(Class<T> clazz){
System.out.println("In class Autowired Setter");
this.clazz = clazz;
}
public Class<T> getClazz(){
return clazz;
}
public BaseDAOImpl(MongoCollection mongoCollection, Class<T> clazz) {
this.mongoCollection = mongoCollection;
this.clazz = clazz;
this.collection = MongoDbUtil.getCollection(mongoConnection.mongoDb(), clazz);
}
}
Spring configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:annotation-config/>
<context:component-scan base-package="za.co.thekeeper"/>
<bean class="za.co.thekeeper.dao.BaseDAOImpl">
<constructor-arg index="0" ref="mongoCollection"/>
<constructor-arg index="1">
<value type="java.lang.Class">CustomerEntity</value>
</constructor-arg>
</bean>
Spring will detect the type T from the second constructor injection and allow you to autowire beans of type BaseDAOImpl<CustomerEntity>
.
Note: I assume mongoCollection is declared as a spring bean elsewhere. Otherwise you need to add that in the spring configuration file.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.