Groovy++ With Gradle

I’ve been playing with Groovy++ a bit. It’s evolving very fast, so it can be a pain to keep up to date. Besides, I tend to use Gradle for build. I figure I’ll let Gradle take care of this.

As it turn out, it was very easy to do so. Here is my build.gradle. You can use it to play around with groovy++ to see if it fits your need.

apply {
    plugin 'groovy'
}

group = 'com.example'
version = '1.0.0'

repositories {
  mavenCentral()
  mavenRepo urls: "http://groovypp.artifactoryonline.com/groovypp/libs-releases-local"
}

dependencies {
  groovy 'org.mbte.groovypp:groovypp-all:0.2.24'
}

task copyToLib(dependsOn: configurations.default.buildArtifacts, type: Copy) {
  into('build/lib')
  from configurations.default
  from configurations.default.allArtifacts*.file
}

It will grab the most recent release and use it to build and run all groovy files. I also have my standard copyToLib task to copy all jars into build/lib.

Clojure Web Development WAR Style With Gradle

I don’t normally use Clojure to do web development, at least not in the full stack sense. I normally use Grails with the Clojure plugin. In short, I use Groovy and Grails to deal with the mutable stuff, and call Clojure function as if it’s a blackbox.

Lately, using Clojure for web development seems to be a hot topic. I decided to explore it a bit to see where things stand. I’ll be using Gradle 0.9-preview3 as the build tool, with Clojuresque as the plugin. Unlike other tutorials you may have come across, my focus is producing WAR files so the output can be deployed in any application server like Tomcat.

To start, all you need is to install Gradle 0.9-preview3, and download Clojuresque as outlined in the first 2 steps here
Someone pointed out the change from yesterday’s Clojuresque broke it. So here is the link to the one I built from last week.

Once you have it working, first create a sandbox directory called “webexample”. Inside, you want to create a file called build.gradle

apply {
    plugin 'clojure'
    plugin 'war'
    plugin 'jetty'
}

group = 'com.example'
version = '1.0.0'

warnOnReflection = true
aotCompile = true
clojarsUpload = false

//jettyRun.contextPath = '/'

repositories {
  clojureReleasesRepo()
  clojureSnapshotsRepo()
  clojarsRepo()
  mavenCentral()
}

war {
  copy {
    from 'src/main/clojure/views'
    into 'src/main/webapp/WEB-INF/classes/views'
  }
}

dependencies {
  compile 'org.clojure:clojure:1.2.0-beta1'
  compile 'org.clojure:clojure-contrib:1.2.0-beta1'
  compile 'ring:ring-core:0.2.5'
  compile 'ring:ring-devel:0.2.5'
  compile 'ring:ring-servlet:0.2.5'
  compile 'compojure:compojure:0.4.1'
  compile 'enlive:enlive:1.0.0-SNAPSHOT'
}

The aot is set to true because we need to produce class files for the servlet. The only other special task is the copy task inside WAR. I keep all the Enlive template in src/main/clojure/views because enlive needs to see it there during compile. However, when a WAR is being created, those template files need to be in WEB-INF/classes/views otherwise your classes can’t see it. So I create a copy task whenever a WAR is being created. As you can see from the dependencies, I’m using the latest shiny version of everything.

You may also notice jettyRun.contextPath = ‘/’ is commented out. I’ll come back to this later.

Now create src/main/clojure/mywebapp directory. It’s time to write the first servlet. Create firstservlet.clj with the content below

Some of this will look familiar to you. I’m using the same example as shown by Mark McGranaghan in his post of the same topic.

There are a few differences. I’m using gen-class because I need to create the servlet. The route pattern instead of just “/”, each of them has the web context prefix. Gradle by default, places your webapp under the context of the same name as your sandbox directory. So it would place it under webexample in this case. But Compojure’s route matching doesn’t take context into account. I was totally stumped by this. Thanks to the James Reeves and Saul Hazledine on the Compojure mailing list’s help, I got this to work. Now you know why I left jettyRun.contextPath = ‘/’ in the build.gradle file. That was the other way to solve the problem. Instead of having /webexample in every route, you can tell Gradle jetty plugin to run your webapp at contextPath /. But in general, I don’t think this is a good idea. On our application servers, we have a lot of apps deployed, each under its own context. I don’t think you can assume your app will always be deployed as ROOT.war. James has stated he’s working on a middleware to take care of this.

Having defined the routes. It’s time to write the heavy lifting part. Create src/main/clojure/mywebapp/add.clj

I’m using Enlive for the template. There are also two other functions for returning the result in either JSON or XML.
We still need the template though

Create src/main/clojure/views/addtwonums.html

I really like Enlive. I first saw this style of template system in Wicket. I also like it quite a bit in Lift. Lift calls this “View” first. For a functional language like Clojure, I’m not convinced the traditional MVC is a good match. Clojure has not yet found its own voice in web development up to this point.

One last detail to take care of. We need to define a web.xml file. So create src/main/webapp/WEB-INF/web.xml

That’s it. You can run it by using “gradle jettyRun”. It will compile everything, and start jetty for you. Try out some of the urls

http://localhost:8080/webexample/

http://localhost:8080/webexample/view

http://localhost:8080/webexample/add?a=1&b=2

