2012-02-29 188 views
1

我正在Tomcat 7环境中使用Java访问Oracle 9数据库。由于多次提交而导致“Stream Closed”错误导致

的context.xml

<Resource type="javax.sql.DataSource" auth="Container" 
    name="jdbc/myDB" 
    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
    driverClassName="oracle.jdbc.OracleDriver" 
    url="jdbc:oracle:thin:@localhost:1521:db" maxwait="10000" 
    username="temp" password="temp" maxActive="20" maxIdle="10"/> 

我的Java代码工作的大部分时间,但有时随机我得到流封闭例外。我怀疑这可能是因为用户太快地按下应用程序中的按钮,因此在完成另一个查询之前启动一个查询。

此异常是由以下代码中的doEndTag函数引起的。

public class SQLIteratorTag extends BodyTagSupport 
{ 
public SQLIteratorTag() 
{ 
    query = ""; 
    rs = null; 
    stmt = null; 
    rsmd = null; 
    dbConn = null; 
    con = null; 
} 

public int doStartTag() 
    throws JspTagException 
{ 
    String fieldName = ""; 
    try 
    { 
     DBConnection d=DBConnection.getInstance(); 

     con = d.getConnection(); 
     ... 

public int doAfterBody() 
    throws JspException 
{ 
    try 
    { 
    ....  


public int doEndTag() 
    throws JspException 
{ 
    try 
    { 
     if(bodyContent != null) 
     { 
      bodyContent.writeOut(bodyContent.getEnclosingWriter()); 
     } 
    } 
    catch(IOException ex) 
    { 
     Log.getIns 

我不想发布太多的代码,但我可能发布的太少。我不知道问题出在哪里,但如有必要,我会更新问题。

例外本身是:

SEVERE: Servlet.service() for servlet [jsp] in context with path [/charm] threw exception [javax.servlet.ServletException: javax.servlet.jsp.JspTagException: Stream closed] with root cause 
javax.servlet.jsp.JspTagException: Stream closed 
at c.tags.sql.SQLIteratorTag.doEndTag(SQLIteratorTag.java:218) 
at org.apache.jsp.comp_005fpara_jsp._jspService(comp_005fpara_jsp.java:708) 
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) 
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432) 
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390) 
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
at com.jspbook.GZIPFilter.doFilter(Unknown Source) 
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) 
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) 
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) 
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) 
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) 
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927) 
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) 
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987) 
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579) 
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 
at java.lang.Thread.run(Thread.java:722) 
+1

什么是实际的异常 - 你可以发布堆栈跟踪?你确定它来自数据库方面,而不是服务器和浏览器之间的中断连接 - 这可能与点击两次方案相匹配? – 2012-02-29 15:08:56

+0

嗨,亚历克斯。我按要求添加了堆栈跟踪。我不确定错误来自哪里! – gordon613 2012-02-29 15:50:20

回答

2

从堆栈跟踪,这并不似乎任何与数据库连接,但看起来与用户提交从后端两个请求。我已经更改了标签,但您可能需要重新修改该问题并更改标题以获得更多关注。

本质上,您的应用程序接收到两个请求,并对它们进行处理。我已经看到了这一段时间,但据我记得第一个得到这个错误是因为浏览器关闭了TCP/IP连接,以便为第二个请求打开一个新连接。 (这对HTTP/1.1来说可能有点简单,因为它重用了连接)。

我认为我们通过在页面生成时隐藏一个唯一标识符来解决这个问题,然后检测我们是否在与该UID相同的会话上获得第二个POST请求 - 表示它们已提交两次。一段时间以前,我对我们所做的事情都很朦胧,以及我们如何阻止它对用户可见;我记得我们在HttpServletRequestWrapper中为HttpServletRequestWrapper包装了HttpServletRequest,而HttpServletRequestWrapper似乎将请求从POST改变为GET,但我不得不做一些挖掘以确定发生了什么。

编辑:This link是很老,但似乎有更好的办法来解决它比什么都古老我可以拖动了(这似乎是主要选项2在后)。有可能有几种常见的方法来解决这个问题。

+0

谢谢Alex。我已经按照你的建议更新了标题。不过,我可能会补充说,使用OC4J应用服务器的Java代码工作正常。自从我将它移到Tomcat后,这个问题才发生。所以我的想法是,也许我错误地设置了数据库连接(这就是为什么我从context.xml中发布提取文件),以致它没有以正确的方式处理同时连接。 – gordon613 2012-02-29 17:13:26

+0

@ gordon613 - 也许OC4J正在做某种过滤,已经隐藏了问题?纯粹的猜测当然。由于它并不明显与数据库相关,所以我在这里远远超过了我的用处。祝你好运! – 2012-02-29 17:22:01