tomcat 6/7 stream closed error in ring json - works in lein ring server

347 views
Skip to first unread message

Colin Yates

unread,
Nov 3, 2013, 7:20:29 PM11/3/13
to clo...@googlegroups.com
Hi all,

I have developed a ring/compojure app which receives and servers JSON.  All is well in 'lein ring server' but as soon as I do 'lein ring uberwar' and deploy it to tomcat 6 or 7 it fails.  To be explicit, the app deploys and I can view the static resources, but as soon as I issue a JSON POST I get the following error:

[code]
java.io.IOException: Stream closed
org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:325)
org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:193)
sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
java.io.InputStreamReader.read(InputStreamReader.java:184)
java.io.BufferedReader.fill(BufferedReader.java:154)
java.io.BufferedReader.read(BufferedReader.java:175)
clojure.core$slurp.doInvoke(core.clj:6279)
clojure.lang.RestFn.invoke(RestFn.java:410)
ring.middleware.json$read_json.doInvoke(json.clj:12)
clojure.lang.RestFn.invoke(RestFn.java:423)
ring.middleware.json$wrap_json_body$fn__1031.invoke(json.clj:19)
ring.middleware.json$wrap_json_params$fn__1035.invoke(json.clj:31)
compojure.core$routing$fn__362.invoke(core.clj:107)
clojure.core$some.invoke(core.clj:2443)
compojure.core$routing.doInvoke(core.clj:107)
clojure.lang.RestFn.applyTo(RestFn.java:139)
clojure.core$apply.invoke(core.clj:619)
compojure.core$routes$fn__366.invoke(core.clj:112)
health.servlet$_service$fn__1016.invoke(servlet.clj:1)
ring.util.servlet$make_service_method$fn__50.invoke(servlet.clj:126)
health.servlet$_service.invoke(servlet.clj:1)
health.servlet.service(Unknown Source)
[/code]

Any help?

Colin Yates

unread,
Nov 3, 2013, 7:24:45 PM11/3/13
to clo...@googlegroups.com
Apologies - I just realised a Compojure group existed.  I have posted in there (https://groups.google.com/forum/#!topic/compojure/_jut36dXmCM) as well.

James Reeves

unread,
Nov 3, 2013, 8:02:31 PM11/3/13
to clo...@googlegroups.com
Hi Colin,

One of the compromises Ring makes for efficiency is that the body of a request is an InputStream, rather than a static string or byte array pre-loaded into memory. Because it's a stream, it can potentially be consumed by previous middleware.

For some reason you have both wrap-json-body and wrap-json-params in your stacktrace:

    ring.middleware.json$wrap_json_body$fn__1031.invoke(json.clj:19)
  ring.middleware.json$wrap_json_params$fn__1035.invoke(json.clj:31)

Both middleware read from the body InputStream, so one of them is going to fail when you try and read the body twice.

- James


--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Colin Yates

unread,
Nov 3, 2013, 8:40:28 PM11/3/13
to clo...@googlegroups.com
Hi James,

Not sure why I did that double wrapping..

However, wouldn't that also fail in Jetty?


You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/RxctbwMoOPU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.

James Reeves

unread,
Nov 3, 2013, 9:46:55 PM11/3/13
to clo...@googlegroups.com
It would. I'm not sure why one fails and the other does not, unless the request object passed through Tomcat is different somehow, or unless you accidentally sent two different HTTP requests when testing.

Regardless, the error message you've received is pretty clear - the JSON stream is consumed by the first JSON middleware before the second can get to up.

- James

Colin Yates

unread,
Sep 3, 2014, 9:02:13 AM9/3/14
to clo...@googlegroups.com, ja...@booleanknot.com
(is this is the longest delay in replying ever? :))

You are right - I mistakenly thought that json-wrap-params only exposed the request params as oppose to exposing the JSONified body in the params; I thought json-wrap-body and json-wrap-params were complimentary.

Now I have read the docs (https://github.com/ring-clojure/ring-json) it is clear that only one is required.

Problem solved - chose one or the other.
Reply all
Reply to author
Forward
0 new messages