Clojure for module development in Google Guice?

I’ve been learning Clojure for some time and been meaning to use it for development with Java EE. So far, I’ve been unable to find anything very inspiring and stumbled upon Google Guice.

One reason to learn dynamic languages like Clojure, Scala or Groovy is that they’re dynamic and can still run on JVM. That’s exactly what we gain learning Java, but very often Java is not as dynamic as I wish to – it’s certainly not according todynamic languages at Wikipedia. Dynamicity makes them very useful while learning Java APIs and I thought about using Clojure for my learning endeavors around Guice. I know Clojure and Guice very little, but it turned out enough. It also turned out very easy to set up the learning environment with Clojure REPL.

I remember I ended up with the following and that’s when I begun wondering what it could’ve been useful for.

jacek:~
$ CLASSPATH=~/apps/guice/guice-3.0-rc1.jar:~/apps/guice/javax.inject.jar:~/apps/guice/aopalliance.jar clj -13
CLOJURE_DIR:  /Users/jacek/apps/clojure
CLOJURE_CONTRIB_JAR:  /Users/jacek/apps/clojure-contrib-1.3.0-alpha3.jar
Clojure 1.3.0-alpha4
user=> (import  '(com.google.inject Guice AbstractModule))
com.google.inject.AbstractModule
user=> (def module (proxy [AbstractModule] [] (configure [] (println "configure called"))))
#'user/module
user=> (Guice/createInjector [module])
configure called
#<InjectorImpl Injector[bindings=[ProviderInstanceBinding[key=Key[type=com.google.inject.Injector, annotation=[none]], source=[unknown source], scope=Scopes.NO_SCOPE, provider=Provider<Injector>], ProviderInstanceBinding[key=Key[type=java.util.logging.Logger, annotation=[none]], source=[unknown source], scope=Scopes.NO_SCOPE, provider=Provider<Logger>], InstanceBinding[key=Key[type=com.google.inject.Stage, annotation=[none]], source=[unknown source], instance=DEVELOPMENT]]]>

In the above session with Clojure REPL, I defined a very rudimentary module that did nothing but print out a message “configure called” and instantiated Guice’s Injector – the entry point.

The interesting part begun when I decided to find out how it was to create a more complex module – in other words, more complex Guice configuration.

I started with the following…

user=> (import java.util.Map)
java.util.Map
user=> (import java.util.HashMap)
java.util.HashMap

user=> (def module (proxy [AbstractModule] [] (configure [] (.to (.bind this Map) HashMap))))
#'user/module

user=> (Guice/createInjector [module])
#<InjectorImpl Injector[bindings=[ProviderInstanceBinding[key=Key[type=com.google.inject.Injector, annotation=[none]], source=[unknown source], scope=Scopes.NO_SCOPE, provider=Provider<Injector>], ProviderInstanceBinding[key=Key[type=java.util.logging.Logger, annotation=[none]], source=[unknown source], scope=Scopes.NO_SCOPE, provider=Provider<Logger>], InstanceBinding[key=Key[type=com.google.inject.Stage, annotation=[none]], source=[unknown source], instance=DEVELOPMENT], LinkedKeyBinding[key=Key[type=java.util.Map, annotation=[none]], source=user.proxy$com.google.inject.AbstractModule$0.bind(Unknown Source), scope=Scopes.NO_SCOPE, target=Key[type=java.util.HashMap, annotation=[none]]]]]>

With the help of Clojure’s documentation – Java Interop – The Dot special form – (.. instance-expr member+) it morphed…

user=> (def module (proxy [AbstractModule] [] (configure [] (. (. this bind Map) to HashMap))))
#'user/module

…gradually…

user=> (def module (proxy [AbstractModule] [] (configure [] (-> this (.bind Map) (.to HashMap)))))
#'user/module

…to its final shape.

user=> (def module (proxy [AbstractModule] [] (configure [] (.. this (bind Map) (to HashMap)))))
#'user/module

All the above 3 snippets let me create a Guice module to bind every occurrence of java.util.Map’s instance to java.util.HashMap.

user=> (def injector (Guice/createInjector [module]))
#'user/injector

user=> (.getInstance injector Map)
#<HashMap {}>

With Clojure REPL, it’s so easy to change the mapping to other, still compatible types.

user=> (import java.util.LinkedHashMap)
java.util.LinkedHashMap
user=> (def module (proxy [AbstractModule] [] (configure [] (.. this (bind Map) (to LinkedHashMap)))))
#'user/module
user=> (def injector (Guice/createInjector [module]))
#'user/injector
user=> (.getInstance injector Map)
#<LinkedHashMap {}>

I must admit it wasn’t easy to figure out all the Guice stuff to use and how to translate it to Clojure, but still doing all this within Clojure REPL was quite a fun. I’m still unable to find a place for such dynamic Guice configuration, esp. when my current Guice knowledge let me only think about it in object-oriented manner where dependency injection (DI) matters.

com.google.inject.Guice‘s says:

Guice supports a model of development that draws clear boundaries between APIs, Implementations of these APIs, Modules which configure these implementations, and finally Applications which consist of a collection of Modules.

What about Clojure as a way to tie Guice Modules up for a fully working, final Application’s setup?

Be Sociable, Share!
This entry was posted in Frameworks, Languages.

One Response to Clojure for module development in Google Guice?

  1. Pingback: Dynamically redefining classpath in Clojure REPL | Japila :: verba docent, exempla trahunt

Leave a Reply

%d bloggers like this: