Fork me on GitHub
Mikhail Turilin02:06:36

Hey folks, is anybody using aleph? Any thoughts on whether the project is still alive? I see that the last commit is more than 1 year ago.


@mikhail Clojure favors stability and for libraries to be focused, so a library can be "done" and not need constant changes, like you'll see in a lot of other languages.


I see quite a few people talking about #aleph (there's a dedicated channel here for it) so it is definitely used, in production. I don't know how widely used it is, compared to other similar things in Clojure.


Zach commented recently on an issue opened about the lack of updates


(I suspect if I was an Aleph user, I would have stepped up to help maintain it by this point, as I did with several other projects that we relied on at work -- but then it's also true that when we stopped using a project at work, it became much harder for me to justify spending time on it, and I had to find another maintainer -- that was CongoMongo, and we stopped using MongoDB)

Mikhail Turilin03:06:43

Thanks for the detailed reply! Based on the comments of the author aleph is looking for a new maintainer and probably not a great choice for new projects due to uncertainty.


@mikhail I would say that Aleph is suitable for a very specific type of application. I've been doing Clojure in production for nearly a decade and not needed anything as specialized as Aleph. What sort of app are you looking at using Aleph for?

Mikhail Turilin04:06:18

I’m looking for a general purpose http server/framework based on some modern architecture. I don’t need millions of requests per second. However, since many modern frameworks give you non blocking IO almost for free, I don’t see why I should not have in Clojure.

Mikhail Turilin04:06:40

I thought the way to get NIO / Netty in Clojure is aleph.

Mikhail Turilin04:06:47

For a baseline, if I was using dotnet, I would get Kestrel (MS analog of netty) as a default web server.


(you may have some concerns about the maintenance status of that too, but we used it in production for a while and were very happy with it -- but the lack of New Relic support was a big issue for us, so we switched back to embedded Jetty)

Mikhail Turilin04:06:37

Will take a look! Thanks!

Mikhail Turilin04:06:19

I’m curious why so many important Clojure projects are looking for maintainers. Do you feel like it’s a trend?


Which other "important Clojure projects" have you encountered that are looking for maintainers? I don't see that with any of the libraries I use in production really.


I think http-kit's readme mentions they are looking for maintainers


I think that in the early days of Clojure there were a lot of somewhat exotic, unusual projects that got started and then ultimately didn't get a lot of traction. But there's plenty of well-maintained mainstream stuff.


@andy.fingerhut Yeah, I mentioned that above,


Sorry, missed that. Perhaps Mikhail was seeing two for two, and wondering.


The only reason we stopped using http-kit was that New Relic don't support it properly (and I spent some time working with NR on that but, ultimately, it's just too niche for NR to care).


I’ve used http-kit for several projects and haven’t had any issues


Yeah, ironically the reason we started using http-kit in the first place was that we were seeing random thread death exceptions with Jetty under load and because both were Ring-compatible, it was trivial to try out a bunch of different servers...

Mikhail Turilin04:06:17

Sorry for the generalization. I was looking for NIO web server and both that I found were looking for maintainers.


...and those thread death issues got fixed in Jetty by the time we switched back 🙂

Mikhail Turilin04:06:09

It’s funny that Jetty 1.0 was developed in 1995 and it’s still going!


It's pretty much the default for folks in Clojure because it comes with Ring 🙂


I have this to list all keywords defined in my program:

