clj.orcery

Language, Expression and Design

Friday

03

January 2014

Dynamic reloading of java code in emacs/nrepl

by Chris Zheng,

Following up from the previous article on vinyasa, I'm happy to announce the newest feature in this library.

I wrote this as I found that I wasted way to much time when using mixed java/clojure projects. I hated to restart the repl everytime I made a change. Now that I am working in mixed java/clojure projects full time, I decided that this functionality is a MUST.

reimport

Don't you wish that you could make some changes to your java files and have them instantly loaded into your repl without restarting? Well now you can!

For example, in project.clj, you have specified your :java-source-paths

(defproject .....
   :source-paths ["src/clojure"]
   :java-source-paths ["src/java"]
   ....)

and you have a file src/java/testing/Dog.java

package testing;  
public class Dog{  
  public int legs = 3;  
  public Dog(){};
}

You can load it into your library dynamically using reimport

(reimport '[testing.Dog])
;;=> 'testing.Dog' imported from <project>/target/reload/testing/Dog.class

(.legs (Dog.))
;; => 3

You can then change legs in testing.Dog from 3 to 4, save and go back to your repl:

(reimport '[[testing Dog]]) ;; supports multiple classes
;;=> 'testing.Dog' imported from <project>/target/reload/testing/Dog.class

(.legs (Dog.))
;; => 4

If you have more files, ie. copy your Dog.java file to Cat.java and do a global replace:

(reimport) ;; will load all classes into your namespace
;;=> 'testing.Dog' imported from <project>/target/reload/testing/Dog.class
;;   'testing.Cat' imported from <project>/target/reload/testing/Cat.class

(.legs (Cat.))
;; => 4

Now the pain associated with mixed clojure/java development is gone!

comments powered by Disqus