Hello Alan,
unfortunately I'm not very experienced in "thread programming". But as I
understand does the proposed solution in the docs avoid the problem of
closing the connection object of the second thread. Yes, I find the
solution somewhat ugly and not very intuitive.
But the code below should also work. So it looks easier for me. This
sequence...
- Request 1 running in Thread 1 gets a db connection.
- Request 1 closes the db connection.
- The JVM switches the running thread to Thread 2
- Request 2 running in Thread 2 gets a db connection (the same db
connection just closed by Request 1).
- The JVM switches the running thread back to Thread 1
- Request 1 closes the db connection a second time in a finally block.
- The JVM switches the running thread back to Thread 2
- Request 2 Thread 2 tries to use the db connection but fails because
Request 1 closed it.
... cannot happen any more, because the connection gets closed exactly
once (only if it is opened before).
So I'm still confused about the docs. They exist for a long time and I
cannot believe, that no one before me wondered about it. So I guess I'm
missing something. But what?
Alan Chaney schrieb:
Hi Stefan
I went and read the comments more carefully and it seems to me that the
proposed solution is an attempt to avoid a race condition between
issuing the 'close' in
one thread and then it being closed again whilst its being used in
another thread.
If the problem is closing it twice then I can't see why its not just
closed in the 'finally' block, once for each thread.
If it is a concurrency problem then I suspect that the proposed solution
in the docs isn't the right one anyway. I'd suspect that the problem is
more to do with threads not seeing each others memory state properly.
Isn't this is a case of a variable (in this case 'conn') actually being
a reference to an object which is shared between threads?
Because of the JVM memory model it is possible for two threads not to be
properly synchronized - see Doug Lea et.al and 'happens before' .
Personally, I feel that the correct solution is to synchronize access
to the connection object when it is retrieved and closed.
I have to go out now and I don't have any more time to consider this
today, but I'd be interested to hear other people's comments on this topic.
Regards
Alan Chaney
Stefan Riegel wrote:
Thanks Alan, just to make the thing really clear. You propose code
like this:
public void execute() {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Context envContext = null;
try {
Context initContext = new InitialContext();
envContext = (Context) initContext.lookup("java:/comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/swex");
conn = ds.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery("some sql");
// iterate through the result set ...
} catch (SQLException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (envContext != null) {
try {
envContext.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
}
For me this looks fine but I'm still confused, why they complicated
things in the example of "properly written code"
http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html?
Hmm... frankly the code in the docs you refer to above seems odd to
me... why repeat in the 'finally' something you've done in the 'try'?
I can see that setting the variables to null would ensure that all
references were released and the objects were made candidates for garbage
collection but that could be done in the finally block anyway at some
convenient point.
Obviously in your code you might not want to obtain and release the
context for every JDBC operation - that would probably be done in some
kind of start-up/shutdown code for your app, and of course your
exception handling may need some more work depending upon the way you
want to present the error
to your users, but I assumed that the issue you are concerned with is
preventing resource leaks.
Any comments anyone else?
Regards
Alan
Do I miss some important point here?
Stefan
Alan Chaney schrieb:
Hi Stefan
You don't need to repeat the stmt.close();conn.close() etc in the
'try' body. The 'finally' by definition is ALWAYS called and that is
where you should do the tidy up...
Alan Chaney
Stefan Riegel wrote:
I guess I understood the point with the "Random Connection Closed
Exceptions" Problem.
See at the end of
http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html
As I understand, only the connection itself must be protected this
way. The statement and ResultSet must not. Is the following,
simplified code also correct?
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = ... get connection from connection pool ...
stmt = conn.createStatement("select ...");
rs = stmt.executeQuery();
... iterate through the result set ...
// SUPERFLUsOUS
rs.close();
stmt.close();
conn.close(); // Return to connection pool
conn = null; // Make sure we don't close it twice
//SUPERFLUOUS
} catch (SQLException e) {
... deal with errors ...
} finally {
try {
rs.close();
} catch (SQLException e) {
// deal with errors
}
try {
stmt.close();
} catch (SQLException e) {
// deal with errors
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// deal with errors
}
conn = null;
}
}
Thanks.
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org