如何覆盖Play的默认Ebean服务器配置?

时间:2015-12-18 07:47:15

标签: playframework ebean playframework-2.4

我不想在application.conf文件中定义默认数据库配置。相反,我想以编程方式构造默认的EbeanServer并将其自己注入DAO。

我遇到的问题是,如果我为EbeanServer提供程序创建了一个guice绑定而没有在application.conf文件中定义任何配置,则播放错误,说它无法找到默认配置。

这是我的代码:

public class EbeanServerProvider implements Provider<EbeanServer> {

    final Logger.ALogger log = Logger.of(this.getClass());

    @Override
    public EbeanServer get() {

        ServerConfig serverConfig = new ServerConfig();
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        Config dbConfig = ConfigFactory.load(classLoader,"env/default.conf");

        /* Read the config files */
        final String DB_DRIVER   = dbConfig.getString("db.default.driver");
        final String DB_URL      = dbConfig.getString("db.default.url");
        final String DB_USERNAME = dbConfig.getString("db.default.username");
        final String DB_PASSWORD = dbConfig.getString("db.default.password");

        log.debug("{}",DB_DRIVER);
        log.debug("{}",DB_URL);
        log.debug("{}",DB_USERNAME);
        log.debug("{}",DB_PASSWORD);
        /* Load the database driver */
        dataSourceConfig.setDriver(DB_DRIVER);
        try{
            Class.forName(DB_DRIVER).newInstance();
        }
        catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            log.error("Unable to load database driver:{}",DB_DRIVER);
            throw new WrappedServerError(InternalErrorCode.TA_ERROR,"Failed to load database driver",e);
        }

        /* Set the data source configs */
        dataSourceConfig.setUrl(DB_URL);
        dataSourceConfig.setUsername(DB_USERNAME);
        dataSourceConfig.setPassword(DB_PASSWORD);
        dataSourceConfig.setCaptureStackTrace(true);


        serverConfig.setDataSourceConfig(dataSourceConfig);
        serverConfig.setName("mysql");
        serverConfig.setDefaultServer(true);
        serverConfig.setDdlGenerate(false);
        serverConfig.setDdlRun(false);
        serverConfig.setRegister(true);

        EbeanServer dbServer=null;
        try {
            dbServer = EbeanServerFactory.create(serverConfig);
        }
        catch (Exception e){
            throw new WrappedServerError(InternalErrorCode.TA_INIT_ERROR,"Failed to create ebean server",e);
        }

        return dbServer;
    }
}

application.conf

# Ebean configuration
ebean.default = ["com.giraffe.models.*"]

guice模块绑定

    //Ebean server
  bind(EbeanServer.class).toProvider(EbeanServerProvider.class).asEagerSingleton();

错误:

play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:

1) Error in custom provider, Configuration error: Configuration error[null]
  while locating play.db.ebean.DefaultEbeanConfig$EbeanConfigParser
  at play.db.ebean.EbeanModule.bindings(EbeanModule.java:24):
Binding(interface play.db.ebean.EbeanConfig to ProviderConstructionTarget(class play.db.ebean.DefaultEbeanConfig$EbeanConfigParser) eagerly) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
  while locating play.db.ebean.EbeanConfig
    for parameter 0 at play.db.ebean.EbeanDynamicEvolutions.<init>(EbeanDynamicEvolutions.java:36)
  at play.db.ebean.EbeanDynamicEvolutions.class(EbeanDynamicEvolutions.java:33)
  while locating play.db.ebean.EbeanDynamicEvolutions
  at play.db.ebean.EbeanModule.bindings(EbeanModule.java:23):
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: Configuration error: Configuration error[null]
    at play.api.Configuration$.configError(Configuration.scala:178)
    at play.api.Configuration.reportError(Configuration.scala:829)
    at play.Configuration.reportError(Configuration.java:351)
    at play.db.ebean.DefaultEbeanConfig$EbeanConfigParser.parse(DefaultEbeanConfig.java:81)
    at play.db.ebean.DefaultEbeanConfig$EbeanConfigParser.get(DefaultEbeanConfig.java:60)
    at play.db.ebean.DefaultEbeanConfig$EbeanConfigParser.get(DefaultEbeanConfig.java:44)
    at com.google.inject.internal.ProviderInternalFactory.provision(ProviderInternalFactory.java:81)
    at com.google.inject.internal.BoundProviderFactory.provision(BoundProviderFactory.java:72)
    at com.google.inject.internal.ProviderInternalFactory.circularGet(ProviderInternalFactory.java:61)
    at com.google.inject.internal.BoundProviderFactory.get(BoundProviderFactory.java:62)
    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)

2 个答案:

答案 0 :(得分:5)

