Path: csiph.com!aioe.org!.POSTED!not-for-mail From: =?UTF-8?Q?Arne_Vajh=c3=b8j?= Newsgroups: comp.lang.java.programmer Subject: Re: Eclipse doesn't like else Date: Sat, 13 May 2017 21:04:52 -0400 Organization: Aioe.org NNTP Server Lines: 165 Message-ID: References: <3c792901-a05d-4a02-b058-20b9e0576095@googlegroups.com> NNTP-Posting-Host: PBuS014lhzVyHjLbXmo/ZQ.user.gioia.aioe.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Complaints-To: abuse@aioe.org User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.8.0 X-Notice: Filtered by postfilter v. 0.8.2 Xref: csiph.com comp.lang.java.programmer:36614 On 5/12/2017 1:44 PM, Eric Douglas wrote: > Why must it give a warning on this else condition? > > import java.sql.Connection; > import java.sql.DriverManager; > import java.sql.PreparedStatement; > import java.sql.SQLException; > > public class CompileMe { > public static void testMe() { > try { > Connection conn = DriverManager.getConnection("db_connect_string", "db_userid", "db_password"); > String someCondition = "check me"; > PreparedStatement myPrep; > myPrep = conn.prepareStatement("initial query"); > myPrep.executeQuery(); > myPrep.close(); > if (someCondition.equals("one")) { > myPrep = conn.prepareStatement("query something"); > } else { > myPrep = conn.prepareStatement("query something else"); > } > myPrep.executeQuery(); > myPrep.close(); > } catch (SQLException e) { > e.printStackTrace(); > } > } > } > > This example will run the same whether we have 2 calls to > prepareStatement, or set one common string to pass into prepareStatement > after the if, but if we write it this way Eclipse gives a warning > "Resource leak: 'myPrep' is not closed at this location". > > Take out the 3 lines above the if (prepare, execute, and close a > different query) and the warning goes away. As already explained by other then there are a resource leak. And as I said in another reply then I don't think Eclipse detects all resource leaks. But if we take a step back and look at the code then there are several things that comes to my mind: * I do not like the reuse of the PreparedStatement ref I would use different ref's * all statements and connection need to be closed to avoid resource leak (well - statements should be closed when connection is closed per specs, but I would not rely on that) * the only way to get this right is to have a systematic approach Here are 3 different approaches: import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class ToCloseOrNotToclose { // Approach 1: // * close everything as soon as possible in good flow // * close in catch block if necessary to handle bad flows public static void approach1(String cond) { Connection con = null; PreparedStatement upd1 = null; PreparedStatement upd2a = null; PreparedStatement upd2b = null; try { con = DriverManager.getConnection("db_connect_string", "db_userid", "db_password"); upd1 = con.prepareStatement("initial query"); upd1.executeQuery(); upd1.close(); if (cond.equals("one")) { upd2a = con.prepareStatement("query something"); upd2a.executeQuery(); upd2a.close(); } else { upd2b = con.prepareStatement("query something else"); upd2b.executeQuery(); upd2b.close(); } con.close(); } catch (SQLException e) { e.printStackTrace(); try { if(upd1 != null && !upd1.isClosed()) upd1.close(); if(upd2a != null && !upd2a.isClosed()) upd2a.close(); if(upd2b != null && !upd2b.isClosed()) upd2b.close(); if(con != null && !con.isClosed()) con.close(); } catch (SQLException e2) { e2.printStackTrace(); // consider what to do here } // consider what to do here } } // Approach 2: // * close in finally block for both good and bad flows public static void approach2(String cond) { Connection con = null; PreparedStatement upd1 = null; PreparedStatement upd2a = null; PreparedStatement upd2b = null; try { con = DriverManager.getConnection("db_connect_string", "db_userid", "db_password"); upd1 = con.prepareStatement("initial query"); upd1.executeQuery(); if (cond.equals("one")) { upd2a = con.prepareStatement("query something"); upd2a.executeQuery(); } else { upd2b = con.prepareStatement("query something else"); upd2b.executeQuery(); } con.close(); } catch (SQLException e) { e.printStackTrace(); // consider what to do here } finally { try { if(upd1 != null) upd1.close(); if(upd2a != null) upd2a.close(); if(upd2b != null) upd2b.close(); if(con != null) con.close(); } catch (SQLException e2) { e2.printStackTrace(); // consider what to do here } } } // Approach 3: // * use Java 7+ try with resource public static void approach3(String cond) { try (Connection con = DriverManager.getConnection("db_connect_string", "db_userid", "db_password")) { try(PreparedStatement upd1 = con.prepareStatement("initial query")) { upd1.executeQuery(); } if (cond.equals("one")) { try(PreparedStatement upd2a = con.prepareStatement("query something")) { upd2a.executeQuery(); } } else { try(PreparedStatement upd2b = con.prepareStatement("query something else")) { upd2b.executeQuery(); } } } catch (SQLException e) { e.printStackTrace(); // consider what to do here } } } Arne