EntityManagerProvider is injected as null

933 views Asked by At

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.");
    }

}
1

There are 1 answers

3
OndroMih On BEST ANSWER

The problem is that injection does never work with objects created directly using new keyword. And this is what you are doing in the getInstance() 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