18 February 2013

Home-grown ConnectionPool

I've written some code that act as a simple connection Pool. This code is not a production code, you need to test it carefully before using it. First, the DAO interface:
package com.forat.model;

import java.util.List;

public interface DAO<T> {
    public void persist(T o);
    public T find (int id);
    public List<T> findAll();
    public void remove(int id);
    public void update(T o);
}
And a domain object represents a User:
package com.forat.model;

import java.io.Serializable;

public class User implements Serializable {
    private int id;
    private String username;
    private String password;
    private String fullName;
    private String email;
    
    public User() {
    }
    
    public int getId() {
        return id;
    }
    private void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getFullName() {
        return fullName;
    }
    public void setFullName(String fullName) {
        this.fullName = fullName;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
}
And here's the connection Pool code (3 Classes)
package com.forat.db;

import java.sql.Connection;

public class PooledConnection {
    
    private Connection connection;
    private boolean inUse = false;
    
    public PooledConnection(Connection connection) {
        this.connection = connection;
    }
    
    /**
     * 
     * @return
     */
    public synchronized Connection getConnection() {
        if (!inUse) {
            inUse = true;
            return connection;
        }
        return null;
    }
    
    
    Connection _getUnderlyingConn() {
        return connection;
    }
    
    public synchronized void releaseConnection() {
        inUse = false;
    }
}
package com.forat.db;

import java.sql.Connection;
import java.sql.DriverManager;

class ConnectionFactory {
    static Connection createConnection() {
        try {
            return DriverManager.getConnection("jdbc:mysql://localhost:3306/register", "root", "system");
        }catch(Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage(), ex);
        }
    }
    
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        }catch(Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException(ex.getMessage(), ex);
        }
    }
}
package com.forat.db;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.forat.model.User;

/**
 * This class needs extensive testing before used in real applications
 * @author mohammed
 *
 */
public class Manager {
    
    private static List<PooledConnection> connectionPool = new ArrayList<PooledConnection>();
    
    public static synchronized Connection getConnection() {
        for (PooledConnection pconn : connectionPool) {
            Connection conn = pconn.getConnection() ; 
            if (conn != null)
                return conn;
        }
        
        PooledConnection pconn = new PooledConnection(ConnectionFactory.createConnection()); 
        connectionPool.add(pconn);
        return pconn.getConnection();
    }
    
    public static synchronized void closeConnection(Connection conn) {
        for (PooledConnection pconn : connectionPool) {
            if (pconn._getUnderlyingConn() == conn) {
                pconn.releaseConnection();
                return;
            }
        }
        System.err.println("Connection " + conn + " Cannot be release!");
    }
    
    static {
        for (int i=0; i < 10; i++) {
            connectionPool.add(new PooledConnection(ConnectionFactory.createConnection()));
        }
    }
    
}
And here's the UserDAO; a DAO for the User Object
package com.forat.model;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import com.forat.db.Manager;

public class UserDAO implements DAO<User> {

    @Override
    public void persist(User o) {
        Connection conn = null;
        try {        
            conn = Manager.getConnection();
            String sql = "INSERT INTO user (username, password, fullname, email) VALUES (?, ?, ?, ?)";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, o.getUsername());
            pstmt.setString(2, o.getPassword());
            pstmt.setString(3, o.getFullName());
            pstmt.setString(4, o.getEmail());
            int result = pstmt.executeUpdate();
            
            if (result != 1)
                throw new SQLException("no row inserted!");
        }catch (Exception ex) {
            ex.printStackTrace();
            throw new RuntimeException("Cannot add new User", ex);
        }finally {
            Manager.closeConnection(conn);
        }
    }
    @Override
    public User find(int id) {
        return null;
    }

    @Override
    public List<User> findAll() {
        return null;
    }

    @Override
    public void remove(int id) {
        
    }

    @Override
    public void update(User o) {
        
    }

    public static void main(String[] args) {
        User u = new User();
        u.setUsername("Ahmed");
        u.setPassword("system");
        u.setEmail("ahmed.hewedy@yahoo.com");
        new UserDAO().persist(u);
    }
    
}
That's all. Note, I've write this code in ArabTeam2000 forum a long time ago.

No comments: