4

Running Leiningen 2.3.4 on Java 1.7.0_21 Java HotSpot(TM) 64-Bit Server VM

I am having trouble connecting to an nREPL server.

I setup a new project using lein new luminus, and then added a dependency to drawbridge ([com.cemerick/drawbridge "0.0.6"]).

I added a handler route for the repl as follows (based on https://devcenter.heroku.com/articles/debugging-clojure):

(def drawbridge-handler
  (-> (cemerick.drawbridge/ring-handler)
      (wrap-keyword-params)
      (wrap-nested-params)
      (wrap-params)
      (wrap-session)))

(defn wrap-drawbridge [handler]
  (fn [req]
    (if (= "/repl" (:uri req))
      (drawbridge-handler req)
      (handler req))))

And added wrap-drawbridge to my middlewares.

I then start the server using

lein ring server-headless

The connection seems to be working well because performing a GET request on http:localhost:3000/repl yields a response: ["[\n","\n]"]

But I can't connect to the REPL:

> lein repl :connect 0.0.0.0:3000/repl
Connecting to nREPL at 0.0.0.0:3000/repl

And, after some time:

SocketException The transport's socket appears to have lost its connection to the nREPL server
    clojure.tools.nrepl.transport/bencode/fn--4287/fn--4288 (transport.clj:95)
    clojure.tools.nrepl.transport/bencode/fn--4287 (transport.clj:95)
    clojure.tools.nrepl.transport/fn-transport/fn--4261 (transport.clj:42)
    clojure.core/binding-conveyor-fn/fn--4107 (core.clj:1836)
    java.util.concurrent.FutureTask$Sync.innerRun (FutureTask.java:334)
    java.util.concurrent.FutureTask.run (FutureTask.java:166)
    java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1145)
    java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:615)
    java.lang.Thread.run (Thread.java:722)
Bye for now!

Am I missing something?

Edit:

Added the following logging code to my handler:

(defn wrap-drawbridge [handler]
  (fn [req]
    (if (= "/repl" (:uri req))
      (do (println "IN REPL ")
        (drawbridge-handler req))
      (handler req))))

When connecting with lein repl :connect http://localhost:3000/repl as suggested, I see the line IN REPL being printed in an infinite loop, on the servers console.

jd.
  • 4,057
  • 7
  • 37
  • 45
  • For an up-to-date example of Drawbridge server & client check out [nREPL over HTTP(s) with Drawbridge in 2020](http://localhost:3000/nrepl-over-http-with-drwabridge-in-2020/). This is still a top hit when looking for Drawbridge so it might be good to point people to a more current code example :-) – Jakub Holý Dec 12 '19 at 10:36

3 Answers3

5

Not really a direct answer, but I've found that I was not approaching this problem the right way.

Luminus creates a project-name.repl namespace that should be used for interactive development.

I found that I could do what I wanted by adding to my project.clj

:repl-options {
                  :init-ns project-name.repl
                  :init (start-server)}

And then simply starting the server with lein repl.

Much simpler than setting up an nREPL middleware!

jd.
  • 4,057
  • 7
  • 37
  • 45
1

Have you made sure that there actually is a request entering your server (e.g. by printlining)?

However, my first guess would be that lein repl :connect behaves differently depending on whether you pass it an IP/Port pair or a fully-qualified URL. Since drawbridge seems to make nREPL accessible via HTTP I'd suggest you try:

lein repl :connect http://localhost:3000/repl
xsc
  • 5,983
  • 23
  • 30
  • I added some logging and it does seem to connect, but is looping almost like in an infinite loop (see my edit above). – jd. Nov 20 '13 at 15:52
  • From the README: `Drawbridge is compatible with Clojure 1.2.0 - 1.4.0.`. Not sure if that still holds but it could definitely indicate that the version of nREPL `drawbridge` is supposed to work with is not fully compatible with the client included in Leiningen. So, what happens when you try to connect to your server using an older version of Leiningen? And when you switch to Clojure 1.4.0? – xsc Nov 20 '13 at 19:25
  • That sounds like a loss. Maybe I'm doing this the wrong way. Is there a way to connect a REPL to running server (using ring/compojure) for live debugging? – jd. Nov 20 '13 at 20:24
0

You need to add wrap-drawbridge at the first place in you middleware list.

If you do something like that

(def app (-> #'all-routes
               wrap-drawbridge
               ...
               ...
               ...
               ))

It works like a charm.