Arguments getting mismatched

FUNCTION:

(defn download-chatrooms
  "Export chatrooms of the workflow template in CSV format"
  [db-spec org-id uid template-id & {:keys [order-by filter-by report-id]}]
    (println "ORDR_BY FILTR_BY RPTID " order-by filter-by report-id))

FUNCTION CALL:

(fn [context]
     (let [{:keys [org-id uid]} (get-in context [:request])
           db (get-in context [:request :system :db])
           id (get-in context [:request :path-params :id])
           {sort :sort :as params} (context :kebab-params)
           {:keys [filename data]} (p/download-chatrooms db
                                                         org-id
                                                         uid
                                                         (read-string id)
                                                         (query/sorting-intent->map sort)
                                                         (dissoc params :page :sort))]

REQ:
http://localhost:3593/workflow/4/chatroom/download?page=1&sort=seqNo:desc&reportId=3
OUTPUT:
ORDR_BY FILTR_BY RPTID [{:seq-no desc}] {:report-id 3} nil

Why are these arguments getting mismatched?

But If I keep everything the same and just change the function signature to

(defn download-chatrooms
  "Export chatrooms of the workflow template in CSV format"
  [db-spec org-id uid template-id & [[order-by filter-by] report-id]]
  (println "ORDR_BY FILTR_BY RPTID " order-by filter-by report-id)

OUTPUT LOOKS CORRECT:
ORDR_BY FILTR_BY RPTID {:seq-no desc} nil {:report-id 3}

BUT THERE’S AN ERROR:
: clojure.lang.ExceptionInfo: java.lang.ClassCastException in Interceptor :workflow-instances-download - class clojure.lang.MapEntry cannot be cast to class clojure.lang.IPersistentMap (clojure.lang.MapEntry and clojure.lang.IPersistentMap are in unnamed module of loader 'app')

When you say & {:keys [foo bar]} in a function signature, it is expecting named arguments like this:

(some-func :foo 42 :bar "arg")

You are calling the function download-chatrooms with six positional arguments.

In the & [foo bar] case, you are describing optional positional arguments instead of named arguments.

Only the ones after & are the positional arguments, right?

If I keep the function

(defn download-chatrooms
  "Export chatrooms of the workflow template in CSV format"
  [db-spec org-id uid template-id & {:keys [order-by filter-by report-id]}]

And call it directly in the REPL (download-chatrooms (:myapp/db integrant.repl.state/system) 1 "L0QGp8J3P0fFNq7eGeR7Tl61UuL2" 4 :report-id 3)
I’m passing only report-id and ignore order-by and filter-by, then I get this ORDR_BY FILTR_BY RPTID nil nil 3 along with the data

But for the same function if I have another method call it like this:

(let [{:keys [org-id uid]} (get-in context [:request])
           db (get-in context [:request :system :db])
           id (get-in context [:request :path-params :id])
           {sort :sort :as params} (context :kebab-params)
           {:keys [filename data]} (p/download-chatrooms db
                                                         org-id
                                                         uid
                                                         (read-string id)
                                                         :report-id
                                                         {:report-id 3})]

The send a request http://localhost:3593/workflow/4/chatroom/download?page=1&sort=seqNo:desc&reportId=3 Then I get same like above ORDR_BY FILTR_BY RPTID nil nil 3 But doesn’t show the data and says this

ERROR [myapp.service:202] - : clojure.lang.ExceptionInfo: java.lang.IllegalArgumentException in Interceptor :workflow-instances-download - Failed to fetch the report {:execution-id 1, :stage :enter, :interceptor :workflow-instances-download, :exception-type :java.lang.IllegalArgumentException, :exception #error {
 :cause "Failed to fetch the report"
 :via
 [{:type java.lang.IllegalArgumentException
   :message "Failed to fetch the report"
   :at [myapp.db.process$get_report invokeStatic "process.clj" 677]}]

How is the req method making a difference than calling it direct?

They are positional before the &. They are positional after & as well if you use sequence destructuring & [foo bar]. They are named if you use map destructuring & {:keys [foo bar]}.

In both cases, the arguments after & are optional.

Your two calls – via the REPL and via the “req method” – are different. In the REPL you pass :report-id 3 but in the other code you pass :report-id {:report-id 3}. In the first case, report-id is bound to 3 in the call. In the second case, report-id is bound to a hash map (which is why you get the illegal argument exception): {:report-id 3}

oh…
So it should be?

(let [{:keys [org-id uid]} (get-in context [:request])
           db (get-in context [:request :system :db])
           id (get-in context [:request :path-params :id])
           {sort :sort :as params} (context :kebab-params)
           {:keys [filename data]} (p/download-chatrooms db
                                                         org-id
                                                         uid
                                                         (read-string id)
                                                         :report-id
                                                         3)]

That would match the (successful) call from the REPL, yes.

There’s no error now but the postman just says 200OK no output

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.