Fork me on GitHub
#clojure
<
2022-06-24
>
Otto Nascarella14:06:15

Hi y’all! so, tricky question about protocols, reify…

(ns dog.protocol)

(defprotocol Dog
  (-get-name [this]))


(ns dog.implementation
  (:require [dog.protocol]))

(def doggy 
  (reify dog.protocol/Dog
    (-get-name [_] "Doggy"))

(defn logging-dog [original-dog]
  (reify dog.protocol/Dog
    (-get-name [_]
      (let [name (dog.protocol/-get-name original-dog)
      	(println name)
      	name]))))

(def logging-doggy (logging-dog doggy))

(-get-name logging-doggy) ;; should return name and print it
as usual, contrived example. I have a very similar situation, where I override some behaviour. It works all fine in the REPL and in local dev… when I try to build an uberjar, it says that one of the methods of my protocol is not being implemented….which is not true. Any clues?

Alex Miller (Clojure team)14:06:18

can you fix all the syntax errors in that code. if you then run it, does it exhibit the same problem that you observe in the real code?

cjohansen14:06:07

In situations like this it could also be helpful to restart your REPL, to see if it still works there

Alex Miller (Clojure team)14:06:18

it's most likely an issue with order of compilation, but without knowing more about how you're building the uberjar and the actual issue, it's hard to guess what's wrong

Otto Nascarella14:06:55

hm… that’s a good clue

Alex Miller (Clojure team)14:06:50

the key is that you want the ns with the protocol compiled first

Alex Miller (Clojure team)14:06:45

otherwise it will get compiled twice and you can have instances of the first (dead) class that no longer implement the second (alive) class

Alex Miller (Clojure team)14:06:43

but also, doing top-level def's is something I would avoid as much as possible as they will happen during compilation too, if you're doing that in your actual code

p-himik14:06:20

What could be possible reasons of the same ns being compiled multiple times when building an uberjar?

borkdude15:06:18

This happens in leiningen, if you're using that. A solution there is to just say: :aot [my.main-ns] instead of :aot :all

borkdude15:06:40

Similarly in tools.build: :ns-compile '[my.main-ns]

kanwei15:06:05

Does anyone know how to invalidate ring session cookies? Went through a security audit and even though logout (setting :session to nil) deletes the cookie from browser, someone can technically just save the cookie before logging out and then restoring the cookie after logging out

lukasz15:06:08

My answer to this question is always: how do they get the cookie in the first place? If you're using HTTP only, secure cookies along with correct SameSite attribute - they become quite hard to exfiltrate in the first place.

lukasz15:06:02

That said, if you do need that then you need to move to session handling in the backend and your session cookie should only store session ID. I believe there's a ring middleware/extensions that let's you use Redis for that - then on log out you "simply" delete the session from your session store and the value in the cookie is immediately invalidated

kanwei15:06:08

Yeah, I totally get that it's extremely hard to get the cookie if you don't already have it. Was wondering if there was an easy way to maybe expire the cookie during the logout

lukasz16:06:31

Pretty hard unless you track live sessions somewhere - one small thing is to attach expiration date as cookie value, and renew it on each request. This way if someone steals the cookie (somehow) has a limited window of using it because if they don't it will be past the expiration date - this is in addition to the cookie's own expiry date

Drew Verlee16:06:47

whats the best way to write pretty foramtted (human readable) edn so that you can read it back in?

Drew Verlee16:06:49

edn/read-string doesn't seem to understand "#:mvn{:version "..."}"

Drew Verlee16:06:43

then i guess the question is, how do you write human readable edn to a file?

p-himik16:06:27

If you trust the data, you can probably just use clojure.core/read-string and print it the way you do. If you don't trust the data, you can bind *print-namespace-maps* to false before printing.

🎉 1
Drew Verlee16:06:31

thanks, that works in my case. 🙂 :thumbsup:

👍 2
borkdude21:06:39

The EDN reader should understand these "namespace maps":

user=> (clojure.edn/read-string "#:mvn{:version \"123\"}")
#:mvn{:version "123"}

Drew Verlee01:06:45

We're on an older version of clojure. That might be part of the issue.

borkdude07:06:20

That makes sense

apt23:06:12

Hi folks. How do I dynamically find a var by its name? (because I need its metadata) My failed attempt:

(meta (var (symbol "clojure.core" "assoc")))
I’d like to get the same result as
(meta #'clojure.core/assoc)

1
apt23:06:48

Found it, resolve 🙂

apt23:06:45

Marking as resolved (pun intended)

3
emccue13:06:37

requiring-resolve is a tad more robust depending on your use^

👍 1