I have a simple JDBC app (not using Spring or Hibernate) that connects to MySQL. In production, the MySQL connection uses SSL, but it doesn't use SSL in development mode. In development mode, I added "&useSSL=false" to the database URL in order to prevent the MySQL warning "Establishing SSL connection without server's identity verification is not recommended" from filling up my log files.
Now, I am adding a database connection pool using C3P0. Instead of getting a connection from DriverManager.getConnection, I get the connection from C3P0 by calling POOL.getConnection().
The code that sets up C3P0 is pretty simple:
POOL = new ComboPooledDataSource();
POOL.setDriverClass("com.mysql.cj.jdbc.Driver");
POOL.setJdbcUrl(DB_URL);
POOL.setUser(USER);
POOL.setPassword(PASSWORD);
The problem is that this doesn't work. If the DB_URL string contains "&useSSL=false", then POOL.getConnection() hangs. I've removed "&useSSL=false" from the DB_URL, and everything works ok, except that now I'm getting the MySQL SSL warnings.
Can anyone advise me on how to correctly configure C3P0 so that I no longer get the MySQL SSL warnings?
JDBC Connections silently collect warnings that must be actively checked to be seen. Most applications never check them. c3p0 does. Whenever a Connection is checked back in, c3p0 checks, logs, and clears Connection warnings before making the Connection available again within the pool.
If the logging of warnings is annoying to you, just configure your logging library to filter them. All warnings are logged at INFO to a logger called com.mchange.v2.c3p0.SQLWarnings. Just configure whatever logging library you are using not to log `com.mchange.v2.c3p0.SQLWarnings, or to filter it to a higher level of severity than INFO.
See SQLWarnings.
Related
I added setMaxActive(8) on org.apache.tomcat.jdbc.pool.PoolProperties. Every time the DB restarts, the application is unusable because the established connections remain. I get the following error:
org.postgresql.util.PSQLException: This connection has been closed
I've tried using some other settings on the pool to no avail...
Thank you for help!
Use the validationQuery property which will check if the connection is valid before returning the connection.
Ref: Tomcat 6 JDBC Connection Pool
This property is available on latest tomcat versions.
Look at this link:
Postgres connection has been closed error in Spring Boot
Very valid question and this problem is usually faced by many. The
exception generally occurs, when network connection is lost between
pool and database (most of the time due to restart). Looking at the
stack trace you have specified, it is quite clear that you are using
jdbc pool to get the connection. JDBC pool has options to fine-tune
various connection pool settings and log details about whats going on
inside pool.
You can refer to to detailed Apache documentation on pool
configuration to specify abandon timeout
Check for removeAbandoned, removeAbandonedTimeout, logAbandoned parameters
Additionally you can make use of additional properties to further
tighten the validation
Use testXXX and validationQuery for connection validity.
My own $0.02: use these two parameters:
validationQuery=<TEST SQL>
testOnBorrow=true
I am using JBoss datasource (<local-tx-datasource>) on IBM DB2 9.7 database. The connectivity works fine.
However, I have tried enabling the <track-statements>, <valid-connection-checker>, and <check-valid-connection-sql> properties, but how do I know they are working? I get no errors or warnings on server console when using the datasource, but I also don't get any enhanced logging.
Below is a slightly modified version of what I am using. I have tried various property combinations. Below I have commented out the check-valid-connection-sql property, but enabled the valid, stale and exception sorter properties. I am using JBoss5 and I wonder if it has an impact.
I have tried e.g. to remove a hibernate session close statement in a finally clause, but nothing is logged. It just seems that the additional properties below are not enabled for some reason, or at least they are not logged in the JBoss server.log log file.
<datasources>
<local-tx-datasource>
<jndi-name>[jndiname]</jndi-name>
<connection-url>jdbc:db2://[ip]:[port]/[dbname]</connection-url>
<driver-class>com.ibm.db2.jcc.DB2Driver</driver-class>
<user-name>[user]</user-name>
<password>[password]</password>
<min-pool-size>10</min-pool-size>
<valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.db2.DB2ValidConnectionChecker"></valid-connection-checker>
<stale-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.db2.DB2StaleConnectionChecker"></stale-connection-checker>
<exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.db2.DB2ExceptionSorter"/>
<track-statements>true</track-statements>
<metadata>
<type-mapping>DB2</type-mapping>
</metadata>
If you have valid-connection-checker-class-name, check-valid-connection-sql, and validate-on-match (set to true by default) properly configured then you can test that it works by manually performing an outage on your database server and see if JBoss reconnects and refreshes the datasource pool with valid connections.
I would not recommend keeping track-statements enabled in production. It is mainly a debug feature to track whether you are not closing statements and resultSets properly in your code. Turn it on in dev or test servers to validate that you are properly closing them (e.g. close them in a finally block). You can test it by validating messages like "Closing a result set you left open! Please close it yourself." in server log.
I'm trying to write a really simple GUI app for inserting some records
into a database, and reading back some records (nothing fancy, just 1 table with 3 rows, no relations).
The source...
package EntryProg;
import java.sql.*;
import com.microsoft.sqlserver.jdbc.*;
public class CourseDataEntryHandler
{
private Connection connect;
private CallableStatement callState;
private ResultSet rSet;
private SQLServerDataSource dSource;
public CourseDataEntryHandler()
{
rSet = null;
callState = null;
dSource = new SQLServerDataSource();
dSource.setUser(REDACTED);
dSource.setPassword(REDACTED);
dSource.setServerName(REDACTED);
dSource.setPortNumber(REDACTED);
dSource.setDatabaseName(REDACTED);
dSource.setEncrypt(true);
dSource.setTrustServerCertificate(true);
try
{
Error here
connect = dSource.getConnection();
end error
}
catch (SQLServerException e)
{
//TODO Figure out how to handle -- logging for now, console
do
{
System.out.println(e.getErrorCode());
System.out.println(e.getMessage());
System.out.println(e.getSQLState());
e = (SQLServerException) e.getNextException();
} while (e != null);
System.out.println("END");
System.out.println();
}
}
I get the following error...
(code)0
(message)SQL Server did not return a response. The connection has been closed.
(state)08S01
I've verified that the user,pass,server name,port, and DB name are all accurate.
If I change the username to a non-valid one, I get a "could not log in" error reported back so I know I'm hitting the server.
I've not been able to fully connect once, so I know it's not a "too many connections" issue, as the only person currently logged into the server is me via sql management studio. It doesn't work when I log out of that either so definitely not a connections # issue.
The applications user has datareader/datawriter permissions as well.
(I'm using Eclipse, if that matters. And am referencing the sqljdbc4.jar library).
I'm at a loss as to where to go with troubleshooting this. Any help would be greatly appreciated.
EDIT
Update - I've also tried a connection string and using DriverManager.getConnection(connString) to set the connection, that didn't work either. The result is the same.
Also, SQL server 2008 r2 is the sql server version I'm using.
EDIT
I wrote a quick C# program to test the connection, sure enough the connection works fine in .net, unfortunately I have to use java for this project (it's a project I've chosen to do on my own for a class, only requirement is it be in Java...teacher has no clue what's going on either).
Comment the line with setEncrypt(true):
...
dSource.setDatabaseName(REDACTED);
//dSource.setEncrypt(true);
dSource.setTrustServerCertificate(true);
...
You might have trouble with the encryption setting. From the setEncrypt(...) documentation:
If the encrypt property is set to true, the Microsoft SQL Server JDBC Driver uses the JVM's default JSSE security provider to negotiate SSL encryption with SQL Server. The default security provider may not support all of the features required to negotiate SSL encryption successfully. For example, the default security provider may not support the size of the RSA public key used in the SQL Server SSL certificate. In this case, the default security provider might raise an error that will cause the JDBC driver to terminate the connection. In order to resolve this issue, do one of the following:
Configure the SQL Server with a server certificate that has a smaller RSA public key
Configure the JVM to use a different JSSE security provider in the "/lib/security/java.security" security properties file
Use a different JVM
Update
With Java versions 1.6.0_29 and 7.0.0_1 Oracle introduced a security fix for the SSL/TLS BEAST attack that very likely will cause the very same problem. The above security fix is known to make trouble for database connections to MSSQL Server with both the jTDS driver and the Microsoft driver. You can either
decide not to use encryption by not using setEncrypt(true) (as specified above)
or, if it is enforced by MSSQL Server, you could turn off the Java fix in your JVM by setting the -Djsse.enableCBCProtection=false system property. Be warned, it will affect all SSL connections within the same VM.
Sometimes, the engine configuration is modified in such a way it doesn't accept external connections. After some research, the following worked for me:
Open SQL Server Configuration Manager
Get to SQL SERVER Network Configuration
MSSQLSERVER Protocols (Double click)
View TCP/IP (must be enabled) (Open)
Go to tab "IP Addresses"
Type into "TCP Port" :1433
The enabled and activated options must be Enabled: Yes
Restart the service
I have a long-running method which executes a large number of native SQL queries through the EntityManager (TopLink Essentials). Each query takes only milliseconds to run, but there are many thousands of them. This happens within a single EJB transaction. After 15 minutes, the database closes the connection which results in following error:
Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2.1 (Build b02-p04 (04/12/2010))): oracle.toplink.essentials.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Closed Connection
Error Code: 17008
Call: select ...
Query: DataReadQuery()
at oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:319)
.
.
.
RAR5031:System Exception.
javax.resource.ResourceException: This Managed Connection is not valid as the phyiscal connection is not usable
at com.sun.gjc.spi.ManagedConnection.checkIfValid(ManagedConnection.java:612)
In the JDBC connection pool I set is-connection-validation-required="true" and connection-validation-method="table" but this did not help .
I assumed that JDBC connection validation is there to deal with precisely this kind of errors. I also looked at TopLink extensions (http://www.oracle.com/technetwork/middleware/ias/toplink-jpa-extensions-094393.html) for some kind of timeout settings but found nothing. There is also the TopLink session configuration file (http://download.oracle.com/docs/cd/B14099_19/web.1012/b15901/sessions003.htm) but I don't think there is anything useful there either.
I don't have access to the Oracle DBA tables, but I think that Oracle closes connections after 15 minutes according to the setting in CONNECT_TIME profile variable.
Is there any other way to make TopLink or the JDBC pool to reestablish a closed connection?
The database is Oracle 10g, application server is Sun Glassfish 2.1.1.
All JPA implementations (running on a Java EE container) use a datasource with an associated connection pool to manage connectivity with the database.
The persistence context itself is associated with the datasource via an appropriate entry in persistence.xml. If you wish to change the connection timeout settings on the client-side, then the associated connection pool must be re-configured.
In Glassfish, the timeout settings associated with the connection pool can be reconfigured by editing the pool settings, as listed in the following links:
Changing timeout settings in GlassFish 3.1
Changing timeout settings in GlassFish 2.1
On the server-side (whose settings if lower than the client settings, would be more important), the Oracle database can be configured to have database profiles associated with user accounts. The session idle_time and connect_time parameters of a profile would constitute the timeout settings of importance in this aspect of the client-server interaction. If no profile has been set, then by default, the timeout is unlimited.
Unless you've got some sort of RAC failover, when the connection is terminated, it will end the session and transaction.
The admins may have set into some limits to prevent runaway transactions or a single job 'hogging' a connection in a pool. You generally don't want to lock a connection in a pool for an extended period.
If these queries aren't necessarily part of the same transaction, then you could try terminating and restarting a new connection.
Are you able to restructure your code so that it completes in under 15 minutes. A stored procedure in the background may be able to do the job a lot quicker than dragging the results of thousands of operations over the network.
I see you set your connection-validation-method="table" and is-connection-validation-required="true", but you do not mention that you specified the table you were validating on; did you set validation-table-name="any_table_you_know_exists" and provide any existing table-name? validation-table-name="existing_table_name" is required.
See this article for more details on connection validation.
Related StackOverflow article with similar problem - he wants to flush the entire invalid connection pool.
I am using connection pooling of tomcat with oracle database. It is working fine, but when i use my application after a long time it is giving error that "connection reset". I am getting this error because of physical connection at oracle server closed before logical connection closed at tomcat datasource. So before getting the connection from datasource i am checking the connection validity with isValid(0) method of connection object which gives false if the physical connection was closed. But i don't know how to remove that invalid connection object from the pool.
This could be because on the db server, there is a timeout to not allow connections to live beyond a set time, or to die if it does not receive something saying it is still valid. One way to fix this is to turn on keepalives. These basically ping the db server saying that they are still valid connections.
This is a pretty good link on Tomcats DBCP configurations. Take a look at the section titled "Preventing dB connection pool leaks". That looks like it may be a good place to start.
I used validatationquery while configuring the datasource in server.xml file. It is going to check the validity of the connection by executing the query at database before giving to the application.
for Oracle
validationQuery="/* select 1 from dual */"
for MySql
validationQuery="/* ping */"
Try closing it and opening it if it's invalid. I mean u would reinitialize it in this way so u won't need to remove it from the pool and reuse it.
If we want to dispose an ill java.sql.connection from Tomcat jdbc connection pool,
we may do this explicitly in the program.
Unwrap it into an org.apache.tomcat.jdbc.pool.PooledConnection,
setDiscarded(true) and close the JDBC connection finally.
The ConnectionPool will remove the underlying connection once it has been returned.
(ConnectionPool.returnConnection(....))
e.g.
PooledConnection pconn = conn.unwrap(PooledConnection.class); pconn.setDiscarded(true);
conn.close();