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.
Related
I am using Netbeans 16 and Java 19.0.2 on Windows 11.
I am getting:
java.lang.ClassNotFoundException: org.sqlite.JDBC
when I try to access a new sqlite file:
package com.thompco.propertymanager.table;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Database {
String filename;
Connection connection;
public Database(String filename) throws ClassNotFoundException {
this.filename = filename;
connect();
}
public final void connect() throws ClassNotFoundException {
try {
Class.forName("org.sqlite.JDBC");
String url = String.format("jdbc:sqlite:%s", filename);
connection = DriverManager.getConnection(url);
System.out.println("Connection to SQLite has been established.");
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
try {
if (connection != null) {
connection.close();
}
} catch (SQLException ex) {
System.out.println(ex.getMessage());
}
}
}
public static void main(String[] args) {
try {
Database database = new Database("newFile.sqlite");
database.connect();
database.createTransactionTable();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
I (think) I have added the sqlite jar to my path:
I tried to add it at the top of my file:
It looks like you added the sqlite jar to the list of jars for the library Absolute Layout.
Now you still need to make sure that this library is added to your project (a prerequisite before you can import the classes in your source code).
Hints:
You likely should have added sqlite as a separate library.
It would be more advisable to use the Maven build system and specify dependencies in pom.xml. That one can be version controlled. And Maven will download the libraries on your behalf.
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?
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
Does anyone know what the best way is to create a new oracle database connection. This is what I currently have:
private static getConnection() throws Exception {
if (!isDriverRegistered){
DriverManager.registerDriver(new oracle.jdbc.OracleDriver());
isDriverRegistered = true;
}
return DrvierManager.getConnection(connectionString);
}
You are not supposed to register the driver yourself; the JDBC driver itself will do that, when its class is loaded. So, do not call DriverManager.registerDriver yourself.
There are two steps: make sure the JDBC driver class is loaded, and get a connection.
To load the JDBC driver class, use a line like this:
Class.forName("oracle.jdbc.OracleDriver");
Then get the connection with a call to DriverManager.getConnection:
Connection conn = DriverManager.getConnection(connectionString);
Note that if you are using a newer JDBC version and a suitable driver, you do not even need to load the driver class explicitly; it will be found and loaded automatically (via Java's service discovery mechanism). In that case you only need to call DriverManager.getConnection.
this class may help you
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 void close(Statement obj)
{
try
{
if(obj!=null)
obj.close();
}
catch(SQLException e)
{
e.printStackTrace();
}
}
public static void close(ResultSet obj)
{
try
{
if(obj!=null)
obj.close();
}
catch(SQLException e)
{
e.printStackTrace();
}
}
public static void close(Connection obj)
{
try
{
if(obj!=null)
obj.close();
}
catch(SQLException e)
{
e.printStackTrace();
}
}
public static Connection getConnection()
{
Connection con = null;
String url = "url" //give url
String pwd = "password";//give password
String uid = "userId";//give userid
try
{
Class.forName("oracle.jdbc.OracleDriver"); //pass driver name
con = DriverManager.getConnection(url,uid,pwd);
con.setAutoCommit(false);
}
catch(Exception e)
{
if(con!=null)
try {
con.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
return con;
}
}
I have a funny requirement.
We need to have a command-line interaction in a Java Stored Procedure. In spite of granting appropriate permissions using the dbms_java.grant_permission commands, I am encountering java.io.IOException, where I read from System.in using java.io.InputStreamReader.
Where is the problem?
The Java Source is here:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.Connection;
import java.sql.SQLException;
import oracle.jdbc.driver.OracleDriver;
public class ExecuteInteractiveBatch {
public static void aFunction() {
Connection connection = null;
try {
int rowFetched = 0;
connection = new OracleDriver().defaultConnection();
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT count(1) cnt from sometable where c = 2");
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
stmt.close();
rs = null;
stmt = null;
if (count == 1) {
System.out.println("Do you want to continue?");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String response = reader.readLine();
if ("Y".equalsIgnoreCase(response)) {
stmt = connection.createStatement();
int rowsAffected = stmt.executeUpdate("DELETE from sometable where c=2");
System.out.println("" + rowsAffected + " row(s) deleted");
stmt.close();
}
}
} catch (IOException ex) {
ex.printStackTrace();
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
try {
if (connection != null || !connection.isClosed()) {
connection.close();
}
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
}
You can't perform I/O to the console from within Oracle... not in java, not in PL/SQL, nowhere. Oracle is running in a separate process from the user, quite likely even a different computer, and java stored procedures are being run in that process. You will need some java code running on the client system to perform console I/O.