CreationException: Unable to create injector error in Play 2.5.18 in replacement for GlobalSettings Java code using com.google.inject.Ab


(Dan Zeller) #1

I am upgrading my Play application from 2.5.12 to 2.5.18 and when I start up the application (using sbt ), I am receiving this error:

CreationException: Unable to create injector, see the following errors:

  1. Error injecting constructor, java.lang.NullPointerException
    at modules.OnStart.(OnStart.java:15)
    at modules.Global.configure(Global.java:9) (via modules: com.google.inject.util.Modules$OverrideModule -> modules.Global)
    while locating modules.OnStart

1 error

The rest of the error is:

No source available, here is the exception stack trace:
->com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.lang.NullPointerException
  at modules.OnStart.<init>(OnStart.java:15)
  at modules.Global.configure(Global.java:9) (via modules: com.google.inject.util.Modules$OverrideModule -> modules.Global)
  while locating modules.OnStart

1 error
     com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:470)
     com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:184)
     com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110)
     com.google.inject.Guice.createInjector(Guice.java:99)
     com.google.inject.Guice.createInjector(Guice.java:84)
     play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:181)
     play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:137)
     play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
     play.core.server.DevServerStart$anon$1.$anonfun$get$6(DevServerStart.scala:171)
     play.utils.Threads$.withContextClassLoader(Threads.scala:21)
     play.core.server.DevServerStart$anon$1.$anonfun$get$3(DevServerStart.scala:168)
     scala.Option.map(Option.scala:146)
     play.core.server.DevServerStart$anon$1.$anonfun$get$2(DevServerStart.scala:133)
     scala.util.Success.flatMap(Try.scala:247)
     play.core.server.DevServerStart$anon$1.$anonfun$get$1(DevServerStart.scala:131)
     scala.concurrent.Future$.$anonfun$apply$1(Future.scala:655)
     scala.util.Success.$anonfun$map$1(Try.scala:251)
     scala.util.Success.map(Try.scala:209)
     scala.concurrent.Future.$anonfun$map$1(Future.scala:289)
     scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:29)
     scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:29)
     scala.concurrent.impl.CallbackRunnable.run(Promise.scala:60)
     scala.concurrent.impl.ExecutionContextImpl$AdaptedForkJoinTask.exec(ExecutionContextImpl.scala:140)
     java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
     java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
     java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
     java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)

I created new modules to replace the deprecated GlobalSettings based on this post:

https://www.playframework.com/documentation/2.5.x/GlobalSettings

Here are the classes mentioned in the error:

Global.java

package modules;

import com.google.inject.AbstractModule;

public class Global extends AbstractModule {

    @Override
    public void configure() {
        bind(OnStart.class).asEagerSingleton();
        bind(OnStop.class).asEagerSingleton();
    }

}

OnStart.java

package modules;

import javax.inject.Inject;
import javax.inject.Singleton;

import jobs.JobControl;
import play.Configuration;
import play.Logger;

@SuppressWarnings("deprecation")
@Singleton
public class OnStart {

    @Inject
    public OnStart() {
        Logger.debug("Application started...");     
        // Turn on scheduler?
        String schedulerEnabled;
        String dueDateRun;
        schedulerEnabled = Configuration.root().getString("scheduler.enabled");
        dueDateRun = Configuration.root().getString("duedate.run.flag");
        if (schedulerEnabled.equals("true")) {
            //JobControl.cleanupTables();
            //JobControl.emptyRecycleBin();
            if (dueDateRun.equals("on")) {
                JobControl.dueDateNotifications();
            }
        }
    }
}

I am not sure what to do to fix this.


(Dan Zeller) #2

I updated my OnStart.java to:

package modules;

import javax.inject.Inject;
import javax.inject.Singleton;

import jobs.JobControl;
import com.typesafe.config.Config;
import play.Logger;

@Singleton
public class OnStart {

    @Inject
    public OnStart(Config config) {
        Logger.debug("Application started...");     
        // Turn on scheduler?
        String schedulerEnabled;
        String dueDateRun;
        schedulerEnabled = config.getString("scheduler.enabled");
        dueDateRun = config.getString("duedate.run.flag");
        if (schedulerEnabled.equals("true")) {
            //JobControl.cleanupTables();
            //JobControl.emptyRecycleBin();
            if (dueDateRun.equals("on")) {
                JobControl.dueDateNotifications();
            }
        }
    }
}

Fixed the problem…


(Rich Dougherty) #3

Glad you got it worked out. Which line was throwing the NPE?


(Dan Zeller) #4

It was:

public OnStart() {


(Rich Dougherty) #5

That’s odd since that line doesn’t have any code!


(Greg Methvin) #6

I’m pretty sure the problem was Configuration.root(). Strangely, Configuration.root() doesn’t use play.api.Play.current() to get the current app like most other global state in Play. Instead it uses play.api.Play.unsafeApplication(), which would be null before the app starts. So you get a NPE rather than a more useful “there is no started application” error. Either way, the problem is trying to use global application state before the app is actually started.