Hi Stefan

you´re right, I wrote this with your first example in mind.

Regards
Flavio

Stefan Riegel <stefan.rie...@telig.de> gravou em 21/01/2009 01:36:34:

> Hello Flavio,
>
> thank You for your answer but isn't Your code the same as my code below?
> I don't see any significant difference.
>
> Regards
> Stefan
>
> Flavio Crispim schrieb:
> > Hi Stefan
> >
> > I would try this one:
> >
> >       Connection conn = null;
> >       Statement stmt = null;  // Or PreparedStatement if needed
> >       try {
> >             conn = ... get connection from connection pool ...
> >             stmt = conn.createStatement("select ...");
> >             ResultSet rs = stmt.executeQuery();
> >             ... iterate through the result set ...
> >       } catch (SQLException e) {
> >             ... deal with errors ...
> >       } finally {
> >             // Always make sure result sets and statements are closed,
> >             // and the connection is returned to the pool
> >             if (stmt != null) {
> >                   try { stmt.close(); } catch (SQLException e) { ; }
> >             }
> >             if (conn != null) {
> >                   try { conn.close(); } catch (SQLException e) { ; }
> >             }
> >       }
> >
> > We don´t need to null conn and stmt variables because the sanity check
on
> > finally block.
> > The resultset will only exist if and only if you already have a
statement,
> > and "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. ", thats why it is in a
more
> > restrictive scope w/out close()
> > http://java.sun.com/j2se/1.4.2/docs/api/java/sql/ResultSet.html
> >
> >
> > On the race condition:
> >
> > javadoc on Connection.close() states "Calling the method close on a
> > Connection object that is already closed is a no-op. ",
> > see:
http://java.sun.com/javase/6/docs/api/java/sql/Connection.html#close()
> >
> > This race condition should be threated as connection pool´s bug, IMHO.
> >
> > Flavio Crispim
> > PS: English isn´t my mother language...
> >
> >
> > Alan Chaney <a...@compulsivecreative.com> gravou em 19/01/2009
21:24:43:
> >
> >> 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
>
>
> ---------------------------------------------------------------------
> 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

Reply via email to