http://localhost:8080/webexample/addjson?a=1&b=2

http://localhost:8080/webexample/addxml?a=1&b=2

You can produce a WAR file by using “gradle war”. It will produce a WAR file in build/libs. You can take that WAR file and upload it to tomcat, it will just work.

There is also another downside with this approach. Anytime you make any changes, you’ll have to restart.

One of Clojure’s strength is the fact it runs on JVM. For those of you that want to produce WAR files so you can run Clojure code on existing JVM application servers, I hope this is useful to you.

I also want to thank Meikel Brandmeyer for continuing to work on Clojuresque and his tireless support.

The Hand That Rocks The Gradle

A few more month passed, and much has happened in the clojure scene. Clojure 1.1.0 was released in 2009-12. The clojure plugin clj-gradle has been renamed to clojuresque and updated to 1.3. Clojars.org, which is a community repo of clojure libraries accessable via mvn and ivy is online. I’ve done some clojure talks, added a few people to my clojure army. :)

But it means my previous two posts on clojure and gradle are very outdated. So I figure it’s time to share my current clojure and gradle setup. It’s much more simple now. The only thing you are required to do before following this, is to have gradle 0.8 setup. That’s it.

First you need to setup a sandbox directory. Inside the directory, you want to create a file build.gradle
Here is what I use.

buildscript {
  repositories {
    mavenRepo name: 'clojars', urls: 'http://clojars.org/repo'
  }
  dependencies {
    classpath 'clojuresque:clojuresque:1.3.0'
  }
}

usePlugin(clojuresque.ClojurePlugin)

group = 'yourgrouphere'
version = '1.0.0'

warnOnReflection = true
aotCompile = true

clojureSnapshotsRepo(repositories)
clojarsRepo(repositories)
gradleHomeRepo(repositories)

repositories {
  mavenCentral()
  mavenRepo urls: "http://build.clojure.org/releases"
}

dependencies {
  compile 'org.clojure:clojure:1.2.0-master-SNAPSHOT'
  compile 'org.clojure:clojure-contrib:1.2.0-master-SNAPSHOT'
  compile 'enlive:enlive:1.0.0-SNAPSHOT'
  compile 'org.ccil.cowan.tagsoup:tagsoup:1.2'
//  compile 'org.clojure:clojure:1.1.0'
//  compile 'org.clojure:clojure-contrib:1.1.0'
}

configureClojarsDeploy(uploadArchives)

task initProject(description: 'Initialize project directory structure.') << {
  ['clojure'].each {
  convention.sourceSets.all*."${it}".srcDirs*.each { it.mkdirs() }
  }
}

task copyToLib(dependsOn: configurations.default.buildArtifacts, type: Copy) {
  into('build/lib')
  from configurations.default
  from configurations.default.allArtifacts*.file
}

It has a couple of helpful targets. The initProject setup the src subdirectories for you. If you have groovy and java code, you can of course append to that. The copyToLib target will copy all the jars into build/lib.

The script also set up clojars.org repo for you. In fact, it pulls clojuresque from it. I also enable mvn central repo, as well as the build.clojure.org repo to pull either release or nightly snapshot version of the clojure and clojure-contrib.

I also went ahead and added enlive to the dependencies to show you how to add dependencies from clojars.org. No, it’s not a typo. It really is enlive:enlive:1.0.0-SNAPSHOT. Beacuse in clojars.org, the name of the project is used in both group and artifact id. It doesn’t follow the java convention. The tagsoup dependency is because of enlive. That one is from mvn repo and does follow the java convention.

You’ll see I have the 1.1.0 release for clojure and clojure-contrib commented out. It’s very important you use matching clojure and clojure-contrib version. I tend to do my development using the bleeding edge version. But if you want to swtich back to release. It’s as easy as comment out the two 1.2.0 entries, and uncomment the two 1.1.0 entries.

Now, let’s create src/main/clojure/mystuff/example.clj

(ns mystuff.example
    (:use net.cgrand.enlive-html)
    (:import java.net.URL)
    (:gen-class))

  (defn -main []
      (println (-> "http://www.penny-arcade.com/comic/" URL. html-resource
                     (select [:.body :img]) first :attrs :src)))

Then issue “gradle build”. If all goes well, you will get a build successful. Now issue “gradle copyToLib”. All the jars will be copied to build/lib. I named my sandbox directory blogtest. So I have a blogtest-1.0.0.jar.

Time to see the url of the latest comic.

java -cp ./clojure-1.2.0-master-SNAPSHOT.jar:./clojure-contrib-1.2.0-master-SNAPSHOT.jar:./enlive-1.0.0-SNAPSHOT.jar:./tagsoup-1.2.jar:./blogtest-1.0.0.jar mystuff.example

http://art.penny-arcade.com/photos/807260572_n6CMU-L.jpg

Well, that worked, even if the comic isn’t very funny today. Yes, you can in fact use wildcard for classpath if you want. :)

My Google Nexus One

