From 2fb3e8c2b916d0cc6a6873be281bd1de7c023054 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Thu, 8 Oct 2026 18:35:09 +0200 Subject: [PATCH 1/2] Fix the default datasource setting in the docs, explain startup usage The docs named a non-existent ebeanconfig.datasource.default setting to choose the default Ebean server; it's play.ebean.defaultDatasource. Also explain that components using Ebean while they get created have to depend on DynamicEvolutions, which creates the Ebean databases, that this doesn't mean that the evolutions have been applied yet, and how to let Play apply them automatically in dev mode only. --- .../working/javaGuide/main/sql/JavaEbean.md | 16 +++++++++++- .../code/javaguide/ebean/TaskRepository.java | 26 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 docs/manual/working/javaGuide/main/sql/code/javaguide/ebean/TaskRepository.java diff --git a/docs/manual/working/javaGuide/main/sql/JavaEbean.md b/docs/manual/working/javaGuide/main/sql/JavaEbean.md index ef7102ee..9286a012 100644 --- a/docs/manual/working/javaGuide/main/sql/JavaEbean.md +++ b/docs/manual/working/javaGuide/main/sql/JavaEbean.md @@ -26,7 +26,7 @@ The runtime library can be configured by putting the list of packages and/or cla ebean.default = ["models.*"] ``` -This defines a `default` Ebean server, using the `default` data source, which must be properly configured. You can also override the name of the default Ebean server by configuring `ebeanconfig.datasource.default` property. This might be useful if you want to use separate databases for testing and development. You can actually create as many Ebean servers you need, and explicitly define the mapped class for each server: +This defines a `default` Ebean server, using the `default` data source, which must be properly configured. You can also override the name of the default Ebean server by configuring the `play.ebean.defaultDatasource` property. This might be useful if you want to use separate databases for testing and development. You can actually create as many Ebean servers you need, and explicitly define the mapped class for each server: ```properties ebean.orders = ["models.Order", "models.OrderItem"] @@ -138,3 +138,17 @@ If your class is an action, you can annotate your action method with `@play.db.e Or if you want a more traditional approach you can begin, commit and rollback transactions explicitly: @[traditional](code/javaguide/ebean/JavaEbeanTest.java) + +## Using Ebean during application startup + +Play Ebean creates the Ebean databases while the application starts, and Ebean's static API (like `DB.getDefault()`, but also the methods of `Model` and finders) only works afterwards. So if a component uses Ebean while it gets created, e.g. in the constructor of an eagerly bound component, or of one created via Guice's static injection, make it depend on `play.api.db.evolutions.DynamicEvolutions`. Play Ebean binds that one, and it creates the databases: + +@[startup](code/javaguide/ebean/TaskRepository.java) + +Otherwise Ebean tries to create the database itself from its own configuration. That usually fails, e.g. with `Configuration error creating DataSource for the default Database`, and leaves Ebean unusable until the JVM restarts. A later error like `NoClassDefFoundError: Could not initialize class io.ebean.DbContext` only means that this initialization failed before, so look for the first error to find out why. + +Note that this only makes sure that the databases exist, not that the evolutions have been applied. In dev mode, Play only applies pending evolutions once you confirm them in the browser, and it can't show that page if the application fails to start, e.g. because a component queries a table that doesn't exist yet. Depending on `play.api.db.evolutions.ApplicationEvolutions` doesn't help with that either, as in dev mode it doesn't wait for pending evolutions (its `upToDate()` method tells if there are any). So don't use the database schema while components get created, but later, e.g. when they get used for the first time. Or let Play apply the evolutions automatically, which you can limit to dev mode in your `build.sbt`: + +```scala +PlayKeys.devSettings += "play.evolutions.db.default.autoApply" -> "true" +``` diff --git a/docs/manual/working/javaGuide/main/sql/code/javaguide/ebean/TaskRepository.java b/docs/manual/working/javaGuide/main/sql/code/javaguide/ebean/TaskRepository.java new file mode 100644 index 00000000..8fd0f4e9 --- /dev/null +++ b/docs/manual/working/javaGuide/main/sql/code/javaguide/ebean/TaskRepository.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) from 2022 The Play Framework Contributors , 2011-2021 Lightbend Inc. + */ + +// #startup +// ###replace: package repositories; +package javaguide.ebean; + +import io.ebean.DB; +import io.ebean.Database; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; +import play.api.db.evolutions.DynamicEvolutions; + +@Singleton +public class TaskRepository { + + private final Database database; + + @Inject + public TaskRepository(DynamicEvolutions ebeanDatabases) { + // Play Ebean has created its Ebean databases by now + this.database = DB.getDefault(); + } +} +// #startup From b1cd30b71c4162ced9c7b1b52ffe6d1dd0d52f21 Mon Sep 17 00:00:00 2001 From: Matthias Kurz Date: Thu, 8 Oct 2026 18:52:49 +0200 Subject: [PATCH 2/2] Clarify the dev mode default, warn about automatically applied downs In dev mode, Play only waits for pending evolutions to be confirmed by default, i.e. without autoApply. And with autoApply, a regenerated 1.sql makes Play apply the downs of its previous version first, which drops the tables, so the development data gets lost. --- docs/manual/working/javaGuide/main/sql/JavaEbean.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/manual/working/javaGuide/main/sql/JavaEbean.md b/docs/manual/working/javaGuide/main/sql/JavaEbean.md index 9286a012..2be237b8 100644 --- a/docs/manual/working/javaGuide/main/sql/JavaEbean.md +++ b/docs/manual/working/javaGuide/main/sql/JavaEbean.md @@ -147,8 +147,10 @@ Play Ebean creates the Ebean databases while the application starts, and Ebean's Otherwise Ebean tries to create the database itself from its own configuration. That usually fails, e.g. with `Configuration error creating DataSource for the default Database`, and leaves Ebean unusable until the JVM restarts. A later error like `NoClassDefFoundError: Could not initialize class io.ebean.DbContext` only means that this initialization failed before, so look for the first error to find out why. -Note that this only makes sure that the databases exist, not that the evolutions have been applied. In dev mode, Play only applies pending evolutions once you confirm them in the browser, and it can't show that page if the application fails to start, e.g. because a component queries a table that doesn't exist yet. Depending on `play.api.db.evolutions.ApplicationEvolutions` doesn't help with that either, as in dev mode it doesn't wait for pending evolutions (its `upToDate()` method tells if there are any). So don't use the database schema while components get created, but later, e.g. when they get used for the first time. Or let Play apply the evolutions automatically, which you can limit to dev mode in your `build.sbt`: +Note that this only makes sure that the databases exist, not that the evolutions have been applied. By default, in dev mode, Play only applies pending evolutions once you confirm them in the browser, and it can't show that page if the application fails to start, e.g. because a component queries a table that doesn't exist yet. Depending on `play.api.db.evolutions.ApplicationEvolutions` doesn't help with that either, as in dev mode it doesn't wait for pending evolutions (its `upToDate()` method tells if there are any). So don't use the database schema while components get created, but later, e.g. when they get used for the first time. Or let Play apply the evolutions automatically, which you can limit to dev mode in your `build.sbt`: ```scala PlayKeys.devSettings += "play.evolutions.db.default.autoApply" -> "true" ``` + +Be aware that this also applies down scripts automatically: when Play Ebean regenerates `conf/evolutions/default/1.sql` because your models changed, Play first reverts the previous version of that script, which drops the tables, so the data in your development database gets lost.