Reputation: 408
I'm using JDBC like this in OpenJDK1.8 on Ubuntu to try to connect to an MSSQL server instance on a remote Windows server running on the local class B LAN:
public static DataSource getMsSqlPoolSource(String server, String database, String user, String password) throws ClassNotFoundException {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String connectionString = "jdbc:sqlserver://" + server + ";databaseName=" + database + ";sendStringParametersAsUnicode=false;";
System.out.println("Connection String for MSSQL is:: " + connectionString);
org.apache.commons.dbcp2.ConnectionFactory factory = new DriverManagerConnectionFactory(connectionString, user, password);
PoolableConnectionFactory poolFactory = new PoolableConnectionFactory(factory, null);
ObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolFactory);
poolFactory.setPool(connectionPool);
PoolingDataSource<PoolableConnection> dataSource = new PoolingDataSource<>(connectionPool);
return dataSource;
}
Executing the above results in
java.sql.SQLException: invalid database address: jdbc:sqlserver://172.17.12.14;databaseName=DB;sendStringParametersAsUnicode=false;
at org.sqlite.JDBC.createConnection(JDBC.java:111) ~[verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at org.sqlite.JDBC.connect(JDBC.java:88) ~[verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at java.sql.DriverManager.getConnection(DriverManager.java:664) ~[?:1.8.0_292]
at java.sql.DriverManager.getConnection(DriverManager.java:247) ~[?:1.8.0_292]
at org.apache.commons.dbcp2.DriverManagerConnectionFactory.createConnection(DriverManagerConnectionFactory.java:90) ~[verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at org.apache.commons.dbcp2.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:291) ~[verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at org.apache.commons.pool2.impl.GenericObjectPool.create(GenericObjectPool.java:883) ~[verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:436) ~[verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:365) ~[verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at org.apache.commons.dbcp2.PoolingDataSource.getConnection(PoolingDataSource.java:134) ~[verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at verishare.db.SqlDataHelper.ExecuteQuery(SqlDataHelper.java:66) ~[verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at verishare.db.SqlDataHelper.ExecuteQuery(SqlDataHelper.java:59) ~[verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at verishare.verdial_db.KeepVNEmpSyncedToVDAgent.updateEmployeesFromVeriNet(KeepVNEmpSyncedToVDAgent.java:284) [verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at verishare.verdial_db.KeepVNEmpSyncedToVDAgent.run(KeepVNEmpSyncedToVDAgent.java:58) [verdi-1.0-SNAPSHOT-jar-with-dependencies.jar:?]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_292]
A wireshark on the Windows machine shows that the above Linux server is sending traffic to port 1433 on the Windows server, so the traffic reaches the Windows MSSQL server containing the MSSQL instance. The wireshark trace also reveals that the Windows MSSQL instance is replying back on a high port to the application running in OpenJDK1.8 on the Linux machine from which I'm trying to connect.
If I use the MSSQL username, MSSQL password and database on MSSQL studio they allow me to log in and access the MSSQL server instance using MSSQL studio.
I'm not getting any error except that
java.sql.SQLException: invalid database address:jdbc:sqlserver://172.17.12.14;databaseName=DB;sendStringParametersAsUnicode=false;
Anybody any idea why the above would now be an invalid database address in the JDBC driver?
Any way I can turn up verbosity on the JDBC driver in Java, maybe see what exactly it is transmitting (so I can try and determine why it is an invalid database address?)
Thanks!
EDIT: My maven fragment in Netbeans 11 for MS JDBC is:
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>6.4.0.jre8</version>
<scope>test</scope>
</dependency>
EDIT: The MSSQL server's log shows no failed login (if I deliberately mistype the password, for example, in MSSQL studio for that instance, it does log into the MSSQL server's logs. So my connection attempt - even though wireshark shows traffic and replies from MSSQL outward) don't seem to reach the level in MSSQL where the failed connection attempt is even logged...)
EDIT: Ok I removed the SQLLite POM artifact, and now I'm getting a different error - it seems I'm now using the correct driver, close, but no cigar:
Connection String for MSSQL is:: jdbc:sqlserver://172.17.12.14;databaseName=DB;sendStringParametersAsUnicode=false;
Error On Verinet MSSQL The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "The server selected protocol version TLS10 is not accepted by client preferences [TLS12]". ClientConnectionId:3b85afc0-3e6d-4cad-bf16-bedb9f70241c
Upvotes: 0
Views: 598
Reputation: 408
This was solved with the kind assistance of Mark Rotteveel and AlwaysLearning.
The problem was threefold.
First, in my Netbeans 11 project, in the "Dependencies" folder, I had a jar called
MSSQL-4.0.jar
which was apparently placed there manually by a previous dev on the project.
I removed this file - I did not know which driver was being used, as I had a maven artifact as detailed above, ALSO for the MSSQL JDBC driver.
Second, AlwaysLearning then kindly pointed out that my connection exception to MSSQL was referring to SQLLite (NOT MSSQL) and the exception of an invalid database address was being reported by the SQLLite driver, NOT the MSSQL driver.
The core issue was that for some reason when I tried to connect to MSSQL using the source code as above, the MSSQL JDBC driver was trying an SQLLite connection to MSSQL.
This was why I was constantly getting
java.sql.SQLException: invalid database address:jdbc:sqlserver://172.17.12.14;databaseName=DB;sendStringParametersAsUnicode=false;
as of course the SQLLite connection protocol will never work on an MSSQL server...
Thirdly, the exception on the connection attempt to MSSQL then changed to refer to the fact that the MSSQL server was using a too-old TLS encryption for the connection, and my client was rejecting this on the JDBC side - see above. Mark Rotteveel then assisted with editing the file
/etc/java-8-openjdk/security/java.security
on my Ubuntu 20.11 LTS OpenJKD1.8 install to lower the security on TLS so that my OpenJDK1.8 instance would allow the TLS encryption level the quite old MSSQL instance I was trying to connect to, was requiring.
In /etc/java-8-openjdk/security/java.security I changed the line
jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
include jdk.disabled.namedCurves
to
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, \
DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \
include jdk.disabled.namedCurves
So in summation, after removing the spurious MSSQL-4.0.jar from my NetBeans project's "Dependencies" folder, I also commented out the Maven artifacts for SQLLite (as it is no longer used in my project, and is a legacy library). Once the SQLLite library was removed by Maven on the next compile, AND I edited the java.security file as detailed above, the produced .JAR was able to connect to the MSSQL server from my Ubuntu machine, AFTER I lowered the security requirments in /etc/java-8-openjdk/security/java.security and restarted my application on the Ubuntu machine using the OpenJDK1.8 installation.
This was because the MSSQL JDBC driver was now using a "genuine" MSSQL protocol to try to connect from my Ubuntu machine to the MSSQL server, instead of trying to use SQLLite protocol to connect to the MSSQL server, -AND- the JDBC driver was being allowed to talk an "old enough" TLS version to the MSSQL server after the changes to java.security.
Hope this helps somebody else.
Upvotes: 1