Tech behind Tech

Raw information. No finesse :)

Posts Tagged ‘clojure

Compojure Demystified with an example – Part 3

with 19 comments

In part2 we saw how to setup a skeleton project with Compojure. In this part we will see how to add static files to a Compojure project.

For our application, we will use JQuery as front end and Clojure as a backend. I will concentrate more on Compojure.

1) Create folders for static files.

mkdir public
mkdir public/css
mkdir public/js

It is better to have static files under a seperate directory that way you could use your webserver to serve these files. For now we will use Compojure to serve these files.

2) Create index.html under public folder

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
	"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
	<head>
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
		<title>My Address book</title>
		<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
	</head>

  <body id="main">
    <p>
      My Address Book
    </p>
  <body>
</html>

3) Start your server

lein repl src/address_book/core.clj

4) Access index.html

Go to http://localhost:8080/index.html . You will get “Page not found” instead of “My Address Book”. This is happening because we have not told compojure about our static files folder.

Route helper functions in Compojure

In Compojure we have two route helper functions. We have seen one already in core.clj file.

1) not-found :

This function is used to capture all other routes that are not defined in Compojure. As we still have not defined index.html we got “Page not found”.

2) files :

This function is used to inform Compojure where static files are present.

Lets change our core.clj to handle static files

(ns address_book.core
  (:use [compojure.core]
        [ring.adapter.jetty])
  (:require [compojure.route :as route]))

(defroutes example
  (GET "/" [] "<h1>My Address Book!</h1>")
  (route/files "/" {:root "public"})
  (route/not-found "Page not found"))

(run-jetty example {:port 8080})

Restart your server (there is a way to avoid restarting using futures. I will show that in a later blog) and access http://localhost:8080/index.html . Now you should see “My Address Book”.

In this part we saw how we can handle static files. In next part we will implement Add , View and View All functionalities.

PS: Using Hiccup you can create HTML and css in clojure. I will try to cover this in future blogs.

Source code is now available at github . Created branches for each part.

Checkout PART4

Written by Siva Jagadeesan

August 16, 2010 at 9:04 pm

Posted in Clojure

Tagged with , ,

Compojure Demystified with an example – Part 2

with one comment

In part 1 I introduced the address book application that we are going to build.

In this part we will setup our skeleton project with compojure.

1) Install Leiningen

http://github.com/technomancy/leiningen/blob/master/README.md

2) Create a new project using Leiningen

lein new address_book

3) Add Compojure to our project:

a) Edit project.clj

(defproject address_book "1.0.0-SNAPSHOT"
  :description "Address Book"
  :dependencies [[org.clojure/clojure "1.1.0"]
                 [org.clojure/clojure-contrib "1.1.0"]
                 [compojure "0.4.1"]
                 [ring/ring-jetty-adapter "0.2.3"]])

b) Install dependencies

lein deps

This should install all dependencies of compojure

c) Test whether our setup is working

Edit src/address_book/core.clj

(ns address_book.core
  (:use [compojure.core]
           [ring.adapter.jetty])
  (:require [compojure.route :as route]))

(defroutes example
  (GET "/" [] "My Address Book!")
  (route/not-found "Page not found"))

(run-jetty example {:port 8080})

Run the server

lein repl src/address_book/core.clj

Goto http://localhost:8080 and you should see “My Address Book!”

In next part we will start implementing our functionalities.

Written by Siva Jagadeesan

August 15, 2010 at 6:49 pm

Posted in Clojure

Tagged with , ,

Compojure Demystified with an example – Part 1

with one comment

In this part, I am going to talk about what application we are going to implement.

Lets build a simple address book web application using compojure. This will be a RESTFUL application. As we go through this example we will see some interesting aspects of compojure.

Functionalities

  • Add / Edit / Delete Address book
  • View All Addresses
  • View a single Address

Domain

Address

  • Name
  • Street1
  • Street2
  • City
  • Country
  • ZipCode

REST interfaces we will implement

  • View All Addresses – GET – http://localhost:8080/addresses
  • View single address – GET – http://localhost:8080/addresses/:id
  • Add Address - POST – http://localhost:8080/addresses
  • Edit Address - PUT – http://localhost:8080/addresses/:id
  • Delete Address – DELETE – http://localhost:8080/addresses/:id

Next part 2 we will setup our base project with compojure.

Written by Siva Jagadeesan

August 14, 2010 at 12:15 pm

Posted in Clojure

Tagged with , ,

Map, Reduce and Filter in Clojure

with 2 comments

Map

Map applies a function to each element in a collection and returns a new collection with the results of each function.

map.png

user> (map #(+ 10 %1) [ 1 3 5 7 ])
(11 13 15 17)

Reduce

Reduce applies a function on all elements of a collection and returns a value. This value could also be another collection.

reduce.png

user> (reduce * [2 3 4])
24

Filter

Filter applies a predicate function to each element in a collection and returns a new filtered collection.

filter.png

user> (filter even? [1 2 3 4 5 6])
(2 4 6)

Written by Siva Jagadeesan

July 26, 2010 at 10:00 pm

Posted in Clojure

Tagged with , , ,

Different tools to help you test your clojure code

leave a comment »

Problem :

We need to parse a xml string and be able to query using xpath style tag list.

Ex :

<friends>
  <person>
   <name>Siva</name>
  </person>
</friends>

I need a function that can do this,

(get-value xml :person :name)
returns “Siva”

Solution :

To parse and query xml we need to do these following three things in clojure.

1) Convert xml string (file) to Struct Map

Clojure core comes with a build in xml library (clojure.xml http://richhickey.github.com/clojure/clojure.xml-api.html) that has a parse function which takes in InputStream and returns a struct map that represents xml.

(defn get-struct-map [xml]
  (let [stream (ByteArrayInputStream. (.getBytes (.trim xml)))]
    (xml/parse stream)))

user> (get-struct-map xml)
{:tag :friends, :attrs nil, :content [{:tag :person, :attrs nil, :content [{:tag :name, :attrs nil, :content ["Siva"]}]}]}

This struct map is cumbersome to query.

2) Convert Struct Map to Zipper Data Structure

“A zipper is a technique of representing an aggregate data structure so that it is convenient for writing programs that traverse the structure arbitrarily and update its contents, especially in purely functional programming languages.” http://en.wikipedia.org/wiki/Zipper_%28data_structure%29

To make it easy for us to traverse we will change struct map to zipper data structure. Clojure comes with zip library ( it is short form for zipper ) http://richhickey.github.com/clojure/clojure.zip-api.html

We will this zip library to convert xml struct map to zipper data structure.

user> (clojure.zip/xml-zip xml-struct)
[{:tag :friends, :attrs nil, :content [{:tag :person, :attrs nil, :content [{:tag :name, :attrs nil, :content ["Siva"]}]}]} nil]

3) Use Zip-filter library and query zipper data structure.

Now that we have our xml in zipper data structure we could use zip-filter library that is present in clojure.contrib. http://richhickey.github.com/clojure-contrib/zip-filter-api.html

user> (clojure.contrib.zip-filter.xml/xml-> zipper-struct :person :name)
("Siva")

Putting this altogether

(ns com.sivajag.utils.xml
  (:import (java.io ByteArrayInputStream))
  (:require [clojure.xml :as xml])
  (:require [clojure.zip :as zip])
  (:require [clojure.contrib.zip-filter.xml :as zf]))

(defn get-struct-map [xml]
  (if-not (empty? xml)
    (let [stream (ByteArrayInputStream. (.getBytes (.trim xml)))]
      (xml/parse stream))))

(defn get-value [xml &amp; tags]
  (apply zf/xml1-> (zip/xml-zip (get-struct-map xml)) (conj (vec tags) zf/text)))

user> (get-value xml :person :name)
"Siva"

Happy Coding!!!

Written by Siva Jagadeesan

July 24, 2010 at 12:51 am

Posted in Clojure

Tagged with ,

Clojure futures – A Walkthrough

leave a comment »

What is Future?

It is a simple mechanism to execute a snippet of code on a background thread.

How to use Future?

We can use Future in two ways.

1) Using macro “future”

	
  (def f
	(future
 		(prn "going to sleep...")
		(Thread/sleep 10000)
		(prn "slept good")))

2) Using function “future-call”

(defn long-process[]
  (Thread/sleep 10000))

(future-call long-process)

Under the shell both these ways are equivalent. The macro is syntax sugar and it gets converted to future-call.

Even though “long-process” function is put to sleep for 10 secs, it will return immediately. It returns a “future” object. We can use this object to inspect whether the function has been executed in background thread.

(future-done? f)
(future-cancelled? f)
(future-cancel f)

Limitations of Future?

As you known clojure comes with a bounded thread pool and unbounded thread pool. Mostly CPU bound operations should be using bounded thread pool and IO operations should be using unbound thread pool. Clojure Future uses unbounded thread pool, so it is good for IO operations but not for CPU bound operations. So for CPU bound operations Future might not be a good choice. But there is a open source project that helps to overcome this limitations. Check out http://github.com/amitrathore/medusa

Written by Siva Jagadeesan

July 14, 2010 at 4:22 am

Posted in Clojure

Tagged with , ,

clj-web-crawler – Web Crawling tool in clojure

leave a comment »

I was looking for a simple web crawler in clojure and came across clj-web-crawler (http://github.com/heyZeus/clj-web-crawler) . It took me less than 2 minutes to get started. (thanks to Leiningen)

1) In project.clj add these two lines for :dependencies

                 [com.jmeeks/clj-web-crawler "0.1.0-SNAPSHOT"]
                 [org.clojars.kjw/commons-httpclient "3.1"]	

2) Run lein deps and you ready to play with clj-web-crawler.

Checkout http://github.com/heyZeus/clj-web-crawler for more information

Written by Siva Jagadeesan

July 7, 2010 at 7:22 am

Posted in Clojure

Tagged with , ,

Leiningen Tips

leave a comment »

Tip 1 : Adding License info

To add your license info, add these following lines in project.clj

:license {:name "Eclipse Public License - v 1.0"
          :url "http://www.eclipse.org/legal/epl-v10.html"
          :distribution :repo
          :comments "same as Clojure"}

Tip 2: Turning off auto delete of lib folder

:disable-implicit-clean true

Tip 3: Turning on reflection warning calls

:warn-on-reflection true

Tip 4: Changing JVM level options

:jvm-opts "-Xmx1g"

Written by Siva Jagadeesan

June 29, 2010 at 8:08 pm

Posted in Clojure

Tagged with , ,

Parsing XML in Clojure

with 5 comments

Problem :

We need to parse a xml string and be able to query using xpath style tag list.

Ex :

<friends>
  <person>
   <name>Siva</name>
  </person>
</friends>

I need a function that can do this,

(get-value xml :person :name)

returns “Siva”

Solution :

To parse and query xml we need to do these following three things in clojure.

1) Convert xml string (file) to Struct Map

Clojure core comes with a build in xml library (clojure.xml http://clojure.github.com/clojure/clojure.xml-api.html) that has a parse function which takes in InputStream and returns a struct map that represents xml.

(defn get-struct-map [xml]
  (let [stream (ByteArrayInputStream. (.getBytes (.trim xml)))]
    (xml/parse stream)))

user> (get-struct-map xml)
{:tag :friends, :attrs nil, :content [{:tag :person, :attrs nil, :content [{:tag :name, :attrs nil, :content ["Siva"]}]}]}

This struct map is cumbersome to query.

2) Convert Struct Map to Zipper Data Structure

“A zipper is a technique of representing an aggregate data structure so that it is convenient for writing programs that traverse the structure arbitrarily and update its contents, especially in purely functional programming languages.” http://en.wikipedia.org/wiki/Zipper_%28data_structure%29

To make it easy for us to traverse we will change struct map to zipper data structure. Clojure comes with zip library ( it is short form for zipper ) http://clojure.github.com/clojure/clojure.zip-api.html

