Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion docs/manual/working/javaGuide/main/sql/JavaEbean.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down Expand Up @@ -138,3 +138,19 @@ 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. 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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
*/

// #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