I'm not sure I agree that the syntax below is all that confusing.  First of
all, I don't think it's as common a situation as you imply.  A db connection
can have more than one open statement, so the only reason to need multiple
connections is when you are querying or updating more than one database or
the same database with different user credentials.  The only time they would
ever be nested is if you're copying data from one db to another or need data
from one db as query parameters in a second db.  I'm not saying that never
happens, but it is certainly not the typical case.  Plus, your syntax below
could just as easily be rewritten (if you don't want a new connection for
every iteration) as:

<connection>
  <url/>
  <user_name/>
  <password/>
  <statement>
    <connection>
      <resultset>
        <url/>
        <user_name/>
        <password/>
        <statement>
          <resultset/>
        </statement>
      </resultset>
    </connection>
  </statement>
</connection>


Although, if you're updating a database and that update needs to be
committed on every iteration, you would want it the other way around.  Plus,
if you're using a pooling datasource, creating connections is a cheap
operation anyway.

Sean

-----Original Message-----
From: Morgan Delagrange [mailto:[EMAIL PROTECTED]]
Sent: Tuesday, June 19, 2001 9:59 AM
To: '[EMAIL PROTECTED]'
Subject: RE: Major design flaw in DBTags!


I still think this syntax is confusing.  What's going on inside of nested
loops?

<connection>
  <url/>
  <user_name/>
  <password/>
  <statement>
    <resultset>
      <connection>
        <url/>
        <user_name/>
        <password/>
        <statement>
          <resultset/>
        </statement>
      </connection>
    </resultset>
  </statement>
</connection>

Is a new connection being created for every row in the enclosing
resultset?  Yuck.  Of course, we could just refuse to instantiate the same
Connection attribute more than once, but this usage is very confusing (and
too deeply nested).

There should be other ways to implement the release() that that don't
rely on a begin/end format.  The connection tag could maintain a stack of
all the connections it has open, and then insure they've all been closed
before termination of the page; the begin/end tag would have to do this as
well, since release() is only called once per page.  I'm a little nervous
to do this, because the JSP 1.1 spec was very vague on the meaning of the
release() tag and there are lots of interpretations out there.  But I
think it's probably manageable as long as closeConnection is still an
option.

I think that the current design is more pleasing and has greater
chi.  Shawn, wouldn't you agree?  When you factor in nested connections 
and the subtags of connection, begin/end gets pretty messy.

- Morgan



On Mon, 18 Jun 2001, Sean Rohead wrote:

> What you say about tags not getting cleaned up may be true in older
> containers, but in the current version of tomcat, the release() method is
> called in a finally block and is *guaranteed* by the 1.2 spec to be
called.
> I think it would make more sense to write a robust library for modern
> containers and where necessary provide alternate tags as work-arounds on
> older containers rather than the other way around.  Otherwise the library
is
> forever useless in enterprise programming since there is no way to prevent
> resource leaks.  I'm not sure what you mean when you propose a solution of
> 'monitor your system closely for exceptions', but counting stack traces in
> the logfile and restarting the server every time your pool has leaked away
> all its connections doesn't sound like a robust or realistic approach.
> 
> Sean Rohead
> 
> -----Original Message-----
> From: Morgan Delagrange [mailto:[EMAIL PROTECTED]]
> Sent: Monday, June 18, 2001 4:25 PM
> To: '[EMAIL PROTECTED]'
> Subject: Re: Major design flaw in DBTags!
> 
> 
> The original implementation of this tag library used begin/end tags, but
> there are some problems with that approach.  
> 
> The main problem is that most servlet containers will not allow includes
> inside of custom tags.  This was a limitation in the currently-released
> Servley spec, driven by limitations in Tomcat's I/O model.  That
> restriction is removed in the proposed spec, and it's no longer an issue
> in the most recent version of Tomcat and Weblogic.  But lots of current
> deployments don't let you do it.
> 
> Couple this with a page that utilizes multiple statements, and you have a
> problem.  It means that you can't do includes without closing the
> connection first.  That does not seem like an acceptable solution.
> 
> Also the syntax is awkward when using more than one connection on the
> page.  Nesting those connections seemed confusing and illogical.
> 
> In addition, I wanted people to be able to use their own means for
> obtaining connections, if the connection tag doesn't suit their
> needs.  The statement tags accept a regular old Connection attribute, so
> you can use whatever means you want to obtain it.  Generally speaking,
> DataSources and pooling drivers are the way to go, but some people use
> custom code for pooling connections and such.
> 
> Finally, as a taglib designer, I can tell you that if a fatal exception
> occurs within the body of the tag, the conenction will not be closed
> regardless of whether or not there is an end tag for the
> connection.  Servlet engines terminate immediately upon an exception, so
> the end tag will never be reached.
> 
> So that's why there's a separate end tag for closing connections.  Just be
> disciplined in your use of it, and monitor your system closely for
> exceptions, and you should be fine.
> 
> - Morgan
> 
> 
> On Fri, 15 Jun 2001, Sean Rohead wrote:
> 
> > I recently downloaded the DBTags library and quickly wrote the following
> > JSP:
> > 
> > <%@ taglib uri="dbtags" prefix="sql" %>
> > <sql:connection id="connection"
dataSource="com.webmiles.tomcat.database"
> />
> >   <sql:preparedStatement id="statement" conn="connection">
> >     <sql:query>select sysdate from dual</sql:query>
> >     <sql:resultSet id="results">
> >       The time is: <sql:getDate position="1" format="FULL"/>
> >     </sql:resultSet>
> >   </sql:preparedStatement>
> > <sql:closeConnection conn="connection"/>
> > 
> > 
> > 
> > However, upon further reflection, it seems like a bad design choice to
> have
> > separate 'connection' and 'closeConnection' tags since there is no way
to
> > guarantee that the connection will be closed (not only that, but it's
also
> > more error prone as the user may forget to include the closeConnection
> tag).
> > The closeConnection tag *must* be enclosed in a finally block to prevent
> > resource leaks in the presence of exceptions.  When I tried this (using
> > tomcat), I got the following error.
> > 
> > 
> > <%@ taglib uri="dbtags" prefix="sql" %>
> > <sql:connection id="connection"
dataSource="com.webmiles.tomcat.database"
> />
> > <% try { %>
> >   <sql:preparedStatement id="statement" conn="connection">
> >     <sql:query>select sysdate from dual</sql:query>
> >     <sql:resultSet id="results">
> >       The time is: <sql:getDate position="1" format="FULL"/>
> >     </sql:resultSet>
> >   </sql:preparedStatement>
> > <% } finally { %>
> > <sql:closeConnection conn="connection"/>
> > <% } %>
> > 
> > 
> > 
> > Internal Servlet Error:
> > 
> > javax.servlet.ServletException: (class:
_0002fdbtags_0002ejspdbtags_jsp_4,
> > method: _jspService signature:
> >
>
(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletRespo
> > nse;)V) Incompatible object argument for function call
> >     at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:508)
> >     at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
> >     at
> > org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:405)
> >     at org.apache.tomcat.core.Handler.service(Handler.java:287)
> >     at
> > org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372)
> >     at
> >
>
org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:79
> > 7)
> >     at
> > org.apache.tomcat.core.ContextManager.service(ContextManager.java:743)
> >     at
> >
>
org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpC
> > onnectionHandler.java:213)
> >     at
> >
org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416)
> >     at
> >
org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:501)
> >     at java.lang.Thread.run(Thread.java:484)
> > 
> > Root cause: 
> > java.lang.VerifyError: (class: _0002fdbtags_0002ejspdbtags_jsp_4,
method:
> > _jspService signature:
> >
>
(Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletRespo
> > nse;)V) Incompatible object argument for function call
> >     at java.lang.Class.newInstance0(Native Method)
> >     at java.lang.Class.newInstance(Class.java:237)
> >     at
> >
>
org.apache.jasper.servlet.JspServlet$JspServletWrapper.instantiateServlet(Js
> > pServlet.java:204)
> >     at
> > org.apache.jasper.servlet.JspServlet.doLoadJSP(JspServlet.java:617)
> >     at
> >
org.apache.jasper.servlet.JasperLoader12.loadJSP(JasperLoader12.java:146)
> >     at org.apache.jasper.servlet.JspServlet.loadJSP(JspServlet.java:542)
> >     at
> >
>
org.apache.jasper.servlet.JspServlet$JspServletWrapper.loadIfNecessary(JspSe
> > rvlet.java:258)
> >     at
> >
>
org.apache.jasper.servlet.JspServlet$JspServletWrapper.service(JspServlet.ja
> > va:268)
> >     at
> > org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:429)
> >     at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:500)
> >     at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
> >     at
> > org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:405)
> >     at org.apache.tomcat.core.Handler.service(Handler.java:287)
> >     at
> > org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372)
> >     at
> >
>
org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:79
> > 7)
> >     at
> > org.apache.tomcat.core.ContextManager.service(ContextManager.java:743)
> >     at
> >
>
org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpC
> > onnectionHandler.java:213)
> >     at
> >
org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416)
> >     at
> >
org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:501)
> >     at java.lang.Thread.run(Thread.java:484)
> > 
> > 
> > 
> > 
> > Wouldn't it make much more sense to enclose everything in the connection
> tag
> > and not have a separate closeConnection?  This way the connection could
be
> > automatically closed when the connection tag ended (why would you *ever*
> not
> > want to close the connection?)  This should happen in the release()
method
> > of the connection tag.  From the JSP 1.2 pfd 2 pg 164, "The page
compiler
> > guarantees that release() will be invoked on the Tag handler before the
> > handler is released to the GC".  This means that release() is called in
a
> > finally block and there will be no connection leaks.
> > 
> > 
> > The resulting jsp would look like this:
> > 
> > <%@ taglib uri="dbtags" prefix="sql" %>
> > <sql:connection id="connection"
dataSource="com.webmiles.tomcat.database">
> >   <sql:preparedStatement id="statement" conn="connection">
> >     <sql:query>select sysdate from dual</sql:query>
> >     <sql:resultSet id="results">
> >       The time is: <sql:getDate position="1" format="FULL"/>
> >     </sql:resultSet>
> >   </sql:preparedStatement>
> > </sql:connection>
> > 
> > 
> > Just as concise with no possibility for resource leaks!
> > 
> > 
> > Sean Rohead
> > 
> 

Reply via email to