I’ve been using Google Nexus One since its release. Google got the phone to me within 24 hours of the announcement. (Thank you Google!) This isn’t the first Android phone I used. I also have the HTC Magic aka T-Mobile myTouch 3G aka Google Ion. To be blunt, up till now Android has been a disappointment to me. They are sluggish, ugly, and the software were very rough. I was cautiously optimistic about Nexus One. After all, this time around Google is selling it directly unlocked. The specs look great on paper, but will it actually translate to good user experience this time? I resisted writing this review right away, because I really want to give it a fair chance. So other than posting a bunch of pictures on Flickr, I waited till now to write this after using it since Jan 6th.

So what’s the verdict? For those of you who just want to know right now. The short version is “Google Nexus One wins on hardware, Apple iPhone 3GS wins on software.”

First let’s talk about hardware. When you hold Nexus One. The first thing you notice is the lovely AMOLED screen. The phone is thinner than iPhone. The build quality is high. The images are crisp thanks to the high resolution. The iPhone screen is 3.5 inches with resolution of 320×480. The Nexus One is 3.7 inches with resolution of 480×800. Though at the default setting, the Nexus One screen is much darker than iPhone. The 5 megapixel camera takes excellent photos. The color palette produce high contrast and saturated photo, much like a Canon DSLR, which I love. The camera is also able to capture video at 720×480 at 20fps+. In fact, the camera has hardware based autofocusing system. It has a LED flash, which is useful in a pinch when you are taking night shoots.

It has a removable battery. The 3G support for T-Mobile’s new full speed HSPA 7.2Mbps is very fast. It also has a active noise canceling mic. On Nexus One, there is a 2nd mic which is used to measure ambient noise and filter it out during your phone call. It works very well in a noisy environment. The call quality is good. Though the speaker at high volume is a bit metallic.

The 1ghz SnapDragon processor is very very fast. The first place you’ll notice this is when you rotate the phone. On other Android phones I’ve used, rotating the phone causes a lag before the screen will redraw in different orientation. On Google Nexus One, it happens right away. No more lag. The built-in GPU also makes this the first Andorid phone I would actually consider develop game for. It supports OpenGL ES 2.0, and has excellent performance. It’s really the first phone I’ve played with that surpass iPhone 3GS’s OpenGL ES 2.0 performance, and that’s no small feat. It has excellent hardware support for H264 decoding too. Videos playback is very smooth and easy on the battery life. The memory has been increased to 512MB, it’s still quite small due to the fact that you can ONLY install Android apps to system memory only. So the MicroSD Slot which allows you to use a 32GB card is basically only for data. It of course has Active GPS, digital compass and accelerometer.

The only con I have on the hardware side is, the touch screen isn’t very accurate. I’m very used to the very accurate iPhone. On Nexus One, touching a small navigation button leads to mistouch very often. This is compounded by the fact that Nexus doesn’t support pinch and zoom. It makes using the web browser a frustrating experience at times. On the bottom row of the screen are 4 dedicated touch buttons for “Previous Screen”, “Menu”, “Home”, and “Search”. I can’t begin to tell you how many times that in the middle of using the virtual keyboard to input my new tweet only to accidentally trigger “Home” button, thus losing EVERYTHING I just typed. It happens a lot because the “Home” key is just below “Space” on the virtual keyboard and with how inaccurate the touch screen is, I mistouch it very often. The other issue deal with editing existing text I typed. On Android, to place the cursor between letters you tap between the two letters. It doesn’t let you zoom and hover like iPhone. So with the inaccuracies of the touch screen, I end up keep taping hoping to land the cursor in the right place.

The other small complaint is, no accessories at all. It launched with nothing. The phone does come with charger, USB cable, headphone and a very cute carrying case. But the dock that was talked about quite a bit only came out a couple of days ago. Mine should be here in the next day or so.

Onward to software. Android has come a long way. I’ve used Android since the pre 1.0 SDK. And I’ve played with each major release since. So I saw how Android is growing up every step of the way. It’s getting much better. But still rough in places. First let’s talk about the good stuff. I love how Google implemented voice input feature. It’s part of the virtual keyboard as a mic icon. You tap it and process with voice input. It translates it into text as if you just typed it. This means it will work on anything that is a text input. Very well thought out. The new Google Maps with the turn by turn voice navigation is the first alternative I would consider against my favorite: TeleNav on Blackberry. Though Google Maps’ speech synthesis for voice navigation is still to robot sounding, it’s very useable. The home screen is now very iPhone-ish. You have multiple pages of apps you can scroll back and forth. But in addition to app shortcuts, you can also place widgets that are irregular size. I especially like the new News and Weather widget, given that I’m a news junkie. The new weather app is also very cool, giving you very detail break down on a interactive timeline. The new full 3d wallpaper is lovely both as eyecandy as well as a demonstration of the GPU’s power. Even if it does suck your battery. Another widget I really like let you change bluetooth/wifi/gps/sync/brightness with a single toggle. No need to go to setting screen. I’m a Google Voice heavy user. Nexus One’s total integration with Google Voice is second to none. The gmail app also address one of my long standing complaint. Up till now you can only access the gmail account that’s associated with your Android phone, to read other gmail accounts you have to set it up as a pop3/imap in the other mail app. That’s just totally silly. In Google Nexus One, finally you can access multiple gmail accounts. The web browser receives some UI tweaks also. The url window is now always visible. The surfing experience is also far more responsive. Not having multitouch is still annoying, but patents, what can you do? The over all UI also has many more transition effects to give it a more smooth experience. This is especially obvious when you bring up the “List of All Apps” screen.

