nested try block without a catch or finally block - java

Is it fine to have a nested try block without a catch or finally block and let the outer catch block handle the exception if any from the nested try block?
Something like:
try (Connection con = ds.getConnection();
PreparedStatement ps = con.prepareStatement(sql);) {
//nested try block without a catch or finally block
try (ResultSet rs = ps.executeQuery();) {
while (rs.next()) {
list.add(rs.getInt("id"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}

If you remove the 'try' the result set will not close automatically.
The try-with-resources statement sort of executes rs.close in a hidden finally.
It is good practice to close the resultset, open resultset can lead to problems : java.sql.SQLException: - ORA-01000: maximum open cursors exceeded
Problem with exception catching in this example is how do you differentiate between datasource exceptions, query creation exceptions or query execution SQLExceptions? I would probably throw a specific RuntimeException when my datasource can not deliver an connection.

No. Your code won't compile.
Every try block (even nested) must be followed with catch(..) and/or finally.
In your case add a second catch block if you want to handle any other additional exceptions.
Sample code:
try {
// code which may throw exceptions
} catch(Exception e1) {
// e1 specific code
} catch (Exception e2) {
// e2 specific code
} finally {
// Optional. Executes whether exception thrown or not!
}

Related

Closing Resultset, statement and Connection [duplicate]

Consider the code:
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.createStatement(myQueryString);
rs = ps.executeQuery();
// process the results...
} catch (java.sql.SQLException e) {
log.error("an error!", e);
throw new MyAppException("I'm sorry. Your query did not work.");
} finally {
ps.close();
rs.close();
}
The above does not compile, because both PreparedStatement.close() and ResultSet.close() throw a java.sql.SQLException. So do I add a try/catch block to the finally clause? Or move the close statements into the try clause? Or just not bother calling close?
In Java 7, you should not close them explicitly, but use automatic resource management to ensure that resources are closed and exceptions are handled appropriately. Exception handling works like this:
Exception in try | Exception in close | Result
-----------------+--------------------+----------------------------------------
No | No | Continue normally
No | Yes | Throw the close() exception
Yes | No | Throw the exception from try block
Yes | Yes | Add close() exception to main exception
| | as "suppressed", throw main exception
Hopefully that makes sense. In allows pretty code, like this:
private void doEverythingInOneSillyMethod(String key)
throws MyAppException
{
try (Connection db = ds.getConnection()) {
db.setReadOnly(true);
...
try (PreparedStatement ps = db.prepareStatement(...)) {
ps.setString(1, key);
...
try (ResultSet rs = ps.executeQuery()) {
...
}
}
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
Prior to Java 7, it's best to use nested finally blocks, rather than testing references for null.
The example I'll show might look ugly with the deep nesting, but in practice, well-designed code probably isn't going to create a connection, statement, and results all in the same method; often, each level of nesting involves passing a resource to another method, which uses it as a factory for another resource. With this approach, exceptions from a close() will mask an exception from inside the try block. That can be overcome, but it results in even more messy code, and requires a custom exception class that provides the "suppressed" exception chaining present in Java 7.
Connection db = ds.getConnection();
try {
PreparedStatement ps = ...;
try {
ResultSet rs = ...
try {
...
}
finally {
rs.close();
}
}
finally {
ps.close();
}
}
finally {
db.close();
}
If you're really hand-rolling your own jdbc it definitely gets messy. The close() in the finally needs to get wrapped with its own try catch, which, at the very least, is ugly. You can't skip the close, although the resources will get cleared when the connection is closed (which might not be right away, if you're using a pool). Actually, one of the main selling points of using a framework (e.g. hibernate) to manage your db access is to manage the connection and result set handling so you don't forget to close.
You can do something simple like this, which at least hides the mess, and guarantees that you don't forget something.
public static void close(ResultSet rs, Statement ps, Connection conn)
{
if (rs!=null)
{
try
{
rs.close();
}
catch(SQLException e)
{
logger.error("The result set cannot be closed.", e);
}
}
if (ps != null)
{
try
{
ps.close();
} catch (SQLException e)
{
logger.error("The statement cannot be closed.", e);
}
}
if (conn != null)
{
try
{
conn.close();
} catch (SQLException e)
{
logger.error("The data source connection cannot be closed.", e);
}
}
}
and then,
finally {
close(rs, ps, null);
}
For file I/O, I generally add a try/catch to the finally block. However, you must be careful not to throw any exceptions from the finally block, since they will cause the original exception (if any) to be lost.
See this article for a more specific example of database connection closing.
Don't waste your time coding low-level exception management, use an higher-level API like Spring-JDBC, or a custom wrapper around connection/statement/rs objects, to hide the messy try-catch ridden code.
Also note:
"When a Statement object is closed, its current ResultSet object, if one exists, is also closed. "
http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Statement.html#close()
It should be sufficient to close only the PreparedStatement in a finally, and only if it is not already closed. If you want to be really particular though, close the ResultSet FIRST, not after closing the PreparedStatement (closing it after, like some of the examples here, should actually guarantee an exception, since it is already closed).
I usually have a utility method which can close things like this, including taking care not to try to do anything with a null reference.
Usually if close() throws an exception I don't actually care, so I just log the exception and swallow it - but another alternative would be to convert it into a RuntimeException. Either way, I recommend doing it in a utility method which is easy to call, as you may well need to do this in many places.
Note that your current solution won't close the ResultSet if closing the PreparedStatement fails - it's better to use nested finally blocks.
Building on #erickson's answer, why not just do it in one try block like this?
private void doEverythingInOneSillyMethod(String key) throws MyAppException
{
try (Connection db = ds.getConnection();
PreparedStatement ps = db.prepareStatement(...)) {
db.setReadOnly(true);
ps.setString(1, key);
ResultSet rs = ps.executeQuery()
...
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
Note that you don't need to create the ResultSet object inside the try block as ResultSet's are automatically closed when the PreparedStatement object is closed.
A ResultSet object is automatically closed when the Statement object
that generated it is closed, re-executed, or used to retrieve the next
result from a sequence of multiple results.
Reference: https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
If your are using Java 7 you can use the improvements in the exception handling mechanisms in those classes that implement AutoCloseable (i.e. PreparedStatement, Resultset)
You might also find this question interesting: Closing ResultSet in Java 7
I know this is an old question, but just in case someone is looking for the answer, java now has the try-with-resouce solution.
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
Do no omit calling close. It may cause problems.
I prefer adding try/catch block to the finally.
focus finally clause,
finally {
try {
rs.close();
ps.close();
} catch (Exception e) {
// Do something
}
}
I think you have to modify 2 points.
First, use try & catch again in fainlly clause.
Second, do rs.close() before doing ps.close().
fly1997#naver.com
Probably an old (though simple) way to do things, but it still works:
public class DatabaseTest {
private Connection conn;
private Statement st;
private ResultSet rs;
private PreparedStatement ps;
public DatabaseTest() {
// if needed
}
public String getSomethingFromDatabase(...) {
String something = null;
// code here
try {
// code here
} catch(SQLException se) {
se.printStackTrace();
} finally { // will always execute even after a return statement
closeDatabaseResources();
}
return something;
}
private void closeDatabaseResources() {
try {
if(conn != null) {
System.out.println("conn closed");
conn.close();
}
if(st != null) {
System.out.println("st closed");
st.close();
}
if(rs != null) {
System.out.println("rs closed");
rs.close();
}
if(ps != null) {
System.out.println("ps closed");
ps.close();
}
} catch(SQLException se) {
se.printStackTrace();
}
}
}
I use this..
finally
{
if (ps != null) ps.close();
if (rs != null) rs.close();
}

MySQL lock wait timeout with a form submit

Here is my doPost method of my servlet that in theory add data in db
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
Date d=(Date) request.getAttribute("data");
DatiAnagrificiImpl dai=new DatiAnagrificiImpl();
dai.addDatiAnagrafici(new DatiAnagraficiBean(request.getParameter("username"),request.getParameter("cap"),request.getParameter("nome")
,request.getParameter("cognome"),request.getParameter("telefono"),d));
}
And here the method that will insert data in db
enter public void addDatiAnagrafici(DatiAnagraficiBean dab) {
// TODO Auto-generated method stub
try {
Statement s=c.createStatement();
s.executeUpdate("insert into Dati_anagrafici values('"+dab.getIdUtente()+"','"+dab.getIdCittà()+"',"
+ "'"+dab.getNome()+"','"+dab.getCognome()+"','"+dab.getTelefono()+"','"+dab.getDataNascita()+"')");
}catch(SQLException e) {
}finally {
al.add(dab);
}
}
But when I try to do that with a servlet I have this error
ERROR 1205 (HY000): Lock wait timeout exceeded;
Someone knows how to resolve? If I do the same thing with a normal java class is all fine.
It appears you have a transaction that's not completing. In MySQL, try running these to get a view into what's going on:
SHOW ENGINE INNODB STATUS;
SHOW FULL PROCESSLIST;
One or both should provide some clues.
A few issues stand out in your code. The first thing I would address is that the Statement is never closed (but should be). You can close the statement in a few places, but as the simplest example, you could close it right after you call executeUpdate(), like this:
Statement s = c.createStatement();
s.executeUpdate("...");
s.close();
Another easy change: when catching an exception, do something with it (instead of "swallowing" the exception silently). It's possible there's an exception being thrown, but the code above will hide that exception. For example, instead of this:
catch (SQLException e) {
}
try this:
catch (SQLException e) {
e.printStackTrace();
}
A final improvement would be to rework the code a bit to use "try-with-resources" - a nice convenience to automatically close a resource for you (in this case, your Statement). That could look like this:
Connection connection = getConnection();
try (Statement statement = connection.createStatement()) {
statement.executeUpdate("...");
} catch (SQLException e) {
e.printStackTrace();
}
EDIT: One more thing.. the connection can (and should) be committed by calling commit() (or rollback() if something went wrong). Here's a final edit to try which shows commit() in the main try block, and a rollback() in the catch block to undo the transaction if an exception is thrown:
Connection connection = getConnection();
try (Statement statement = connection.createStatement()) {
statement.executeUpdate("...");
connection.commit();
} catch (SQLException e) {
e.printStackTrace();
try {
connection.rollback();
} catch (SQLException ex) {
ex.printStackTrace();
}
}

Glassfish JDBC Connection Pooling Issue on Ubuntu

A sever issue I am facing after deployment on Glassfish4 and Ubuntu 14.04 . In java, I am not using hibernate due to some reasons. I am manually getting the resultset as a result of query, sending the result set to JSP page and iterating over it.
Problem is, I have set the finally block as below:
finally {
try {
if (conn != null) {
conn.close();
}
if (ctx != null) {
ctx.close();
}
if (cstatement != null) {
cstatement.closeOnCompletion();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
And because I am sending the Resultset to JSP page through session, I am closing the result on JSP page as follows:
if(resultset!=null) resultset.close();
Now, problem is, after few minutes my application starts giving exception that max of the connection pools has been used.
What should I do to avoid exception?
The problem with your current finally block is:
If any exception is thrown from one of the close command, the following command will not be run. Since the issue seems to be resource leak so that might be the cause.
If you are running under JDK7+ and the resource is auto-closable, try to use
try(Connection conn=DriverManager.getConnection();
Statement stat=conn.createStatement){
}
Then the resources will be closed safely exiting try block.
And if you need to close resource from finally block, try to wrap a try catch for each close statement.
For ordering of closing resource, always close the resource you created later first.

How to Correctly Close Resources

As I was cleaning up some code, FindBugs pointed me to a bit of JDBC code that uses Connection, CallableStatement, and ResultSet objects. Here's a snippet from that code:
CallableStatement cStmt = getConnection().prepareCall("...");
...
ResultSet rs = cStmt.executeQuery();
while ( rs.next() )
{
...
}
cStmt.close();
rs.close();
con.close();
FindBugs pointed out that these should be within a finally block. I started refactoring my code to do this and I started to wonder how to handle the code within the finally block.
It's possible that the creation of the CallableStatement of Connection objects would throw an exception, leaving my ResultSet object as null. When I try to close the ResultSet, I'd get a NullPointerException and my Connection would, in turn, never get closed. Indeed, this thread brings up the same concept and shows that wrapping your close() invocations in a null check is a good idea.
But what about other possible exceptions? According to the Java API spec, Statement.close() can throw a SQLException "if a database error occurs". So, even if my CallableStatement is not null and I can successfully call close() on it, I might still get an exception and not have a chance to close my other resources.
The only "fail safe" solution I can think of is to wrap each close() invocation in its own try/catch block, like this:
finally {
try {
cStmt.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
try {
rs.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
try {
con.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
}
Boy, if that doesn't look awful. Is there a better way to go about this?
I think the best answer has already being mentioned, but I thought it could be interesing to mention that you could consider the new JDK 7 feature of autoclosable resources.
try{
try(Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/hrdb", "obiwan", "kenobi");
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery("select name from department")) {
while(rs.next()){
System.out.println(rs.getString("name"));
}
}
}catch(SQLException e){
//you might wanna check e.getSuppressed() as well
//log, wrap, rethrow as desired.
}
Not all of us can migrate to JDK 7 now, but for those who can start playing with the developer preview, this offer an interesting way of doing things and certainly may deprecate other approaches in the near future.
Use Lombok's cleanup, if you can:
#Cleanup
Connection c = ...
#Cleanup
statement = c.prepareStatement(...);
#Cleanup
rs = statement.execute(...);
This works translates to three nested try-finally blocks and works fine with exception. Never ever swallow an exception without a very good reason!
An alternative:
Write an own utility method like this:
public static void close(ResultSet rs, Statement stmt, Connection con) throws SQLException {
try {
try {
if (rs!=null) rs.close();
} finally {
if (stmt!=null) stmt.close();
}
} finally {
if (con!=null) con.close();
}
}
and use it in
try {
Connection con = ...
Statement stmt = ...
ResultSet rs = ...
} finally {
close(rs, stmt, con);
}
and let the Exception bubble up or handle it as you want.
Well basically that is what you do except you first of all don't necessarily swallow the exception (you can null check and at least LOG the exception). Second, you can set up a nice utility class with things like
public static void close(ResultSet rs) {
try { if (rs != null) rs.close();
} catch (SQLException (e) {
log.error("",e);
}
}
Then you just static import that class.
your finally becomes something like
finally {
close(resultset);
close(statement);
close(connection);
}
which really isn't that hideous.
You only have to close the Connection.
try
{
cStmt.close();
}
catch(Exception e)
{
/* Intentionally Swallow Exception */
}
From docs.oracle.com:
A Statement object is automatically closed when it is garbage collected. When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
Calling close() on a Connection releases its database and JDBC resources.
The only way I know to hide all that ugly try-catch boilerplate code is to utilize something like Spring's JBDC Template.
You can wrap one block into another block:
try{
Connection c = ...
try{
statement = c.prepareStatement(...);
try{
rs = statement.execute(...);
}finally{
rs.close();
}
}finally{
statement.close()
}
}finally{
c.close();
}
}catch(SQLException e){}
Use the lowermost catch-block for everything that might crop up

Can't determine what is throwing a NullPointer exception

I have a method that looks like this:
try {
doStuff();
} catch (Exception ex) {
logger.error(ex);
}
(I don't really use method names like doStuff - this is just to make things easy)
In doStuff I do a variety of things, among them is call a data access method (so, another method within doStuff) that ends with the following:
} catch (SQLException ex) {
logger.error(ex);
} finally {
try {
connection.close();
proc.close();
results.close();
} catch (Exception e) {
logger.error(e);
} //<--Exception thrown here. HUH?
}
return stuff;
When stepping through this code I get to the second to last curly brace (marked with a comment) and then jump up to the catch in the first code block with a NullPointer exception. The results.close() is what is being run right before it (results is not null). My IDE (NetBeans) doesn't provide a stack trace (it shows the stack trace is null) or any other information other than the name of the exception (from what I can tell).
This code was running fine previously. In fact while it was running, I changed the stored procedure that the data access method (where I'm getting this exception) was calling, and then this error started to occur (without the application having been stopped at all). I've since tried rebuilding and restarting but to no avail. I could change the sproc back but I really want to find out what this error is from since it makes no sense that the sproc would even be a part of this considering where in the code the exception is occurring.
your doStuff() method is throwing something other than a SQLException and it is not being caught. add a catch(Exception e) block and log that exception and see what happens.
this code sample exhibits the same behaviour you are describing:
public class TryCatchTest {
public static void main(String[] args) {
try {
System.out.println("foo");
throw new NullPointerException();
} finally {
try {
System.out.println("bar");
} catch (Exception e) {
e.printStackTrace();
}
} // exception thrown here
}
}
Close the resources in the reverse order in which they were obtained:
try
{
results.close();
proc.close();
connection.close();
}
catch (Exception e)
{
logger.error(e);
} //<--Exception thrown here. HUH?
I'd also recommend methods like these:
public class DatabaseUtils
{
// similar for ResultSet and Statement
public static void close(Connection c)
{
try
{
if (c != null)
{
c.close();
}
}
catch (SQLException e)
{
// log or print.
}
}
}
It could well be that logger is null.
Hard-to-pinpoint exceptions are often thrown in the exception handler itself.
NullPointerException can not be thrown in a line without a statement.
Check that the class file you are executing is of the same version as the source you view (I have had similar issues when an incorrectly configured classpath contained a class twice and the older version was found first in the classpath, or a recompiled class files for not correctly copied to the web container I used for testing).
Edit: As emh points out, it could also be that exception occured prior to entering the finally block.
I'm 99% sure this is happening in the JDBC driver. For starters, your close statements are backwards. You should close the resultset, the statement and the connection, in that order.
If you are running in an application server which is managing the transactions, then the attempt to commit the transaction may trigger the exception inside the JDBC driver.
It could also be something about how result sets are generated in the stored proceedure, such as accessing one, then accessing another, and then referring back to the first one.
As I said in a comment, never catch an exception that you don't want to deal with. In your code, assuming that it is complete, you are not doing anything interesting with the exception, and it is causing you confusion on where and why the exception is happening. If you really want to do more than log or printStackTrace(), like wrapping it with a domain-specific exception (like your.package.DataAccessException or something), then great.
Do something more like this:
ResultSet results = null;
CallableStatement proc = null;
Connection connection = null;
try {
connection = >
proc = connection.createCallableStatement(..);
results = proc.execute(..);
>
} finally {
try {
if ( results != null ) {
results.close();
}
} catch (Exception e) {
logger.error(e);
}
try {
if ( proc != null ) {
proc.close();
}
} catch (Exception e) {
logger.error(e);
}
try {
if ( connection != null ) {
connection.close();
}
} catch (Exception e) {
logger.error(e);
}
}
And then in the caller:
try {
doStuff();
} catch ( SQLException e ) {
throw new your.package.DataAccessException(e);
// or just let the SQLException propagate upward
} catch ( Exception e ) {
throw new your.package.AppException("omg, crazy pills!", e);
// or, once again, just let the exception
// propagate and don't catch anything
}
So, take-away:
don't log exception where they happen, just pass them on, nested in another exception. You don't want your process to not know whether or not the SQL action succeeded or not. You would rather stop and do something else.
Nest exceptions until the get to the end of the line, that way, you always have the complete trace in the place that you wanted to deal with the exception, not in five places scattered throughout your server log.
Nest exceptions (yes, I said that twice!) so that you don't care where the JVM actually throws the exception from, you have the next exception to follow, telling you it was actually a callable statement, or improper closing of your resources, etc.
Don't nest and throw exceptions from errors caught in your finally code, that will interfere with the original exception and that will be more interesting than the failure to close and statement that didn't get opened in the first place.
Set variables to null before you use them, and then check for null before close()ing them.
Catch each problem in the finally block individually, as you might not be able to close your ResultSet (because some execution error caused it not to open in the first place), but you should still try to close the CallableStatement and Connection, as it is probably unaffected and will still cause you to leak resources.
Hope that helps.

Categories