JDBC drivers should not be registered via `Class.forName()`

java

(Jens Bannmann) #1

Rule description & motivation
Today I learned that as of JDK 6, JDBC 4.0 drivers are discovered automatically (stated in Oracle’s Java tutorial). Therefore you no longer need to invoke Class.forName() which I and probably many other developers have been using for years. I think that SonarJava should tell developers to remove such calls.

Impact to keep this code as it is
Having such a call makes it more cumbersome to switch JDBC drivers, because otherwise one would only have to change the classpath. Also, such code triggers S2658 ("Classes should not be loaded dynamically.”) - however, that could be considered a false positive (see my corresponding post).

Notes
SonarJava most likely cannot determine whether the hard-coded class name actually refers to a JDBC 4.0 driver (after all, the driver may only be on the runtime classpath, or not even there but added during packaging).

However, I think it is still worthwhile to detect Class.forName() calls that are either close to DriverManager calls or load one of the common JDBC drivers (multiple lists linked below). Obviously, the rule still can’t be sure whether it’s the JDBC 4.0 version or an older one, but today, chances are good that it’s a newer one. This fact just has to be stated clearly in the rule description and issue text.

Noncompliant Code

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

public class Demo
{
    private static final String DRIVER_CLASS_NAME = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
    private final Connection connection;

    public Demo(String msSqlServerUri) throws SQLException, ClassNotFoundException
    {
        Class.forName(DRIVER_CLASS_NAME);
        connection = DriverManager.getConnection(msSqlServerUri);
    }
}

Compliant Code

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

public class Demo
{
    private final Connection connection;

    public Demo(String msSqlServerUri) throws SQLException
    {
        connection = DriverManager.getConnection(msSqlServerUri);
    }
}

References

Type
Code Smell

Tags
Tags could be “clumsy” or “unused”, probably even “obsolete”, but to me, none of them feel like an exact fit given the official definitions.


(Alexandre Gigleux) #5

Hello Jens,

Let’s do it!

Here is the specification https://jira.sonarsource.com/browse/RSPEC-4925 for the rule “Class.forName() should not load JDBC 4.0+ drivers” and its related implementation ticket https://jira.sonarsource.com/browse/SONARJAVA-2917

Regards


(Alexandre Gigleux) #7

Hello Jens,

FYI, SonarJava 5.9 is available for download and it contains https://jira.sonarsource.com/browse/SONARJAVA-2917.

Thanks for your contribution.

Regards