javapostgresqlplayframeworkebean

How to use double database in Play Framework with Ebean


I'm brand new with Play Framework and with Ebean. I need to configure a Play application to use two different database instances, one for reading and another for writing. I have been looking in it seems that this is a recurrent issue and I've tried all the possible solutions that I've been able to find, even the once that works for somebody and isn't working for me, for sure I'm doing something wrong, because the error has to do or looks like with the classloader.

build.sbt

lazy val root = (project in file(".")).enablePlugins(PlayJava, PlayEbean)
val playEbean = "6.0.0"
libraryDependencies ++= Seq(
...
"com.typesafe.play" % "play-ebean_2.13" % playEbean,
...

application.conf

db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://localhost:5432/db_writer"
db.default.username=username
db.default.password=pass

db.reader.driver=org.postgresql.Driver
db.reader.url="jdbc:postgresql://localhost:5432/db_reader"
db.reader.username=username
db.reader.password=pass

ebean.default = ["models.db_writer.*"]
ebean.reader = ["models.db_reader.*"]

play.ebean.defaultDatasource = "db_writer"

EbeanServerReader

import io.ebean.Ebean;
import io.ebean.EbeanServer;

public class EbeanServerReader {

    public static EbeanServer getReader() {
        return Ebean.getServer("reader");
    }
}

myDaoClass

public class myDaoClass {

    private final FetchConfig fetchConfig = new FetchConfig();
    private final EbeanServer reader = EbeanServerReader.getReader();
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
      public PagedList<SomeClass> findAllWithNoLimit(int pageIndex, int pageSize, String type) {
        return reader.find(SomeClass.class)
                .fetch("path", fetchConfig.lazy(100))
                .fetch("path", fetchConfig.lazy(100))
                .fetch("path", fetchConfig.lazy(100))
                .where()
                .eq("propertyName", type)
                .order()
                .desc("updatedAt")
                .setFirstRow(pageIndex * pageSize)
                .setMaxRows(pageSize)
                .findPagedList();
    }

Error trace:

1) Error injecting constructor, java.lang.NoClassDefFoundError: Could not initialize class io.ebean.Ebean
  at models.myDaoClass.<init>(myDaoClass.java:12)
  while locating models.myDaoClass
    for the 1st parameter of models.myDaoClass.<init>(myDaoClass.java:33)
  while locating models.myDaoClass

1 error
    at com.google.inject.internal.InternalProvisionException.toProvisionException(InternalProvisionException.java:226)
    at com.google.inject.internal.InjectorImpl$1.get(InjectorImpl.java:1097)
    at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1131)
    at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:436)
    at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:431)
    at play.api.inject.ContextClassLoaderInjector.$anonfun$instanceOf$2(Injector.scala:119)
    at play.api.inject.ContextClassLoaderInjector.withContext(Injector.scala:128)
    at play.api.inject.ContextClassLoaderInjector.instanceOf(Injector.scala:119)
    at play.api.libs.concurrent.ActorRefProvider.$anonfun$get$1(Akka.scala:268)
    at akka.actor.TypedCreatorFunctionConsumer.produce(IndirectActorProducer.scala:91)
    at akka.actor.Props.newActor(Props.scala:226)
    at akka.actor.ActorCell.newActor(ActorCell.scala:613)
    at akka.actor.ActorCell.create(ActorCell.scala:640)
    ... 9 common frames omitted
Caused by: java.lang.NoClassDefFoundError: Could not initialize class io.ebean.Ebean
    at module.EbeanServerReader.getReader(EbeanServerReader.java:8)

What am I doing wrong here? I've try another stuffs, like @Inject but is the same.

Kind regards


Solution

  • Problem solved by replacing:

    ebean.default = ["models.db_writer.*"]
    ebean.reader = ["models.db_reader.*"]
    

    with this:

    ebean.default = ["models.*"]
    ebean.writer = ["models.*"]
    

    as my application uses the same class model just different db instances, one for reading and another for writing.