Last active
August 29, 2015 14:00
-
-
Save xhanin/11319869 to your computer and use it in GitHub Desktop.
RESTX JDBC support with BoneCP for connexion pool and Flyway for migration
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// In AppModule class, or could be in a dedicated module. | |
@Provides | |
public DBI dbi(@Named("datasource") DataSource ds) { | |
return new DBI(ds); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.google.common.base.Optional; | |
import com.google.common.base.Throwables; | |
import com.jolbox.bonecp.BoneCPDataSource; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import restx.config.Settings; | |
import restx.config.SettingsKey; | |
import restx.factory.AutoStartable; | |
import restx.factory.Module; | |
import restx.factory.Provides; | |
import javax.inject.Named; | |
import javax.sql.DataSource; | |
@Module | |
public class BoneCpModule { | |
private static final Logger logger = LoggerFactory.getLogger(BoneCpModule.class); | |
@Settings | |
public static interface DatasourceSettings { | |
@SettingsKey(key = "restx.jdbc.driver") | |
String jdbcDriver(); | |
@SettingsKey(key = "restx.jdbc.url") | |
String jdbcUrl(); | |
@SettingsKey(key = "restx.jdbc.username") | |
String jdbcUsername(); | |
@SettingsKey(key = "restx.jdbc.password") | |
Optional<String> jdbcPassword(); | |
@SettingsKey(key = "restx.jdbc.admin.username") | |
Optional<String> jdbcAdminUsername(); | |
@SettingsKey(key = "restx.jdbc.admin.password") | |
Optional<String> jdbcAdminPassword(); | |
} | |
@Provides | |
public AutoStartable startDatasources(@Named("datasource") DataSource dataSource, | |
@Named("adminDatasource") DataSource adminDatasource) { | |
return new AutoStartable() { | |
@Override | |
public void start() { | |
logger.info("connected to database"); | |
} | |
}; | |
} | |
// datasource used for the app, DML grants are enough | |
@Provides | |
public DataSource datasource(DatasourceSettings settings) { | |
try { | |
Class.forName(settings.jdbcDriver()); | |
} catch (ClassNotFoundException e) { | |
throw new IllegalArgumentException("invalid driver " + settings.jdbcDriver() + ": it can't be loaded." + | |
" Check your classpath and settings."); | |
} | |
BoneCPDataSource ds = new BoneCPDataSource(); | |
ds.setJdbcUrl(settings.jdbcUrl()); | |
ds.setUsername(settings.jdbcUsername()); | |
ds.setPassword(settings.jdbcPassword().or("")); | |
return ds; | |
} | |
// datasource used to migrate the schema, need DDL grants | |
@Provides | |
public DataSource adminDatasource(DatasourceSettings settings) { | |
try { | |
Class.forName(settings.jdbcDriver()); | |
} catch (ClassNotFoundException e) { | |
throw new IllegalArgumentException("invalid driver " + settings.jdbcDriver() + ": it can't be loaded." + | |
" Check your classpath and settings."); | |
} | |
BoneCPDataSource ds = new BoneCPDataSource(); | |
ds.setJdbcUrl(settings.jdbcUrl()); | |
ds.setUsername(settings.jdbcAdminUsername().or(settings.jdbcUsername() + "-admin")); | |
ds.setPassword(settings.jdbcAdminPassword().or(settings.jdbcPassword()).or("")); | |
return ds; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.skife.jdbi.v2.Handle; | |
import static com.google.common.base.Preconditions.checkNotNull; | |
/** | |
* Store current DBI context in a thread local | |
*/ | |
public class DBIContext { | |
private static final ThreadLocal<Handle> current = new ThreadLocal<>(); | |
public static void set(Handle handle) { | |
current.set(handle); | |
} | |
public static Handle get() { | |
return checkNotNull(current.get()); | |
} | |
public static void clear() { | |
current.remove(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.google.common.base.Optional; | |
import org.skife.jdbi.v2.DBI; | |
import org.skife.jdbi.v2.Handle; | |
import restx.*; | |
import restx.factory.Component; | |
import java.io.IOException; | |
/** | |
* Auto Open DBI Handle for each request, setting the current Handle in DBIContext. | |
*/ | |
@Component | |
public class DBIFilter implements RestxFilter, RestxHandler { | |
private final DBI dbi; | |
public DBIFilter(DBI dbi) { | |
this.dbi = dbi; | |
} | |
@Override | |
public Optional<RestxHandlerMatch> match(RestxRequest req) { | |
if (req.getRestxPath().startsWith("/@")) { | |
return Optional.absent(); | |
} | |
return RestxHandlerMatch.of(Optional.of(new StdRestxRequestMatch(req.getRestxPath())), this); | |
} | |
@Override | |
public void handle(RestxRequestMatch match, RestxRequest req, RestxResponse resp, RestxContext ctx) throws IOException { | |
try (Handle h = dbi.open()) { | |
DBIContext.set(h); | |
ctx.nextHandlerMatch().handle(req, resp, ctx); | |
} finally { | |
DBIContext.clear(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.googlecode.flyway.core.Flyway; | |
import restx.AppSettings; | |
import restx.factory.AutoStartable; | |
import restx.factory.Component; | |
import javax.inject.Named; | |
import javax.sql.DataSource; | |
@Component | |
public class FlywayAutoMigrate implements AutoStartable { | |
private final DataSource dataSource; | |
private final AppSettings appSettings; | |
public FlywayAutoMigrate(@Named("adminDatasource") DataSource dataSource, | |
AppSettings appSettings) { | |
this.dataSource = dataSource; | |
this.appSettings = appSettings; | |
} | |
@Override | |
public void start() { | |
Flyway flyway = new Flyway(); | |
flyway.setDataSource(dataSource); | |
// set the locations depending on the mode, allow for instance to have more scripts in 'dev', like data initialization | |
if ("dev".equals(appSettings.mode())) { | |
flyway.setLocations("db"); | |
} | |
flyway.migrate(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment