Need Code to create Connection Pool in java
Asked Answered
M

10

33

Need code to create the connection pool in java? How does we make sure that connection pool doesn't return the same object which is already in use? How happens if client closed the connection after taking it out from Connection pool?

Update 1:

I want to create this in Simple Java terms and want to see how it works in Multithreading Env. I mean which methods would be synchronized and which are not. Also will this class would be a public class? If yes then any one can access this class and reinitialize the connection pool?

Update 2:

I have some code as below. But i don't how "Closing a connection coming from a pool returns it to the pool, it doesn't close the connection physically." Also i didn't understood this "Because if a connection has been borrowed from the pool and not returned yet, it's not "available" and can't be redistributed to another client of the pool."

import java.util.*;
import java.sql.*;

class ConnectionPoolManager
{

 String databaseUrl = "jdbc:mysql://localhost:3306/myDatabase";
 String userName = "userName";
 String password = "userPass";

 Vector connectionPool = new Vector();

 public ConnectionPoolManager()
 {
  initialize();
 }

 public ConnectionPoolManager(
  //String databaseName,
  String databaseUrl,
  String userName,
  String password
  )
 {
  this.databaseUrl = databaseUrl;
  this.userName = userName;
  this.password = password;
  initialize();
 }

 private void initialize()
 {
  //Here we can initialize all the information that we need
  initializeConnectionPool();
 }

 private void initializeConnectionPool()
 {
  while(!checkIfConnectionPoolIsFull())
  {
   System.out.println("Connection Pool is NOT full. Proceeding with adding new connections");
   //Adding new connection instance until the pool is full
   connectionPool.addElement(createNewConnectionForPool());
  }
  System.out.println("Connection Pool is full.");
 }

 private synchronized boolean checkIfConnectionPoolIsFull()
 {
  final int MAX_POOL_SIZE = 5;

  //Check if the pool size
  if(connectionPool.size() < 5)
  {
   return false;
  }

  return true;
 }

 //Creating a connection
 private Connection createNewConnectionForPool()
 {
  Connection connection = null;

  try
  {
   Class.forName("com.mysql.jdbc.Driver");
   connection = DriverManager.getConnection(databaseUrl, userName, password);
   System.out.println("Connection: "+connection);
  }
  catch(SQLException sqle)
  {
   System.err.println("SQLException: "+sqle);
   return null;
  }
  catch(ClassNotFoundException cnfe)
  {
   System.err.println("ClassNotFoundException: "+cnfe);
   return null;
  }

  return connection;
 }

 public synchronized Connection getConnectionFromPool()
 {
  Connection connection = null;

  //Check if there is a connection available. There are times when all the connections in the pool may be used up
  if(connectionPool.size() > 0)
  {
   connection = (Connection) connectionPool.firstElement();
   connectionPool.removeElementAt(0);
  }
  //Giving away the connection from the connection pool
  return connection;
 }

 public synchronized void returnConnectionToPool(Connection connection)
 {
  //Adding the connection from the client back to the connection pool
  connectionPool.addElement(connection);
 }

 public static void main(String args[])
 {
  ConnectionPoolManager ConnectionPoolManager = new ConnectionPoolManager();
 }

}
Meli answered 13/5, 2010 at 11:2 Comment(1)
Regardless of what some answers below say, DO WRITE your own connection pool. Take your in comparison with the others around, and learn much about JDBC and other stuff in the process. Just having a bunch of estabilished products shouldn't deter you from making your own. Just take them into consideration as standards to be beaten. Go for itLadon
N
49

Need code to create the connection pool in java?

Not sure what the question is but don't create yet another connection pool, use an existing solution like C3P0, Apache DBCP, Proxool or BoneCP (a new player in that field). I would use C3P0.

How does we make sure that connection pool doesn't return the same object which is already in use?

Because if a connection has been borrowed from the pool and not returned yet, it's just not in the pool and can't be assigned to another client of the pool (resources are removed from the pool until they are returned).

How happens if client closed the connection after taking it out from Connection pool?

