I have just started using BoneCP and this is my first time using a connection pool. I'm somewhat confused as to how I am supposed to use it. Currently I am saving the BoneCP-object as a static variable, and thus I can use it between different connections.
When I'm done with the connection, I close it with connection.close().
Should I do this, or should I not close it to enable it to be reused by the pool?
This is my current implementation to get a connection:
private static BoneCP connectionPool;
public Connection getConnection() throws SQLException {
if (connectionPool == null) {
initPool();
}
return connectionPool.getConnection();
}
private void initPool() throws SQLException {
BoneCPConfig config = new BoneCPConfig();
config.setJdbcUrl(DB_URL);
config.setUsername(DB_USERNAME);
config.setPassword(DB_PASSWORD);
config.setMinConnectionsPerPartition(5);
config.setMaxConnectionsPerPartition(10);
config.setPartitionCount(1);
connectionPool = new BoneCP(config);
}
Does this seem correct or have I misunderstood how I am supposed to use BoneCP?
Other than making your private static final and changing the init to a static block (or alternaitvely making your getConnection synchronized), you are ok.
You are correct you MUST do connection.close() to return to the pool. When your app shuts down, shut down the connection pool
Related
I ask this question especially for Stateless Session Bean. I knew that I can easily inject the DataSource with the #Resource annotation. But I don't know what is the proper way to get the Connection. Is it in each method of the bean, or in the method annotated with #PostConstruct? And also for the closing of the Connection. Do I have to close it within the finally block in each method call, or in the method annotated with #PreDestroy?
Is it safe to create an instance variable for the Connection, for example:
#Stateless
public class MyBean {
#Resource private DataSource ds;
private Connection conn;
#PostConstruct
public void onCreate() {
conn = ds.getConnection(); // within try catch block
}
#PreDestroy
public void onDestroy() {
conn.close() // within try catch block
}
}
Or should I create them locally in each method like this:
#Stateless
public class MyBean {
#Resource private DataSource ds;
public void method1() {
Connection conn = null;
// get and close connection...
}
public void method2() {
Connection conn = null;
// get and close connection...
}
}
Some people in the Internet do this way, and some other do that way. What is the proper method to be implemented in an application with a high request traffic? When the bean instance is returned back to the EJB pool, does the Connection remains opened or does it returned to the database pool?
Note: The application is using native JDBC API. There are no JPA, JDO, etc.. The application server is Wildfly.
TL;DR
The second approach is the correct one. Just make sure to close the connection to return it to the Pool.
The Datasource is a pool of connections, every time you get a connection it borrows one from the datasource and when you close that connection it will be returned to the pool, so you will always want to release the connection as soon as possible.
In the first approach you will retain the connection for as long as the EJB lives in memory. Since the EJB is an Stateless bean it will be alive for long and reused by diferent consumenrs. Making you have at least 1 connection open per EJB that is alive thus this approach is not practical.
The second approach is the correct one. Just make sure to close the connection to return it to the Pool. With this approach the Bean will only retain the connection while in use. Just make sure to close the connection to return it to the Pool.
#Stateless
public class MyBean {
#Resource private DataSource ds;
public void method1() {
try(Connection conn = ds.getConnection()){
// Do anything you need with the connection
}
}
public void method2() {
Connection conn = ds.getConnection();
try {
// Do anything you need with the connection
} finally {
connection.close();
}
}
}
Many JDBC calls (querying DB and get results) are executed through ExecutorService. I found that when those calls are executed, JDBC connections gets a long time to get closed the connection even though those connections are closed correctly. Why I say so is, when a load test is run through JMeter, the database shows that many connections are in IDLE in transaction. If the number of thread which run the test is high, the number of connections in Idle in transactions goes up. If the test is run slowly, then connections get closed slowly (1, 2 minutes), that means there are connections in IDLE in transactions, but after few minutes they become IDLE. I use connection pool here too. If I run the JDBC querying functions as a sequence ( one after another), then database doesn't show any connections in IDLE in transactions. Below is how I run my runnable tasks which run JDBC queries. TaskManager class handles whole ExecutorService related functions.
public class TaskManager {
final private ThreadServiceFactory threadFactory;
private int concurrentThreadCount;
private ExecutorService executerSV;
private final CountDownLatch latch;
// I keep a count of proposed tas task as servicecount
public TaskManager(int serviceCount) {
threadFactory = new ThreadServiceFactory();
this.concurrentThreadCount = serviceCount;
latch = new CountDownLatch(serviceCount);
}
public void execute( ThreadService runnableTask) {
Object rv = null;
runnableTask.setCountDownLatch(latch);
if(executerSV == null) {
executerSV = Executors.newFixedThreadPool(this.concurrentThreadCount, getThreadFactory());
}
executerSV.execute(runnableTask);
}
public boolean holdUntilComplete(){
try {
latch.await();
executerSV.shutdown();
return true;
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
private ThreadServiceFactory getThreadFactory(){
threadFactory.setDeamon( Boolean.FALSE);
return threadFactory;
}
}
In my test class ;
public void test(){
TaskManager tm = new TaskManager(3);
tm.execute(queryTask1);
tm.execute(queryTask2);
tm.holdUntilComplete();
}
queryTask1 is a Runnable and it calls JDBC select query.
If I run, queryTask1.run(); queryTask2.run(); then there are no any IDLE in connections in DB.
I use java 7. Please any one can let me know where the problem is.
There is no code in your question that opens any connection to a database. As such, it is difficult to suggest an answer. However, since you state that you are using a connection pool, you should better look at the pool configuration parameters, since they dictate how long an idle connection may be open before being elegible for eviction. For instance, if you are running a connection pool in tomcat, you should look particularly at "minIdle", "maxIdle" and "minEvictableIdleTimeMillis" properties. See https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html
Assume the following pseudo code for a simple two thread scenario:
I have two threads, I would like to insert data to different tables to database. On thread1, I would like to insert to some table, at same time, I want to insert other data to thread 2. My question is how/where to place connection.close(), if I place it on thread 1 and it executes while thread2 is still processing, or vice versa, if thread2 has finished and closed the connection, yet thread1 hasn't finished.
Note, the database is just an example, it can be anything like a file,logger..etc.
class Thread1{
DataBaseConnection connection;
main(){
threadPool = Executors.newFixedThreadPool(1);
connection.open();
if(ThisMightTakeSomeTime)
threadPool.submit(new MyRunnable(connection));
InsertDataToDataBase(Table A, Table B));
connection.Close(); //What if thread2 isn't done yet?
}
}
public class MyRunnable implements Runnable {
MyRunnable(connection){}
#override
void Run() { ...}
void TaskThatMayTakeWhile(){
...get data ...
...Connection.InsertToTables(table X, table Y)
}
}
My question is how/where to place connection.close(),
To start, as far as I know, you should not be sharing a single connection with 2 different threads. Each thread should have it's own database connection, possibly utilizing a database connection pool such as Apache's DBCP.
Once you have multiple connections, I would have each thread manage and release its own connection back to the pool. You should make sure this is done in a finally block to make sure that if there is a database exception, the connection is still released.
If you are forced to have multiple threads share the same connection then they will have to use synchronized to make sure they have an exclusive lock to it:
synchronized (connection) {
// use the connection
}
As to when to close it if it is shared, you could have a shared usage counter (maybe an AtomicInteger) and close it when the counter goes to 0. Or as others have recommended you could use a thread-pool and then the thread pool is done free the connection.
Note, the database is just an example, it can be anything like a file,logger..etc.
In terms of a more generic answer I always try to mirror where the thing is created. If a method opens the stream then it should have the finally that closes the stream.
public void someMethod() {
InputStream stream = ...
try {
// process the stream here probably by calling other methods
} finally {
// stream should be closed in the same method for parity
stream.close();
}
}
The exception to this pattern is a thread handler. Then the Thread should close the stream or release connection in a finally block at the end of the run() or call() method.
public void serverLoopMethod() {
while (weAcceptConnections) {
Connection connection = accept(...);
threadPool.submit(new ConnectionHandler(connection);
}
}
...
private static class ConnectionHandler implements Runnable {
private Connection connection;
public ConnectionHandler(Connection connection) {
this.connection = connection;
}
// run (or call) method executed in another thread
public void run() {
try {
// work with the connection probably by calling other methods
} finally {
// connection is closed at the end of the thread run method
connection.close();
}
}
}
If you run your code it's likely that database connection will be closed before insert statement execution and of course insert will be unsuccessful.
Proper solutions
If you have multiple insert tasks:
Use ExecutorService instead of Execuutor
Submit all tasks
Invoke executorService.shutdown() it will wait until all submitted tasks are done.
Close connection
If you have only one task to submit:
You should close the connection after Connection.InsertToTables(table X, table Y) in your task.
Good for both scenarios and recommended:
Each tasks has it own connection.
Example:
class Thread1 {
private static DataSource dataSource; // initialize it
public static void main(String[] args){
ExecutorService threadPool = Executors.newFixedThreadPool(1);
threadPool.submit(new MyRunnable(dataSource));
}
}
class MyRunnable implements Runnable {
private final DataSource dataSource;
MyRunnable(DataSource dataSource) {
this.dataSource = dataSource;
}
public void run() {
Connection connection = dataSource.getConnection();
// do something with connection
connection.close();
}
}
class Thread1{
DataBaseConnection connection;
main(){
threadPool = Executors.newFixedThreadPool(1);
connection.open();
if(ThisMightTakeSomeTime)
Future f = threadPool.submit(new MyRunnable(connection));
InsertDataToDataBase(Table A, Table B));
f.get(); // this will hold the program until the Thread finishes.
connection.Close(); //What if thread2 isn't done yet?
}
}
the Future is the reference resulting from the submit call. if we call Future.get(), that will block the current thread until the submited thread finishes.
When you inject a datasource in your application and get a connection by invoking getConnection() on it, are you supposed to close the connection?
Even though the datasource itself is container managed, the API indeed requires the programmer to close connections. This is different from a couple of other container managed resources (like the entity manager), where the container takes care of closing. Note that closing here in the majority of cases doesn't actually closes the connection here, but returns the connection to a connection pool.
As a rule of thumb, if you use a factory-ish resources to obtain one or more other resources from that can be closed, you have to close them. Otherwise the container does this.
Since Connection implements AutoCloseable, you can use a try-with-resources block for this:
#Stateless
public class MyBean {
#Resource(lookup = "java:/app/datasource")
private DataSource dataSource;
public void doStuff() {
try (Connection connection = dataSource.getConnection()) {
// Work with connection here
} catch (SQLException e) {
throw new SomeRuntimeException(e);
}
}
}
Of course, otherwise you'll exhaust your connection pool. It's best to do this in finally block:
#Resource(mappedName="jndi/yourDatasource")
DataSource ds;
..
Connection conn = null;
try {
conn = ds.getConnection();
//PERFORM QUERY, ETC..
}
catch(SQLException ex) {
//EXCEPTION HANDLING
}
finally {
try {
if(conn != null)
conn.close();
}
catch(SQLException ex) {..}
}
Picture that you have a chat program where you want to send and recive data to & from the server. would it be smart to turn the clients connection into a singleton? or will this ruin the data stream.
my example of a client singleton:
public class Client {
private static Client client;
private final int portNumber = 7070;
private Socket socket;
private Client(){
connect();
}
public static synchronized Client getClient(){
if (client == null) {
client = new Client();
}
return client;
}
public void connect(){
try {
InetAddress adr = InetAddress.getByName("localhost");
socket = new Socket(adr, portNumber);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
There are two issues with your code:
singletons are very inflexible. If you want to implement load-balancing or connection pooling in the future, your hands are tied. Only one connection is allowed. And what about reconnecting? How do you get rid of old connection and create a new one?
connecting (or any operation that has side-effects) inside a constructor is not a good practice. Imagine unit-testing this class
So I don't advice singleton connection object. Instead have a ClientConnections manager class with Client connect() method. This manager class keeps track of all opened connections, can cache them, close unused, test periodically, etc. ClientConnections is a better candidate for singleton.
Make sense to use singleton clients if you dont want more than one connection per client. This should be fine for most cases, except when you want to support sending multiple files simultaneously.