Home / Blog

Introduction

Jwt is a "Java library for developing web applications" with a widget-centric API. Jwt is actually the result of a translation to Java of the original Wt C++ code, which was originally developed by Koen Deforche and both are now maintained by Emweb .

I've been intrigued by Wt since I saw an (was that 3 year ago?!) announcement on Ajaxian for its widget approach, but I never used it due to its C++ base. Not that C++ is bad, it certainly has its justification in the embedded space, but I got used to dynamic scripting languages.

When Koen told me some months ago a Java version was on its way, I immediately told him I was eager to test it. Not with Java the language, but on Java the platform with Clojure (which I'll cover in this post) and JRuby (maybe for a future post, but if you want to test Wt from Ruby, take a look at Richard Dale's WtRuby which uses the C++ Wt).

Clojure is a "dynamic programming language that targets the Java Virtual Machine" which is a dialect of Lisp sharing with it "the code-as-data philosophy and a powerful macro system". Clojure is a recent language with a vibrant and steadily growing community. Despite being so young, there's already a book covering Clojure by the Pragmatic Programers .

Setup

I'm using Sun's Java 6 on an Debian, and got code for Clojure, Clojure-contrib and Jwt from their respective repositories. If this is fine for Clojure and Clojure-contrib, which build flawlessly with ant giving you a usable jar file, it caused problems with Jwt as the git repo seems to be out of sync... One advice here: be sure to download the Jwt zip file (currently 2.99.3) to avoid headaches wondering why you get blank pages served!

First step

Jwt applications need to run in a servlet container, and Compojure, a Clojure web development framework provides jetty.clj module allowing to create a servlet holder in which you can add an instantiated Jwt servlet. (thanks to Adrian Cuthbertson for this info!).

So, the only thing I needed to find is how to instanciate a WtServlet. To find out I decided to translate in Clojure the HelloWorld found in Jwt's examples . My first attempt was some some of literal translation of the Java code which was not very "clojurish" nor working as I always got blank pages served. Eventually I got everything sorted out: the problem was because the git repo doesn't contain the latest release, and the code was improved by Chouser on irc to look like this:

(ns be.nsa.server
  (:use compojure))

(import '(eu.webtoolkit.jwt WApplication
                    WEnvironment WtServlet WText 
                    WPushButton WLineEdit WBreak))

(defn make-hello-app [env]
  (let [wapp (new WApplication env)
        root (.getRoot wapp)
        line-edit (WLineEdit.)
        result-text (WText. "")
       ]
    (.setTitle wapp "HelloWorld")
    (.addWidget root (WText. "Hello there! "))
    wapp))

(def my-servlet
  (proxy [WtServlet] []
    (createApplication [env]
      (make-hello-app env))))

(defserver my-server {:port 8080} "/*" my-servlet  )

After declaring our namespace and saying we use compojure, we import the classes needed from Jwt.

The code itself is not very complex: it creates an instance of a proxy class to WtServlet, of which we overwrite the method createApplication (which receives as argument a WEnvironment instance). This method simply return the WApplication we instanciate in make-hello-app.

Implementing listeners

The second step needed to get the working hello world application, is to add a text field and a button. This is straight-forward, but then we need to add a listener on the button, which is defined like this in Java:

b.clicked().addListener(this, new Signal1.Listener<WMouseEvent>() {
   public void trigger(WMouseEvent a1) {
     greet();
   }
});

The listener needs to implement the nested interface Signal1.Listener. To get access to it, you use the syntax Signal1$Listener, but it is accessible only after you have imported it! If you don't import Signal1$Listener, you'll have to reference it by its fully qualified name (even if you imported Signal1)! I got a useful help from Cark on IRC for this, thanks!

Once accessing the nested interface was sorted out, implementing the listener was easy:

(.. (WPushButton. "Greet me" root) clicked
    (addListener  
          wapp
          (proxy [Signal1$Listener] [] 
               (trigger [ mouse-event ] 
                 (.setText result-text (.getText line-edit)) ))))

we add a listener to the object returned by the button's clicked method. The first argument to addListener is the wapp, the second argument is the proxy class' instance of which we implement the trigger method. This code to create the widget seems to be screaming for macros, see below.

At that time I though I was done, as implementing the second listener is done by this code:

(.. line-edit enterPressed
    (addListener 
       wapp   
        (proxy [Signal$Listener] [] 
            (trigger [] 
             (.setText result-text (.getText line-edit))))))

But it didn't work :(

