For many clients for things like redis and mongodb, you normally have to create a singleton reference to the client because it is a pool of connections to redis/mongodb.
In a play app, how can I create a static reference that I can just use in all my controller or model logic etc?
In my case, I am using slick and MySQL, but I think that what You want to achieve is similar. I also don't know if it is the best solution... I am defining scala object with connection to database, than this conection is wrapped in trait, wich is extended in places where I need a database connection. (In the middle is of course pooling framework).
package models
import scala.slick.driver.MySQLDriver.simple._
import play.api.Play
import play.api.Play.current
import com.mchange.v2.c3p0._;
object Connection {
val databaseURL = Play.configuration.getString("db.default.url").get
val databaseUser = Play.configuration.getString("db.default.user").get
val databasePassword = Play.configuration.getString("db.default.password").get
val databaseDriver = Play.configuration.getString("db.default.driver").get
val singletonDatabase = {
val ds = new ComboPooledDataSource
ds.setDriverClass(Connection.databaseDriver)
ds.setJdbcUrl(Connection.databaseURL)
ds.setUser(Connection.databaseUser)
ds.setPassword(Connection.databasePassword)
ds.setMinPoolSize(0);
ds.setMaxPoolSize(1000);
ds.setCheckoutTimeout(3000);
ds.setAcquireIncrement(10);
ds.setMaxStatements(50);
ds.setIdleConnectionTestPeriod(60);
ds.setPreferredTestQuery("SELECT 1;");
ds.setTestConnectionOnCheckout(false);
Database.forDataSource(ds)
}
}
trait DatabaseConnector {
val database = Connection.singletonDatabase
}
You can create a singleton object by creating it as a Plugin. For my project I had a similar need to build a singleton for RedisPool class. See the complete working code below:
package plugins.redis;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.Application;
import play.Configuration;
import play.Plugin;
import plugins.PluginUtils;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class RedisPlugin extends Plugin {
private final Application application;
private JedisPool jedisPool;
private static final Logger LOGGER = LoggerFactory.getLogger("application");
//default constants for Redis
public static final String REDIS_DEFAULT_HOST="localhost";
public static final int REDIS_DEFAULT_PORT=6379;
public static final int REDIS_DEFAULT_TIMESOUT=2000;
public RedisPlugin(Application application){
this.application = application;
}
public static Integer getIntConfig(Configuration configuration, String configKey, Integer... defaultVal) {
String val = configuration.getString(configKey);
if (StringUtils.isBlank(val)) {
if(defaultVal != null && defaultVal.length>0){
return defaultVal[0];
}
return null;
} else {
return NumberUtils.toInt(val);
}
}
public static Long getLongConfig(Configuration configuration, String configKey, Long... defaultVal) {
String val = configuration.getString(configKey);
if (StringUtils.isBlank(val)) {
if(defaultVal != null && defaultVal.length>0){
return defaultVal[0];
}
return null;
} else {
return NumberUtils.toLong(val);
}
}
public static Boolean getBoolConfig(Configuration configuration, String configKey, Boolean... defaultVal) {
return BooleanUtils.toBooleanObject(configuration.getString(configKey));
}
@Override
public void onStart() {
Configuration configuration = application.configuration();
String host = getConfig(configuration, "redis.host", REDIS_DEFAULT_HOST);
if (StringUtils.isBlank(host)) {
LOGGER.error("Redis host is absent");
return;
}
Integer port = getIntConfig(configuration, "redis.port", REDIS_DEFAULT_PORT);
if (port == null) {
LOGGER.error("Redis port is absent");
return;
}
Integer timeout = getIntConfig(configuration, "redis.timeout", REDIS_DEFAULT_TIMESOUT);
if (timeout == null) {
LOGGER.error("Redis timeout is absent");
return;
}
String password = getConfig(configuration, "redis.password");
jedisPool = new JedisPool(getJedisConfig(), host, port, timeout, password);
super.onStart();
}
public JedisPool getJedisPool() {
return jedisPool;
}
@Override
public void onStop() {
jedisPool.destroy();
super.onStop();
}
@Override
public boolean enabled() {
return true;
}
public JedisPoolConfig getJedisConfig(){
JedisPoolConfig poolConfig = new JedisPoolConfig();
Configuration configuration = application.configuration();
Integer maxIdle = getIntConfig(configuration, "redis.pool.maxIdle");
if(maxIdle != null){
poolConfig.setMaxIdle(maxIdle);
}
Integer minIdle = getIntConfig(configuration, "redis.pool.minIdle");
if(minIdle != null){
poolConfig.setMinIdle(minIdle);
}
Integer numTestsPerEvictionRun = getIntConfig(configuration, "redis.pool.numTestsPerEvictionRun");
if(numTestsPerEvictionRun != null){
poolConfig.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
}
Boolean testOnBorrow = getBoolConfig(configuration, "redis.pool.testOnBorrow");
if(testOnBorrow != null){
poolConfig.setTestOnBorrow(testOnBorrow);
}
Boolean testOnReturn = getBoolConfig(configuration, "redis.pool.testOnReturn");
if(testOnReturn != null){
poolConfig.setTestOnReturn(testOnReturn);
}
Boolean testWhileIdle = getBoolConfig(configuration, "redis.pool.testWhileIdle");
if(testWhileIdle != null){
poolConfig.setTestWhileIdle(testWhileIdle);
}
Boolean lifo = getBoolConfig(configuration, "redis.pool.lifo");
if(lifo != null){
poolConfig.setLifo(lifo);
}
Long timeBetweenEvictionRunsMillis = getLongConfig(configuration, "redis.pool.timeBetweenEvictionRunsMillis");
if(timeBetweenEvictionRunsMillis != null){
poolConfig.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
}
Long softMinEvictableIdleTimeMillis = getLongConfig(configuration, "redis.pool.softMinEvictableIdleTimeMillis");
if(softMinEvictableIdleTimeMillis != null){
poolConfig.setSoftMinEvictableIdleTimeMillis(softMinEvictableIdleTimeMillis);
}
Boolean exhaustedAction = getBoolConfig(configuration, "redis.pool.blockWhenExhausted");
if(exhaustedAction != null){
poolConfig.setBlockWhenExhausted(exhaustedAction);
}
return poolConfig;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With