Configuring MongoDB in Clojure Luminus Web Framework
I am having trouble setting up a MongoDB database inside a Luminus project. This should be pretty straightforward considering lein templates: https://github.com/yogthos/luminus-template . Typing lein new luminus <name> +mongodb
will give you the default mongoDB setting, which is a file: src/app-name/db/core.clj
To start the server, enter lein ring server
which should open the web browser and point it to by default localhost:3000
.
The default home page will be displayed and for me it tells me "MongoDB setup is required". It informs me that I can set it up in the same file: src/app-name/db/core.clj.
I have tried several different things, but what I am currently trying and what makes sense to me is the following:
(defonce coll "collection-name")
(defonce db (let [uri "mongodb://127.0.0.1/db-name"
{:keys [conn db]} (mg/connect-via-uri uri)]
db))
Unfortunately, when I connect my browser, I still get the same "MongoDB configuration required" message. I have also tried using CURL and various HTTP routes defined in my application, which fail on the database. However, the strange thing is that this works in the REPL.
EDIT: To be clearer, here's an example in the REPL:
clj-project-name.db.core> (get-replies 2)
["mew-mew" [1.0 "hello"]]
In the code, I have the following snippets:
(ns clj-project-name.routes.home
(:require [compojure.core :refer :all]
[clj-project-name.layout :as layout]
[clj-project-name.util :as util]
[clj-project-name.db.core :as project-db]))
(defn get-replies [id] (mc/distinct db coll "replies" {:_id id}))
(GET "/user" [id] (user-page id)) ; defined in home-routes inside namespace clj-project-name.routes.home
(defn user-page [& [id]] ;defined inside namespace clj-project-name.routes.home
(layout/render "user.html"
{:id id
:replies (projectl-db/get-replies id)}))
<h1>User {{id}} page</h1> ; part of the HTML template
<p> <b>Replies:</b> {{replies}} </p>
Here is the page loaded in the browser:
As we can see, the list is replies
empty when it should be ["mew-mew" [1.0 "hello"]]
, as we saw in the REPL.
EDIT: Another oddity is that only when the browser is loaded after input lein ring server
, I can see the following output from mongodb
in the terminal:
2014-12-02T21:16:57.941-0500 [initandlisten] connection accepted from 127.0.0.1:38854 #28 (5 connections now open).
What else can I do to connect to MongoDB? Thanks for your help.
source to share
I followed your steps and created a new Luminus project using the luminus template.
I also looked into the generated code I found, this default home page is 100% static. Thus, it shows MongoDB Configuration is Required
whether it is actually configured or not:
(defn home-page [] (layout/render "home.html" {:content (util/md->html "/md/docs.md")}))
In other words, it just renders resources/public/md/docs.md
in .html
and shows it, always the same html page.
As far as your configuration is concerned, this is absolutely fine.
As far as your page is concerned user.html
, the actual problem is that id
in the user-page
route is a string, and _id
in your database is a number. So instead, (get-replies 2)
you call (get-replies "2")
. Try using string _id
s, or parse your input id
with read-string
function or Long/parseLong
first:
(defn user-page [& [id]]
(layout/render "user.html"
{:id id
:replies (-> id
Long/parseLong ; throws NumberFormatException
project-db/get-replies)}))
I would recommend using string _id
s because it is easier and safer than parsing strings in numbers.
source to share
Perhaps because you are using defonce
instead def
, these vars ( coll
and db
in the namespace app-name.db.core
) have not been reloaded. Try to stop the lane process and start again with:
lein do clean, ring server
When you're done with that, consider the next component
workflow step :
source to share
There are too many moving parts in your application, and you have given us access to too few of those moving parts for us to clearly identify what is bothering you. All we can do is provide general debugging advice.
- Make sure you have a clean environment. Turn off your REPL, your web server, maybe even your editor. Reboot everything in order and remember this order.
- I see a bunch of oddities in the code of your post, but I can't tell if they are from your codebase or a product of your copying the code to the question. Which project is l -db? Is
get-replies
in the same namespace asuser-page
or not? Make sure you are not referencing the old definitionget-replies
in your replica. - In what order are things defined in a namespace
db
? Perhapscoll
,db
orget-replies
are in the wrong order and not working safely. - You say it
(get-replies)
works in repl. What doesuser-page
the REPL say ? - You say you see the message "MongoDB configuration required", but I don't. Is it from the call server displayed in the browser or in the browser console?
- What happens if you switch the current value definition
replies
to an integer value? For example. insideuser-page
, return the card{:id id, :replies 5}
instead of callingget-replies
. The answer to this question will help narrow down the question from which the problem arose. - Can you deduce
user-page
from the equation and return the string fromget-routes
? Once you do that, what happens if you returnget-replies
(again, withoutuser-page
)?
The principle here, as with all debugging, is to reduce the problem to the smallest number of chunks that reproduce the problem. Right now, you have a lot of pieces that could be a problem and you are only showing us glimpses of them. Help yourself by removing items until you have the smallest possible sequence of calls causing the problem. When asking for help or reporting a bug, show people a minimal example so they don't have to go through your entire codebase. More importantly, the copied version of the code (which you produce for people to help debug) might not even have a bug!
You can also debug in the other direction by starting from a new working repository and adding items from the paged repo one by one until an error occurs. This can be useful when learning about the ins and outs of a new structure like Luminus.
source to share