question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

cannot start in PROD mode when assigning port explicitly with ebean

See original GitHub issue

Play Version (2.5.x / etc)

2.5.x

API (Scala / Java / Neither / Both)

Java

Operating System (Ubuntu 15.10 / MacOS 10.10 / Windows 10)

CentOS 7

JDK (Oracle 1.8.0_72, OpenJDK 1.8.x, Azul Zing)

openJDK 1.8.x

Library Dependencies

ebean

Expected Behavior

when I run:

applicationName/target/universal/stage/bin/applicationName -Dconfig.resource=production.conf -Dplay.evolutions.db.default.autoApply=true

The application works well.

However, when I run:

applicationName/target/universal/stage/bin/applicationName -Dhttp.port=9000 -Dconfig.resource=production.conf -Dplay.evolutions.db.default.autoApply=true

application cannot start.

Please describe the expected behavior of the issue, starting from the first action.

Actual Behavior

[error] c.a.ebean.Ebean - Error trying to create the default EbeanServer
java.lang.RuntimeException: DataSource user is null?
    at org.avaje.datasource.pool.ConnectionPool.<init>(ConnectionPool.java:204)
    at org.avaje.datasource.Factory.createPool(Factory.java:12)
    at com.avaje.ebeaninternal.server.core.DefaultContainer.getDataSourceFromConfig(DefaultContainer.java:309)
    at com.avaje.ebeaninternal.server.core.DefaultContainer.setDataSource(DefaultContainer.java:262)
    at com.avaje.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:105)
    at com.avaje.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:77)
    at com.avaje.ebeaninternal.server.core.DefaultContainer.createServer(DefaultContainer.java:44)
    at com.avaje.ebean.EbeanServerFactory.create(EbeanServerFactory.java:55)
    at com.avaje.ebean.Ebean$ServerManager.getWithCreate(Ebean.java:201)
    at com.avaje.ebean.Ebean$ServerManager.<init>(Ebean.java:159)
Oops, cannot start the server.
com.google.inject.CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.lang.NoClassDefFoundError: Could not initialize class com.avaje.ebean.Ebean
  at play.db.ebean.EbeanDynamicEvolutions.<init>(EbeanDynamicEvolutions.java:55)
  at play.db.ebean.EbeanDynamicEvolutions.class(EbeanDynamicEvolutions.java:44)
  while locating play.db.ebean.EbeanDynamicEvolutions
  at play.db.ebean.EbeanModule.bindings(EbeanModule.java:24):
Binding(class play.api.db.evolutions.DynamicEvolutions to ConstructionTarget(class play.db.ebean.EbeanDynamicEvolutions) eagerly) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
  while locating play.api.db.evolutions.DynamicEvolutions
Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.avaje.ebean.Ebean
    at com.avaje.ebean.EbeanServerFactory.create(EbeanServerFactory.java:73)
    at play.db.ebean.EbeanDynamicEvolutions.lambda$start$2(EbeanDynamicEvolutions.java:118)
    at java.util.HashMap.forEach(HashMap.java:1288)
    at play.db.ebean.EbeanDynamicEvolutions.start(EbeanDynamicEvolutions.java:114)
    at play.db.ebean.EbeanDynamicEvolutions.<init>(EbeanDynamicEvolutions.java:58)
    at play.db.ebean.EbeanDynamicEvolutions$$FastClassByGuice$$52c94231.newInstance(<generated>)
    at com.google.inject.internal.cglib.reflect.$FastConstructor.newInstance(FastConstructor.java:40)
    at com.google.inject.internal.DefaultConstructionProxyFactory$1.newInstance(DefaultConstructionProxyFactory.java:61)
    at com.google.inject.internal.ConstructorInjector.provision(ConstructorInjector.java:105)
    at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:85)
    at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:267)
    at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
    at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
    at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145)
    at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
    at com.google.inject.internal.FactoryProxy.get(FactoryProxy.java:56)
    at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
    at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
    at com.google.inject.internal.SingletonScope$1.get(SingletonScope.java:145)
    at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:41)
    at com.google.inject.internal.InternalInjectorCreator$1.call(InternalInjectorCreator.java:205)
    at com.google.inject.internal.InternalInjectorCreator$1.call(InternalInjectorCreator.java:199)
    at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1092)
    at com.google.inject.internal.InternalInjectorCreator.loadEagerSingletons(InternalInjectorCreator.java:199)
    at com.google.inject.internal.InternalInjectorCreator.injectDynamically(InternalInjectorCreator.java:180)
    at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:110)
    at com.google.inject.Guice.createInjector(Guice.java:96)
    at com.google.inject.Guice.createInjector(Guice.java:84)
    at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:181)
    at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:123)
    at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
    at play.core.server.ProdServerStart$.start(ProdServerStart.scala:47)
    at play.core.server.ProdServerStart$.main(ProdServerStart.scala:22)
    at play.core.server.ProdServerStart.main(ProdServerStart.scala)

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:6
  • Comments:35 (8 by maintainers)

github_iconTop GitHub Comments

11reactions
rowanlcommented, Dec 13, 2017

Essentially it’s not loading the EbeanDynamicEvolutions if you create your repository class like this you can make it work

` private final EbeanServer ebeanServer; private final DatabaseExecutionContext executionContext; private final EbeanDynamicEvolutions ebeanDynamicEvolutions;

@Inject
public YourRepository(EbeanConfig ebeanConfig, EbeanDynamicEvolutions ebeanDynamicEvolutions, DatabaseExecutionContext executionContext) {
    this.ebeanDynamicEvolutions = ebeanDynamicEvolutions;
    this.ebeanServer = Ebean.getServer(ebeanConfig.defaultServer());
    this.executionContext = executionContext;
}

`

Taken from in here :: https://github.com/playframework/play-ebean/issues/51

4reactions
antonhacommented, Nov 8, 2017

After banging my head against this issue for way too long, I have a theory. This is running play 2.6.7, but I think it probably applies to earlier versions as well.

The DataSource user is null? message gets printed when creating an EbeanServer. EbeanServer instances are created, and registered, through the static Ebean class.

The Play framework (at least in most examples) tries to create EbeanServers according to application config in EbeanDynamicEvolutions. This happens in the constructor, which is called by Guice (again, at least in most examples).

The thing that I think bites many people is that the examples, Ebean.getServer(name) is called in the constructor of Repository classes (e.g. CompanyRepository.java). This is again, called by Guice. The important thing here is that the getServer(name) method will try to create the ebean server if it does not exist.

Since, afaik, Guice has no pre-defined order when instantiating classes, the repository class might be created before the EbeanDynamicEvolutions instance. This leads to the repository class trying to create a server without any config, and thus the error. Since this depends on the rather arbitrary guice injection order + timing, a lot of the weird ‘causes’ in the comments above kind of makes sense.

I have been able to make this error stop happening by starting to use the Ebean.getServer(name) when accessing the database, instead of in repository constructors. E.g:

public class UserRepository {

    private final String ebeanServer;
    private final DatabaseExecutionContext executionContext;

    @Inject
    public UserRepository(EbeanConfig ebeanConfig, DatabaseExecutionContext executionContext) {
        this.ebeanServer = ebeanConfig.defaultServer();
        this.executionContext = executionContext;
    }

    public CompletionStage<Void> insert(User user) {
        return supplyAsync(
                () -> {
                    Ebean.getServer(ebeanServer).insert(user);
                    return null;
                },
                executionContext);
    }
}

I believe that either the docs should be updated with this, or that the race condition at DI should be resolved somehow. I don’t know which though 😉

Read more comments on GitHub >

github_iconTop Results From Across the Web

Play framework 2.3 - cannot start in production - Stack Overflow
This is a known issue caused by long variables beying generated when the project directory structure is too long.
Read more >
Play Change Log
Ebean is (also) its own project! HikariCP is the default connection pool; WS supports Server Name Identification (SNI). Highlights · Migration Guide ·...
Read more >
sbt Reference Manual — Combined Pages
You can also run sbt in batch mode, passing sbt commands directly from the ... Note: You cannot have a project subdirectory or...
Read more >
3.12 - The history of jOOQ. From 2009 to 2022
#9287, Parser cannot handle enum literals that are invalid java ... This is why, starting from jOOQ 3.12, we are now offering some...
Read more >
Modern Best Practices for Testing in Java - Philipp Hauer's Blog
Write dumb tests by avoiding the reuse of production code and ... Moreover, you can easily run into situations where you can't use...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found