We will this zip library to convert xml struct map to zipper data structure.

user> (clojure.zip/xml-zip xml-struct)
[{:tag :friends, :attrs nil, :content [{:tag :person, :attrs nil, :content [{:tag :name, :attrs nil, :content ["Siva"]}]}]} nil]

3) Use Zip-filter library and query zipper data structure.

Now that we have our xml in zipper data structure we could use zip-filter library that is present in clojure.contrib. http://clojure.github.com/clojure-contrib/zip-filter-api.html

user> (clojure.contrib.zip-filter.xml/xml-> zipper-struct :person :name)
("Siva")

Putting this altogether

(ns com.sivajag.utils.xml
  (:import (java.io ByteArrayInputStream))
  (:require [clojure.xml :as xml])
  (:require [clojure.zip :as zip])
  (:require [clojure.contrib.zip-filter.xml :as zf]))

(defn get-struct-map [xml]
  (if-not (empty? xml)
    (let [stream (ByteArrayInputStream. (.getBytes (.trim xml)))]
      (xml/parse stream))))

(defn get-value [xml & tags]
  (apply zf/xml1-> (zip/xml-zip (get-struct-map xml)) (conj (vec tags) zf/text)))

user> (get-value xml :person :name)
"Siva"

Happy Coding!!!

Written by Siva Jagadeesan

June 25, 2010 at 1:57 pm

Posted in Clojure

Tagged with , , ,

Clojure test-is library examples and explanation – Basic

leave a comment »

Clojure contrib comes with a testing framework test-is. Even though it is a small library it does its job. test-is consists many useful functions and macros to help us test our code. I am going to go through some of them and show some examples. Some examples I took it from http://richhickey.github.com/clojure-contrib/test-is-api.html

deftest
Is a macro to define a test function.

Usage

(deftest name & body)

Example

(deftest test-addition
   (is (= (+ 1 2) 3)))

is
It is a generic assertion macro. You will end up using this a lot in your test code.

Usage

(is form)
(is form msg)

Examples

(is (= (+ 1 2) 3))

[or]

user> (is (= (+ 2 1) 3) "should be 3")
true
user> (is (= (+ 3 1) 3) "should be 3")

FAIL in clojure.lang.PersistentList$EmptyList@1 (NO_SOURCE_FILE:1)
should be 3
expected: (= (+ 3 1) 3)
actual: (not (= 4 3))
false

This “is” macro could be used to test exceptions too.

(is (thrown? c body))
(is (thrown-with-msg? c re body))

are

Sometimes just using “is” will become tedious.

(deftest test-addition
   (is (= (+ 2 1) 3))
   (is (= (+ 0 0) 0))
   (is (= (+ -1 -1) -2)))

Using “are” we could clean up this test function as

(deftest test-addition
  (are [x y] (= x y)
     3 (+ 2 1)
     0 (+ 0 0)
     -2 (+ -1 -1)))

The only problem using “are” is when a test fails it screws up line number where failure happened.

testing

This is my favorite macro. It allows me organize my tests.

Lets take this test

(deftest test-addition
   (is (= (+ 2 1) 3))
   (is (= (+ 0 0) 0))
   (is (= (+ -1 -1) -2)))

Imagine it is doing some complicated stuff. This test does not express intent. Using “testing” we can rewrite

(deftest test-addition
   (testing "should add positive numbers"
      (is (= (+ 2 1) 3)))
   (testing "should add zeros"
     (is (= (+ 0 0) 0)))
   (testing "should be able to add negative numbers"
      (is (= (+ -1 -1) -2))))

The best part if a test fails it prints the string next to “testing”

(test-addition)

FAIL in (test-addition) (NO_SOURCE_FILE:1)
should be able to add negative numbers
expected: (= (+ -1 -1) -3)
actual: (not (= -2 -3))

Happy testing …

Written by Siva Jagadeesan

June 22, 2010 at 5:47 am

Posted in Clojure

Tagged with , ,

Follow

Get every new post delivered to your Inbox.

Join 105 other followers