【问题标题】:Stream Closed error on Tomcat 7 with Clojure Compojure Application使用 Clojure Compojure 应用程序在 Tomcat 7 上出现 Stream Closed 错误
【发布时间】:2013-08-11 17:07:53
【问题描述】:

我正在使用 compojure、ring-json 在 clojure 中开发一个应用程序,并在开发时使用 lein-ring 进行测试(使用“lein ring server”命令)并将应用程序打包成一个 war 文件以部署在 Tomcat 7.0 上.42.我有一个页面,它使用 jQuery 向 url 发出 ajax post 请求,该请求响应来自更新的数据库记录的数据。在开发时,在“lein ring server”命令下运行,javascript 运行良好。它收集输入,发送发布数据,然后服务器用我正在寻找的数据进行响应。

当我将应用打包并部署在Tomcat的“webapps”目录中时,我的应用运行正常,让我登录,从数据库中提取数据,并正确处理表单发布请求(例如登录,通过登录表单将数据发送到服务器,一切正常)。但是,当我使用 javascript ajax 请求导航到页面时,出现以下错误:

SEVERE: Servlet.service() for servlet [performancecenter.routes/app servlet] in context with path [/performance] threw exception
java.io.IOException: Stream closed
    at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:312)
    at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:200)
    at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
    at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
    at sun.nio.cs.StreamDecoder.read(Unknown Source)
    at java.io.InputStreamReader.read(Unknown Source)
    at java.io.BufferedReader.fill(Unknown Source)
    at java.io.BufferedReader.read(Unknown Source)
    at clojure.core$slurp.doInvoke(core.clj:6279)
    at clojure.lang.RestFn.invoke(RestFn.java:410)
    at ring.middleware.json$read_json.doInvoke(json.clj:12)
    at clojure.lang.RestFn.invoke(RestFn.java:423)
    at ring.middleware.json$wrap_json_body$fn__3427.invoke(json.clj:19)
    at ring.middleware.json$wrap_json_params$fn__3431.invoke(json.clj:31)
    at ring.middleware.json$wrap_json_response$fn__3438.invoke(json.clj:42)
    at performancecenter.servlet$_service$fn__706.invoke(servlet.clj:1)
    at ring.util.servlet$make_service_method$fn__50.invoke(servlet.clj:126)
    at performancecenter.servlet$_service.invoke(servlet.clj:1)
    at performancecenter.servlet.service(Unknown Source)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

这里是 post 请求 url 的组合路由函数和使用 ring-json 函数包装请求的 app 函数:

(defroutes page-routes
  (POST "/log/performance/api" {session :session params :params} 
        (enter-production-record (:user session) params)))

(def app
  (-> (routes login-routes main-routes)
      (auth/with-user)
      (handler/site :session)
      (middleware/wrap-json-body)
      (middleware/wrap-json-params)
      (middleware/wrap-json-response)))

这是返回 json 数据的函数(并且正在开发中):

(defn enter-production-record [user params]
  (let [m (data/insert-producer-metric (:id user))
        r (data/get-productivity m)]
    {:body {:productivity (float (:productivity_factor r))}}))

诚然,我对 Tomcat 知之甚少,但通过阅读我发现了这个错误的示例,它通常与应用程序中的函数提前关闭流或其他什么有关。我不明白这里到底发生了什么,或者我的函数将如何做到这一点。任何帮助将不胜感激,谢谢!

【问题讨论】:

    标签: tomcat clojure leiningen compojure


    【解决方案1】:

    我遇到了类似的问题,它是由未传递标头“Content-Type: application/json”的请求引起的。如果您没有输入正确的内容类型,则 json 包装器可能无法正常工作,因此,它们可能会导致 IO 错误(在我的情况下,我没有使用中间件,但我直接 slurped {request :body},未能给出 IO 错误)。

    【讨论】:

      【解决方案2】:

      我经常遇到这样的情况,当对数据库的调用返回一个惰性记录序列时,某些东西在开发中有效而在生产中失败,该记录被打印到开发中的 repl 或记录器,而在生产系统。可能是对 get-productivity 的调用中的某些内容在返回的行周围缺少对 doall 的调用。

      另一种情况是异常处理程序环绕对with-connection 的调用,因此当异常发生时,数据库连接不再可用,尽管根据我对可能发生的情况的猜测,这似乎比丢失doall 的可能性要小在get-productivity

      如果您包含get-productivity 并记录失败期间它的返回值示例,我们将能够做出更好的猜测。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-04-24
        • 1970-01-01
        • 1970-01-01
        • 2021-07-29
        • 1970-01-01
        • 2013-07-25
        • 1970-01-01
        • 2011-11-02
        相关资源
        最近更新 更多