The connection a client gets from a pool is not really a java.sql.Connection, it's a wrapper (a proxy) for a java.sql.Connection that customizes the behavior of some methods. The close() method is one of them and does not close the Connection instance but returns it to the pool.

Noelianoell answered 13/5, 2010 at 11:17 Comment(3)
+1 for C3PO... I've been using it with very good results. It is light weight and extremely easy to use.Dombrowski
"does not close the Connection instance but returns it to the pool" - How would the connection class know about the pool and be able to return itself to it when the close method is called?Resultant
Be sure to checkout Hikari CP: github.com/brettwooldridge/HikariCP. From what I've read, It seems to be much faster than those listed.Maud
M
14

Don't write your own. There are plenty of librarires out there that will do this for you that are open source and easy to use and will have solved all the problems you'll encounter trying to make it yourself.

Here is a simple example that uses Apache's Commons DBCP and Commons Pool:

First set up a DataSource.

javax.sql.DataSource source = new org.apache.commons.dbcp.BasicDataSource();
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUsername("username");
source.setPassword("password");
source.setUrl("jdbc:mysql://localhost:3306/myDatabase");

Once you have a DataSource, it is easy to get a connection from the pool.

java.sql.Connection connection = source.getConnection();

closing the connection will return it to the pool for you.

connection.close();
Mascle answered 13/5, 2010 at 14:47 Comment(2)
+1. but,one correction - the methods setDriverClassName() and others are not available in javax.sql.DataSource[java 1.6]. The type should be BasicDataSource . ie: BasicDataSource source = new BasicDataSource(); for more details: svn.apache.org/viewvc/commons/proper/dbcp/trunk/doc/…Flyback
Don't write your own, use the existing "unsupported, cancelled support, historical" libraries and learn nothing. I don't agree that. Why new developers should not write their own, at least they should be supported to implement on their own so that they can learn. Why not? "Write your own and write with well written unit tests and documentation"Grisham
A
14

I hope this source code helps http://jagadeeshmanne.blogspot.com/2014/03/connection-pool-in-java-jdbc.html

Configuration.java

package com.jmanne.utils;
 
public class Configuration {
  
 public String DB_USER_NAME ;
  
 public String DB_PASSWORD ;
  
 public String DB_URL;
  
 public String DB_DRIVER;
  
 public Integer DB_MAX_CONNECTIONS;
  
 public Configuration(){
  init();
 }
  
 private static Configuration configuration = new Configuration();
  
 public static Configuration getInstance(){ 
  return configuration;
 }
  
 private void init(){
  DB_USER_NAME = "root"
  DB_PASSWORD = "root"
  DB_URL = "jdbc:mysql://localhost:3306/jmanne"
  DB_DRIVER = "com.mysql.jdbc.Driver"
  DB_MAX_CONNECTIONS = 5
 }     
}

JdbcConnectionPool.java

package com.jmanne.db;
 
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
 
import com.jmanne.utils.Configuration;
import com.mysql.jdbc.Connection;
 
public class JdbcConnectionPool {
  
 List<connection> availableConnections = new ArrayList<connection>();
 
 public JdbcConnectionPool()
 {
  initializeConnectionPool();
 }
 
 private void initializeConnectionPool()
 {
  while(!checkIfConnectionPoolIsFull())
  {
   availableConnections.add(createNewConnectionForPool());
  }
 }
 
 private synchronized boolean checkIfConnectionPoolIsFull()
 {
  final int MAX_POOL_SIZE = Configuration.getInstance().DB_MAX_CONNECTIONS;
 
  if(availableConnections.size() < MAX_POOL_SIZE)
  {
   return false;
  }
 
  return true;
 }
 
