How to run/debug compojure web app via counterclockwise (or la clojure) - clojure

I'm trying to write my first web app in compojure. I'm using ccw, and I File-New-Project, Clojure Project and use the "compojure" leiningen template. End up with project.clj looking like
(defproject asdf "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:dependencies [[org.clojure/clojure "1.4.0"]
[compojure "1.1.5"]]
:plugins [[lein-ring "0.8.2"]]
:ring {:handler asdf.handler/app}
:profiles
{:dev {:dependencies [[ring-mock "0.1.3"]]}})
src/asdf/handler.clj looks like
(ns asdf.handler
(:use compojure.core)
(:require [compojure.handler :as handler]
[compojure.route :as route]))
(defroutes app-routes
(GET "/" [] "Hello World")
(route/not-found "Not Found"))
(def app
(handler/site app-routes))
I found I can run this using lein ring server from the command line, but I'm not sure how to run this from eclipse. I'm of course hoping to be able not only to run it, but also to debug it and set breakpoints and such. Is there a way to do this in eclipse? Or, if not, how about IntelliJ/La-Clojure? (I'm a bit afraid of emacs, for now, but maybe if it's super-simple I'd give it a try).
Or, is this just not the typical development process for a compojure app? (If not, what is? Just run lein ring server and pray?)
If it makes a difference this is on Win7.

Here's a recipe that's work great for me while developing Ring applications:
Ensure you have leiningen support properly configured for your projet (do it once if in doubt):
in the package explorer, select the project, and invoke the contextual command Leiningen > Reset configuration
then also invoke the Leiningen > Update dependencies command
you should see a Leiningen Dependencies virtual node in your project, referencing the direct and transitive dependencies of your project
Select the asdf.handler file, right click and then Debug as > Clojure Application
Open the asdf.handler namespace in an editor
With the cursor currently still in the editor, type Ctrl+Alt+N to jump to the REPL and switch the REPL's current namespace to asdf.handler at the same time
Start the app by typing (app) + Enter (or Ctrl+Enter if your cursor is not at the end of the line)
You can now navigate between the editors and the REPL.
To send editor content to the REPL, select it, and hit Ctrl+Enter
If you hit Ctrl+Enter without a selection, the whole 'top level expression' (e.g. a defn) will be sent to the REPL
To resend the whole file to the REPL, type Ctrl+Alt+S
the whole list of keyboard shortcuts specific to CCW is here: http://code.google.com/p/counterclockwise/wiki/EditorKeyBindingsFeatures
Note that a future version of Counterclockwise will integrate a little bit more with Leiningen 2, but as it currently stands, the very nature of developing ring applications make it not so painful to bootstrap things as described above, IMHO

You can run Compojure/Ring apps on IntelliJ IDEA and La Clojure with the following steps:
Generate pom.xml from leiningen's project.clj using lein pom command.
Import maven project with IntelliJ IDEA as usual. You might want to make sure that you have Clojure jar in classpath.
Once the project is loaded, you can start Clojure REPL using Tools -> Start Clojure Console.
To load a Clojure file to REPL, select Tools -> Clojure REPL -> Load file to REPL.
After that, to start a Ring app you can just load a Clojure file that invokes ring.adapter.jetty/run-jetty.
The code to run a simple route on http://localhost:4004/ would look like this:
(require 'compojure.core)
(require 'ring.adapter.jetty)
(ring.adapter.jetty/run-jetty
(compojure.core/routes (compojure.core/ANY "/" [] "Hello world!"))
{:port 4004 :join? false})
:join? option is important, if it would be set to true (the default), the REPL would not accept more commands. Your routes will usually be more complex and compojure.core/defroutes or other means should be used.
You can put such file in test path, so it wouldn't be loaded when running the project outside of IDEA.
If Clojure facet is not added to your module, you can add it in File -> Project Structure -> Modules.
A complete sample (with jetty reloading) is available here: https://github.com/tlipski/ganelon-demo - development is done with IDEA and real site runs on Heroku: http://ganelon.herokuapp.com.
Debugging Clojure apps run with the technique above is possible as well - you just have to:
Create Remote debugging Run profile in IntelliJ IDEA
Add apropriate JVM options from a profile above (e.g. agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005) to REPL settings in File -> Project Structure -> Modules -> [your module] -> Clojure facet -> JVM Arguments field.
Start REPL with Tools -> Start Clojure Console.
Start Remote debugging profile.
After that, you can add breakpoints, inspect variables, etc.

Related

Can I start Gorilla REPL from an uberjar?

I play with this great Gorilla REPL powered project ( https://bitbucket.org/probprog/anglican-examples/ to be specific), and want to use it under certain restricted circumstances.
Is there a way to produce an uberjar that can be started using only a JVM?
Well, I know how to create an uberjar for this project, but can I start a Gorilla REPL from it? If not what do I have to add and how do I start it?
EDITED Note on Juraj's answer:
I added a start file src/gorillaproxy/gorillaproxy.clj with the following content:
(ns gorillaproxy.gorillaproxy
(:use [gorilla-repl.core :only [run-gorilla-server]])
(:gen-class))
(defn -main
[& args]
(run-gorilla-server {:port 8990}))
Then I added [gorilla-repl "0.4.0"] to the dependency list (in project.clj), and the line
:main gorillaproxy.gorillaproxy
In that way the uberjar started the Gorilla REPL, and when I put the worksheets (and data, resources, .. if needed) into the same directory, everything worked fine.
Gorilla is typically run via the lein-gorilla plugin and thus isn't a part of an uberjar.
If you really want to create a bundle containing gorilla repl dependencies, then you need to add it this capability manually to your project.
The question is why would you want to do that.
Do you want to distribute these samples to somebody else? If that's the case, you'll still need to have all those worksheets in the current directory from where your uberjar is run because that's how gorilla repl discovers worksheets.
You can look at lein-gorilla source code to see how gorilla repl can be started.
I'd then at the same code to your project (create new src/core.clj file or whatever) and configure it in your project.clj as :main.
You'll also need to add gorilla-repl as a dependency to your project.clj
Notice however, that you'll need to run that uberjar from a directory where your anglican worksheets are (or a parent directory of such a directory).

access library functions in leiningen REPL

For the development of a library I started from a lein project, invoked like so:
lein new mylib
if I call lein install now, I can access my library in other projects. But trying to immidiately test the functions I wrote failed:
lein repl
...
(dir mylib.core)
Exception No namespace: mylib.core found clojure.core/the-ns (core.clj:4008)
Do I have to add something to the project.clj file maybe?
In order to use a library you must cause the code to be loaded - that it be on the classpath is not sufficient.
You can do this easily in an ns declaration in a file of course, but in the repl it can be easier to use (require '[my-lib.whatever :as w]) after which one can call (w/foo) (w/bar) etc. as expected. You can also use (in-ns 'my-lib.whatever) in order to switch to the namespace, but this will not give you a good result unless you have previously used require or use or load-file etc. to get the definitions first.
Let's say you created a new library named clj-foo.
% lein new clj-foo
Start your repl.
% cd clj-foo
% lein repl
In the repl, load the main entry point to your library and switch to its namespace.
(load-file "src/clj_foo/core.clj")
(ns clj-foo.core)
Now you're in the clj-foo.core namespace, make sure to add back in the repl ns to get things like doc available.
(use 'clojure.repl)
That's it. You're all set to start calling functions in your library. Note that other library files will be available from the clj-foo.core namespace if they were loaded by namespace declaration at the top of clj_foo/core.clj. If not, then you'll need to invoke load-file with their path as well.
If you make changes in core.clj. You can invoke load-file again to pick up the new code. As you progress, you can use cider to facilitate loading of individual functions and files. But that's for another question. :)
You need to add a dependency to use your library from another project. To do this add a vector (a tuple-2) to the vector that is the value of the :dependencies key in the project.clj file. Here's an example:
:dependencies [[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.170"]
[org.clojure/core.async "0.2.371"]
[default-db-format "0.1.0-SNAPSHOT"]
[com.andrewmcveigh/cljs-time "0.3.14"]]
My own local library is called default-db-format. Its really no different to adding a dependency for com.andrewmcveigh/cljs-time.
As you say you can already do this, but are having trouble getting a REPL connection to the project of the library itself. When you go (in-ns 'some-path), you need the single quote in front of some-path. Note that some-path is a different thing to the name of your library.
Rather than use lein repl you can use the figwheel repl - if your project is setup with figwheel. My library has only one entry point and that is lein figwheel devcards. After that I had no problem going to a namespace and trying out a function:
cljs.user=> (in-ns 'default-db-format.core)
nil
default-db-format.core=> (check 1 2)
As noisesmith mentioned having a REPL in your IDE is the best setup. No fiddly typing just bring up pre-configured REPLs (per namespace) with the click of a button (or keystroke). Figwheel/Cursive setup instructions here.
I was also facing the same issue with the following configuration:
Leiningen 2.9.0 on Java 1.8.0_201 Java HotSpot(TM) 64-Bit Server VM
My file looks like this, and from the repl I desired to invoke the foo function
(ns cljtest.test
(:gen-class))
(defn foo [input]
(assoc {} "a" 123))
Both these approaches worked fine for me on the repl.
1)Switch to the appropriate name space:
cljtest.core=> (in-ns 'cljtest.test)
#object[clojure.lang.Namespace 0x90175dd "cljtest.test"]
cljtest.test=> (foo nil)
{"a" 123}
cljtest.test=>
2)Require the appropriate name space:
cljtest.core=> (require '[cljtest.test :as test])
nil
cljtest.core=> (test/foo nil)
{"a" 123}
cljtest.core=>

How can I conditionally load functionality in a clojure web-app

I have a clojure web app (standard ring handlers and compojure routes on a jetty server) for which I enabled live asset recompilation as middleware, which has been very very handy in development. As we get closer to production I would like to find a way not to load that code in production and instead read the pre-compiled assets (which I am able to generate as a lein task).
Currently the asset compilation machinery lives in the project code - it can be loaded from the lein task using eval-in-project, so I am able to reuse the same code in both places. However this means that the un-needed files are compiled and included in the production app.
The other issue is that there is one asset compilation tool I'm using that causes the app to fail to load at initialisation time if uberjar'ed since it makes use of native bindings to v8, which are not available (and not needed) when the precompiled assets are available.
How can I avoid loading this code in a production uberjar, but still benefit from dynamic re-compilation at run-time during development and testing?
Your :source-paths key in Leiningen decides which directories are checked for Clojure source code. With per-environment settings of :source-paths you can prevent unwanted namespaces from being included in your depoloyed uberjar.
The next piece of the puzzle is to ensure your code does not rely on the dev code on the production instance. This can be done with the help of the environ lib.
; excerpt of project.clj
(defproject your-org/your-project "version"
:source-paths ["src"] ; the main source location
:profiles {:dev {:source-paths ["dev-src"] ; added directory
:env {:dev "true"}}}
...)
; excerpt of project code for src/your_org/your_project.clj
(ns your-org.your-project
(:require environ.core :refer [env]))
(def maybe-launch-optional-thing
(if (= (env :dev) "true") ; checking a profile specific value
(do (require 'dev-only-dep.core)
(resolve 'dev-only-dep/launch))
(constantly nil))
...
(defn -main
[& args]
(maybe-launch-optional-thing)
...)
The if wrapped require, and the usage of resolve, ensure that this code is valid whether dev-only-dep.core is an available or not. maybe-launch-optional-thing is bound to the appropriate function in the optional namespace under a :dev profile, and is otherwise a no-op.

Dependencies in profiles.clj aren't loaded in lein repl

.lein/profiles.clj has dependencies as,
{:user {}
:repl {:dependencies [[org.clojure/clojure "1.4.0"]
[ring/ring "1.1.6"]]
}}
in repl
(require 'ring.adapter.jetty)
throws,
java.io.FileNotFoundException: Could not locate ring/adapter/jetty__init.class or ring/adapter/jetty.clj on classpath: (NO_SOURCE_FILE:0)
This means, ring dependency is not loaded in repl shell. Any mistakes?
Firstly, I would recommend reading https://github.com/technomancy/leiningen/blob/stable/doc/PROFILES.md as I'm not sure you are using profiles correctly. In particular, at the end it shows a way of debugging your profiles, which will show you what is going on.
Secondly, I'm not sure about "there is no project - I am running it from bash shell". If your loading jetty and using ring, you will also need code which sets handlers, routes and probably middleware. this means code files, which means a project tree. Create a basic project with lein new and run from the root of that project.
However, if you really do need to do it as you say, I would suggest you just do
{:user {:dependencies [[....]]}} as your profiles.clj as I suspect that what is happening is that lein is not loading your :repl profile. You could also try running lein with the explicit profile i.e. lein with-profile +repl repl

leinigen repl with profile

This question is a follow up to How does one pre-load a clojure file in the leiningen repl?.
My ~/.lein/profiles.clj looks as follows:
{
:user {:source-paths ["C:/Users/username/.lein/src"] }
}
My ~/.lein/src/user.clj might look as follows:
(ns user)
(println "user file loaded")
When I run lein repl within a folder containing a project.clj, then the user.clj file is executed, but when I run lein repl from another folder it doesn't load my user profile. Is there a workaround for this or is this behavior by design? In fact, I know that Leinigen is indeed loading my profile.clj (even when there is no project.clj) because there are also other things inside (taken from the excellent pimp my repl article). Leinigen is just having problems with my additional source-paths setting.
One other question related to this is the fact that I need to specify the full path of the folder for my user.clj file : "C:/Users/username/.lein/src". When I change that to "~/.lein/src" leiningen fails to load my file.
It sounds like you just want some code loaded for your lein repl sessions. This is done with the :init key of the :repl-options in your profiles.clj. You can load-file other files in init if you want to organize in that fashion.
{:user
{:repl-options
{:init (load-file "path-to-file/user.clj")}
...}}
Note: If you are using Windows-style path delimiters /, you'll need to escape them //.