The addListener method could not be resolved. After looking at it for hours spread on multiple days with the help of clojure wizards on the #clojure IRC channel, cgrand finally identified the problem (update (20090901): this problem has been patched and will be gone in future Clojure releases): proxy objects for nested interfaces are cached and identified by the interface's name. Meaning that if you have multiple interfaces with the same name in different packages, you'll get in trouble. The solution is to call proxy with a dummy interface that we don't care about, but which will change the key used to stored it in the proxy cache... In this example I added the interface Runnable:

(.. line-edit enterPressed 
    (addListener 
       wapp  
        (proxy [Signal$Listener Runnable] [] 
           (trigger [] 
             (.setText result-text (.getText line-edit))))))

And that's it, the first Jwt app written with Clojure is now running :-D

The code (that you'll find at the bottom of this page) is to be place in the file be/nsa/server.clj under your classpath, and can be loaded in a repl with

(use 'be.nsa.server.clj)

You can then start and stop the server with:

(compojure.server.jetty/start my-server)
(compojure.server.jetty/stop my-server)

Macro

Here is a macro greatly simplifying the creation of listeners:

(defmacro create-listener [ args & body]
  (let [argsnum# (if (< 0 (count args)) (count args) "") ]
  `(proxy [ ~(symbol (str "Signal" argsnum# "$Listener")) ] []
          (trigger ~args ~@body))))

It's really heloing development in our case, as the interface implemented will be determined based on the number of arguments we want trigger to have. So this call

(create-listener [a1 a2] (do-stuff a1 a2))

will implemented the interface Signal2$Listener and this call

(create-listener [] (do-stuff))

will implement Signal$Listener.

This macro is not usable in this state though, due to the Clojure bug describe above. To work around that bug, it is possible to add an argument to the macro, so say which dummy interface we want to implement:

(defmacro create-listener [ interface args & body]
  (let [argsnum# (if (< 0 (count args)) (count args) "") ]
  `(proxy [ ~(symbol (str "Signal" argsnum# "$Listener")) ~interface ] []
       (trigger ~args ~@body))))

The code

This code is compatible with Clojure 1.0. See below for updates...

(ns be.nsa.server
  (:use compojure))

(set! *warn-on-reflection* true)

(defmacro create-listener [ interface args & body]
  (let [argsnum# (if (< 0 (count args)) (count args) "") ]
  `(proxy [ ~(symbol (str "Signal" argsnum# "$Listener")) ~@interface ] []
         (trigger ~args ~@body))))

(import '(eu.webtoolkit.jwt WObject WApplication
                  WEnvironment WtServlet WText WPushButton 
                  WLineEdit WBreak Signal1 Signal1$Listener 
                  Signal Signal$Listener EventSignal))

(defn make-hello-app [env]
  (let [wapp (new WApplication env)
        root (.getRoot wapp)
        line-edit (WLineEdit.)
        result-text (WText. "")
       ]
    (.setTitle wapp "HelloWorld")
    (.addWidget root (WText. "Your name, please ? "))
    (.. (WPushButton. "Greet me" root) clicked 
          (addListener  
             wapp
             ( create-listener [] [mouse-event] 
               (.setText result-text (.getText line-edit)))))
   (.. line-edit enterPressed 
           (addListener 
               wapp  
             (create-listener [Runnable] [] 
               (.setText result-text (.getText line-edit)))))
    (.addWidget  root (WBreak.))
    (.addWidget  root line-edit)
    (.addWidget  root (WBreak.))
    (.addWidget  root result-text)
    wapp))

(def my-servlet
  (proxy [WtServlet] []
    (createApplication [env]
      (make-hello-app env))))


(defserver my-server {:port 8080} "/*" my-servlet  )

Update

With the Clojure bug mentioned above gone, and removing the unecessary gensym as it is outside the escaped code, the macro can be written:

(defmacro create-listener [ args & body]
  (let [argsnum (if (< 0 (count args)) (count args) "") ]
  `(proxy [ ~(symbol (str "Signal" argsnum "$Listener")) ] [] (trigger ~args ~@body))))

As I'm progressing with Jwt app development in Clojure, I encountered the question of structuring my code. I'm not yet talking of namespaces, but simply how I should my code in functions, and how do I translate the OO code, heavily using instance variables. See this code from a WT Ruby example to get an idea.

I wanted to develop a login widget with login and password fields and a submit button. I wanted this login widget to be displayed in a modal dialog that disappears when valid credentials are submitted.

I've started with the same approach as my previous post : a function creating the WApplication instance that is passed to the servlet. In this function, I instanciate all main components of the application: the WApplication, the modal dialog, the login widget and the main application screen:

(defn make-login-app [env]
  (let [wapp (new WApplication env)
        root (.getRoot wapp)
        result-text (WText. "")
        user nil
        dialog (WDialog. "test")
        dialog-container (.getContents dialog)
        app-screen (make-app-screen)
        form (make-login-form)
       ]
    ; function code will come here
))

Creating the login form is done by the function make-login-form. This function creates the form elements and lays them out. As Jwt is a framework using the signal/slot idea to implement communication between application components, I've decided to use it with the login form. A signal is triggered when the login is successful, and another signal is triggered when the creadential provided are incorrect.

Using signal is really simple: just instanciate the Signal class and give a way to access this instance to the component wishing to connect to it. In the OO world, this is implemented by an instance variable and a get method. So, how do we translate that in Clojure?

The trick is that the make-login-form will not only return the login widget, but also both signal instances, all placed in a map. That way, inmake-login-app, we will be able to add listeners to these signals.

The signals are triggered by a listener attached to the button's clicked signal: if the credential provided are correct the loggedin-signal is trigger, else the wrong-credentials-signal is triggered.

Here's the function's code (the last line returns the map):

(defn make-login-form []
  (let [layout (WGridLayout.)
        container (WContainerWidget.)
        password-field (doto (WLineEdit. container) 
                  (.setEchoMode WLineEdit$EchoMode/Password ) )
        password #(.getText password-field)
        login-field (WLineEdit. container)
        login #(.getText login-field)
        loggedin-signal (Signal.)
        wrong-credentials-signal (Signal.)
        do-login (fn [evt] 
             (if (authenticate (login) (password)) 
                (.trigger loggedin-signal ) 
                (.trigger wrong-credentials-signal)  ))
        submit-button (WPushButton. "Login")]
    (-> submit-button .clicked
              (.addListener  container 
                   ( create-listener [mouse-event] 
                    (do-login mouse-event) )))
    (.addWidget layout (WLabel. "Login:") 0 0 )
    (.addWidget layout login-field 0 1 )
    (.addWidget layout (WLabel. "Password:") 1 0 )
    (.addWidget layout password-field 1 1)
    (.addWidget layout  submit-button 2 0 1 2)
    (.setLayout container layout)
    (.setFocus login-field)
   { :container container 
    :authenticated loggedin-signal 
    :rejected wrong-credentials-signal}))

The credentials are checked by the function authenticate which takes the login and password as argument. This naive authentication method only to be used in an example will simply check if it finds a user entry with the corresponding user and password (using clj-record):

(defn authenticate [login password]
    (user/find-record {:login login :password password}))

And here we see why I'm so interested in Jwt: I don't have to care about server side or client side! I just code my app and Jwt handles all the rest. I don't have to care about making a request to the server which then will check the credentials in the database, and send a response that I would need to handle at the client side. It's all Clojure code, and Jwt handles all that trasparently.

In the make-login-app I also already initialised the app's main screen, thanks to a function that simply creates a text widget that will be updated by the login widget's signal's listeners:

(defn make-app-screen []
 (let [ container (WContainerWidget.)
        layout (WGridLayout.)
        text (WText. "Hello")]
  (.addWidget layout text 0 0)
  (.setLayout container layout)
  container))

Now that we know how all "variables" are initialised in the make-login-app function, we can take a closer look to that function's body, where we set up the listeners:

(defn make-login-app [env]
  (let [wapp (new WApplication env)
        root (.getRoot wapp)
        result-text (WText. "")
        user nil
        dialog (WDialog. "test")
        dialog-container (.getContents dialog)
        app-screen (make-app-screen)
        form (make-login-form)
       ]
    (.addListener (form :authenticated) wapp  
             (create-listener [] 
               (.remove dialog) 
                (.setText (-> app-screen .getLayout (.getItemAt 0) .getWidget) "Logged in!")))
    (.addListener (form :rejected) wapp  
              (create-listener []  
                 (.setText (-> app-screen .getLayout (.getItemAt 0) .getWidget) "Wrong credentials!")))
    (.setTitle wapp "Login Example")
    (doto dialog (.. getContents (addWidget (form :container))) .show)
    (.addWidget  root app-screen)
    wapp))

We simply add a listener to each signal, which will update the text element we placed in the app-screen. Also note the doto usage: many Jwt methods return void, and the doto macro is really a time-saviour.

Advices and remarks to improve the code are welcome!

Update

Jonathan Smith noted that the multiple calls to (.addWidget layout ...) in make-login-form could be grouped in a doto:

(doto layout
   (.addWidget  (WLabel. "Login:") 0 0 )
    (.addWidget  login-field 0 1 )
    (.addWidget  (WLabel. "Password:") 1 0 )
    (.addWidget  password-field 1 1)
    (.addWidget  submit-button 2 0 1 2))

Jonathan also mentioned the possibility of using a 'continuation passing' style, which rather than using signals, passes functions to be called when an action occurs. The first version of my code was actually like that, and I paste it here for completeness (see the anonymous functions passed to make-login-form):

(defn make-login-form [ succes-fn failure-fn]
  (let [layout (WGridLayout.)
        container (WContainerWidget.)
        password-field (doto (WLineEdit. container) 
           (.setEchoMode WLineEdit$EchoMode/Password ) )
        password #(.getText password-field)
        login-field (WLineEdit. container)
        login #(.getText login-field)
        do-login (fn [evt] (if (authenticate (login) (password)) 
            (succes-fn) (failure-fn)  )) 
        submit-button (WPushButton. "Login")]
    (-> submit-button .clicked 
            (.addListener  container 
              (create-listener [mouse-event] (do-login mouse-event))))
    (.addWidget layout (WLabel. "Login:") 0 0 )
    (.addWidget layout login-field 0 1 )
    (.addWidget layout (WLabel. "Password:") 1 0 )
    (.addWidget layout password-field 1 1)
    (.addWidget layout  submit-button 2 0 1 2)
    (.setLayout container layout)
    (.setFocus login-field)
   container))
    
(defn make-login-app [env]
  (let [wapp (new WApplication env)
        root (.getRoot wapp)
        result-text (WText. "")
        form (make-login-form 
          #(.setText result-text "Welcome back!") 
          #(.setText result-text "Check your credentials!"))
        user nil
        dialog (WDialog. "test")
        dialog-container (.getContents dialog)
       ]
    (.setTitle wapp "Login Example")
    (doto dialog (.. getContents (addWidget form)) .show)
    (.addWidget  root result-text)
    wapp))
</pre>

The other day, I read the blog post Agents of Swing by Stuart Sierra describing the use of agents in combination with a Swing UI. As soon as I read it I wanted to implement it with Jwt in the hope it would be easy. And I wasn't disappointed!

As I had expected, I was able to reuse the agents code from Stuart and integrate it very easily in my web app. Actually, the development op the web interface was similar to the development of the swing interface. It's so similar I can only paste it here without further explanations:

; Create the Timer that will update results on the page 
; by calling the function passed
(defn create-timer [wapp fn-update-results]
  (let [timer (WTimer.)]
        (.setInterval timer 1000)
   (.. timer timeout (addListener wapp (create-listener [event] 
                                                                      (fn-update-results))))
   timer))

(defn make-flipper-app [env]
  (let [wapp (new WApplication env)
        root (.getRoot wapp)
        result-text (WText. "")
        flipper (new-flipper)
        fn-update-results (fn []
               (.setText result-text (
                   str "error: " (error @flipper) " after " 
                       (:total @flipper)  " flips, of which " 
                       (:heads @flipper) " where heads"  )))
        timer (create-timer wapp fn-update-results)
       ]
    (.setTitle wapp "Agents of Jwt")
    (.. (WPushButton. "Start counter" root) clicked
               (addListener  wapp ( create-listener [mouse-event] 
                   (send flipper start) 
                   (fn-update-results)  
                   (.start timer)  )))    
   (.. (WPushButton. "Stop counter" root) clicked 
              (addListener  wapp ( create-listener [mouse-event] 
                   (send flipper stop) 
                   (.stop timer) 
                   (fn-update-results)   )))
    (.addWidget  root (WBreak.))
    (.addWidget  root result-text)
    (.addWidget  root (WBreak.))
    wapp))


The only thing needed in addition to this is importing the necessary jwt classes, the definition of the servlet, and starting the server, the last two being done with this code:

(def my-servlet
  (proxy [WtServlet] [] 
    (createApplication [env]
      (make-flipper-app env))))


(def my-server (jetty-server))
(add-servlet my-server my-servlet "/*")

;(org.bitumenframework.jettify.clj_jettify/start-server 
       jwt-toss/my-server)


Here is the file with the complete code that I was able to run:

If someone's interested, I can possibly bundle a complete environment to be able to run it immediately. Just give me a sign.

I'm available for hire 

If you're looking for someone to temporarily join your IT team, or if you need help to put IT to work in your company, I'm ready to help. Contact me now !

Mon Tue Wed Thu Fri Sat Sun
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31