Fork me on GitHub
Clark Urzo00:08:12

So I'm starting a server with lein ring server-headless but there's something going wrong when I connect to the accompanying nREPL server via lein repl :connect localhost:<port>

Clark Urzo00:08:02

I'm getting this error:

$ lein repl localhost:38875 
Connecting to nREPL at localhost:38875 
Syntax error (ClassNotFoundException) compiling at (form-init5283084375133054559.clj:1:82). 
#object[clojure.lang.Namespace 0x2d4efbbb "user"] 
Error loading namespace; falling back to user 

Clark Urzo00:08:13

What's happening here?

Clark Urzo00:08:58

For reference, here's my project.clj file:

(defproject hello-compojure "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url ""
  :min-lein-version "2.0.0"
  :dependencies [[org.clojure/clojure "1.10.0"]
                 [org.clojure/tools.nrepl "0.2.13"]
                 [nrepl/drawbridge "0.2.1"]
                 [compojure "1.6.2"]
                 [ring/ring-defaults "0.3.2"]]
  :plugins [[lein-ring "0.12.5"]]
  :ring {:handler hello-compojure.handler/app
         :nrepl {:start? true}}
  {:dev {:dependencies [[javax.servlet/servlet-api "2.5"]
                        [ring/ring-mock "0.3.2"]]}})


can you create a git repo and push the whole project somewhere (eg github) and post a link to it?


not that i expect i'll be able to help


but seems like it'd be useful

Clark Urzo00:08:47

To be fair, I literally just ran the default compojure template

Clark Urzo00:08:54

But maybe I'm missing something here


says i need to sign in or sign up before continuing


cloned, trying lein ring server-headless


worked for me. i see "Hello World" at localhost:3000


have you tried squinting your eyes and looking at the terminal with your head slightly turned away?


that's what i did


does git status show anything not committed and pushed?

Clark Urzo00:08:50

I mean, try doing a defroute

Clark Urzo00:08:59

It's not being found is what i'm saying

Clark Urzo00:08:36

so i think compojure isn't being loaded properly


oh, woops, i forgot that part, sorry. i'll try that


so the sequence is: 0. lein ring server-headless 1. lein repl :connect localhost:PORT? where does PORT come from? i was expecting to find it in the output of step 0


oh, there it is, i missed it


ok, confirmed, i see the same issue

Clark Urzo01:08:36

I'm thinking it could be an unresolved issue or something but my google-fu is failing me


i am also not sure


i was able to do a plain "lein repl" and that seemed to work

Clark Urzo01:08:28

Yes, but it just starts another nREPL server


The problem is that lein-ring uses an older version of nREPL (`org.clojure/tools.nrepl "0.2.3"` per which is not compatible with modern nREPL (which is nrepl/nrepl "0.6.0" at this point).


My advice: do not use lein-ring. Learn to start your server via the -main function and from a regular lein repl.


(seriously, most of these plugins meant to "make life easier" just end up making life harder)


And it is compounded here because the compojure template for Leiningen doesn't give you a proper "application" with a -main function 😞


@signup867 Here's the Compojure template project updated with a proper -main and updated project.clj and handler.clj files:


See the README for how to start a server from the REPL, and how to run the project without a REPL.


I removed lein-ring, added the full ring/ring dependency, added a :main entry point (that's all project.clj). In handler.clj I added a -main function.


The key is ring.adapter.jetty and the run-jetty function. Calling it with just {:port 3000} will block -- until the server exits, i.e., until you kill the process. Calling it with {:port 3000 :join? false} will kick off the server in a background thread.

Clark Urzo02:08:25

Oh wow. Thank you so much @seancorfield!

Clark Urzo02:08:29

I love this community so much


LMK if you have any Qs about the changes or the process.


You may also find helpful as a way to explore Compojure/Ring with Component, Selmer, and next.jdbc to have a full but small web app with a database.


Worth mentioning here for everyone curious about REPL-Driven Development: Eric Normand has made two of the lessons in his excellent RDD course free for a short time (in addition to the overview which was always free): * -- what is "flow" and why it is important * -- a look at an idealized development workflow and how it maps onto RDD I highly recommend his paid course (there are several others that make it worth having a monthly membership, even if you only sign up for a month).


thanks for sharing this, Sean! this is the course i really wanted out of his subscription. would you recommend this particular course for one who already knows a thing or two about repl-aided development and already established a workflow of his own?


Yes, I found it valuable, and I've been doing this for a decade.

👍 3

I'm probably going to take the three property-based testing courses at some point.


(making sure you have a smooth, fast REPL workflow is the best investment you can make in becoming an effective Clojure programmer)


I’ve edited my REPL session to make things simpler, so don’t mind the pointlessness of my code or usage of ->>

  [132 132]
  (reduce +)
  (mod 11))
This produces 264 which. (mod 264 11) => 0 which is expected, but I was wondering if it were possible to use mod in the thread-last macro? For instance, I can do:
  [132 132]
  (reduce +)
  (= 264)) => true
But mod doesn’t seem to work that way. Is that truee?


@skendrick366 Thread last would put 264 as last argument so you would end up with (mod 11 264) You can use an anonymous function in the threading though: #(mod % 11)


I have a spec that uses a generator referred from another library for testing. Is there a simple way to disclude the generator from our production build (short of having a test-spec and prod-spec for the same entity) so that we can use spec for validation without having to pull in the generator's dependency?


you can dynamically load the generator from the other library


you set the generator to be something like (fn [] ((resolving-require 'some.other.lib.namespace/generator))))


I forget if it is resolving-require or requiring-resolve


the way I remember it is if the verb were require, the thing to resolve would be ambiguous or undecidable


when the verb is resolve, the rest is trivial to determine

Justin Roche21:08:28

does anybody do tutoring here? I am confused about the build chain for a template.


I'm trying to work out how to wrap a common layout around page content using hiccup and don't understand what I'm doing wrong. A working example would really help, but I haven't found one yet. Here are stripped down versions of the handler functions.

(ns telo.request-handler
  (:require [ring.util.response :refer [response]]
            [hiccup.core :refer [html]]
            [ :refer [html5 include-js include-css]]
            [hiccup.element :refer [link-to]])

(defn layout

(defn home
   (layout[(html [:div.container
                  [:h1.display3 "Hello there!"]])
Here's the html this is returning, the intended content is missing: