I'm using the ninja framework, which utilizes JPA to access a database.
I've managed to set up a connection and get it running in an example controller class.
I'd like to model a "userManager" which, upon initialization, loads all current users from the database into a java map.
When doing so, I face a java.lang.NullPointerException upon calling entitiyManagerProvider.get() since entitiyManagerProvider is set to null.
I'm not sure what is causing this problem and how to solve it, as the "UserManager" has the same annotations as my (problem-free) test controller. Since I don't have any experience with ninja or JPA it might be a very simple fix I simply overlook and I'd appreciate any help.
This is the code for "UserManager.java":
package model;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import com.google.inject.Inject;
import com.google.inject.Provider;
import dto.UserDTO;
import ninja.jpa.UnitOfWork;
public class UserManager {
@Inject
Provider<EntityManager> entitiyManagerProvider;
private static UserManager instance;
private Map<Integer, UserDTO> users = new HashMap<Integer, UserDTO>();
//UserManager is a Singleton
public static synchronized UserManager getInstance(){
if (UserManager.instance == null){
UserManager.instance = new UserManager();
}
return UserManager.instance;
}
private UserManager() {
// load all existing users to map
reloadUsersFromDb();
}
public int getAmountUsers(){
return users.values().size();
}
/**
* reloads ALL users in the map from the db
*/
@UnitOfWork
private void reloadUsersFromDb() {
if (entitiyManagerProvider == null) {
System.out.println("provider is null"); //this is printed
} else {
System.out.println("provider is NOT null"); //not printed
}
EntityManager entityManager = entitiyManagerProvider.get();
//^-- causes null Pointer exception
Query q = entityManager.createQuery("SELECT users FROM users");
List<UserDTO> dbUsers = q.getResultList();
int loadedUsers = 0;
users.clear();
for (UserDTO dbUser : dbUsers) {
users.put(dbUser.getId(), dbUser);
loadedUsers++;
}
System.out.println("loaded " + loadedUsers + "users from db to applicaton.");
}
}
The problem is that injection does never work with objects created directly using
new
keyword. And this is what you are doing in thegetInstance()
method. Also you should not depend on injected values in the constructor, as they are injected only after the object is created.To turn on injection, the instance of
UserManager
must be created by the framework. Controllers are automatically created by the framework, therefore injection works there.To fix your code, you could create a service out of
UserManager
, remove call to reloadUsersFromDb from constructor and mark this method to run at startup with@Start
as described here in Ninja framework documentation