jakarta-taglibs-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sean Rohead <SRoh...@webmiles.com>
Subject RE: Major design flaw in DBTags!
Date Tue, 19 Jun 2001 00:14:15 GMT
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:morgand@apache.org]
Sent: Monday, June 18, 2001 4:25 PM
To: 'taglibs-dev@jakarta.apache.org'
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
> 

Mime
View raw message