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.
Related
I am passing Resultset object to each thread. Each thread is connecting to the database and inserting data. Untill thread 110 it is working fine. After it crosses 111 thread it throws the above exception.
I am using oracle 11g.
My sample Thread code is:
class MyThreadClass implements Runnable
{
public Connection connection;
public Statement statement2;
public ResultSet rs2;
public String cookie;
public MyThreadClass(ResultSet rs1)
{
rs2=rs1;
}
public void run()
{
try
{
cookie=rs2.getString("COOKIE");
driver = "oracle.jdbc.driver.OracleDriver";
url = "jdbc:oracle:thin:#127.0.0.1:1521:xx";
/* connection
statement2.executeUpdate("INSERT INTO visit_header VALUES ('"+cookie+"')");
}
I am not getting how to handle this exception.
Your multi-threaded application is opening too many Connections/Sessions. Hence, the listener is dropping and blocking new connections for a while.
Check your DB resource usage first:
SELECT * FROM v$resource_limit WHERE resource_name IN ('processes','sessions');
Check to see if your MAX_UTILIZATION for either your Processes or Sessions is getting too close to the LIMIT_VALUE. If yes, you should either:
Use DB Connection pooling to share Connection objects between threads. Or,
Increase the number of processes/sessions that Oracle can service simultaneously.
Actually, Connection Pooling (#1) should always be done. An application cannot scale up otherwise. Check Apache Commons DBCP for details. For #2, open a new SQL*Plus session as SYSTEM and run:
ALTER system SET processes=<n-as-per-number-of-threads> scope=spfile;
to increase backend concurrency. Then RESTART the Database. IMPORTANT!
I guess the database just don't accept more connections from your host. If I understand your question right you are making maybe 100 threads which each connects to the database in short time. Maybe you don't even close the connection correctly, or the accesses are lasting so long that a huge amount of connections are opened. The database have a limit to which it accepts connections.
You should definitely reduce the number of connections by some clever technique. Maybe reduce the number of concurrent threads and/or use a connection pool.
Try this solution at your end. It worked for me.
Close the connection in try/catch block and just after closing the connection,
write-
Thread.sleep(1000);
In this case you can write it as-
finally {
try {
if (conn != null && !conn.isClosed())
{
conn.close();
Thread.sleep(1000);
}
}
catch (SQLException e) {
e.printStackTrace();}
}
I have a main controller servlet in which i instantiate a datasource. The servlet opens and closes the connections. Mainly, the servlet instantiates a command from the application using the "factory pattern". here is some code to explain:
public void init() throws ServletException {
super.init();
try {
datasource =(DataSource) getServletContext().getAttribute("DBCPool");
}
catch (Exception e) {
}
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//some code...
Connection connection = null;
if(cmd.mightNeedLazyLoadingAConnection)
{
connection = null;
}
else
connection = getConnection();//where getConnection is a method: datasource.getconnection();
//now a command (a java class) is instantied, to which the "null" CONNECTION obj is passed as parameter
cmdFactory.getInstance().getCommand(Cmd).execute(tsk,connection);
//some code
//Then wherever there is catch exception i close() the connection
// and it is always closed in finally
finally {
if(connection!=null)
connection.close()
}
}
Now , this has a problem for the first case, ie connection=null, as it does never close the connection in the "finally" part (explained why in Update below).
"connection=null" is for cases where commands might not need to open a db connection because the data it is seeking for are cached in an identity map.
I tried to pass the "Connection" obj as a "null" parameter in the .execute(tsk,connection); and then in the corresponding java class to open a connection if needed
--> it did open the connection inside the command, however when process goes back to servlet : "Connection" is null as thus not closed.
What can i do to make the "Connection" obj's value get updated so that when back in servlet it is not "Null" anymore and i'd be able to close it?
I generally prefer to use a controller servlet that opens/close db connections, so what would be the best way to deal this kind of scenario where you have to do some sort of "lazy loading" a db connection from the pool and at the same time keep the opens/close of db connection assigned to the servlet?
Update (to explain further):
say i have a command : X.java
this command might/might not need a db connection (depends if the data searched for are in the identity map or not)
The system that i would like to have is:
(1)"client request"
(2)---> "Servlet": command.execute(connection)//where connection = null for now
(3) ---> "Command X": Do i need to go to database or record is in identity map?
(3.a) Case where it is needed to go to the database:
(3.a.1)connection = datasource.getconnection
(3.a.2) go get the data
(4)--->back to servlet: close "connection" in "Servlet"
Right now it is working until (3.a.2), but once back in (4) it appears that connection is still "null" and thus the code:
finally {
if(connection!=null)
connection.close()
}
Does not work (doesn't close the connection) and thus the db pool get drained like that.
How could connection - which starts as "null" and changes inside command "X"- get "globaly" updated to the its new value, and not only "updated" inside the scope of command "X"?
SOLUTION(S)
In case you are encountering the same scenario, you can chose of these 2 solutions:
You can Either use LazyConnectionDataSourceProxy, as mentionned by #Ryan Stewart for a "clean abstraction" and more professional solution
Or if you'd like use my solution described below (Basically i implemented a class similar to "LazyConnectionDataSourceProxy" but it is not as clean, it has less abstraction of details than "LazyConnectionDataSourceProxy")
My personal solution, Details:
I created a "Helper" class, which constructor takes the "datasource" as parameter
This helper class has methods to: "Lazy get" connection from pool,"close" connection
This class is instantiated in the servlet, and it gets a connection from the pool Only if needed throughout the application.
This is the code i added/modified in the servlet:
Connection connection = null;
if(cmd.mightNeedLazyLoadingAConnection)
{
helper hp = new helper(datasource);
cmdFactory.getInstance().getCommand(Cmd).execute(tsk,hp);
}
else
{
connection = getConnection();
cmdFactory.getInstance().getCommand(Cmd).execute(tsk,connection);
}
Then say in a command "X" , a db connection is needed i do:
Connection connection = hp.LazyGet();//Now got a connection from the pool
And this way, when proccess flow is back to the servlet level, i can :
Close
rollback
commit
etc..
All on this hp object of the helper class.
What benefits do i get from this:
I limit all database open / close / commit / rollback in one place, ie the Servlet, which is responsible of executing commands.
Having 3 cases: never needs db / always needs db / might need db thus now i decreased calls to the database by 1/3 , which is quite a lot knowing that database call grows exponentially with new features and new users registrations.
It might not be the Cleanest workaround, but between this way and having an additional "unnecessary" 1/3 database calls, it surely is better. Or just use LazyConnectionDataSourceProxy if you want a Tested, abstract and clean method.
Use a LazyConnectionDataSourceProxy. Then just get a "connection" every time, but a real connection is opened only when you actually do something that requires one. Thus you obey the "create/destroy" wisdom which Hiro2k pointed out because the connection's lifecycle is completely managed by your servlet.
In your specific case the only way to do it would be to return the connection. Java doesn't have any pass by reference semantics that could help you, unlike C where you could pass in the reference to the connection and then set it within the method.
I don't recommend your method return the connection, instead remember this simple rule and everything will work as you expect:
The object that creates it, is responsible for destroying it.
If what you want to do is not instantiate a connection for commands that don't require one, then add a method to your command interface that simply returns if needs one.
Command command = cmdFactory.getInstance().getCommand(Cmd);
if(command.requiresConnections){
connection = getConnection();
}
command.execute(tsk,connection);
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.
I created one thread with java.sql.Connection and String parameters.
But from within the thread, I observed that String value was available but Connection object was not. Any clues?
(Editing details into question):
Well, it seems the connection object is available, but closed inside the thread.
Here's the code:
package com.catgen.helper;
import java.sql.Connection;
public class ImageCheckHelper extends Thread{
public Connection conn = null;
public String str = null;
public ImageCheckHelper(Connection conn, String str){
this.conn = conn;
this.str = str;
try{
System.out.println("From inside the constructor");
System.out.println((this.conn!=null)?"Connection is not null":"Connection is null");
System.out.println((this.str!=null)?"String is not null":"String is null");
System.out.println((this.conn.isClosed())?"Connection is closed.":"Connection is not closed");
System.out.println("\n\n");
}catch(Exception e){
e.printStackTrace();
}
}
public void run(){
try{
System.out.println("From inside the thread");
System.out.println((conn!=null)?"Connection is not null":"Connection is null");
System.out.println((str!=null)?"String is not null":"String is null");
System.out.println((conn.isClosed())?"Connection is closed.":"Connection is not closed");
}catch(Exception e){
e.printStackTrace();
}
}
public void initiateImageCheck(){
this.start();
return;
}
}
And here's the output:
From inside the constructor
Connection is not null
String is not null
Connection is not closed
From inside the thread
Connection is not null
String is not null
Connection is closed.
Is another thread closing the connection between the time it is given to the constructor and the time it is used in the run() method? My guess is that the connection is closed after the call to initiateImageCheck() returns but before the run() method has got as far as the isClosed() check.
If not, do you have access to the JDBC driver's source code? I wonder if it is protecting itself against multi-threaded use.
Connections are not guaranteed to be thread-safe, so you should obtain the connection from within the thread that is going to use it.
You also have unsynchronized access to conn from two different threads. Public member variables are not a good idea either - especially in classes that need to be thread-safe.
I don't see what your problem is - looking at the output, you can see that both the Connection and String are non-null within the constructor and when you come to run the thread.
The only difference is that the connection has been closed at some point between the thread being constructed, and the thread being run. Depending on how you provided the connection, and how other threads were using it, this is not particularly unusual. In any case, you should be looking at other threads calling close() on the same Connection object if you want to track this down.
As a general guideline, it's typically easiest to have each thread manage its own Connection, because otherwise you end up with some very tricky semantics about committing and closing them (as you've seen here). Sharing a connection between multiple threads can work, and on rare occasions is necessary, but in general it should be the exception rather than the rule.
Edit: Additionally, a lot of Connection implementations are not even threadsafe, so you can't really use them between multiple threads in a reliable fashion. If one thread is running a statement and you then try to use the connection on a different thread, bad things will happen. Even more justification to just give each thread its own connection and let it get on with what it wants to do, without having to engage in some kind of mutex synchronization (a bottleneck that removes some of the attraction of multithreading, too!).
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.