Why connection close doesnt work in this code? I tried way without finally block by creating connection in try() but after executing testDbConnection a few times I have too many connections error and when I am trying to connect to my database by pgAdmin I see too many clients connected. How can I resolve it? Why closing connection doesn't work?
private List<DataSource> getDataSources() {
connectionsNumber = 2;
List<DataSource> dataSources = new ArrayList<>();
for (int i = 1; i <= connectionsNumber; i++) {
Connection connection;
DataSource dataSource;
String jdbcUrl = environment.getProperty(String.format("database%d.url", i));
String user = environment.getProperty(String.format("database%d.username", i));
String password = environment.getProperty(String.format("database%d.password", i));
ComboPooledDataSource cpds = new ComboPooledDataSource();
try {
cpds.setDriverClass("org.postgresql.Driver");
} catch (PropertyVetoException e) {
e.printStackTrace();
}
cpds.setJdbcUrl(jdbcUrl);
cpds.setUser(user);
cpds.setPassword(password);
cpds.setMinPoolSize(3);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
cpds.setMaxIdleTime(1);
cpds.setMaxConnectionAge(600);
cpds.setMaxStatements(500);
dataSource = cpds;
dataSources.add(dataSource);
}
return dataSources;
}
public void testDbConnection() throws SQLException {
String query = "select id from users;";
Statement st = null;
ResultSet rs = null;
Connection connection = null;
List<DataSource> dataSources = getDataSources();
for (DataSource dataSource : dataSources) {
try {
connection = dataSource.getConnection();
st = connection.createStatement();
rs = st.executeQuery(query);
while (rs.next()) {
System.out.println("Connection");
}
} finally {
if (st != null) {
st.close();
}
if (rs != null) {
rs.close();
}
if (connection != null) {
connection.close();
}
st = null;
rs = null;
connection = null;
}
}
}
In my opinion,when using the c3p0, connection.close() is not really closing the connection, just put it back in the pool.if you want to clean up the DataSource,you can use DataSources.destroy(dataSource);
Related
I was working on a java project and it was working just fine. I was able to make connections. I closed all the connections properly in finally block. Now I am not able to make connections or even open psql in my terminal. How can I make it work as before. Much much appreciated
import java.sql.Connection;
import com.mchange.v2.c3p0.*;
public class MyConnection {
public static Connection getConnection(){
ComboPooledDataSource cpds1 = new ComboPooledDataSource();
String dbDriver = "org.postgresql.Driver";
String dbName = "jdbc:postgresql://localhost/postgres";
cpds1.setJdbcUrl(dbName);
String userName = "user_1";
cpds1.setUser(userName);
String password = "mypass";
cpds1.setPassword(password);
cpds1.setMaxStatements( 180 );
try
{
cpds1.setDriverClass(dbDriver);
return cpds1.getConnection();
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
}
This is where I'm calling it
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException
{
PrintWriter writer = response.getWriter();
JSONObject jo = new JSONObject();
JSONObject jObj;
Statement stmt = null;
Connection con = null;
PreparedStatement ps;
ResultSet rs = null;
try
{
jObj = UtilityClass.getJSON(request);
String uname = ((String) jObj.get("uname"));
String pass = ((String) jObj.get("pass"));
String sql = "SELECT * FROM users WHERE username = ?";
try
{
con = MyConnection.getConnection();
System.out.println("Got Connection");
stmt = con.createStatement();
ps = con.prepareStatement(sql);
ps.setString(1, uname);
rs = ps.executeQuery();
if(rs.next())
{
if(BCrypt.checkpw(pass,rs.getString("password")))
{
HttpSession session = request.getSession();
session.setAttribute("uname", uname);
if(session.isNew())
{
System.out.println("new");
}
if(uname.equals("admin"))
{
session.setAttribute("role", "admin");
jo.put("status", "admin");
}
else
{
session.setAttribute("role", "user");
jo.put("status", "authenticate");
}
}
}
writer.print(jo);
}
catch (Exception e)
{
e.printStackTrace();
System.out.println("Not Connected");
}
finally
{
if(rs != null)
{
rs.close();
}
if(stmt != null)
{
stmt.close();
}
if(con != null)
{
con.close();
}
}
}
catch(Exception e)
{
System.out.print("JSON Exception");
}
}
Usually, DB Admins are using pooling technologies on Databases. For PostgreSQL one of the more popularly is a PGBOUNCER. We used PGBOUNCER in our large project, the result is excellent. I recommend it to you. To get more information about the pooling system you can read this link. For About Pooling
I'm getting "While trying to lookup 'jdbc.LogDB' didn't find subcontext 'jdbc'. Resolved ''" error when i try to get connection from the Weblogic. I created and tested the datasource and it's working. Also created the target servers. Datasource name is "jdbc/LogDb". Below is the test code i wrote.
public class TestUtils {
private static final Logger logger = LoggerFactory.getLogger(TestUtils.class.getName());
public DataSource ds = null;
public String testConnectionPool() throws SQLException {
Context ctx = null;
Hashtable ht = new Hashtable();
Connection conn;
String result = "";
ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
ht.put(Context.PROVIDER_URL, "t3://localhost:7001");
ht.put(Context.SECURITY_PRINCIPAL, "weblogic");
ht.put(Context.SECURITY_CREDENTIALS, "weblogic");
try {
ctx = new InitialContext(ht);
ds = (DataSource) ctx.lookup("jdbc/LogDB");
logger.debug("Weblogic Connection Pool Created");
conn = ds.getConnection();
Statement stmt = conn.createStatement();
stmt.execute("some sql");
ResultSet rs = stmt.getResultSet();
if(rs.next()){
result = result + rs.getString(1);
}
stmt.close();
conn.close();
} catch (NamingException e) {
logger.error("Naming Exception occured at connect: " + e.getMessage());
} catch (Exception e){
logger.error("Exception occured at connect: "+ e.getMessage());
} finally {
try {
if (ctx != null) {
ctx.close();
}
}
catch (Exception e) {
logger.error("Ctx Error");
}
}
return result;
}
}
I tried the following names
"java:jdbc/LogDb"
"java:comp/env" variations etc.
Thanks for the kind answers
I have the following Callable instance where the SQLException is thrown here:
public long[] call() throws Exception {
long[] stats = new long[6];
try {
executer.acquire();
PreparedStatement statement =
connection
.prepareStatement("SELECT `War`.`EndTime` FROM `WarSim`.`War` WHERE `War`.`WarName` = ?");
statement.setString(1, warName);
ResultSet res = statement.executeQuery(); //<--------------SQLEXCEPTION HERE
if (res.first()) {
Timestamp ts = res.getTimestamp("EndTime");
if (ts != null)
stats[0] = 1;
statement =
connection
.prepareStatement("SELECT COUNT(`ID`) FROM `Missile` WHERE `WarName` = ?");
statement.setString(1, warName);
res = statement.executeQuery();
stats[1] = res.getInt(1);
statement =
connection
.prepareStatement("SELECT COUNT(`ID`) FROM `Missile` WHERE `WarName` = ? AND `Intercepted` = '1'");
statement.setString(1, warName);
res = statement.executeQuery();
stats[2] = res.getInt(1);
stats[3] = stats[1] - stats[2];
statement =
connection
.prepareStatement("SELECT COUNT(`ID`) FROM `EnemyLauncher` WHERE `WarName` = ? AND `Intercepted` = '1'");
statement.setString(1, warName);
res = statement.executeQuery();
stats[4] = res.getInt(1);
statement =
connection
.prepareStatement("SELECT SUM(`Damage`) FROM `Missile` WHERE `WarName` = ? AND `Intercepted` = '0'");
statement.setString(1, warName);
res = statement.executeQuery();
stats[5] = res.getInt(1);
}
} catch (SQLException e) {
System.out.println(warName + " is problematic");
while (e != null) {
System.out.println("\tmsg: " + e.getMessage()+
"\n\tstate: " + e.getSQLState());
e = e.getNextException();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
executer.release();
}
return stats;
}
executer is a single-permit, fair semaphore I use.
When I debug the code, everything works perfectly (no exceptions), yet when I run the program "normally" I get the "start of result set" SQLException thrown along with SQLState S1000.
How come I get exceptions even though I used a semaphore to acquire the mutex to query?
Help please :)
EDIT: here's the stack trace.
java.sql.SQLException: Before start of result set
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1075)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:929)
at com.mysql.jdbc.ResultSetImpl.checkRowPos(ResultSetImpl.java:841)
at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2672)
at db.jdbc.GetWarStatsTask.call(GetWarStatsTask.java:37)
at db.jdbc.GetWarStatsTask.call(GetWarStatsTask.java:1)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
The class handling the Connection to the database:
public class JDBCConnection implements DBConnection {
private Connection connection;
private String dbUrl;
private Semaphore executer;
private ExecutorService es;
private static JDBCConnection instance;
public static JDBCConnection getInstance() {
if (instance == null) {
instance = new JDBCConnection();
}
return instance;
}
private JDBCConnection() {
dbUrl = "jdbc:mysql://---------/WarSim";
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection =
DriverManager.getConnection(dbUrl, "------", "-------");
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
while (e != null) {
System.out.println(e.getMessage());
e = e.getNextException();
}
}
es = Executors.newCachedThreadPool();
executer = new Semaphore(1, true);
}
public Future<long[]> getWarStats(String warName) {
return es.submit(new GetWarStatsTask(executer, connection, warName));
}
public void closeDB() {
try {
if (connection != null) {
connection.close();
}
} catch (Exception e) {
System.out.println("Could not close the current connection.");
e.printStackTrace();
}
}
Basically you are positioning the cursor before the first row and then requesting data. You need to move the cursor to the first row.
So first call result.next();
By the use of the semaphore, you understand the JDBC rule that a connection should only be in use by a single thread at a time. However, there are other threads that you need to be aware of, namely the garbage collector thread.
In this case, you need to close all the statement objects that are created before releasing the semaphore. If you don't close the statement objects, they will be closed by the garbage collector thread at an indeterminate time, causing unusual behavior on the connection.
So, before you prepare a new statement object, you need to close the old one.
statement.close()
statement =
connection
.prepareStatement("SELECT COUNT(ID) FROM Missile WHERE WarName = ?");
At the end you need to close the statement.
stats[5] = res.getInt(1);
statement.close()
You may want to get in the practice of running "findbugs" on your code. I think that may have spotted the problem of not closing the Statement object.
I'm new to Java web service. I've been playing with it for a few days and finally I am able to connect to the Oracle database on a different machine. Happy so far.
The samples that I have seen on the web so far saying that you only need to register the oracle.jdbc.OracleDriver once.
How do you do that on a web service? Right now I register it every time the function e.g. getUserFullName is called.
Any input is appreciated.
Edited:
here's one of the functions:
public static String getUserName(int id) throws SQLException {
String returnValue = "";
Statement stmt = null;
ResultSet rset = null;
Connection conn = null;
try {
DriverManager.registerDriver (new oracle.jdbc.OracleDriver());
conn = DriverManager.getConnection("jdbc:oracle:thin:#//myOracleIP:1521/myOracleDB", "admin", "password");
stmt = conn.createStatement();
rset = stmt.executeQuery("select name from tbl_users where id = " + id);
while(rset.next()) {
returnValue = rset.getString("name");
}
}
catch(Exception ex) {
returnValue = "jdbc.getUserName -- Exception: " + ex.getMessage();
}
finally {
// close resultset
if(rset != null)
if(!rset.isClosed())
rset.close();
// close statement
if(stmt != null)
if(!stmt.isClosed())
stmt.close();
// close connection
if(conn != null)
if(!conn.isClosed())
conn.close();
}
stmt = null;
rset = null;
conn = null;
return returnValue;
}
JNDI Function
public static String getNameWithJNDI(int id) throws SQLException {
int statusCode = 0;
String returnValue = "Open DB";
DataSource dc = null;
Statement stmt = null;
ResultSet rset = null;
Connection conn = null;
Context context = null;
try {
context = new InitialContext();
// my datasource from the GlassFish
dc = (DataSource)context.lookup("jdbc/myConnection");
context.close();
}
catch(NamingException e) {
statusCode = 1;
returnValue = "jdbc.GetNameWithJNDI - InitialContext Error: " + e.getMessage();
}
if((statusCode == 0) && (dc != null)) {
try {
conn = dc.getConnection();
stmt = conn.createStatement();
rset = stmt.executeQuery("select name from tbl_users where id = " + id);
if(rset != null) {
while(rset.next()) {
returnValue = "JNDI: " + rset.getString("name");
}
}
}
catch(SQLException e) {
statusCode = 1;
returnValue = "jdbc.GetNameWithJNDI - Database Error: " + e.getMessage();
}
finally {
// close resultset
if(rset != null)
if(!rset.isClosed())
rset.close();
// close statement
if(stmt != null)
if(!stmt.isClosed())
stmt.close();
// close connection
if(conn != null)
if(!conn.isClosed())
conn.close();
}
}
dc = null;
stmt = null;
rset = null;
conn = null;
context = null;
return returnValue;
}
JDBC 4 compliant drivers don't need to be registered. If you are using an application server, the usual way is to create a DataSource in your application server and use that from within your application (by referencing it using JNDI) instead of creating connections using DriverManager. The application server DataSource usually also takes care of things like connection pooling.
I would use a JNDI lookup for each time a JDBC resource needs to be used, especially if you are using a Java Application Server, which it seems you are (as you are conducting Web Services). This means that you don't have to keep loading the JDBC Driver each time. For example, you may want to have a look at the following: http://docs.oracle.com/cd/A97335_02/apps.102/a83724/samapp9.htm
Connection Pooling can also be found at the following article: http://www.eclipse.org/jetty/documentation/current/jndi-datasource-examples.html#pooling-datasources
It's been a while since I have done any Java programming. And I find my self a bit stuck.
My problem is that I have a pooled db connection in tomcat. That is working nicely. But there is a lot of boiler plate required.
public void init() {
Connection conn = null;
ResultSet rst = null;
Statement stmt = null;
try {
//SETUP
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env/jdbc");
OracleDataSource ds = (OracleDataSource) envContext.lookup("tclsms");
if (envContext == null) throw new Exception("Error: No Context");
if (ds == null) throw new Exception("Error: No DataSource");
if (ds != null) conn = ds.getConnection();
if (conn == null) throw new Exception("Error: No Connection")
message = "Got Connection " + conn.toString() + ", ";
//BODY
stmt = conn.createStatement();
rst = stmt.executeQuery("SELECT 'Success obtaining connection' FROM DUAL");
if (rst.next()) message = rst.getString(1);
//TEAR DOWN
rst.close();
rst = null;
stmt.close();
stmt = null;
conn.close(); // Return to connection pool
conn = null; // Make sure we don't close it twice
} catch (Exception e) {
e.printStackTrace();
//TODO proper error handling
} finally {
// Always make sure result sets and statements are closed,
// and the connection is returned to the pool
if (rst != null) {
try {
rst.close();
} catch (SQLException e) {;}
rst = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {;}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {;}
conn = null;
}
} //END FINALLY
} //END INIT
So I want to do the equivalent of passing a method into init that will run in the body of the function. I know I can't do this in Java. But I'm sure there must be a nice way to do this. Or at least a best practice for this sort of thing.
Any help much appreciated.
abstract class UseDBConnectionTask extends Runnable {
private Connection conn;
public UseDBConnectionTask(){
setUp();
}
// should probably refine this to specific exceptions
public abstract void process() throws Exception;
public void run(){
try{
process()
// this should catch specific exceptions
} catch (Exception e){
// handle
} finally {
tearDown();
}
}
Connection getConnection(){
return conn;
}
public void setUp(){
// SETUP here
// set the conn field
}
public void tearDown(){
// TEAR DOWN here
}
}
use like:
UseDBConnectionTask dbTransaction = new UseDBConnectionTask(){
public void process(){
// do processing
// use conn via getConnection()
// eg
Statement stmt = conn.createStatement();
ResultSet rst = stmt.executeQuery("SELECT 'Success obtaining connection' FROM DUAL");
String message = null;
if (rst.next()) message = rst.getString(1);
}
}
new Thread(dbTransaction).start();
The advantage of extending Runnable is that you can then pass this instance into a thread pool or similar.
Just have to be careful of threading issues. It also assumes that the tear down is always the same.
You should prefer delegation to inheritance. The above can/will work but isn't well thought out.
Implementing Runnable on the primary class exposes it for abuse because the 'run()' method is public.
A second improvement is to use to delegate your activity to an interface (and this CAN be passed around like a function pointer whereas extending the class cannot). In addition, it makes it Spring friendly
This allows the action implementer to decide if they want multi-threaded behavior or not. You can inject composites, caching delegates, etc and the primary class is none-the-wiser. This conforms with good design practice of separation of concerns
public class MyClass {
private Action action;
public MyClass (Action action) {
this.action = action;
}
public void connection() {
try{
action.perform()
} catch (Exception e){
// handle
} finally {
tearDown();
}
}
Connection getConnection(){
return conn;
}
private void setUp(){
// SETUP here
// set the conn field
}
private void tearDown(){
// TEAR DOWN here
}
}
interface IDbAction {
public DbActionResult runAction(Connection conn);
}
class DbActionResult {
Statement statement;
ResultSet resultSet;
public DbActionResult(Statement statement, ResultSet resultSet){
this.statement = statement;
this.resultSet = resultSet;
}
public void getStatement(){ return this.statement; }
public void getResultSet(){ return this.resultSet; }
}
public void runAgainstDB(IDbAction action) {
Connection conn = null;
ResultSet rst = null;
Statement stmt = null;
try {
//SETUP
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env/jdbc");
OracleDataSource ds = (OracleDataSource) envContext.lookup("tclsms");
if (envContext == null) throw new Exception("Error: No Context");
if (ds == null) throw new Exception("Error: No DataSource");
if (ds != null) conn = ds.getConnection();
if (conn == null) throw new Exception("Error: No Connection")
message = "Got Connection " + conn.toString() + ", ";
//BODY
DbActionResult actionResult = action.runAction(conn);
//TEAR DOWN
if((rst = actionResult.getResultSet()) != null){
rst.close();
rst = null;
}
if((stmt = actionResult.getStatement()) != null){
stmt.close();
stmt = null;
}
actionResult = null;
conn.close(); // Return to connection pool
conn = null; // Make sure we don't close it twice
} catch (Exception e) {
e.printStackTrace();
//TODO proper error handling
} finally {
// Always make sure result sets and statements are closed,
// and the connection is returned to the pool
if (rst != null) {
try {
rst.close();
} catch (SQLException e) {;}
rst = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {;}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {;}
conn = null;
}
} //END FINALLY
} //END
Use like:
IDbAction action = new IDbAction(){
public DbActionResult prcoessAction(Connection conn){
Statement stmt = conn.createStatement();
ResultSet rst = stmt.executeQuery("SELECT 'Success obtaining connection' FROM DUAL");
if (rst.next()) message = rst.getString(1);
return new DbActionResult(stmt, rst);
}
}
runAgainstDB(action);
private void Todo(Context initContext, Context envContext, OracleDataSource ds){
if (envContext == null) throw new Exception("Error: No Context");
if (ds == null) throw new Exception("Error: No DataSource");
if (ds != null) conn = ds.getConnection();
if (conn == null) throw new Exception("Error: No Connection")
message = "Got Connection " + conn.toString() + ", ";
//BODY
stmt = conn.createStatement();
rst = stmt.executeQuery("SELECT 'Success obtaining connection' FROM DUAL");
if (rst.next()) message = rst.getString(1);
//TEAR DOWN
rst.close();
rst = null;
stmt.close();
stmt = null;
conn.close(); // Return to connection pool
conn = null; // Make sure we don't close it twice
} catch (Exception e) {
e.printStackTrace();
//TODO proper error handling
} finally {
// Always make sure result sets and statements are closed,
// and the connection is returned to the pool
if (rst != null) {
try {
rst.close();
} catch (SQLException e) {;}
rst = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {;}
stmt = null;
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {;}
conn = null;
}
} //END FINALLY
}
Then call it from your Init like this this. Todo(initContext,envContext , ds)