 //Creating a connection
 private Connection createNewConnectionForPool()
 {
  Configuration config = Configuration.getInstance();
  try {
   Class.forName(config.DB_DRIVER);
   Connection connection = (Connection) DriverManager.getConnection(
     config.DB_URL, config.DB_USER_NAME, config.DB_PASSWORD);
   return connection;
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return null;
   
 }
 
 public synchronized Connection getConnectionFromPool()
 {
  Connection connection = null;
  if(availableConnections.size() > 0)
  {
   connection = (Connection) availableConnections.get(0);
   availableConnections.remove(0);
  }
  return connection;
 }
 
 public synchronized void returnConnectionToPool(Connection connection)
 {
  availableConnections.add(connection);
 }
}

DataSource.java

package com.jmanne.db;
 
import java.sql.SQLException;
 
import com.mysql.jdbc.Connection;
 
public class DataSource {
  
 static JdbcConnectionPool pool = new JdbcConnectionPool();
  
 public static Connection getConnection() throws ClassNotFoundException, SQLException{
  Connection connection = pool.getConnectionFromPool();
  return connection;
 }
  
 public static void returnConnection(Connection connection) {
  pool.returnConnectionToPool(connection);
 }
}
Aachen answered 13/3, 2014 at 4:36 Comment(3)
what does db driver mean?Purusha
also could you show an example as how you would use this code please?Purusha
Sorry for the delay. db driver means driver class name. need to change that variable name as driverClass. You can use DataSource.getConnection() in your service class. It will return the connection object from poolAachen
B
6

Just use Semaphores. Ideally what you should do is use CP3O or DBCP as your connection pool. Now you can throttle you connection based on Semaphore.

Every time you do Get, you acquire and on every Release you release it from Semaphore. More over semaphores are thread safe.

Breezeway answered 1/11, 2012 at 20:59 Comment(0)
U
4

Use one of the existing, e.g. Apache DBCP

The connections returned by the pool are often proxies which "ignore" the call to close() from the application. When the connections are returned to the pool, they can be reused. Pools also close and reopen automatically if necessary.

Unrivaled answered 13/5, 2010 at 11:9 Comment(0)
I
2

If your application runs on a server, then configure as Data Source, where server will take care of Pooling or else if a simple Java Client then use Apache DBCP(if to the database) or else use Apache Commons Pooling API See here: Apache Commons

Ivanovo answered 13/5, 2010 at 11:56 Comment(0)
P
2

One argument for rolling your own connpool is the configuration and additional jars that are avoided. I agree you need to enable the 3rd party interfaces so you can swap in a mature connpool, but having your own tiny solution can have its place. Self cleaning Vector with synchronized block and a conn wrapper with close() marking the conn as available works very well for servlet apps.

Peach answered 9/8, 2012 at 3:43 Comment(0)
T
0

I have one solution for the same to create a connection pool utility which can help you create a pool of default size 10.

@Component public class ConnectionPool { private static final Logger logger = LoggerFactory.getLogger(ConnectionPool.class); private static final int MAX_POOL_SIZE_LIMIT = 10; private BlockingQueue activeConnectinoQueue = new LinkedBlockingQueue<>(); private BlockingQueue usedConnectinoList = new LinkedBlockingQueue<>(); private int initialPoolSize = 5;

@Autowired
@Qualifier("dataSource")
private DataSource dataSource;

public void initConnectionPool() {
    logger.info("ConnectionPool initialization started.");
    if(activeConnectinoQueue.isEmpty() && usedConnectinoList.isEmpty()) {
        for (int i=0; i<initialPoolSize; i++) {
            createConnections();
        }
    }
    logger.info("ConnectionPool initialization completed. ConnectionPool size : {}", activeConnectinoQueue.size());
}

private void createConnections() {
    try {
        Connection connection = dataSource.getConnection();
        activeConnectinoQueue.add(connection);
    }catch (SQLException e) {
        logger.error("Error in getting connection from pool : ", e);
    }
}

public Connection getConnection() {
    if(activeConnectinoQueue.isEmpty()) {
        initConnectionPool();
    }
    Connection connection =  activeConnectinoQueue.remove();

    try {
        if(connection.isClosed()) {
            connection = dataSource.getConnection();
        }
    }catch (SQLException e) {
        logger.error("Error while getting connection from pool : ", e);
    }

    usedConnectinoList.add(connection);
    return connection;
}


public void releaseConnection(Connection connection) {
    if(connection != null) {
        usedConnectinoList.remove(connection);
        activeConnectinoQueue.add(connection);
    }
}

public void setInitialPoolSize(int initialPoolSize) {
    if(!(initialPoolSize < 0 || initialPoolSize > MAX_POOL_SIZE_LIMIT)) {
        this.initialPoolSize = initialPoolSize;
    }
}

public int getInitialPoolSize() {
    return initialPoolSize;
}

public int getConnectionPoolSize() {
    return activeConnectinoQueue.size() + usedConnectinoList.size();
}

public void setDataSource(AbstractDataSource dataSource) {
    this.dataSource = dataSource;
}

public void closeConnectionPool() {

    logger.info("Closing connectionPool started.");
    close(usedConnectinoList);
    close(activeConnectinoQueue);
    logger.info("ConnectionPool Closed.");
}

private void close(BlockingQueue<Connection> connectinosQueue) {
    for (int i=0; i<connectinosQueue.size(); i++) {
        Connection connection = connectinosQueue.remove();
        if(connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                logger.error("Error in initializing connection pool : ", e);
            }
        }
    }
}

}

