I have quite a few of methods that run some inserts and updates. One example is as follows:
#SuppressWarnings("unchecked")
public void insertStuff( String crap1, String crap2 ) throws SQLException {
Connection conn = null;
PreparedStatement ps1 = null;
try
{
String sqlStr = " INSERT INTO ... "
+ " VALUES (? , ? )" ;
conn = JNDIUtil.getConnection();
ps1 = conn.prepareStatement(sqlStr);
ps1.setString(1, crap1);
ps1.setString(2, crap2);
ps1.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.close(ps1);
DbUtils.close(conn);
}
}
My JNDIUtil is :
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public final class JNDIUtil {
private static final String JDBC_DB_URL = "blah";
public static Connection getConnection() {
Connection conn = null;
try {
Context ctx = (Context) new InitialContext();
DataSource ds = (DataSource)ctx.lookup(JDBC_DB_URL);
conn = ds.getConnection();
} catch (final SQLException e) {
e.printStackTrace();
} catch (final NamingException e) {
e.printStackTrace();
}
return conn;
}
}
Now, this is a jboss eap 6.4 server. I limited the max pool size in order to replicate the same error that happens in production :
<max-pool-size>10</max-pool-size>
When I run a load test with JMeter using 20 threads firing at the same time, I get the following error :
I get the following error :
16:05:20,018 ERROR [stderr] (http-/127.0.0.1:8085-19) java.sql.SQLException: javax.resource.ResourceException: IJ000453: Unable to get managed connection for blah
Each method has a close prepared statement, close result set, and close connection in the reverse order they are created. By the way, DBUtils.close() is from Apache Commons DBUtils. When I look at JBoss Management Console, I see that available connections drop to 0.
Why are these connections not being closed when each method is being executed?
Related
This question already has an answer here:
Manipulating an Access database from Java without ODBC
(1 answer)
Closed 5 years ago.
i'm trying to connect the java to ms access database but it didn't work really well
and i got an error message like this
sun.jdbc.odbc.JdbcOdbcDriver
this is my code :
import java.sql.*;
public class main{
public static void main(String[] args) {
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection("jdbc:odbc:Driver={Microsoft Access Driver(*.accdb)};DBQ=D:\\Andries\\testdatabase.accdb");
Statement st = con.createStatement();
}catch(Exception ex){
System.out.println(ex.getMessage());
}
}
}
you can use ucanacess.jar for connect Ms Aceess database
show some example here http://www.benchresources.net/jdbc-msaccess-database-connection-steps-in-java-8/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class MsAccessDatabaseConnectionInJava8 {
public static void main(String[] args) {
// variables
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
// Step 1: Loading or registering Oracle JDBC driver class
try {
Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
}
catch(ClassNotFoundException cnfex) {
System.out.println("Problem in loading or "
+ "registering MS Access JDBC driver");
cnfex.printStackTrace();
}
// Step 2: Opening database connection
try {
String msAccDB = "D:/WORKSPACE/TEST_WORKSPACE/Java-JDBC/Player.accdb";
String dbURL = "jdbc:ucanaccess://" + msAccDB;
// Step 2.A: Create and get connection using DriverManager class
connection = DriverManager.getConnection(dbURL);
// Step 2.B: Creating JDBC Statement
statement = connection.createStatement();
// Step 2.C: Executing SQL & retrieve data into ResultSet
resultSet = statement.executeQuery("SELECT * FROM PLAYER");
System.out.println("ID\tName\t\t\tAge\tMatches");
System.out.println("==\t================\t===\t=======");
// processing returned data and printing into console
while(resultSet.next()) {
System.out.println(resultSet.getInt(1) + "\t" +
resultSet.getString(2) + "\t" +
resultSet.getString(3) + "\t" +
resultSet.getString(4));
}
}
catch(SQLException sqlex){
sqlex.printStackTrace();
}
finally {
// Step 3: Closing database connection
try {
if(null != connection) {
// cleanup resources, once after processing
resultSet.close();
statement.close();
// and then finally close connection
connection.close();
}
}
catch (SQLException sqlex) {
sqlex.printStackTrace();
}
}
}
}
I'm testing sonar in order to ensure the closing database connections and I'm having extrange results I don't understand.
I'm trying two versions of the code executing the maven goal "sonar:sonar" from eclipse with the embeded maven version 3.3.9.
I've tried with three versions of sonarqube server: 5.6.6, 6.2 and 6.4.
With this code
package db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class TestClosingResources {
public static void main(String[] args) {
Connection con = null;
ResultSet rsGet = null;
PreparedStatement psGet = null;
try {
DriverManager.registerDriver (new com.mysql.jdbc.Driver());
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "test", "test");
psGet = con.prepareStatement("SELECT * FROM TEST");
rsGet = psGet.executeQuery();
int counter = 0;
while (rsGet.next()) {
counter++;
System.err.println(counter);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rsGet != null) {
rsGet.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
rsGet = null;
try {
if (psGet != null) {
psGet.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
psGet = null;
}
}
}
I have these issues about closing resources:
sonarqube 5.6.6:
Close this "Connection"
Close this "PreparedStatement"
sonarqube 6.2:
Close this "Connection"
Close this "PreparedStatement"
sonarqube 6.4:
Close this "Connection"
My question with this code is:
Why does 5.6.6 and 6.2 complain about PreparedStatement when it's
closed exactly the same than the ResultSet?
And whith this code (only changes the way I retrieve the connection, it doesn't matter if it would work or not)
package db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class TestClosingResources {
public static void main(String[] args) {
Connection con = null;
ResultSet rsGet = null;
PreparedStatement psGet = null;
try {
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/testci");
con = ds.getConnection();
psGet = con.prepareStatement("SELECT * FROM TEST");
rsGet = psGet.executeQuery();
int counter = 0;
while (rsGet.next()) {
counter++;
System.err.println(counter);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rsGet != null) {
rsGet.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
rsGet = null;
try {
if (psGet != null) {
psGet.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
psGet = null;
}
}
}
sonarqube 5.6.6:
Close this "PreparedStatement"
sonarqube 6.2:
Close this "PreparedStatement"
sonarqube 6.4:
no issues about closing resources
My questions with this code are:
Why does 5.6.6 and 6.2 complain about PreparedStatement when it's
closed exactly the same than the ResultSet?
Why doesn't any version complain about not closing the connection?
Thanks
The reason why some issues are not detected in more recent versions is due to the fact that static analyzer doing the analysis was improved.
Plugin used for Java source code analysis is called SonarJava, and it has independent release cycle than SonarQube. You should always use the latest release to obtain best results. Use update center on your SonarQube server to update to the latest available release.
Hi I am trying to connect with Cassandra using jdbc driver. I am getting the following exception.
java.sql.SQLNonTransientConnectionException: Connection url must specify a host, e.g., jdbc:cassandra://localhost:9170/Keyspace1
at org.apache.cassandra.cql.jdbc.Utils.parseURL(Utils.java:190)
at org.apache.cassandra.cql.jdbc.CassandraDriver.connect(CassandraDriver.java:85)
at java.sql.DriverManager.getConnection(Unknown Source)
at java.sql.DriverManager.getConnection(Unknown Source)
at com.sub.cas.CqlJdbcTestBasic.main(CqlJdbcTestBasic.java:14)
My cassandra server is running fine and can be accessed from cql shell in windows 10 OS.
This is the java class that I have written.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class CqlJdbcTestBasic {
public static void main(String[] args) {
Connection con = null;
try {
Class.forName("org.apache.cassandra.cql.jdbc.CassandraDriver");
con = DriverManager.getConnection("jdbc:cassandra:/root/root#localhost:9160/hr");
String query = "SELECT empid, emp_first, emp_last FROM User WHERE empid = 1";
Statement stmt = con.createStatement();
ResultSet result = stmt.executeQuery(query);
while (result.next()) {
System.out.println(result.getString("empid"));
System.out.println(result.getString("emp_first"));
System.out.println(result.getString("emp_last"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (con != null) {
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
con = null;
}
}
}
}
I have gathered my jars from this url :: https://code.google.com/archive/a/apache-extras.org/p/cassandra-jdbc. Unable to find any possible solution. Please help.
Please, check if you have two slashes before your user name. According to
http://www.dbschema.com/cassandra-jdbc-driver.html
package WBSer_RwCnt;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Rw_Count {
public static Connection getConnection() throws Exception {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost/hospital_data";
String username = "root";
String password = "mysql";
Class.forName(driver); // load MySQL driver
Connection conn = DriverManager.getConnection(url, username, password);
return conn;
}
public static int countRows(Connection conn, String tableName) throws SQLException {
// select the number of rows in the table
Statement stmt = null;
ResultSet rs = null;
int rowCount = -1;
try {
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT COUNT(*) FROM " + tableName);
// get the number of rows from the result set
rs.next();
rowCount = rs.getInt(1);
} finally {
rs.close();
stmt.close();
}
return rowCount;
}
public static void main(String[] args) {
Connection conn = null;
try {
conn = getConnection();
String tableName = "hospital_status";
System.out.println("tableName=" + tableName);
System.out.println("conn=" + conn);
System.out.println("rowCount=" + countRows(conn, tableName));
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
} finally {
// release database resources
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Error --->
The method "getConnection" on the service class "WBSer_RwCnt.Rw_Count" uses a data type, "java.sql.Connection", that is not supported
When i compile it without creating it as webservice it works correctly
but when i make it as web service it gives output as
Output --->
WBSer_RwCnt.Rw_CountSoapBindingStub#121a412b
Please Help !
Next Try
So this is what i have done after what you have said even then it gives following errors
Exception:
java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost/hospital_data
Message:
java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost/hospital_data
package WBSer_RwCnt;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Rw_Count {
public static int countRows() throws SQLException {
// select the number of rows in the table
Statement stmt = null;
ResultSet rs = null;
System.out.println("ram");
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost/hospital_data";
String username = "root";
String password = "mysql";
try {
Class.forName(driver);
}
catch (ClassNotFoundException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();
}
// load MySQL driver
Connection conn = DriverManager.getConnection(url, username, password);
int rowCount = -1;
try {
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT COUNT(*) FROM hospital_status");
// get the number of rows from the result set
rs.next();
rowCount = rs.getInt(1);
}
catch (Exception e)
{
e.printStackTrace();
System.exit(1);
}
finally {
rs.close();
stmt.close();
conn.close();
}
return rowCount;
}
}
i have the added all jar files including the java mysql connectors
This is not going to be a full answer as I'm not exactly sure about the tools you are using to compile the web service, but anyway, here goes:
Basically, a connection is something that is only valid on a particular machine. If it's a TCP/IP connection, it consists of two pairs: source host and port, and target host and port. If it's a Linux socket, then it is an entry in that particular machine's directory tree.
A database connection is usually built on one of those constructs, so it, too, is particular to a machine.
Therefore, it doesn't make sense to pass a Connection object to the user who calls your method from some remote machine. And since it doesn't make sense, the JAX-RPC standard does not include a serialization for Connection, and that's why it fails.
Your problem is that you have designed your method such that it accepts a connection as a parameter, and uses that connection to access the database. This works OK locally, but is not a good design for a remote service.
Instead, your method should acquire the connection internally. The remote user should access just the countRows method, with the name of the table, and countRows should call getConnection, use the connection, and the close it.
You shouldn't have a main method in a web service. And the getConnection method should be changed from public to private, so that countRows can access it. When it is private, I believe the web service compiler will not complain about it because it doesn't have to create a serialization for it.
Here I am using jdbcHelper to establish connection with database but some times(not all the times) I am getting exception as null pointer in connection establishment but that is not all the time.
here is my code.This code is used to insert data into database..
Connection conn = JDBCHelper.getConnection();
PreparedStatement ps1 = null;
System.out.println("In Side DATA BASE");
System.out.println("in side database deviceid=" + s);
System.out.println("in side database rfide=" + s1);
System.out.println("in side database longitude=" + lati);
System.out.println("in side database latitude= " + lot);
System.out.println("in side database datalength=" + data_length);
Date date = new Date();
java.sql.Timestamp dt = new java.sql.Timestamp(date.getTime());
int flag = 1;
System.out.println("date=" + dt);
System.out.println("flag=" + flag);
try {
String hql = "insert into gpsData1(dateTime,deviceid,latitude,longitude,rfid,flag,datalength) values(?,?,?,?,?,?,?)";
ps1 = conn.prepareStatement(hql);
ps1.setString(1, dt.toString());
ps1.setString(2, s);
ps1.setFloat(3, lati);
ps1.setFloat(4, lot);
ps1.setString(5, s1);
ps1.setInt(6, flag);
ps1.setInt(7, data_length);
ps1.executeUpdate();
conn.commit();
System.out.println("DATA BASE Inserting Completed");
} catch (Exception ex) {
ex.printStackTrace();
} finally {
JDBCHelper.close(ps1);
JDBCHelper.close(conn);
}
This is my JDBC code..
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCHelper {
public static final String url = "jdbc:mysql://localhost:3306/treamisdemo";
public static final String uid = "root";
public static final String pwd = "myserver";
/**
* #param
* args
*/
static {
try {
Class.forName("com.mysql.jdbc.Driver");
System.out.println("connection is sucessful");
} catch (ClassNotFoundException e) {
System.err.println("ERROR: failed to load mysql JDBC driver.");
e.printStackTrace();
}
}
public static void close(ResultSet c) {
try {
if (c != null) {
c.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(Statement c) {
try {
if (c != null) {
c.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(Connection c) {
try {
if (c != null) {
c.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
Connection con = null;
try {
con = DriverManager.getConnection(url, uid, pwd);
System.out.println("obtain connection =" + con);
con.setAutoCommit(false);
return con;
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
}
This is the stack trace..
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data sourc
e rejected establishment of connection, message from server: "Too many connecti
ons"
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstruct
orAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC
onstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1128)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2336)
at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2
369)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2153)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:792)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
at sun.reflect.GeneratedConstructorAccessor39.newInstance(Unknown Source
)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingC
onstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:381)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java
:305)
at java.sql.DriverManager.getConnection(DriverManager.java:571)
at java.sql.DriverManager.getConnection(DriverManager.java:215)
at com.treamis.transport.vehicle.JDBCHelper.getConnection(JDBCHelper.jav
a:71)
at com.treamis.transport.vehicle.MyTimerTask.getRoutePointList(MyTimerTa
sk.java:639)
at com.treamis.transport.vehicle.MyTimerTask.sendSms(MyTimerTask.java:10
8)
at com.treamis.transport.vehicle.MyTimerTask.run(MyTimerTask.java:71)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
The exception states: "Too many connections"
You must close every connection after you finished using it.
Sometimes you don't close the connection you open. You should move getConnection call inside the try block so you will always close if in finally statement.
Another possible reason is that you try to connect too many times simultaneously.
Suggestions:
The connection should be opened only when needed. No need to open it immediately at the beginning of the function.
The NPE you get is because getConnection() returns null on error. I think it is better to throw an exception in this case rather than return null.
If you use Java 7, you can use try-with-resources to close resources after finished using them.
Make sure you use reasonable amount of DB connections. If you need more than available connection, consider using one connection for all your DB accesses.
You can use a single connection for this Timer task. Commit on sucessful update but dont close the connection, reuse it.
Something like this:
boolean doInsert(){
// your insert code
// String hql = "insert into gpsData1(dateTime,deviceid,latitude,longitude,rfid
return ps1.executeUpdate(); // this returns true or false
}
boolean isInsert = doInsert();
if(isInsert){
conn.commit();
}
Use a real connection pool like HikariCP or BoneCP.