Ошибка Stream Closed на Tomcat 7 с приложением Clojure Compojure

Я разрабатываю приложение в clojure, используя compojure, ring-json и используя lein-ring для тестирования во время разработки (используя команду «lein ring server») и упаковывая приложение в военный файл для развертывания на Tomcat 7.0.42. У меня есть страница, которая использует jQuery для отправки запроса ajax на URL-адрес, который отвечает на данные из обновленной записи базы данных. При разработке под командой "lein ring server" javascript работает отлично. Он собирает входные данные, отправляет почтовые данные, а сервер отвечает данными, которые я ищу.

Когда я упаковываю приложение и развертываю его в каталоге «webapps» Tomcat, мое приложение работает правильно, позволяет мне войти в систему, извлекает данные из базы данных и правильно обрабатывает почтовые запросы формы (например, вход в систему отправляет данные через форму входа на сервер и все работает). Но когда я перехожу на страницу с запросом ajax javascript, я получаю следующую ошибку:

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)

Вот функция маршрутов compojure для URL-адреса почтового запроса и функция приложения, которая оборачивает запросы функциями Ring-JSON:

(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, но, читая, я нашел примеры этой ошибки, и обычно она была связана с функцией в приложении, которая раньше закрывала поток или что-то в этом роде. Я не совсем понимаю, что здесь происходит или как моя функция будет это делать. Любая помощь будет оценена, спасибо!


person h2ounderthebridge    schedule 09.08.2013    source источник


Ответы (2)


Я часто сталкиваюсь с такими ситуациями, когда что-то работает в разработке и не работает в продакшене, когда обращение к БД возвращает ленивую последовательность записей, которая печатается в repl или логгер в разработке и не реализуется на продакшене. Возможно, в вызове get-productivity отсутствует вызов doall вокруг возвращаемых строк.

В другом случае обработчик исключений оборачивает вызов with-connection, поэтому, когда возникает исключение, соединение с базой данных больше недоступно, хотя это кажется менее вероятным, чем отсутствие doall, исходя из моего предположения о том, что может быть в get-productivity

если вы включите get-productivity и запишете пример его возвращаемого значения во время сбоя, мы сможем сделать более точные предположения.

person Arthur Ulfeldt    schedule 10.08.2013

У меня была аналогичная проблема, и она была вызвана запросом, сделанным без передачи заголовка «Content-Type: application/json». Если вы не укажете правильный тип контента, json-обертка может работать неправильно и, следовательно, может привести к ошибке ввода-вывода (в моем случае я не использовал промежуточное программное обеспечение, но я прямо хлебнул {request: body}, который не дал ошибку ввода-вывода).

person Davide Vernizzi    schedule 02.08.2016