2012-02-29 162 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