On the negative side. In Android Webkit browser, like iPhone Safari, you can also double tap to “fill” the screen with the section or the graphics you are interested in reading. But Android’s Webkit browser is far worse at guessing. On iPhone, if I double tap on a graphic, it will fill 100% of the screen correctly everytime. On Nexus One, most of time I only end up with 80% of the screen filled. It also guess wrong quite often when I’m reading multi column website and double tap to read a particular section.

The music player is terrible. It’s very barebone. It doesn’t support podcast at all. I use Google Listen, which is an app available from Marketplace. It’s serviceable. But it updates feed very slowly, is missing many popular podcasts, and most importantly it stores the downloaded audio in a goofy file name so if I dock the Nexus One into a mp3 playing device. It won’t play. The clock app only has alarm, but no timer or stop watch function. There is no dedicated video player, only a YouTube player. The calculator supports sin/cos by using a “advance” panel is pretty useless.

I have mix feelings about the Market Place. I’m not the type of person that goes “App Store has 100k apps, Andorid Market Place has 20k, thus, Android sucks!” If that’s the logic you want to use, we should all be using Windows. The reason I have mix feelings are two folds. 1: For the apps I’m looking for, there are less apps which are “good”. 2: The same apps on iPhone vs Nexus One. The Nexus One version are worse, at least for the ones I use.

Let me give an example for the first reason. Twittering Apps. On iPhone I switch back and forth between Tweetie and EchoFon often because they are both very good and they constantly are trying to outdo each other with new features and new UIs. On Android, I use both Twidroid and Seesmic. Frankly, both of them are at best, serviceable. Twidroid’s UI is a mess. It feels like “never saw a dropdown we don’t like”. Seesmic is more polished, but it crashes every so often. And the notification feature is not reliable. Another example would be gaming apps. On iPhone, I’m completely addicted to Civ Revolution. It doesn’t exist on Android, the end.

A couple of example of the 2nd reason are WeatherBugs, and AP Mobile. WeatherBugs is very fast and smooth on iPhone. It displays data right away, and screen updates are fast. Interacting with it is instantaneous. On Nexus One, WeatherBugs is laggy, shows me blank screen with no data often, and seems to take forever to acquire GPS lock to give me current location weather. AP Mobile on Android looks far worse than iPhone. On iPhone it does background push notification to tell you about breaking news. On Android, even though I have the notification turned on, it never works.

Now I can hear it. “But it’s not fair. Just because the apps you use are written badly, it’s not Nexus One’s fault”. Sadly, market place don’t care. All they care about is, do apps I use exist on Nexus One? And if so, do they run well?

From a game developer point of view, there are a couple of road blocks in bringing a high end commercial game to Nexus One. The first one I already touched on, it’s a space issue. I have to fit the entire game into a very small package that can only be installed onto the main memory. The second one is lack of any sound streaming and mixing API. Sound is a major factor in gaming. Android’s sound API is frankly terrible, and it’s not something I can work around by using native SDK.

But at the end of the day, I like Google Nexus One. I think it’s the first credible competitor to iPhone. And I love competitions.

ftp using Groovy and Grape UPDATE

People always look at me in disbelieve when I say I use groovy to setup a bunch of cron scripts to ftp and process millions of records daily. Then they are even more surprised when I said I can set it up in a matter of minutes. Here is how I do it.

import org.apache.commons.net.ftp.FTPClient

start()

@Grab(group='commons-net', module='commons-net', version='2.0')
def start()
{
  def ftpClient = new FTPClient()
  ftpClient.connect("ftp server address here")
  ftpClient.enterLocalPassiveMode()
  println(ftpClient.replyString)
  ftpClient.login("username","password")
  println(ftpClient.replyString)
  ftpClient.changeWorkingDirectory("directory the file is in")
  println(ftpClient.replyString)
  ftpClient.fileType=(FTPClient.BINARY_FILE_TYPE)
  println(ftpClient.replyString)

  def incomingFile = new File("localfilename")
  incomingFile.withOutputStream { ostream ->
    ftpClient.retrieveFile("remotefilename", ostream )
  }
  println(ftpClient.replyString);
  ftpClient.disconnect()
}

I use Grab so I don’t have to worry about dependencies. At each step after issuing a command, I then do a “println(ftpClient.replyString)” to see the output for diagnostic purposes. I’m also using “enterLocalPassiveMode()” to use ftp passive mode. I wrapped it in start() to work around the @Grab in Groovy 1.6 must be attached to something. You won’t need to do that if you are using Groovy 1.7. I also set the transfer mode to explicitly binary because most of the times I’m dealing with zip files.

Then I open a local file, use Groovy’s with block to manage the download. Then disconnect.

Groovy makes this so simple it takes me longer to explain it than writing the code, which is why I post it here instead of keep emailing this to everyone who asked. :)

UPDATE: Guillaume Laforge, the master of Groovy himself suggested I use with.{} block to avoid repeating the prefix over and over again. He posted it here.

It’s a great suggestion. I must admit to this date, I often forget about with.{}. I’ve reproduced his code below.

@Grab(group='commons-net', module='commons-net', version='2.0')
import org.apache.commons.net.ftp.FTPClient

