You are viewing a plain text version of this content. The canonical link for it is here.
Posted to taglibs-dev@jakarta.apache.org by Sean Rohead <SR...@webmiles.com> on 2001/06/15 19:25:01 UTC

Major design flaw in DBTags!

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

Re: Major design flaw in DBTags!

Posted by Morgan Delagrange <mo...@apache.org>.
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
>