Jan 5, 2011

vaadin clojure app (coding onlly)

This is a simple app which get two numeric values and give its sum as a message.

(ns myapp.core
 (import (com.vaadin.ui Layout)))

(defn getSum [tf1 tf2]
(let [a  (Double/parseDouble (. (. tf1 getValue) toString))
      b  (Double/parseDouble (. (. tf2 getValue) toString))
      c (+ a b)]
      (. c toString))
)

(defn main [args]
  (proxy [com.vaadin.Application] []
    (init []
      (let [app this
            l1  (new com.vaadin.ui.Label "My Application")
            tf1 (new com.vaadin.ui.TextField "Input value one :")
            tf2 (new com.vaadin.ui.TextField "Input value two :")]
        (.setMainWindow this
          (doto (new com.vaadin.ui.Window "Welcome to myapp")
            (.addComponent l1)
            (.addComponent tf1)
            (.addComponent tf2)
            (.addComponent
              (doto (new com.vaadin.ui.Button "Click Me")
                (.addListener (proxy [com.vaadin.ui.Button$ClickListener] []
                   (buttonClick [event]
                       (. (. app (getMainWindow)) (showNotification "The Sum is :" (getSum tf1 tf2)  )))))))
           ))))))
To get the real output you need to view the previous post.

Jan 4, 2011

Writin a Vaadin app using Clojure

First of all you need Clojure with leiningen environment. Vaadin jar file.

Setup the leiningen environment and create a new project.
lein new myapp

Then change the directry to myapp and there you can see some flies. Edit the file src/myapp/core.clj file to your vaadin app. After editing it will be like this.

(ns myapp.core)

(defn main [args]
  (proxy [com.vaadin.Application] []
    (init []
      (let [app this]
        (.setMainWindow this
          (doto (new com.vaadin.ui.Window "Test application")
            (.addComponent
              (new com.vaadin.ui.Label "Hello Vaadin/LISP user!"))
            (.addComponent
              (doto (new com.vaadin.ui.Button "button")
                (.addListener (proxy [com.vaadin.ui.Button$ClickListener] []
                                (buttonClick [event] (. (. app (getMainWindow)) (showNotification "test")))))))))))))

Note the (ns **** ).

Then edit the project.clj file.

(defproject myapp "1.0.0-SNAPSHOT"
  :description "FIXME: write"
  :dependencies [[org.clojure/clojure "1.2.0"]
                 [org.clojure/clojure-contrib "1.2.0"]
                 [com.vaadin/vaadin "6.4.8"]]
  :dev-dependencies [[uk.org.alienscience/leiningen-war "0.0.1"]]
  :aot [myapp.core])

In this you can see there is a   :dev-dependencies [[uk.org.alienscience/leiningen-war "0.0.1"]] and   :aot [myapp.core]. First one is a plugin which can createa WAR file. The second one is to create the servlet class from the clojure file.

Now we need to write the web.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        <display-name>testVaadin</display-name>
        <context-param>
                <description>Vaadin production mode</description>
                <param-name>productionMode</param-name>
                <param-value>false</param-value>
        </context-param>
        <servlet>
                <servlet-name>Lisp</servlet-name>
                <servlet-class>org.thilina.Servlet</servlet-class>
                <init-param>
                        <param-name>script-name</param-name>
                        <param-value>myapp.core</param-value>
                </init-param>
                <init-param>
                        <param-name>package-name</param-name>
                        <param-value>myapp.core</param-value>
                </init-param>
                <init-param>
                        <param-name>function-name</param-name>
                        <param-value>main</param-value>
                </init-param>
        </servlet>
        <servlet-mapping>
                <servlet-name>Lisp</servlet-name>
                <url-pattern>/*</url-pattern>
        </servlet-mapping>
</web-app>

Vaadin http handling is little bit different so we neet to some additional task. You need to compile above java code and place those classes in the class directory.

package org.thilina;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import clojure.lang.RT;
import com.vaadin.Application;
import com.vaadin.terminal.gwt.server.AbstractApplicationServlet;

public class Servlet extends AbstractApplicationServlet {

 @Override
 protected Class<? extends Application> getApplicationClass()
   throws ClassNotFoundException {
  return Application.class;
 }

 @Override
 protected Application getNewApplication(HttpServletRequest request) throws ServletException {
  try { //load script, with name provided as a servlet's parameter
   RT.load(getServletConfig().getInitParameter("script-name"), true);

   //run Lisp function
   return (Application)RT.var(getServletConfig().getInitParameter("package-name"),
                 getServletConfig().getInitParameter("function-name")).invoke(new String[0]);
  }
  catch (Exception e) {
   throw new ServletException(e);
  }
 }
}

You need clojure.jar and vaadin.jar in order to compile this java file.

Now you can compile the project and get a WAR file.
lein deps
lein compile
lein uberwar

Then put this *.war file to tomcat/webapps directory.


References :-

https://github.com/technomancy/leiningen
http://dev.vaadin.com/wiki/Articles/ClojureScripting