new FTPClient().with {
    connect "ftp server address here"
    enterLocalPassiveMode()
    login "username", "password"
    changeWorkingDirectory "directory the file is in"
    fileType = FTPClient.BINARY_FILE_TYPE
    def incomingFile = new File("localfilename")
    incomingFile.withOutputStream { ostream -> retrieveFile "remotefilename", ostream }
    disconnect()
}

Ninety-Nine Problems In Clojure Part 1 1-15

The original Ninety-Nine Prolog Problems was written by Werner Hett at the Berne University of Applied Sciences in Berne, Switzerland.  Phil Gold then adapted it to Ninety-Nine Scala Problems. I had fun reading them. It has inspired me to do a series of Ninety-Nine Problems in different languages. I’m starting with Clojure.

I’m taking a more practical approach. I use built-in library whenever possible. I use clojure-contrib as well. Because on a day to day basis, this is what we all do. They exist for a reason after all. If you feel that’s cheating. Feel free to write your own. :)

The difficulty ranking was for Prolog. The original text says

The problems have different levels of difficulty. Those marked with a single asterisk (*) are easy. If you have successfully solved the preceeding problems you should be able to solve them within a few (say 15) minutes. Problems marked with two asterisks (**) are of intermediate difficulty. If you are a skilled Proglog programmer it shouldn’t take you more than 30-90 minutes to solve them. Problems marked with three asterisks (***) are more difficult. You may need more time (i.e. a few hours or more) to find a good solution.

I think the difficulty scale for the most part is comparable in Clojure.

P01 (*) Find the last element of a list.
Example:

user=> (last [1 1 2 3 5 8])
8
P02 (*) Find the last but one element of a list.
Example:

user=> (penultimate [1 1 2 3 5 8])
5
P03 (*) Find the Kth element of a list.
By convention, the first element in the list is element 0.Example:

user=> (nth2 2 [1 1 2 3 5 8])
2
P04 (*) Find the number of elements of a list.
Example:

user=> (length [1 1 2 3 5 8])
6
P05 (*) Reverse a list.
Example:

user=> (reverse [1 1 2 3 5 8])
(8 5 3 2 1 1)
P06 (*) Find out whether a list is a palindrome.
Example:

user=> (palindrome? [1 2 3 2 1])
true
P07 (**) Flatten a nested list structure.
Example:

user=> (flatten [[1 1] 2 [3 [5 8]]])
(1 1 2 3 5 8 )
P08 (**) Eliminate consecutive duplicates of list elements.
If a list contains repeated elements they should be replaced with a single copy of the element. The order of the elements should not be changed.Example:

user=> (compress "aaaabccaadeeee")
(\a \b \c \a \d \e)
P09 (**) Pack consecutive duplicates of list elements into sublists.
If a list contains repeated elements they should be placed in separate sublists.Example:

user=> (pack "aaaabccaadeeee")
((\a \a \a \a) (\b) (\c \c) (\a \a) (\d) (\e \e \e \e))
P10 (*) Run-length encoding of a list.
Use the result of problem P09 to implement the so-called run-length encoding data compression method. Consecutive duplicates of elements are encoded as tuples (N, E) where N is the number of duplicates of the element E.Example:

user=> (encode "aaaabccaadeeee")
((4 \a) (1 \b) (2 \c) (2 \a) (1 \d) (4 \e))
P11 (*) Modified run-length encoding.
Modify the result of problem P10 in such a way that if an element has no duplicates it is simply copied into the result list. Only elements with duplicates are transferred as (N, E) terms.Example:

user=> (encode-modified "aaaabccaadeeee")
((4 \a) (\b) (2 \c) (2 \a) (\d) (4 \e))
P12 (**) Decode a run-length encoded list.
Given a run-length code list generated as specified in problem P10, construct its uncompressed version.Example:

user=> (decode [[4 \a] [1 \b] [2 \c] [2 \a] [1 \d] [4 \e]])
(\a \a \a \a \b \c \c \a \a \d \e \e \e \e)
P13 (**) Run-length encoding of a list (direct solution).
Implement the so-called run-length encoding data compression method directly. I.e. don’t use other methods you’ve written (like P09’s pack); do all the work directly.Example:

user=> (encode-direct "aaaabccaadeeee")
((4 \a) (\b) (2 \c) (2 \a) (\d) (4 \e))
P14 (*) Duplicate the elements of a list.
Example:

user=> (duplicate "abccd")
(\a \a \b \b \c \c \c \c \d \d)
P15 (**) Duplicate the elements of a list a given number of times.
Example:

user=> (duplicate-n 3 "abccd")
(\a \a \a \b \b \b \c \c \c \c \c \c \d \d \d)

Bleeding Edge Clojure Development using clj-gradle

Clojure is evolving very rapidly. I find myself using clojure and clojure-contrib from github most of the time. It’s rather annoying to have to keep git pull and build them often. A few days ago, a CI server was setup for clojure.org to build both clojure and clojure-contrib and made them available in mvn style repo.

Excellent, this means I can just use Gradle to handle it for me. For any new bleeding edge clojure project, all you need is the clj-gradle-1.0.0.jar and build.gradle file. If you don’t have the clj-gradle-1.0.0.jar go here to see how to build it.

