Pleased to announce my first Clojure library!


I am pleased to announce that my first Clojure library is out!

With this lib I tried to embrace the concept of Clojure (composability, separation of concerns), so it does one things: Get an available TCP port with some options. :slight_smile:

It also allowed me to experiment with setting up tests, deploying on Clojars with tools.deps, etc.
The experience was great.

I’m open for reviews and suggestions.



I’m not sure if you’re aware that you can specify :port 0 and the Jetty adapter will find a free port, much like nREPL does:

(! 751)-> clj -Sdeps '{:deps {ring/ring {:mvn/version "RELEASE"}}}'
Clojure 1.10.2
user=> (require '[ring.adapter.jetty :refer [run-jetty]])
2021-02-25 10:38:12.542:INFO::main: Logging initialized @4306ms to org.eclipse.jetty.util.log.StdErrLog
user=> (run-jetty (fn [_] {:status 200 :body "Hello!"}) {:port 0 :join? false})
2021-02-25 10:38:21.375:INFO:oejs.Server:main: jetty-9.4.36.v20210114; built: 2021-01-14T16:44:28.689Z; git: 238ec6997c7806b055319a6d11f8ae7564adc0de; jvm 15+36
2021-02-25 10:38:21.413:INFO:oejs.AbstractConnector:main: Started ServerConnector@cdb2d95{HTTP/1.1, (http/1.1)}{}
2021-02-25 10:38:21.414:INFO:oejs.Server:main: Started @13178ms
#object[org.eclipse.jetty.server.Server 0x1a2bcd56 "Server@1a2bcd56{STARTED}[9.4.36.v20210114]"]
user=> (seq (.getConnectors *1))
(#object[org.eclipse.jetty.server.ServerConnector 0xcdb2d95 "ServerConnector@cdb2d95{HTTP/1.1, (http/1.1)}{}"])
user=> (map #(.getLocalPort %) *1)

I’ve used a trick like that with the Socket Server REPL which also accepts port zero and then you can query for the port it selected: dot-clojure/deps.edn at develop · seancorfield/dot-clojure (

  ;; - start a Socket REPL on an available port, and display that port:
  ;; - specify -r as well if you want a repl
  :socket-zero {:jvm-opts ["-Dclojure.server.repl={:port,0,:accept,clojure.core.server/repl}"]
                :main-opts ["-e" "(.getLocalPort,(get-in,@#'clojure.core.server/servers,[\"repl\",:socket]))"]}

This is really nice, but one small issue: Passing an argument like {:port 80} throws if it can’t assign that port, due to the (next port) form on line 31: Don't know how to create ISeq from: java.lang.Long.

1 Like

No I was not aware of that, although I should have guessed it since this is operating system level behavior. At least for Unix OS.

So thanks for the information!

Knowing this, I guess it will allow me to simplify my library.
I am planning a fallback system for the next version.
In this way we can specify a port in the reserved range (tcp 80, 443 for eg.) and fallback to a random one if a “permission denied” error on a development machine for example.

Thanks for your feedback!
I’ll fix it in the next release.

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