/*
* Copyright (C) 2011-2014 Chris Vest (mr.chrisvest@gmail.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package stormpot.examples;
import stormpot.*;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.concurrent.TimeUnit;
// tag::defineClass[]
public class DaoPoolExample {
// end::defineClass[]
// tag::mydaoStart[]
static class MyDao implements Poolable {
final Slot slot;
final Connection connection;
private MyDao(Slot slot, Connection connection) {
this.slot = slot;
this.connection = connection;
}
// end::mydaoStart[]
// tag::mydaoRelease[]
public void release() {
slot.release(this);
}
// end::mydaoRelease[]
// tag::mydaoClose[]
private void close() throws SQLException {
connection.close();
}
// end::mydaoClose[]
// ...
// public DAO-type methods
// ...
// tag::mydaoGetFirstname[]
public String getFirstName() {
// Stub: get the name from the database using the connection.
// But for now, just always return "freddy"
return "freddy";
}
}
// end::mydaoGetFirstname[]
// tag::allocatorStart[]
static class MyDaoAllocator implements Allocator<MyDao> {
private final DataSource dataSource;
public MyDaoAllocator(DataSource dataSource) {
this.dataSource = dataSource;
}
// end::allocatorStart[]
// tag::allocatorAllocate[]
public MyDao allocate(Slot slot) throws Exception {
synchronized (dataSource) {
return new MyDao(slot, dataSource.getConnection());
}
}
// end::allocatorAllocate[]
// tag::allocatorClose[]
public void deallocate(MyDao poolable) throws Exception {
poolable.close();
}
}
// end::allocatorClose[]
static class TestQueryExpiration implements Expiration<MyDao> {
@Override
public boolean hasExpired(SlotInfo<? extends MyDao> info) {
MyDao dao = info.getPoolable();
Connection con = dao.connection;
Statement stmt = null;
synchronized (con) {
try {
try {
stmt = con.createStatement();
stmt.execute("select 1 from dual;");
} finally {
if (stmt != null) {
stmt.close();
}
}
} catch (SQLException e) {
return true;
}
return false;
}
}
}
// tag::poolStart[]
static class MyDaoPool {
private final Pool<MyDao> pool;
public MyDaoPool(DataSource dataSource) {
MyDaoAllocator allocator = new MyDaoAllocator(dataSource);
Config<MyDao> config = new Config<MyDao>().setAllocator(allocator);
pool = new QueuePool<>(config);
}
// end::poolStart[]
public MyDaoPool(DataSource dataSource, boolean verifyConnections) {
MyDaoAllocator allocator = new MyDaoAllocator(dataSource);
Config<MyDao> config = new Config<MyDao>().setAllocator(allocator);
if (verifyConnections) {
config.setExpiration(new TestQueryExpiration());
}
pool = new QueuePool<>(config);
}
// tag::poolClose[]
public void close() throws InterruptedException {
pool.shutdown().await(new Timeout(1, TimeUnit.MINUTES));
}
// end::poolClose[]
// tag::poolDoWithDao[]
public <T> T doWithDao(WithMyDaoDo<T> action)
throws InterruptedException {
MyDao dao = pool.claim(new Timeout(1, TimeUnit.SECONDS));
try {
return action.doWithDao(dao);
} finally {
dao.release();
}
}
}
interface WithMyDaoDo<T> {
T doWithDao(MyDao dao);
}
// end::poolDoWithDao[]
// tag::main[]
public static void main(String[] args) throws InterruptedException {
DataSource dataSource = configureDataSource();
MyDaoPool pool = new MyDaoPool(dataSource);
try {
String person = pool.doWithDao(MyDao::getFirstName);
System.out.println("Hello there, " + person + "!");
} finally {
pool.close();
}
}
// end::main[]
private static DataSource configureDataSource() {
// Stub: configure and return some kind of DataSource object.
// Allocation will fail with a NullPointerException until this method
// get a proper implementation.
return null;
}
}