2015-12-18 25 views
6

Non voglio definire la configurazione predefinita del database nel file application.conf. Invece, voglio costruire l'EbeanServer di default a livello di codice e iniettarlo da solo nel DAO.Come posso eseguire l'override della configurazione del server Ebean predefinito di Play?

Il problema che sto riscontrando è, se creo un binding guice per un provider EbeanServer e non definisco alcuna configurazione nel file application.conf, riprodurre errori dicendo che non è possibile trovare una configurazione predefinita.

Ecco il codice che ho:

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.*"] 

modulo Guice vincolante

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

Errore:

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) 
+0

Aggiornato la mia risposta qui sotto - confronta le note serverConfigs e application.conf. – BatteryAcid

risposta

3

sono stato in grado di risolvere il problema dopo aver seguito il suggerimento da @BatteryAcid:

  1. Separare il miglioramento ebean dall'istanza di server predefinita ebean. Per fare ciò ho rimosso l'impostazione 'ebean.default = ['models.*]' dal file application.conf. Ho aggiunto quanto segue a build.sbt.

build.sbt

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

Questo assicura che i vostri modelli sono stati migliorati.

  1. per l'esecuzione dell'istanza del server ho mantenuto la mia classe EbeanServerProvider

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; 
    } 
} 

La cosa da notare qui è il metodo serverConfig.addClass. Dovrai registrare tutte le classi di modelli in questo modo. Il che significa che se hai 10 modelli, avrai 10 chiamate di questo tipo allo serverConfig.addClass. Che è stupido

C'è un metodo serverConfig.addPackage, che presumibilmente può leggere tutti i modelli in un determinato pacchetto e registrarlo con EbeanServer. Ma non ha funzionato con me. Poiché al momento ho solo pochi modelli, questa soluzione funziona per ora.

Guice vincolante

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

Se qualcuno di voi leggendo questo ha una soluzione migliore, si prega di non postare qui.

+0

Stavo vedendo lo stesso comportamento con 'serverConfig.addPackage' - non sono sicuro del motivo per cui non funziona. – BatteryAcid

+0

funzionerà con le evoluzioni? – Peace

1

UPDATE

ero in grado di andare in giro la vostra eccezione rimuovendo il ebean.default dal application.conf e utilizzando questo get() in EbeanServerProvider. L'unico problema è che non ho potuto ottenere ebean per scansionare un intero pacchetto, quindi ho elencato manualmente le mie classi modello (Configuration) - sarebbe stato un problema ma almeno l'ho ristretto.

@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); 
    } 

----- Probabilmente si può ignorare il seguito ---

Date un'occhiata a questo, non ho ancora testato io stesso, ma forse sarà farti puntato nella giusta direzione.

Secondo Play 2.4 documenti è possibile implementare ServerConfigStartup per personalizzare un server ebean prima del suo inizio:

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); 
    } 
} 
+0

L'ho provato. Il problema è che se si estrae ebean.default da application.conf, Play non eseguirà l'ottimizzazione del modello ebean. Più in particolare la manipolazione del codice byte su cui si basa ebean. – jesukumar