MySQLNonTransientConnectionException: No operations allowed after connection closed. - java

So Im making a bunch of async calls, only issue is, in my prepare method which generates a PreparedStatement, it grabs the connection (or uses a new one if the connection is faulty), and for some reason still throws this error.
I initially thought (and still kind of do) that it's because majority of the use cases that call this method are called asynchronously. So I made the method synchronized (never used that keyword before, but figured it was fitting after a bit of research), and still, the method throws an error...
public synchronized PreparedStatement prepare(String statement) throws SQLException {
Connection c = getConnection();
if (c == null || c.isClosed()) return getNewConnection().prepareStatement(statement);
Logger.debug("not null and not closed " + Thread.currentThread().getId());
return c.prepareStatement(statement); //throws error here
}
How do I make it so other threads can't alter the connection until the prepare method has finished with it?

Something like this is happening:
Thread 1: calls prepare(), creates a connection and returns a prepared statement and leaves prepare(), so other threads may now enter prepare()
Thread 1: starts running the query
Thread 2: enters prepare and checks that the connection is OK -- this is the same connection that thread 1 created and is using.
Thread 1: closes the connection
Thread 2: tries to call prepareStatement on the connection, which is now closed
You should investigate using a connection pool, which will give each thread its own connection, which is returned to the pool when it is 'closed'.

Related

How to force close JDBC connection from another thread?

