0

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.

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I moved those to initializations into updateMerchantWithAuthToken temporaily. But still getting this error: [info] play.api.UnexpectedException: Unexpected exception[ProvisionException: Unable to provision, see the following errors: [info] [info] 1) Error injecting constructor, org.mongodb.morphia.mapping.MappingException: Could not get map classes from package models [info] at daos.MerchantDAO.<init>(MerchantDAO.java:20) [info] while locating daos.MerchantDAO [info] for field at services.MerchantService.merchantDAO(MerchantService.java:25) ...
I guess the problem is with my mongodb helper class...I think its not able to map the models. Any help will be appreciated. Thanks.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.