This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-10-11
Channels
- # announcements (4)
- # babashka (50)
- # beginners (45)
- # cider (12)
- # clara (1)
- # clj-commons (6)
- # clj-kondo (3)
- # cljdoc (3)
- # cljs-dev (44)
- # clojure (19)
- # clojure-europe (15)
- # clojure-france (1)
- # clojure-nl (13)
- # clojure-portugal (4)
- # clojure-uk (6)
- # clojurescript (3)
- # conjure (3)
- # cryogen (10)
- # datomic (23)
- # emacs (9)
- # fulcro (12)
- # graalvm (1)
- # graphql (2)
- # introduce-yourself (2)
- # jobs (4)
- # jobs-discuss (9)
- # lsp (2)
- # pathom (3)
- # polylith (23)
- # portal (1)
- # reagent (14)
- # releases (4)
- # remote-jobs (3)
- # shadow-cljs (1)
- # sql (8)
- # tools-build (7)
- # tools-deps (10)
- # xtdb (7)
Has anyone added Okta SSO to a Clojure (not -script) app before here? There’s a ring middleware out there, but it’s unmaintained.
Given that it is an oauth provider, I like to keep the login handling out of my app and run https://oauth2-proxy.github.io/oauth2-proxy/ in front of my app. YMMV 🙂
Hello! What is the best (= least work-intensive? easiest to understand and maintain?) way to create a wrapper for a Java object implementing an interface, where I want to modify one method and pass through the rest unchanged? It is https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/javax/sql/DataSource.html, which has about 10 methods, and https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/Connection.html, which has many. The options I can think of:
1. Use IntelliJ to generate a wrapper class for the interface and use that. Likely the least amount of work.
2. Use proxy
to wrap the actual class (HikariDataSource in this case) and only override the fn I need (be default it calls the superclass method, if no def provided) - not as "clean" but little work. I could do the same for Connection, though that binds me to the internals to Hikari (on the other hand, this particular impl. detail - the conn. class - is unlikely to change)
3. Bite the bullet and use reify
on the interfaces, implementing all the methods
4. Write a macro that produces the reify from 3. using reflection
Thoughts / experiences?
Background: I want to run an extra statement whenever I check out a conn from a pool and return it back.
I’m not sure what you mean by “generate a wrapper”. If the class is not final, can’t you just create a subclass and override the one method you’d like to change? Edit: Did not see that you get an existing object, sorry
Wrapper = I want to implement the https://refactoring.guru/design-patterns/decorator, to modify the behavior of an object I have and that is solely used through the interface(s) it implements. I could create a subclass, that is what 2. is about, though using clojure rather than Java, and an ad-hoc generated class rather than once defined more statically.
bite the bullet on 3. is my approach if you don't use proxy+. At least then its explicit
Or do something completley terrible like
(defn emit-method-wrapper
[o {:keys [name return-type parameter-types]}]
(let [params (map
(fn [t]
(cond-> (gensym)
(not= t 'jva.util.Object) (with-meta {:tag t})))
parameter-types)]
`(~name [g# ~@params] (. ~o (~name ~@params)))))
(defn emit-wrap
[c interfaces decls]
(let [g (group-by first decls)]
(concat
(for [i interfaces
:let [clazz (Class/forName (str i))
{:keys [members]} (clojure.reflect/reflect clazz)]
{:keys [flags name] :as member} members
:when (and
(flags :public)
(not (flags :static))
(get member :return-type)
(not (g name)))]
(emit-method-wrapper c member))
decls)))
(defmacro wrap-interfaces
[c interfaces & decls]
`(reify ~@interfaces
~@(emit-wrap c interfaces decls)))
(wrap-interfaces
m
[java.util.Map]
(get [this k] :aha!))
Obviously this is an incomplete and fragile implementation but you get the ideaThank you all! I will look at proxy+
Hm, proxy+ isn't helping, it still requires that I implement all the methods, it seems...
intellij does it all the hard work, you have 1 ugly class no big deal. I made TimedStatement this way wrapping PreparedStatement.
Thanks, Colin. I thought that might be the simplest way forward...
I ended up making a defdecorator
macro (since my team did not want any Java in our source code) https://clojurians.slack.com/archives/C06MAR553/p1634040345143900
Yes but my team does not want to add java sources.
reflection might get problematic with the new java module rules