在遵循@BatteryAcid的提示后,我能够解决问题:

  1. 将ebean增强功能与ebean默认服务器实例化分开。 为此,我从'ebean.default = ['models.*]'文件中删除了application.conf设置。我将以下内容添加到build.sbt
  2. build.sbt

    playEbeanModels in Compile := Seq("models.*")
    playEbeanDebugLevel := 4
    

    这可确保您的模型得到增强。

    1. 对于服务器实例化,我保留了我的EbeanServerProvider类
    2. EbeanServerProvider.java

      public class EbeanServerProvider implements Provider<EbeanServer> {
      
          final Logger.ALogger log = Logger.of(this.getClass());
      
          @Override
          public EbeanServer get() {
      
              ServerConfig serverConfig = new ServerConfig();
              DataSourceConfig dataSourceConfig = new DataSourceConfig();
              ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
      
              Config dbConfig = ConfigFactory.load(classLoader,"env/default.conf");
      
              /* Read the config files */
              final String DB_DRIVER   = dbConfig.getString("db.default.driver");
              final String DB_URL      = dbConfig.getString("db.default.url");
              final String DB_USERNAME = dbConfig.getString("db.default.username");
              final String DB_PASSWORD = dbConfig.getString("db.default.password");
      
              log.debug("{}",DB_DRIVER);
              log.debug("{}",DB_URL);
              log.debug("{}",DB_USERNAME);
              log.debug("{}",DB_PASSWORD);
              /* Load the database driver */
              dataSourceConfig.setDriver(DB_DRIVER);
              try{
                  Class.forName(DB_DRIVER).newInstance();
              }
              catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
                  log.error("Unable to load database driver:{}",DB_DRIVER);
                  throw new WrappedServerError(InternalErrorCode.TA_ERROR,"Failed to load database driver",e);
              }
      
              /* Set the data source configs */
              dataSourceConfig.setUrl(DB_URL);
              dataSourceConfig.setUsername(DB_USERNAME);
              dataSourceConfig.setPassword(DB_PASSWORD);
              dataSourceConfig.setCaptureStackTrace(true);
      
      
              serverConfig.setDataSourceConfig(dataSourceConfig);
              serverConfig.setName("mysql");
              serverConfig.setDefaultServer(true);
              serverConfig.setDdlGenerate(false);
              serverConfig.setDdlRun(false);
              serverConfig.setRegister(true);
      
              /* Add the models to the package */
              serverConfig.addClass(<your model class>);
      
              EbeanServer dbServer=null;
              try {
                  dbServer = EbeanServerFactory.create(serverConfig);
              }
              catch (Exception e){
                  throw new WrappedServerError(InternalErrorCode.TA_INIT_ERROR,"Failed to create ebean server",e);
              }
      
              return dbServer;
          }
      }
      

      这里要注意的是serverConfig.addClass方法。您必须以这种方式注册所有模型类。这意味着如果你有10个模型,你将有10个这样的调用serverConfig.addClass。这是愚蠢的。

      有一个serverConfig.addPackage方法,据说可以读取给定包中的所有模型并将其注册到EbeanServer。但它没有用。由于我目前只有几个型号,因此该解决方案现在可以使用。

      Guice binding

      //Ebean server
       bind(EbeanServer.class).toProvider(EbeanServerProvider.class).asEagerSingleton();
      

      如果您有任何人阅读此内容有更好的解决方案,请在此处发布。

答案 1 :(得分:1)

<强>更新

我能够通过从application.conf中删除ebean.default并在EbeanServerProvider中使用此get()来解决您的异常。唯一的问题是我无法让ebean扫描整个软件包,所以我手动列出了我的模型类(配置) - 这将是一个痛苦但至少我已经缩小了它。

    @Override
    public EbeanServer get() {
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        /* Set the data source configs */
        dataSourceConfig.setDriver("com.mysql.jdbc.Driver");
        dataSourceConfig.setUrl("jdbc:mysql://localhost/my_db");
        dataSourceConfig.setUsername("username");
        dataSourceConfig.setPassword("password");

        ServerConfig serverConfig = new ServerConfig();
        serverConfig.setName("default");
        serverConfig.setRegister(true);
        serverConfig.setDefaultServer(true);
        serverConfig.setDataSourceConfig(dataSourceConfig);
        serverConfig.setDatabasePlatform(new com.avaje.ebean.config.dbplatform.MySqlPlatform());

        //how to add a whole package?
        serverConfig.addClass(Configuration.class);

        return EbeanServerFactory.create(serverConfig);
    }

-----您可以忽略以下---

看看这个,我自己还没有测试过,但也许它会让你指向正确的方向。

根据Play 2.4文档,您可以实现ServerConfigStartup以在启动之前自定义ebean服务器:

  

要自定义基础Ebean服务器配置,您也可以   添加一个conf / ebean.properties文件,或创建一个实例   ServerConfigStartup接口以编程方式操作Ebean   初始化服务器之前的ServerConfig 。   https://www.playframework.com/documentation/2.4.x/JavaEbean#Configuring-the-runtime-library

import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.event.ServerConfigStartup;

public class MyServerConfigStartup implements ServerConfigStartup {

    public void onStart(ServerConfig serverConfig) {
        DataSourceConfig dataSourceConfig = new DataSourceConfig();
        /* Set the data source configs */
        dataSourceConfig.setUrl(DB_URL);
        dataSourceConfig.setUsername(DB_USERNAME);
        dataSourceConfig.setPassword(DB_PASSWORD);
        dataSourceConfig.setCaptureStackTrace(true);

        serverConfig.setDataSourceConfig(dataSourceConfig);
    }
}