I have two threads in java application. The first thread runs the JDBC connection logic. The second one is listening to user's command.
public static void main ...
private Connection c; // this is JDBC connection visible to both Thread 1 and 2
Thread thread1 = new Thread(new Runnable() {
public void run() {
// logic to execute SQL statements on Connection c
}
);
Thread thread2 = new Thread(new Runnable() {
public void run() {
// Here i try to execute connection close on user's demand.
c.close();
// this command executes with no error,
// but the connection doesnt close immediately.
// The SQL statements in thread 1 somehow waits to finish,
// and only then will the connection stop.
// How to forcefully and abruptly stop the connection ?
}
);
How to forcefully and abruptly stop the connection ?
You could try calling c.close() in the 2nd thread, but:
JDBC connection objects are not thread-safe1, so the Java-side behavior is unspecified.
AFAIK, the JDBC spec doesn't say what will happen on the database server if a database connection is closed while a request is in progress. It is not clear if the request is terminated immediately or a bit later (with a transaction rollback or not).
So my advice would be don't do this. Find another way to do what you are trying to do.
(If you want advice on other ways, tell us the real problem you are trying to solve here rather than your roadblock with your attempted solution to the problem.)
1 - More precisely, they are not required to be thread-safe by the JDBC spec. They might actually be (sufficiently) thread-safe in some driver implementations, but ... only if the vendor docs say so. From various sources, at least Oracle DB and Derby support multiple threads sharing a logical JDBC connection, though they seem to support different models.
I don't think you can this way. But you can exit the whole JVM forcely:)

Configure threads in ParallelStream

I have below code
public void addNames(){
List<String> names = new ArrayList<String>
names.parallelStream().foreach(name->add(name));
}
private void add(String name){
SQLSession session = SQLSessionFactory.getSession(config);
Connection con=Session.openConnection();
con.insert(name);
con.commit;
con.close
}
The problem here is “name->add(name)” will execute for each name, there by I am opening and closing connections for each name. If I have millions of records then this is a problem.
I can’t open the connection outside “names.parallelStream().foreach(name->add(name, connection));” and pass it as parameter, because all the threads will get blocked on one connection object.
So, I want to obtain the connection per thread, How can I do this using
“names.parallelStream().foreach(name->add(name));” ?
I want do following per thread
Obtain connection
Insert
Insert
Insert —— N Inserts
Commit and close connection
If I am creating and starting a thread I can do this, How can we achieve this per thread using parallelStreams?
In short, I want the thread in parallelStream to obtain connection per thread and execute name->add(name) and once done the thread should commit and close the connection. Is this possible ?
I think you should not force the parallel stream for this. You will get the best performances if you do bulk inserts in chunks. Nevertheless, if you still want to do it, you should have a connection pool so each thread gets a connection and releases it after done its work. Your add method will look like:
private void add(String name){
Connection con=genCoonection(); //just take a connection from pool
con.insert(name);
con.commit;//commit after each record
}
You can find multiple examples on how to create and use a connection pool here:
How to establish a connection pool in JDBC?
Another option is to provide a custom ThreadLocal as described here and each thread will open the connection in a thread local. Then you shut down the thread pool and the connection will be closed as described here

How do I safely use OracleDriver.defaultConnection() in a multithreaded Java Application?

I have a multithreaded application which uses OracleDriver.defaultConnection() to connect to the database.
This line of code is used in multiple code blocks which are accessed by different threads.
I am getting the error : Java Thread Deadlock detected
This is a sample piece of code :
private void function1() {
//something here
Connection conn = OracleDriver.defaultConnection();
// something here
conn.execute();
conn.close();
}
Second piece of code which is in a separate class :
private void function2() {
//something here
Connection conn = OracleDriver.defaultConnection();
// something here
conn.execute();
conn.close();
}
How do I make this connection "thread-safe"?
Also, I read that defaultConnection() returns a static object. So can this be caused due to the connection being closed by one thread while the other thread is using it?
I cannot use any connection method which requires me to input the database username and password.
Thanks in advance!
Java provides many ways for dealing with concurrency(synchronized, ReentrantLock, ReadWriteLock)
Considering the documentation which says:
The oracle.jdbc.OracleDriver class defaultConnection() method is an Oracle extension and always returns the same connection object.
Since it always returns the same connection object you can synchronize on it:
Connection conn = OracleDriver.defaultConnection();
synchronized (conn) {
// something here
conn.execute();
}
However you would need to remove all conn.close() calls due to:
If you do call the close() method, be aware of the following: All connection instances obtained through the defaultConnection() method, which actually all reference the same connection object, will be closed and unavailable for further use, with state and resource cleanup as appropriate. Executing defaultConnection() afterward would result in a new connection object.
Even though the connection object is closed, the implicit connection to the database will not be closed.

Closing JDBC Connections in Pool

Our standard code section for using JDBC is...
Connection conn = getConnection(...);
Statement stmt = conn.conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet rset = stmt.executeQuery (sqlQuery);
// do stuff with rset
rset.close(); stmt.close(); conn.close();
Question 1: When using Connection Pool, should one close the Connection at the end? If so, isn't the purpose of pooling lost? And if not, how does the DataSource know when a particular instance of Connection is freed up and can be reused? I am a little confused on this one, any pointers appreciated.
Question 2: Is the following method anything close to standard? Looks like an attempt to get a connection from the pool, and if DataSource cannot be established, use the old fashioned DriverManager. We are not even sure which part is getting executed at runtime.
Repeating the question above, should one close the Connection coming out of such a method?
synchronized public Connection getConnection (boolean pooledConnection)
throws SQLException {
if (pooledConnection) {
if (ds == null) {
try {
Context envCtx = (Context)
new InitialContext().lookup("java:comp/env");
ds = (DataSource) envCtx.lookup("jdbc/NamedInTomcat");
return ds.getConnection();
} catch (NamingException e) {
e.printStackTrace();
}}
return (ds == null) ? getConnection (false) : ds.getConnection();
}
return DriverManager.getConnection(
"jdbc:mysql://"+ipaddy+":"+dbPort +"/" + dbName, uName, pWord);
}
Edit: I think we are getting the pooled connection since we do not see a stack trace.
When using Connection Pool, should one close the Connection at the end? If so, isn't the purpose of pooling lost? And if not, how does the DataSource know when a particular instance of Connection is freed up and can be reused? I am a little confused on this one, any pointers appreciated.
Yes, certainly you need to close the pooled connection as well. It's actually a wrapper around the actual connection. It wil under the covers release the actual connection back to the pool. It's further up to the pool to decide whether the actual connection will actually be closed or be reused for a new getConnection() call. So, regardless of whether you're using a connection pool or not, you should always close all the JDBC resources in reversed order in the finally block of the try block where you've acquired them. In Java 7 this can be further simplified by using try-with-resources statement.
Is the following method anything close to standard? Looks like an attempt to get a connection from the pool, and if DataSource cannot be established, use the old fashioned DriverManager. We are not even sure which part is getting executed at runtime. Repeating the question above, should one close the Connection coming out of such a method?
The example is pretty scary. You just need to lookup/initialize the DataSource only once during application's startup in some constructor / initialization of an applicationwide DB config class. Then just call getConnection() on the one and same datasource throughout the rest of application's lifetime. No need for synchronization nor nullchecks.
See also:
Is it safe to use a static java.sql.Connection instance in a multithreaded system?
Am I Using JDBC Connection Pooling?
The pools typically return you a wrapped Connection object, where the close() method is overridden, typically returning the Connection to the pool. Calling close() is OK and probably still required.
A close() method would probably look like this:
public void close() throws SQLException {
pool.returnConnection(this);
}
For your second question, you could add a logger to show whether the bottom block ever runs. I would imagine though you'd only want one way or the other for the configuration of your database connections. We solely use a pool for our database accesses. Either way, closing the connection would be pretty important to prevent leaks.
Actually, the best approach to connection management is to not farm them out to any code anywhere.
Create a SQLExecutor class that is the one and only location which opens and closes connections.
The entire rest of the application then pumps statements into the executor rather than getting connections from the pool and managing (or mismanaging them) all over the place.
You can have as many instances of the executor as you want, but no one should be writing code that opens and closes connections on its own behalf.
Conveniently, this also lets you log all your SQL from a single set of code.

JDBC Query excecution

I am facing an issue while executing queries.I use the same resultSet and statement for excecuting all the queries.Now I face an intermittent SQlException saying that connection is already closed.Now we have to either have separate resultSet for each query or have lock like structure.Can anyone tell which is better.I think introducing locks will slow down the process.Am I right?
Update:
To be more clear.The error may happen because the finally block gets called before all the queries get executed and the connection gets closed and exception will be thrown.
This is the exception I get
java.sql.SQLException: Connection has
already been closed. at
weblogic.jdbc.wrapper.PoolConnection.checkConnection(PoolConnection.java:81)
at
weblogic.jdbc.wrapper.ResultSet.preInvocationHandler(ResultSet.java:68)
at
weblogic.jdbc.wrapper.ResultSet_com_informix_jdbc_IfxResultSet.next(Unknown
Source) at
com.test.test.execute(test.java:76)
at
org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:413)
at
org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:225)
at
org.apache.struts.action.ActionServlet.process(ActionServlet.java:1858)
at
org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:459)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:760)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
at
weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1077)
at
weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:465)
at
weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:348)
at
weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:7047)
at
weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at
weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
at
weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3902)
at
weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2773)
at
weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224)
at
weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183)
Sample code:
ResultSet rst=null;
Statement stmt=null;
Connection con=DBConnection.getConnection();
stmt=con.createStatement();
rst=stmt.executeQuery("select * from dual");
while(rst.next())
{ : ://Some code }
rst=stmt.executeQuery("select * from doctor where degree="BM");
while(rst.next())
{ //blah blah }
finally
{
//close con,rst and stmt
}
you are not reusing the resultset, you are leaking resultsets.
rst=stmt.executeQuery... generates a new resultset and the previous resultset is never closed :(
It appears that the code in question has issues in multi-threaded environment.
DBConnection.getConnection() is probably returning the same connection to all threads. When multiple threads are processing multiple requests, the first thread that finishes execution of the method will close the connection, leaving all other threads high and sundry.
I'm speculating here, but is appears that the connection object returned by DBConnection is an instance member of the DBConnection object, and that would qualify as a bad practice for a connection manager in a multi-threaded environment.
A code fix would avoid the usage of instance members for Connection, Statement (and the like), and the ResultSet objects.
I'm not sure what's going on without knowing more about your code. Is it threaded ? Is the underlying database going down (or are you losing connectivity to it).
One thing I would do is to implement connection pooling (via Apache DBCP, say). This framework will maintain a pool of connections to your database and validate these connections before handing them out to you. You would ask for a new connection each time you make a query (or perhaps set of queries) but because they're pooled this shouldn't be a major oeverhead.
Unless your connection to the database has really been closed I think you did something more like this:
try {
return resultSet.getBoolean("SUCCESS");
} finally {
resultSet.close();
}
This code will actually close the connection before your result set is being evaluated, resulting in the exception you show.

Categories