如何覆盖 Play 的默认 Ebean 服务器配置?
How can I override Play's default Ebean server configuration?
我不想在 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)
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)
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.call(ProviderToInternalFactoryAdapter.java:46)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
更新
我能够通过从 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 服务器:
To customise the underlying Ebean Server configuration, you can either
add a conf/ebean.properties file, or create an instance of the
ServerConfigStartup interface to programmatically manipulate the Ebean
ServerConfig before the server is initialised.
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);
}
}
按照@BatteryAcid 的提示,我能够解决问题:
- 将 ebean 增强功能与 ebean 默认服务器实例化分开。
为此,我从
application.conf
文件中删除了 'ebean.default = ['models.*]'
设置。我将以下内容添加到 build.sbt
.
build.sbt
playEbeanModels in Compile := Seq("models.*")
playEbeanDebugLevel := 4
这确保您的模型得到增强。
- 为了服务器实例化,我保留了我的 EbeanServerProvider class
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
方法。您将必须以这种方式注册所有模型 classes。这意味着如果您有 10 个模型,您将有 10 个这样的 serverConfig.addClass
调用。这是愚蠢的。
有一个serverConfig.addPackage
方法,据说可以读取给定包中的所有模型并将其注册到EbeanServer。但这对我不起作用。由于我目前只有几个模型,因此此解决方案目前有效。
向导绑定
//Ebean server
bind(EbeanServer.class).toProvider(EbeanServerProvider.class).asEagerSingleton();
如果阅读本文的任何人有更好的解决方案,请在此处 post 解决。
我不想在 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)
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)
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.call(ProviderToInternalFactoryAdapter.java:46)
at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1103)
at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
更新
我能够通过从 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 服务器:
To customise the underlying Ebean Server configuration, you can either add a conf/ebean.properties file, or create an instance of the ServerConfigStartup interface to programmatically manipulate the Ebean ServerConfig before the server is initialised. 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);
}
}
按照@BatteryAcid 的提示,我能够解决问题:
- 将 ebean 增强功能与 ebean 默认服务器实例化分开。
为此,我从
application.conf
文件中删除了'ebean.default = ['models.*]'
设置。我将以下内容添加到build.sbt
.
build.sbt
playEbeanModels in Compile := Seq("models.*")
playEbeanDebugLevel := 4
这确保您的模型得到增强。
- 为了服务器实例化,我保留了我的 EbeanServerProvider class
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
方法。您将必须以这种方式注册所有模型 classes。这意味着如果您有 10 个模型,您将有 10 个这样的 serverConfig.addClass
调用。这是愚蠢的。
有一个serverConfig.addPackage
方法,据说可以读取给定包中的所有模型并将其注册到EbeanServer。但这对我不起作用。由于我目前只有几个模型,因此此解决方案目前有效。
向导绑定
//Ebean server
bind(EbeanServer.class).toProvider(EbeanServerProvider.class).asEagerSingleton();
如果阅读本文的任何人有更好的解决方案,请在此处 post 解决。