No implementation of method: :render of protocol: #'compojure.response/Renderable found for class: clojure.lang.PersistentVector

1365 views
Skip to first unread message

Lawrence Krubner

unread,
Jun 16, 2015, 12:37:59 AM6/16/15
to comp...@googlegroups.com
My question is the same as the question  posted here in December of 2014: 


I am curious though why I actually need to specify the response map in this particular case, since this is typically done for me. I also worry that this solution will simply break something else. 

If I look here: 


I see:

clojure.lang.ISeq
(render [coll _]
(-> (response/response coll)
(response/content-type "text/html; charset=utf-8")))

Which would make me think that compojure knows how to render a seq into a response, and yet when I try to return a vector, I get: 

java.lang.IllegalArgumentException: No implementation of method: :render of protocol: #'compojure.response/Renderable found for class: clojure.lang.PersistentVector

I'm facing an odd situation. If I query the database (using the monger library to query MongoDB), and if I get multiple documents, I can return that without a problem, and everything works as I expect. However, if I return just one document, its keys become keys at the top level of the response, rather than being inside of the :body key, and also the :body key is empty, which is frustrating. 

So this is ends up being the response: 

{:updated-at 2015-06-16T03:46:13.148Z,
 :_id 557f9c050cf200d4b66429ed,
 :company-images [
  {:company-image "/assets/open/images/ar/badge-theater-small.png"} 
  {:company-image "/assets/open/images/ar/badge-music-small.png"}
  ],
 :company-name The Ethereal Lightness Of Savings,
 :executives [
  {:contact-name "Mark Stable", :total-sales "157532"} 
  {:contact-name "Tori Notworth", :total-sales "2235111"} 
  {:contact-name "Suzie Undid", :total-sales "1250"}
  ],
 :api-version v1,
 :headers {Access-Control-Allow-Headers Authorization, X-Requested-With, Content-Type, Origin, Accept,
           Access-Control-Allow-Credentials true,
           Access-Control-Max-Age 4440,
           Access-Control-Allow-Methods PUT, DELETE, POST, GET, OPTIONS, XMODIFY,
           Access-Control-Allow-Origin *,
           Content-Type application/json},
 :token 56a85d1d-8b37-4aaa-b7d7-399b6c330abd,
 :status 200,
 :transaction-id 24e6a697-fcf3-4c36-b3d0-d544304c0ee3,
 :body }

but I want all of this to go inside of body: 

:updated-at 2015-06-16T03:46:13.148Z,
 :_id 557f9c050cf200d4b66429ed,
 :company-images [
  {:company-image "/assets/open/images/ar/badge-theater-small.png"} 
  {:company-image "/assets/open/images/ar/badge-music-small.png"}
  ],
 :company-name The Ethereal Lightness Of Savings,
 :executives [
  {:contact-name "Mark Stable", :total-sales "157532"} 
  {:contact-name "Tori Notworth", :total-sales "2235111"} 
  {:contact-name "Suzie Undid", :total-sales "1250"}
  ],
 :api-version v1,
 
I tried to force this issue with this bit in my handler: 

          results (if (vector? results)
                    results
                    [results])

But that simply gave me the Exception that you can see above. Why doesn't this work? 

This happens when I'm creating a new document via a PUT, but I'm trying to return the document that was just created. Does compojure allow me to return an entity on PUT and POST? 

I will, for now, hard-code the response map, including the body key and its contents. But I am curious why, in this one case, I need to. 













James Reeves

unread,
Jun 16, 2015, 6:26:59 AM6/16/15
to Compojure
On 16 June 2015 at 05:37, Lawrence Krubner <lawr...@rollioforce.com> wrote:
My question is the same as the question  posted here in December of 2014: 


I am curious though why I actually need to specify the response map in this particular case, since this is typically done for me. I also worry that this solution will simply break something else. 

You don't need to specify the whole response map, just the body. You could return:

  {:body result}

And the rest of the response map will be filled in.

You can't simply return a result map, because then there would be no way to distinguish between the response and your results.

For example, let's say you want to return the JSON:

  {"status": 200, "headers": {}, "body": "Hello World"}

How would Compojure know you wanted to return that as JSON data, and not as a response?
 
Which would make me think that compojure knows how to render a seq into a response, and yet when I try to return a vector, I get: 

java.lang.IllegalArgumentException: No implementation of method: :render of protocol: #'compojure.response/Renderable found for class: clojure.lang.PersistentVector

Vectors can be turned into seqs, but they're not seqs themselves. You can see this at the REPL:

  user=> (seq? [1 2 3])
  false
  user=> (seq [1 2 3])
  (1 2 3)
 
- James
Reply all
Reply to author
Forward
0 new messages