Here is the updated version of the build.gradle file.

buildscript {
  repositories {
    flatDir(dirs:'lib')
  }
  dependencies {
    classpath name: 'clj-gradle-1.0.0'
  }
}

usePlugin(de.kotka.gradle.ClojurePlugin)
  repositories {
    flatDir(dirs:'lib')
  }

configurations {
  compileOnly {
    setVisible(false)
    setTransitive(false)
  }
  compile.extendsFrom(compileOnly)
}

repositories {
  mavenCentral()
  mavenRepo urls: "http://build.clojure.org/snapshots"
}

dependencies {
  compileOnly name: 'clj-gradle-1.0.0'
  compile 'org.clojure:clojure-lang:1.1.0-alpha-SNAPSHOT'
  compile 'org.clojure:clojure-contrib:1.0-SNAPSHOT'
}

task initProject(description: 'Initialize project directory structure.') << {
  ['clojure'].each {
  convention.sourceSets.all*."${it}".srcDirs*.each { it.mkdirs() }
  }
}

task copyToLib(dependsOn: configurations.default.buildArtifacts, type: Copy) {
  into('build/lib')
  from configurations.default
  from configurations.default.allArtifacts*.file
}

I’m using the shorthand syntax for dependencies. I also added mvn repo support. There is a separate entry to point to build.clojure.org. Two tasks were also added. One is initPrjoject. The initProject task was both inspired by Gradle cookbook as well as Hubert Klein Ikkink’s blog post on mixed Groovy and Java using Gradle.

The copyToLib was from the Gradle cookbook also.

That’s all there is to it. Gradle will now take care of all your build needs. If you want to use clojure 1.0 instead of the bleeding edge. Change the line “compile ‘org.clojure:clojure-lang:1.1.0-alpha-SNAPSHOT'” to “compile ‘org.clojure:clojure:1.0.0′”. There isn’t a mvn repo version of clojure-contrib though.

At some point, the artifact id is changing from clojure-lang to just clojure as per this ticket. When that happens, just change your build.gradle file accordingly.

Wave Robot Using Groovy and Gaelyk Part 1 UPDATE

When I first saw Google Wave, all sorts of ideas came to me right away. I wanted to use Google App Engine and Google Wave to do some prototyping on some of the gaming ideas I have. Really, real time XMPP open system with the scalability of Google App Engine, what’s not to like?

The question is, what tools to use. Right now Wave Robot has to be hosted on Google App Engine. I tend to use Groovy for rapid prototyping. That quickly narrows it down to Grails vs Gaelyk. I decided to go with Gaelyk because this really isn’t a traditional web application. Wave Robots interact with people through a series of servlets. Using Grails would be unnecessary for my needs. The approach Guillaume Laforge took with Gaelyk where he effectively groovifed the GAE API is a good fit. My plan is to split the code into three parts. Groovy servlets to handle Wave Robot interaction. Gaelyk to handle the GAE interaction such as DataStore, TaskQueue, Mail, and also to display some simple info if people come to the app itself. The final part is the Game AI part. Given GAE’s daily cpu quota, I don’t know if a complex AI engine will burn it up. I’ll find out soon enough.

I’ll be using IntelliJ 8.1.3. It has terrific support for Groovy and Google App Engine. So let’s get started. You need to download the Google App Engine SDK if you don’t already have it.

First let’s create a new Google App Engine project. For details on how to do that,  check here

Then we need to set it up for Gaelyk.

Edit web/WEB-INF/appengine-web.xml
You have to put in the application id you’ve registered for Google App Engine.
Version number default is 1. That’s fine. Version number is a string, so you can put anything. you can put “theawesomeapp” if you like. If you do that, that particular version of the app will be available under the url theawesomeapp.latest.(yourappid).appspot.com. This let you test and deploy multiple versions of the app.

Add the following to the file

<static-files>
<exclude path="/WEB-INF/**.groovy" />
<exclude path="**.gtpl" />
</static-files>

Now to edit web/WEB-INF/web.xml

Add the following

<!-- The Gaelyk Groovlet servlet -->
<servlet>
<servlet-name>GroovletServlet</servlet-name>
<servlet-class>groovyx.gaelyk.GaelykServlet</servlet-class>
</servlet>

<!-- The Gaelyk template servlet -->
<servlet>
<servlet-name>TemplateServlet</servlet-name>
<servlet-class>groovyx.gaelyk.GaelykTemplateServlet</servlet-class>
</servlet>

<!-- Specify a mapping between *.groovy URLs and Groovlets -->
<servlet-mapping>
<servlet-name>GroovletServlet</servlet-name>
<url-pattern>*.groovy</url-pattern>
</servlet-mapping>

<!-- Specify a mapping between *.gtpl URLs and templates -->
<servlet-mapping>
<servlet-name>TemplateServlet</servlet-name>
<url-pattern>*.gtpl</url-pattern>
</servlet-mapping>

<!-- Define index.gtpl as a welcome file -->
<welcome-file-list>
<welcome-file>index.gtpl</welcome-file>
</welcome-file-list>

now create web/index.gtpl
put the following in the file.

