I am seeing strange behaviour with a servlet I wrote to return an image from a database table. I'm not sure if it's struts related or not, but I am relying on a datasource defined in the struts-config.xml. It might be a silly mistake in the servlet code itself even.
I've attached the struts-config.xml which shows my datasource definition, the web.xml where I define the servlet and provide an initialization parameter, the servlet code (PhotoServlet.java) and a simple test.jsp page. The code I have seems to work most of the time (about 25/30 requests) before failing a couple of times. The log.txt attachment shows the result of doing: while true do lwp-request \ 'http://localhost:8080/shona/servlets/photo?id=1&class=thumbnail' \ | wc -c done (just sequential requests) The error.txt attachment shows the exception information generated when a request fails. Note there seem to be two types of exceptions occuring here: a low level jdbc error, and a "no results returned" error. I've played with the maxCount and minCount parameters in the struts datasource definition. Same results, except in the case of several simultaneous requests to the servlet -- in which case raising maxCount seems to prolong the interval between exceptions. It's really been baffling me for a while now. What could be going wrong? Am I seeing a limitation of Struts' connection pool perhaps? Even if it's not struts related, suggestions would still be very welcome. Matt
/* * PhotoServlet.java * * Created on February 23, 2002, 2:53 AM */ package mbkennedy.pshop.servlets; import javax.servlet.*; import javax.servlet.http.*; import javax.sql.*; import java.io.*; import java.sql.*; /** * * @author mkennedy * @version */ public class PhotoServlet extends org.apache.struts.action.ActionServlet { private static final long DEFAULT_BUFFER_SIZE = 1024; /** * bufferSize to use when transfering blob to servlet response. */ private long bufferSize; private DataSource dataSource = null; /** * Initializes the servlet. */ public void init(ServletConfig config) throws ServletException { super.init(config); String bufferSizeParam = null; if ((bufferSizeParam = config.getInitParameter("bufferSize")) != null) { // Servlet deployer intends to override default bufferSize this.bufferSize = Long.parseLong(config.getInitParameter("bufferSize")); if (this.bufferSize <= 0) { throw new ServletException("bufferSize must be > 0: bufferSize == " + this.bufferSize); } } else { this.bufferSize = this.DEFAULT_BUFFER_SIZE; } dataSource = this.findDataSource("default"); } /** * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods. * * @param request servlet request * @param response servlet response */ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Check request parameters if (request.getParameter("id") == null || request.getParameter("class") == null) { throw new ServletException("invalid request parameters: id = " + request.getParameter("id") + ", class = " + request.getParameter("class")); } // Validate parameters int paramId = 0; try { paramId = Integer.parseInt(request.getParameter("id")); } catch (NumberFormatException e_nf) { throw (ServletException) new ServletException("id must be an integer: id = " + request.getParameter("id")).initCause(e_nf); } Connection conn = null; try { String paramClass = null; conn = this.dataSource.getConnection(); PreparedStatement stmt1 = conn.prepareStatement("SELECT class FROM image_class WHERE class = ?"); stmt1.setString(1, request.getParameter("class")); if (stmt1.executeQuery().getFetchSize() == 0) { throw new ServletException("class is invalid: class = " + request.getParameter("class")); } else { paramClass = request.getParameter("class"); } stmt1.close(); // At this point parameters have been validated for correctness (it // should be safe to process the request) PreparedStatement stmt2 = conn.prepareStatement("SELECT image, mime_type " + "FROM item_photos WHERE (item_id = ?) AND (image_class = ?)"); stmt2.setInt(1, paramId); stmt2.setString(2, paramClass); ResultSet results = stmt2.executeQuery(); ServletOutputStream out = response.getOutputStream(); if (results.getFetchSize() == 0) { out.close(); } else { // TODO: Handle multiple photos for a single pruduct results.first(); Blob blob = results.getBlob("image"); long length = blob.length(); long chunks = length / this.bufferSize; long remainder = length % this.bufferSize; response.setContentType(results.getString("mime_type")); long pos = 0; for (long i = 0; i < chunks; i++, pos += this.bufferSize) { out.write(blob.getBytes(pos, (int) this.bufferSize)); } out.write(blob.getBytes(pos, (int) remainder)); out.close(); } stmt2.close(); } catch (SQLException e_sql) { throw (ServletException) new ServletException("SQL error").initCause(e_sql); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e_sql) { } } } } /** * Handles the HTTP <code>GET</code> method. * * @param request servlet request * @param response servlet response */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } /** * Handles the HTTP <code>POST</code> method. * * @param request servlet request * @param response servlet response */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } /** * Returns a short description of the servlet. */ public String getServletInfo() { return "Servlet to return photo images from the database."; } }
2002-03-10 02:10:14 - Ctx( /shona ): Exception in: R( /shona + /servlets/photo + null) - javax.servlet.ServletException: SQL error at mbkennedy.pshop.servlets.PhotoServlet.processRequest(PhotoServlet.java:121) at mbkennedy.pshop.servlets.PhotoServlet.doGet(PhotoServlet.java:141) at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:404) at org.apache.tomcat.core.Handler.service(Handler.java:286) at org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372) at org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:797) at org.apache.tomcat.core.ContextManager.service(ContextManager.java:743) at org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpConnectionHandler.java:210) at org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416) at org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:498) at java.lang.Thread.run(Thread.java:536) Caused by: No results were returned by the query. at org.postgresql.jdbc2.Statement.executeQuery(Unknown Source) at org.postgresql.jdbc2.PreparedStatement.executeQuery(Unknown Source) at mbkennedy.pshop.servlets.PhotoServlet.processRequest(PhotoServlet.java:81) ... 12 more 2002-03-10 02:10:44 - Ctx( /shona ): Exception in: R( /shona + /servlets/photo + null) - javax.servlet.ServletException: SQL error at mbkennedy.pshop.servlets.PhotoServlet.processRequest(PhotoServlet.java:121) at mbkennedy.pshop.servlets.PhotoServlet.doGet(PhotoServlet.java:141) at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:404) at org.apache.tomcat.core.Handler.service(Handler.java:286) at org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372) at org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:797) at org.apache.tomcat.core.ContextManager.service(ContextManager.java:743) at org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpConnectionHandler.java:210) at org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416) at org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:498) at java.lang.Thread.run(Thread.java:536) Caused by: No results were returned by the query. at org.postgresql.jdbc2.Statement.executeQuery(Unknown Source) at org.postgresql.jdbc2.PreparedStatement.executeQuery(Unknown Source) at mbkennedy.pshop.servlets.PhotoServlet.processRequest(PhotoServlet.java:81) ... 12 more 2002-03-10 02:11:29 - Ctx( /shona ): Exception in: R( /shona + /servlets/photo + null) - javax.servlet.ServletException: SQL error at mbkennedy.pshop.servlets.PhotoServlet.processRequest(PhotoServlet.java:121) at mbkennedy.pshop.servlets.PhotoServlet.doGet(PhotoServlet.java:141) at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:404) at org.apache.tomcat.core.Handler.service(Handler.java:286) at org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372) at org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:797) at org.apache.tomcat.core.ContextManager.service(ContextManager.java:743) at org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpConnectionHandler.java:210) at org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416) at org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:498) at java.lang.Thread.run(Thread.java:536) Caused by: FastPath call returned ERROR: current transaction is aborted, queries ignored until end of transaction block at org.postgresql.fastpath.Fastpath.fastpath(Unknown Source) at org.postgresql.fastpath.Fastpath.fastpath(Unknown Source) at org.postgresql.fastpath.Fastpath.getInteger(Unknown Source) at org.postgresql.largeobject.LargeObject.<init>(Unknown Source) at org.postgresql.largeobject.LargeObjectManager.open(Unknown Source) at org.postgresql.largeobject.PGblob.<init>(Unknown Source) at org.postgresql.jdbc2.ResultSet.getBlob(Unknown Source) at org.postgresql.jdbc2.ResultSet.getBlob(Unknown Source) at mbkennedy.pshop.servlets.PhotoServlet.processRequest(PhotoServlet.java:104) ... 12 more 2002-03-10 02:11:52 - Ctx( /shona ): Exception in: R( /shona + /servlets/photo + null) - javax.servlet.ServletException: SQL error at mbkennedy.pshop.servlets.PhotoServlet.processRequest(PhotoServlet.java:121) at mbkennedy.pshop.servlets.PhotoServlet.doGet(PhotoServlet.java:141) at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:404) at org.apache.tomcat.core.Handler.service(Handler.java:286) at org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372) at org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:797) at org.apache.tomcat.core.ContextManager.service(ContextManager.java:743) at org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpConnectionHandler.java:210) at org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416) at org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:498) at java.lang.Thread.run(Thread.java:536) Caused by: FastPath call returned ERROR: current transaction is aborted, queries ignored until end of transaction block at org.postgresql.fastpath.Fastpath.fastpath(Unknown Source) at org.postgresql.fastpath.Fastpath.fastpath(Unknown Source) at org.postgresql.fastpath.Fastpath.getInteger(Unknown Source) at org.postgresql.largeobject.LargeObject.<init>(Unknown Source) at org.postgresql.largeobject.LargeObjectManager.open(Unknown Source) at org.postgresql.largeobject.PGblob.<init>(Unknown Source) at org.postgresql.jdbc2.ResultSet.getBlob(Unknown Source) at org.postgresql.jdbc2.ResultSet.getBlob(Unknown Source) at mbkennedy.pshop.servlets.PhotoServlet.processRequest(PhotoServlet.java:104) ... 12 more 2002-03-10 02:11:53 - Ctx( /shona ): Exception in: R( /shona + /servlets/photo + null) - javax.servlet.ServletException: SQL error at mbkennedy.pshop.servlets.PhotoServlet.processRequest(PhotoServlet.java:121) at mbkennedy.pshop.servlets.PhotoServlet.doGet(PhotoServlet.java:141) at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.tomcat.core.ServletWrapper.doService(ServletWrapper.java:404) at org.apache.tomcat.core.Handler.service(Handler.java:286) at org.apache.tomcat.core.ServletWrapper.service(ServletWrapper.java:372) at org.apache.tomcat.core.ContextManager.internalService(ContextManager.java:797) at org.apache.tomcat.core.ContextManager.service(ContextManager.java:743) at org.apache.tomcat.service.http.HttpConnectionHandler.processConnection(HttpConnectionHandler.java:210) at org.apache.tomcat.service.TcpWorkerThread.runIt(PoolTcpEndpoint.java:416) at org.apache.tomcat.util.ThreadPool$ControlRunnable.run(ThreadPool.java:498) at java.lang.Thread.run(Thread.java:536) Caused by: No results were returned by the query. at org.postgresql.jdbc2.Statement.executeQuery(Unknown Source) at org.postgresql.jdbc2.PreparedStatement.executeQuery(Unknown Source) at mbkennedy.pshop.servlets.PhotoServlet.processRequest(PhotoServlet.java:81) ... 12 more
3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 <HTML> <HEAD><TITLE>An Error Occurred</TITLE></HEAD> <BODY> <H1>An Error Occurred</h1> 500 Internal Server Error </BODY> </HTML> 0 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 <HTML> <HEAD><TITLE>An Error Occurred</TITLE></HEAD> <BODY> <H1>An Error Occurred</h1> 500 Internal Server Error </BODY> </HTML> 0 <HTML> <HEAD><TITLE>An Error Occurred</TITLE></HEAD> <BODY> <H1>An Error Occurred</h1> 500 Internal Server Error </BODY> </HTML> 0 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 3635 <HTML> <HEAD><TITLE>An Error Occurred</TITLE></HEAD> <BODY> <H1>An Error Occurred</h1> 500 Internal Server Error </BODY> </HTML>
<?xml version="1.0" encoding="UTF-8" ?> <!-- Created by mkennedy on February 13, 2002, 3:57 PM --> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.0//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd"> <struts-config> <data-sources> <data-source id="default" key="default"> <set-property property="driverClass" value="org.postgresql.Driver"/> <set-property property="user" value="mkennedy"/> <set-property property="password" value=""/> <set-property property="url" value="jdbc:postgresql://localhost/pshop"/> <set-property property="autoCommit" value="false"/> <set-property property="description" value="PostgreSQL"/> <set-property property="maxCount" value="1"/> <set-property property="minCount" value="0"/> </data-source> </data-sources> <global-forwards> <forward name="index" path="/index.jsp"/> </global-forwards> </struts-config>
<?xml version="1.0" encoding="ISO-8859-1"?> <!-- Created by mkennedy on February 13, 2002, 3:57 PM --> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> <web-app> <!-- Action Servlet Configuration --> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>application</param-name> <param-value>mbkennedy.pshop.ApplicationResources</param-value> </init-param> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>2</param-value> </init-param> <init-param> <param-name>validate</param-name> <param-value>true</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> <servlet> <servlet-name>photo</servlet-name> <servlet-class>mbkennedy.pshop.servlets.PhotoServlet</servlet-class> <init-param> <param-name>bufferSize</param-name> <param-value>8192</param-value> </init-param> </servlet> <!-- Action Servlet Mapping --> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>photo</servlet-name> <url-pattern>/servlets/photo</url-pattern> </servlet-mapping> <!-- The Welcome File List --> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- Application Tag Library Descriptor --> <taglib> <taglib-uri>/tags/application.tld</taglib-uri> <taglib-location>/WEB-INF/tld/appilcation/application.tld</taglib-location> </taglib> <!-- Struts Tag Library Descriptors --> <taglib> <taglib-uri>/tags/struts.tld</taglib-uri> <taglib-location>/WEB-INF/tld/struts/struts.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-bean.tld</taglib-uri> <taglib-location>/WEB-INF/tld/struts/struts-bean.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-form.tld</taglib-uri> <taglib-location>/WEB-INF/tld/struts/struts-form.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-logic.tld</taglib-uri> <taglib-location>/WEB-INF/tld/struts/struts-logic.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-html.tld</taglib-uri> <taglib-location>/WEB-INF/tld/struts/struts-html.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-template.tld</taglib-uri> <taglib-location>/WEB-INF/tld/struts/struts-template.tld</taglib-location> </taglib> <!-- DBTags Tag Library Descriptor --> <taglib> <taglib-uri>/tags/dbtags.tld</taglib-uri> <taglib-location>/WEB-INF/tld/dbtags.tld</taglib-location> </taglib> </web-app>
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>