iaL
iaL

Reputation: 386

Error injecting constructor in play java mongodb

I'm trying to inject my dao object in controller. I've done this: I've a:
1. MongoDBHelper
2. MerchantDAO
3. MerchantService
4. MerchantController

This is MongoDBHelper class:

import javax.inject.Singleton;

@Singleton
public class MongoDBHelper {
    private DB db;
    private Datastore datastore;
    private Configuration config = Play.application().configuration();

    private final String SERVER_URL = config.getString("server_url");

    private final String USERNAME = config.getString("database.userName");
    private final String PASSWORD = config.getString("database.password");
    private final String DATABASE_NAME = config.getString("database.name");

    public MongoDBHelper() {

        try {
            MongoClient mongoClient = new MongoClient();
            this.db = mongoClient.getDB(DATABASE_NAME);
            this.db.authenticate(USERNAME, PASSWORD.toCharArray());
            Morphia morphia = new Morphia();
            this.datastore = morphia.createDatastore(mongoClient, DATABASE_NAME);
            morphia.mapPackage("models");
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }

    public DB getDB() {
        return this.db;
    }

    public Datastore getDatastore() {
        return this.datastore;
    }
}

This is MerchantDAO class

public class MerchantDAO {

    @Inject MongoDBHelper mongoDBHelper;
    private Datastore datastore = mongoDBHelper.getDatastore();
    private DB db = mongoDBHelper.getDB();

    private static final String AUTH_TOKEN = "authToken";

    private static final Config config = ConfigFactory.load(Play.application().configuration().getString("property.file.name"));

    public void updateMerchantWithAuthToken(Merchant merchant){

        Query<Merchant> query = datastore.createQuery(Merchant.class).field(config.getString("string.email")).equal(merchant.getEmail());
        UpdateOperations<Merchant> ops = datastore.createUpdateOperations(Merchant.class).set(AUTH_TOKEN, merchant.getAuthToken()).set("lastRequestTime",merchant.getLastRequestTime());
        UpdateResults res = datastore.update(query, ops);
    }
 }
}

This is MerchantService class:

public class MerchantService {

    static final Config config = ConfigFactory.load(Play.application().configuration().getString("property.file.name"));

    @Inject
    MerchantDAO merchantDAO;

    // Creating unique authToken for already logged in merchant
    public String createToken(Merchant merchant) {
        merchantDAO.updateMerchantWithAuthToken(merchant);
        return authToken;
    }
}

This is MerchantController

import javax.inject.Inject;

public class MerchantController extends Controller {

    @Inject MerchantService merchantService;

    public final static String AUTH_TOKEN_HEADER = "X-AUTH-TOKEN";
    public static final String AUTH_TOKEN = "authToken";
    public static final Config config = ConfigFactory.load(Play.application().configuration().getString("property.file.name")); 

    public static Merchant getMerchant() {
        return (Merchant)Http.Context.current().args.get("merchant");
    }

    public Result login() throws Exception {
        // code to perform login
        return ok();  // status success / failure
    }
}

I'm getting following error:

ProvisionException: Unable to provision, see the following errors:

1) Error injecting constructor, java.lang.NullPointerException
  at daos.MerchantDAO.<init>(MerchantDAO.java:22)
  while locating daos.MerchantDAO
    for field at services.MerchantService.merchantDAO(MerchantService.java:26)
  while locating services.MerchantService
    for field at controllers.MerchantController.merchantService(MerchantController.java:21)
  while locating controllers.MerchantController
    for parameter 2 at router.Routes.<init>(Routes.scala:36)
  while locating router.Routes
  while locating play.api.inject.RoutesProvider
  while locating play.api.routing.Router

1 error

What am I possibly doing wrong? Why is DI not working properly?

Thanks in advance.

Upvotes: 0

Views: 1198

Answers (2)

Dordoka Maisu
Dordoka Maisu

Reputation: 101

The problem is that you are trying to access the Configuration object during the MongoDBHelper instantiation. You should just inject the play Configuration object to your module's constructor and initialize all properties within the constructor:

@Inject
public MongoDBHelper(Configuration configuration) {

  config = Play.application().configuration();
  <read the rest of the config values here>

See the note in the configurable bindings section of the D.I. documentation here

Upvotes: 0

schtever
schtever

Reputation: 3250

I think the problem is with these lines:

private Datastore datastore = mongoDBHelper.getDatastore();
private DB db = mongoDBHelper.getDB();

These are evaluated during the object instance's construction. I believe that injection won't occur until AFTER the object instance has completed construction. Therefore, mongoDBHelper is null while the above assignments are made.

One way to solve this would be to set datastore and db in the method updateMerchantWithAuthToken.

Upvotes: 1

Related Questions