<html>
<body>
<p>
<% def message = "Gaelyk is working!" %>
</p>
<ul>
<% 3.times { %>
<li>${message}</li>
<% } %>
</ul>
</body>
</html>

under web/WEB-INF, create a groovy directory and a lib directory.

edit web/WEB-INF/groovy/dostuff.groovy
put the following in the file.

html.html {
body {
[1, 2, 3, 4].each { number -> p number }

p "Let's have a thumb war!"
}
}

you also need to put the following jars in web/WEB-INF/lib

first the two jars from Google App Engine SDK:appengine-api-1.0-sdk-1.2.6.jar and appengine-api-labs-1.2.6.jar.

the Groovy jar: groovy-all-1.6.5.jar

Then the Gaelyk jar. I build gaelyk-0.3-SNAPSHOT.jar from github. Mostly because Guillaume hasn’t had time to build 0.3 yet. You can use 0.2 from Gaelyk site..

After this, add lib to your module library path.

Congratulation, your Gaelyk environment is all set. Run it, and you’ll see the output “Gaelyk is working!” 3 times. That comes from index.gtpl. Now go to http://localhost:8080/dostuff.groovy you’ll see the output from the dostuff.groovy Groovlet.

With Gaelyk setup out of the way, it’s time to get to the Wave Bot.  First you need to download a few files from Wave Robot Java Client Library. Get all 4 of them and place them under WEB-INF/lib.  We only need 3 of them right now. But oauth will come in handy later.

Create a new directory called _wave under web. And create a file web/_wave/capabilities.xml,

<?xml version="1.0"?>
<w:robot xmlns:w="http://wave.google.com/extensions/robots/1.0">
<w:capabilities>
<w:capability name="blip_submitted"/>
</w:capabilities>
<w:version>Alpha1</w:version>
</w:robot>

This is where we tell Wave which events our Wave Robot cares about. In this case, we want blip_submitted. This event occurs everytime someone “completes” a blip by either clicking on “Done”, or hit shift-enter. There is also a version number for the Wave Robot. This version number has NOTHING to do with the Google App Engine version number. Everytime you create a new version of the Wave Robot you have to change this. Because Google Wave caches your robot. Again, it’s a string. So you can put whatever you want.

Now to create the servelets that let our Wave Robot to pretend to be human. Under src, create a groovy directory.

First create src/groovy/ProfileServlet.groovy using the following

import com.google.wave.api.ProfileServlet

class ProfileServlet extends com.google.wave.api.ProfileServlet {

  String RobotName="Wave Nakama"
  String RobotAvatarUrl="http://wavenakama.appspot.com/images/wnlogo.gif"
  String RobotProfilePageUrl="http://wavenakama.appspot.com/"

}

This servlet is called whenever someone try to get the profile on your Wave Robot.

Then create src/groovy/SayanythingServlet.groovy using the following

import com.google.wave.api.*

class SayanythingServlet extends AbstractRobotServlet {