now To make it safe we need to attach a factory object..

public enum ConnectionFactory {
CONNECTION;

private ConnectionPool connectionPool;
public void setConnectionPool(ConnectionPool connectionPool) {
    this.connectionPool = connectionPool;
}

public Connection getConnection() {
    return connectionPool.getConnection();
}

public void closeConnection() {
    connectionPool.closeConnectionPool();
}

public void releaseConnection(Connection connection) {
    connectionPool.releaseConnection(connection);
}

public int getConnectionPoolSize() {
    return connectionPool.getConnectionPoolSize();
}

@Component
public static class ConnectionBuilder {
    @Autowired
    private ConnectionPool connectionPool;

    public void setConnectionPool(ConnectionPool connectionPool) {
        this.connectionPool = connectionPool;
    }
    @PostConstruct
    public void postConstruct() {
        for (ConnectionFactory cfactory : EnumSet.allOf(ConnectionFactory.class)) {
            cfactory.setConnectionPool(connectionPool);
        }
    }
}

}

Tetreault answered 20/7, 2019 at 9:44 Comment(0)
R
0

Java Connection Pool ?
There are three way to create JDBC Connection Pooling is very easy...

  1. Apache Commons DBCP

    public class DBCPDataSource {
    
    private static BasicDataSource ds = new BasicDataSource();
    
    static {
        ds.setUrl("jdbc:h2:mem:test");
        ds.setUsername("user");
        ds.setPassword("password");
        ds.setMinIdle(5);
        ds.setMaxIdle(10);
        ds.setMaxOpenPreparedStatements(100);
    }
    
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
    
    private DBCPDataSource(){ }
    }
    

    Now you can get connection

    Connection con = DBCPDataSource.getConnection();
    
  2. HikariCP

    public class HikariCPDataSource {
    
    private static HikariConfig config = new HikariConfig();
    private static HikariDataSource ds;
    
    static {
        config.setJdbcUrl("jdbc:h2:mem:test");
        config.setUsername("user");
        config.setPassword("password");
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        ds = new HikariDataSource(config);
    }
    
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
    
    private HikariCPDataSource(){}
    }
    

Now you can get connection

Connection con = HikariCPDataSource.getConnection();
  1. C3PO

     public class C3poDataSource {
    
    private static ComboPooledDataSource cpds = new ComboPooledDataSource();
    
    static {
        try {
            cpds.setDriverClass("org.h2.Driver");
            cpds.setJdbcUrl("jdbc:h2:mem:test");
            cpds.setUser("user");
            cpds.setPassword("password");
        } catch (PropertyVetoException e) {
            // handle the exception
        }
    }
    
    public static Connection getConnection() throws SQLException {
        return cpds.getConnection();
    }
    
    private C3poDataSource(){}
    }
    