(let [f (.getDeclaredField clojure.lang.Keyword "table")]
                                   (.setAccessible f true)
                                   (map #(.get %) (vals (.get f nil))))
Can I somehow filter the keywords to get only those defined in a given namespaces (such as only defined in my code not dependencies)?


the registration of keywords doesn't track the active / source ns, so the best option is to use a third party analysis tool and extract keywords in fact, the code to call read on every file in a tree and then tree-walk to find all keywords should be pretty easy to write - likely less than 20 lines total counting the ns form for the new ns


this runs quickly even on a large project

(require '[ :as io])
(import ( PushbackReader))

(defn read-all
  (with-open [i (PushbackReader. reader)]
    ((comp doall take-while)
     (complement #{::done})
     (repeatedly #(try (read i)
                       (catch Exception _

(defn directory-keywords
   (for [f (file-seq (io/file dir))
         :when (.endsWith (str f) ".clj")
         ; file-forms (read-string (str "[" (slurp f) "]"))
         file-forms (read-all (io/reader f))
         kw (filter keyword? (tree-seq coll? seq file-forms))]


the alternate version of file-forms is hacky, but also means not needing the read-all function


hmm - it's not quite right as it doesn't do namespaced keywords correctly :/ - I think you need something like tools.analyzer


FWIW, I've been using http-kit for several years now, in a production system where people really care about downtime and problems.


As to well-maintained stuff, I think the more we adopt the spirit of "if you want it maintained, become a sponsor", the better off we'll be. As my business is growing, I dedicate more and more money to sponsoring Clojure libraries. Both because I thing is the right thing to do, and because I want to see a mature and stable ecosystem.

☝️ 9

maybe better suited for #community-development ?


@U06BE1L6T It was a response to an earlier question about important Clojure projects looking unmaintained / looking for new maintainers, so it was fine here (although perhaps that discussion should have gone to a thread).


#community-development is intended for discussions around the "people" side of things, for the most part, rather than the software side so this discussion is drifting in that direction 🙂

Michael J Dorian14:06:35

Hey, I've got a webserver with a dataset and I want it to display graphs to a page. Anyone have a favorite tool for this sort of thing?

Michael J Dorian14:06:14

Thank you! This looks very interesting

Michael J Dorian14:06:06

Interesting! This looks perhaps more enterprisey than I was thinking though. I have a silly genetic simulation game running and I just want to see what genomes are popular with the virtual plants and animals. On first glance this looks like it would involve logins

Daniel Tan14:06:13

it has a nice gui and it’s relatively simple to start with

Daniel Tan14:06:35

compared to more enterprisy stuff like tableu


And is free to use


(❤️ metabase)


metabase is great :) (and it's oss & in clojure)

Daniel Tan14:06:04

I have problem with ring, or maybe it’s just java. I’m saving images to a ring webserver, under a folder in resources, however, I can’t seem to serve the images later on through ring (in production, jar )? Anyone done this sort of stuff before?


there's a very common newbie trap of using the wrap-file ring middleware, which works locally and not from a jar


the solution is to replace it with wrap-resources


tl;dr java isn't unix, only files are Files


oh - so it's an actual folder on disk, I missed that


you are recreating wrap-file in that code, it takes an optional base directory argument


also that code is a security hazard, for example if ../../../ can be injected into the file path you can serve up files that the user should not be able to access


also, as an alternative to wrap-file with a path arg, you can use wrap-resource and add that "resources" runtime directory to your classpath at startup both of these options will serve your content and avoid the security implications of arbitrary path lookups


@U01458A7CBX I would also say it's an antipattern to store uploaded files in the resources folder. This should either be in /tmp/ if you don't need them after the request or in a dedicated folder on disk with correct rights set that can be backed up, etc.

Daniel Tan01:06:50

my file names are randomly generated (not user generated) so i don’t have that issue, but i do see your point

Daniel Tan01:06:16

Yep, i moved them out to their own dedicated folder

Michael J Dorian14:06:41

Thanks everyone simple_smile

Daniel Tan15:06:31

3hrs wasted when i coulda read the set-body code in ring…

Lone Ranger19:06:19

Getting murdered trying to setup logging on a project. Any suggestions on diagnosing this?

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/jay/.m2/repository/org/slf4j/slf4j-log4j12/1.7.30/slf4j-log4j12-1.7.30.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/home/jay/.m2/repository/org/slf4j/slf4j-nop/1.7.22/slf4j-nop-1.7.22.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See  for an explanation.
SLF4J: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. 
SLF4J: See also  for more details.
Execution error (IllegalStateException) at org.slf4j.impl.Log4jLoggerFactory/<clinit> (
Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. See also  for more details.


add exclusions for the adapters you aren't using.


1) take out slf4j-nop from your project dependencies, 2) take out log4j-over-slf4j


(This is assuming that you are trying to funnel everything to log4j)

Lone Ranger19:06:40

is there a way to globally exclude them properly? (deps.edn)

Lone Ranger19:06:02

I don't really care at this point I just want any logging messages to show up and my application to run at the same time 😅

Lone Ranger19:06:11

not tied to any implementation over the other

Lone Ranger19:06:30

I've tried a few things and it seems I have no idea what I'm doing


paste your clojure -Stree redacting what you need to


the trick to slf4j is to choose your desired backend, then funnel through slf4j all the other logging frameworks that are not your chosen backend


:exclusions in deps.edn go inside the lib coordinate {:mvn/version ..... here}

Lone Ranger19:06:47

using the tree output to suppress the things I'm trying to suppress/exclude?


you'll want to exclude slf4j-nop from datomic-pro


and if you want to use a backend other than log4j12, you'll also want to exclude slf4j-log4j12 from datomic pro

Lone Ranger19:06:24

awesome, thank you 🙏 will give this a shot

Lone Ranger19:06:28

oohhhhh good looks

Lone Ranger20:06:51

yessssss combo of all that, finally a working application with logging. THANK YOU

Purujit Goyal21:06:37

Hey, I am using clj-ssh to ssh into a machine and run some commands, however I am getting this error

sudo: sorry, you must have a tty to run sudo
I know you need to add '-t' option to your ssh command to solve this, I am not able to find how to do this with clj-ssh. Anyone who can help me with this?

Purujit Goyal21:06:31

I am using :in to specify the cmd I want to run

Purujit Goyal21:06:13

I tried adding just :pty true , but that’s still giving the same error


I’m trying to set up a build with deps that adds a couple extra namespaces. These namespaces go to other namespaces and overwrite functions hitting external APIs, idea being adding these will allow less clojure minded to run the program and play with it locally. Issue I’m running into is that just adding them to the paths doesn’t cause them to evaluate. I need to cause them to evaluate in some way. • Running deps with a -e "(require 'mock.namespace)" doesn’t seem to make it eval. • I could create a runner in the added namespace, but it wouldn’t work for running tests/other entry points • Requiring the namespace conditionally is possible, but seems dirty Is there a good way to do this I don’t know about?