    void processEvents(RobotMessageBundle bundle) {
        def wavelet = bundle.wavelet
        if (bundle.wasSelfAdded()) {
            def blip = wavelet.appendBlip()
            def textView = blip.document
            textView.append("Your wish is my command!")
        }
        for (event in bundle.events) {
            if (event.type == EventType.BLIP_SUBMITTED) {
                def blip = wavelet.appendBlip()
                def textView = blip.document
                textView.append("Tell me more about ${event.blip.document.text} Please. You are so interesting!")
            }
        }
    }

The servlet responds to two events. The first was is “wasSelfAdded”. This happens when the Wave Robot is first added to the Wave. Think of it as your Wave Robot’s greeting. The second one is what we marked back in the capabilities.xml, BLIP_SUBMITTED. You can access the blip that just occurred in event.blip.document.text.

Now we have to edit the the web.xml again to register the two servlets. Google Wave expects the Wave Robot to repsond to specific urls.

Add the following to the web.xml

<servlet>
<servlet-name>Sayanything</servlet-name>
<servlet-class>SayanythingServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Sayanything</servlet-name>
<url-pattern>/_wave/robot/jsonrpc</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>Profile</servlet-name>
<servlet-class>ProfileServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>Profile</servlet-name>
<url-pattern>/_wave/robot/profile</url-pattern>
</servlet-mapping>

The Profile servlet must respond to the url /_wave/robot/profile. The Wave Robot communicate with the Wave system using /_wave/robot/jsonrpc

That’s it. Right now there is no way to test Wave Robot locally. However, you can see if the Wave Robot is responding to the Profile call correctly by going to http://localhost:8080/_wave/robot/profile. If everything is working, you’ll see a JSON output of the Wave Robot profile.

I created an image to be used as the Wave Robot profile picture and placed it under web/images.
Final step, time to upload the application to Google App Engine.

When it’s done, try it out by going to (applicationid).appspot.com to verify your app is working. Then create a new Wave. Add your Wave Robot as a participant by using the address (applicationid)@appspot.com. For example, in my case it’s wavenakama@appspot.com.

If all goes well, you now have the basic Gaelyk and Wave Robot setup for you to experiment with.

One thing you’ll notice is the Profile url for the Wave Robot doesn’t appear to be working. I’m guessing it’s a bug of the API.

UPDATE: Thanks to Tim Yate who tracked this done. The official code is wrong. It’s RobotProfilePageUrl, not RobotProfileUrl. I’ve corrected the code sample, and filed an issue with Google.

Gradle + Clojure = clj-gradle

I’m not a maven fan. I use it with lift, but that’s pretty much it. In short, I only use it when I’m forced to. So when Gradle came along, I adapted it pretty early on. If you don’t know what Gradle is. Check it out here. It has extensive documentation, which is very impressive considering the project is so young.

When Meikel Brandmeyer announced he wrote clj-gradle, I really wanted to try it out. I finally found time to give it a spin. I ran into a few bumps, but I did get it to work. Here is what I did, step by step.

Get the source. You need mercurial. Use “hg clone http://bitbucket.org/kotarak/clj-gradle/”

In the directory, “mkdir lib”, then put clojure-1.0.0.jar in lib.

Check the build.gradle file, the version number should be set to 1.0.0

Issue “gradle build”. You should get a build successful. The file clj-gradle-1.0.0.jar is created under build/libs.

You are done. Time to try it out.

Create a new sandbox directory. Then issue “mkdir lib”, you need to put both clj-gradle-1.0.0.jar clojure-1.0.0.jar in lib.

I followed the README and created src/main/clojure/test/example.clj, then pasted in the code from it.

(ns test.example
  (:gen-class))

(defn -main
  []
  (println "Hello, World!"))

I then use the build script from README, with a few changes to put in specific version number.

buildscript {
  repositories {
    flatDir name: 'lib', dirs: 'lib'
  }
  dependencies {
    classpath name: 'clj-gradle-1.0.0'
  }
}

usePlugin(de.kotka.gradle.ClojurePlugin)
  repositories {
    flatDir name: 'lib', dirs: 'lib'
  }

configurations {
  compileOnly {
    setVisible(false)
    setTransitive(false)
  }
  compile.extendsFrom(compileOnly)
}

dependencies {
  compileOnly name: 'clj-gradle-1.0.0'
  compile name: 'clojure-1.0.0'
}

Now issue “gradle build”, you should get a build successful. To run it, I used “java -cp lib/clojure-1.0.0.jar:build/libs/cljgradletest-unspecified.jar test.example” I used cljgradletest-unspecified.jar because the name of my sandbox directory is cljgradetest. All goes well, you’ll see the “Hello, World!” output. Congratulation, your clojure project is now backed by Gradle.

Kindle 2 International Version

I’ve been reading books on laptops and PDAs for years. I still remember fondly of reading on my Clie NZ90. With the latest price drop and the new international version I decided it was time to give Kindle 2 a shot.

It arrived in a tiny brown box, with a cute opening tab

When you open it up, this is what you see.

The unit feels thin and light in your hand.

The manual is under the unit

The cable is under the manual

Here is the charging cable by itself

The back of the unit feels cheap to me. I don’t know why there are all these streaking marks all over the metal plate.

To show you what reading on Kindle 2 is like. I took this picture at normal reading distance using a normal view lens. I also use daylight in a cloudy day. The book on the screen is Programming in Clojure. You can see how it wraps the code due to not enough space.

When you buy Kindle, it comes pre-registered to the amazon account you used to buy it. If it’s a gift or for someone else you’d have to de-register on the buying account first. They did this so it works “out of the box”. Amazon has clearly take a page from Apple when it comes to packaging and presentation. The packaging feels small footprint, environmentally friendly and “green”.

The e-ink screen reading experience is good. I can totally understand why one of my friends said “This is so much better than reading on laptop. I don’t feel like someone is shinning a flashlight into my eyeballs”. But the e-ink display is still slow at refreshing the page. There is a 1-2 sec pause between flipping pages. When you press next page, the screen will go completely black briefly before rendering the next page.

I don’t think Kindle 2 is a good device for reading tech books though. If you look at the screen shot above, you’ll see how the code wraps very badly due to not enough space. I’ve also seen tables rendered very poorly again due to lack of space. When I read tech books, I tend to flip back and forth quite a bit. This is clumsy to do on Kindle 2. The navigation UI is not that great either.

On the other hand, I bought two mystery novels, two fantasy novels, and two political science books. Reading those on Kindle 2 is great. Because they don’t really have any tables/digrams. No color content existed at all. I’m just reading them through, page by page. In those situations, Kindle 2 works as advertised.

So for the time being, I’d say Kindle 2 is excellent if you are reading for fun. But as a tool for teachers/students/researcher, not so much.

I did run into two issues trying to buy books for Kindle 2. The first one was when I tried to buy 6 books rapidly in a row, since Amazon does this as six transactions in a row. The bank rejected the 6th transactions. I wish I can buy them as a single transaction. After all, it’s not uncommon for me to go to bookstore and buy 6 books together.

The second problem isn’t a Kindle one, but really more of a sad note. I was looking for tech books that works on Kindle 2. O’Reilly supports Kindle 2 using the mobi format, and I saw O’Reilly is doing a buy 2 get 1 free. I figured since O’Reilly used to be my favorite publisher, this should be no problem. Sadly after looking for about 30 minutes, I could only find two. One of them in fact is just the ebook version of the printed “Real World Haskell” I already own. Manning and APress really has taken over as the superior tech book publishers.

←Older