Now you can get connection

Connection con = C3poDataSource.getConnection();
Rochus answered 11/2, 2020 at 9:34 Comment(0)
D
0

I have some model code in Java which has connection pool with multithreading.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

abstract class ObjectPool<T> {
    private ConcurrentLinkedQueue<T> pool;
    ScheduledExecutorService executorService;

    ObjectPool(int minObjects) {
        pool = new ConcurrentLinkedQueue<T>();
        for (int i = 0; i < minObjects; i++) {
            pool.add(createObject());
        }
    }

    ObjectPool(final int minObjects, final int maxSize, final long interval){
        pool = new ConcurrentLinkedQueue<T>();
        for (int i = 0; i < minObjects; i++) {
            pool.add(createObject());
        }

        executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleWithFixedDelay(new Runnable(){

            public void run() {
                int size = pool.size();
                while(size > maxSize){
                    pool.remove();
                }
                Iterator i = pool.iterator();
                while(i.hasNext()){
                    T t = (T) i.next();
                    if(checkExpiry(t)){
                        System.out.println("Expiry existed...");
                        i.remove();
                    }
                }

                while(pool.size() < minObjects){
                    System.out.println("Adding more objects to pool");
                    pool.add(createObject());
                }
            }

        }, interval, interval, TimeUnit.MILLISECONDS);

    }

    public T borrowObject() {
        if (pool.peek() == null)
            return createObject();
        return pool.remove();
    }

    public void addObject(T obj) {
        if (obj == null)
            return;
        pool.add(obj);
    }

    public abstract T createObject();

    public abstract boolean checkExpiry(T t);
}

class MultithreadQuery extends Thread{
    private ObjectPool<Connection> pool;
    private int threadNo;
    String query;
    MultithreadQuery(ObjectPool<Connection> pool,int threadNo, String query){
        this.pool = pool;
        this.threadNo = threadNo;
        this.query = query;

    }
    @Override
    public void run(){
        Connection con = pool.borrowObject();
        Statement stmt;
        try {
            stmt = con.createStatement();
            System.out.println("Query started for thread->"+ threadNo);
            ResultSet rs=stmt.executeQuery(query);
            while(rs.next())  
            System.out.println(rs.getInt(1)+"  "+rs.getString(2)+"  "+rs.getString(3));
            System.out.println("closing connection....");
            con.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }  
        pool.addObject(con);        
        System.out.println("Query ended for thread->"+ threadNo);
    }
}

public class ObjectPoolPatternDemo {
    ObjectPool<Connection> pool;

    public void setUp(){
        pool = new ObjectPool<Connection>(4, 10, 1) {

            @Override
            public Connection createObject() {
                Connection con;
                try {
                    con = DriverManager.getConnection("URL","Username","Password");
                    return con;
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return null;
            }

            @Override
            public boolean checkExpiry(Connection conn) {
                boolean expiryFlag = false;
                try {
                    if(conn.isClosed())
                        expiryFlag = true;

                } catch (SQLException e) {
                    e.printStackTrace();
                }
                return expiryFlag;
            }
        };
    }

    public static void main(String[] args) throws SQLException {
        ObjectPoolPatternDemo oppd = new ObjectPoolPatternDemo();
        oppd.setUp();

        ExecutorService es = Executors.newFixedThreadPool(4);
        String query = "select * from TABLE";
        es.execute(new MultithreadQuery(oppd.pool,1,query));
        es.execute(new MultithreadQuery(oppd.pool,2,query));
        es.execute(new MultithreadQuery(oppd.pool,3,query));
        es.execute(new MultithreadQuery(oppd.pool,4,query));
        es.execute(new MultithreadQuery(oppd.pool,5,query));
        es.execute(new MultithreadQuery(oppd.pool,6,query));

        es.shutdown();
        try {
            es.awaitTermination(1, TimeUnit.DAYS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("finally completed...");
    }
}
Deadbeat answered 12/2, 2020 at 8:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.