Permalink
Browse files

Clean up the ClassLoader support from #1152:

The original implementation had to be binary compatible with 3.0.0. It
can be simplified (using default arguments instead of overloads) and
improved (allowing a custom ClassLoader in JdbcBackend) for 3.1 where
binary compatibility with 3.0.0 is not a concern.
  • Loading branch information...
szeiger committed Jul 16, 2015
1 parent b8bc4c9 commit 4565f09fef915b24d2155f5173d0f8053c3ac614
@@ -52,33 +52,11 @@ object DatabaseConfig {
* for the top level of the `Config` object.
* @param config The `Config` object to read from. This defaults to the global app config
* (e.g. in `application.conf` at the root of the class path) if not specified.
* @param classLoader The ClassLoader to use to load any custom classes from. The default is to
* try the context ClassLoader first and fall back to Slick's ClassLoader.
*/
def forConfig[P <: BasicProfile : ClassTag](path: String, config: Config = ConfigFactory.load()): DatabaseConfig[P] = {
forConfig(path, config, ClassLoaderUtil.defaultClassLoader)
}
/** Load a driver and database configuration through
* [[https://github.com/typesafehub/config Typesafe Config]].
*
* The following config parameters are available:
* <ul>
* <li>`driver` (String, required): The fully qualified name of a class or object which
* implements the specified profile. If the name ends with `$` it is assumed to be an object
* name, otherwise a class name.</li>
* <li>`db` (Config, optional): The configuration of a database for the driver's backend.
* For JdbcProfile-based' drivers (and thus JdbcBackend), see
* `JdbcBackend.DatabaseFactory.forConfig` for parameters that should be defined inside of
* `db`.</li>
* </ul>
*
* @param path The path in the configuration file for the database configuration (e.g. `foo.bar`
* would find a driver name at config key `foo.bar.driver`) or an empty string
* for the top level of the `Config` object.
* @param config The `Config` object to read from. This defaults to the global app config
* (e.g. in `application.conf` at the root of the class path) if not specified.
* @param classLoader The ClassLoader to use to load any custom classes from.
*/
def forConfig[P <: BasicProfile : ClassTag](path: String, config: Config, classLoader: ClassLoader): DatabaseConfig[P] = {
def forConfig[P <: BasicProfile : ClassTag](path: String, config: Config = ConfigFactory.load(),
classLoader: ClassLoader = ClassLoaderUtil.defaultClassLoader): DatabaseConfig[P] = {
val n = config.getString((if(path.isEmpty) "" else path + ".") + "driver")
val untypedP = try {
if(n.endsWith("$")) classLoader.loadClass(n).getField("MODULE$").get(null)
@@ -105,14 +83,7 @@ object DatabaseConfig {
* the root of the class path), otherwise as a path in the configuration located at the URI
* without the fragment, which must be a valid URL. Without a fragment, the whole config object
* is used. */
def forURI[P <: BasicProfile : ClassTag](uri: URI): DatabaseConfig[P] = forURI(uri, ClassLoaderUtil.defaultClassLoader)
/** Load a driver and database configuration from the specified URI. If only a fragment name
* is given, it is resolved as a path in the global app config (e.g. in `application.conf` at
* the root of the class path), otherwise as a path in the configuration located at the URI
* without the fragment, which must be a valid URL. Without a fragment, the whole config object
* is used. */
def forURI[P <: BasicProfile : ClassTag](uri: URI, classLoader: ClassLoader): DatabaseConfig[P] = {
def forURI[P <: BasicProfile : ClassTag](uri: URI, classLoader: ClassLoader = ClassLoaderUtil.defaultClassLoader): DatabaseConfig[P] = {
val (base, path) = {
val f = uri.getRawFragment
val s = uri.toString
@@ -218,9 +218,12 @@ trait JdbcBackend extends RelationalBackend {
* the `driver` key from the configuration is ignored. The default is to use the
* standard lookup mechanism. The explicit driver may not be supported by all
* connection pools (in particular, the default [[HikariCPJdbcDataSource]]).
* @param classLoader The ClassLoader to use to load any custom classes from. The default is to
* try the context ClassLoader first and fall back to Slick's ClassLoader.
*/
def forConfig(path: String, config: Config = ConfigFactory.load(), driver: Driver = null): Database = {
val source = JdbcDataSource.forConfig(if(path.isEmpty) config else config.getConfig(path), driver, path, ClassLoaderUtil.defaultClassLoader)
def forConfig(path: String, config: Config = ConfigFactory.load(), driver: Driver = null,
classLoader: ClassLoader = ClassLoaderUtil.defaultClassLoader): Database = {
val source = JdbcDataSource.forConfig(if(path.isEmpty) config else config.getConfig(path), driver, path, classLoader)
val executor = AsyncExecutor(path, config.getIntOr("numThreads", 20), config.getIntOr("queueSize", 1000))
forSource(source, executor)
}
@@ -23,10 +23,6 @@ trait JdbcDataSource extends Closeable {
}
object JdbcDataSource {
/** Create a JdbcDataSource from a `Config`. See [[JdbcBackend.DatabaseFactoryDef.forConfig]]
* for documentation of the supported configuration parameters. */
def forConfig(c: Config, driver: Driver, name: String): JdbcDataSource = forConfig(c, driver, name, ClassLoaderUtil.defaultClassLoader)
/** Create a JdbcDataSource from a `Config`. See [[JdbcBackend.DatabaseFactoryDef.forConfig]]
* for documentation of the supported configuration parameters. */
def forConfig(c: Config, driver: Driver, name: String, classLoader: ClassLoader): JdbcDataSource = {
@@ -17,7 +17,7 @@ The prefered way to configure database connections is through `Typesafe Config`_
.. includecode:: resources/application.conf#mydb
Such a configuration can be loaded with `Database.forConfig` (see the
:api:`API documentation <slick.jdbc.JdbcBackend$DatabaseFactoryDef@forConfig(String,Config,Driver):Database>`
:api:`API documentation <slick.jdbc.JdbcBackend$DatabaseFactoryDef@forConfig(String,Config,Driver,ClassLoader):Database>`
of this method for details on the configuration parameters).
.. includecode:: code/Connection.scala#forConfig
@@ -69,7 +69,7 @@ for asynchronous execution of Database I/O Actions. Its size is the main paramet
performance of the ``Database`` object. It should be set to the value that you would use for the
size of the *connection pool* in a traditional, blocking application (see `About Pool Sizing`_
in the HikariCP_ documentation for further information). When using
:api:`Database.forConfig <slick.jdbc.JdbcBackend$DatabaseFactoryDef@forConfig(String,Config,Driver):Database>`,
:api:`Database.forConfig <slick.jdbc.JdbcBackend$DatabaseFactoryDef@forConfig(String,Config,Driver,ClassLoader):Database>`,
the thread pool is configured directly in the external configuration file together with the connection
parameters. If you use any other factory method to get a ``Database``, you can either use a default
configuration or specify a custom AsyncExecutor:
@@ -91,7 +91,7 @@ middle of a transaction) but are not actively doing any work on the database.
Note that reasonable defaults for the connection pool sizes are calculated from the thread pool
size when using
:api:`Database.forConfig <slick.jdbc.JdbcBackend$DatabaseFactoryDef@forConfig(String,Config,Driver):Database>`.
:api:`Database.forConfig <slick.jdbc.JdbcBackend$DatabaseFactoryDef@forConfig(String,Config,Driver,ClassLoader):Database>`.
Slick uses *prepared* statements wherever possible but it does not cache them on its own. You
should therefore enable prepared statement caching in the connection pool's configuration.

0 comments on commit 4565f09

Please sign in to comment.