Monday, March 28, 2011

Getting Started with Ring and Compojure - Clojure Web Programming

I am currently testing out different technologies to run a small web service in a windows environment at my day job. I have worked with Node.js on Linux but have not had much luck with it on windows. At the same time I am also learning Clojure so I did some checking to see what type of web development options are available in Clojure and I found Ring and Compojure. In this post I will follow the same process I did in my Getting Started with Node.js post, that is to start off with a bare bones ‘Hello World’ sample with Ring and then follow that up with a sample using Compojure to receive parameters by GET and POST.

The Setup

If you don’t already have Clojure installed you can get everything you need from the download page. While you are there go ahead and grab the clojure-contrib zip as well. Assuming you already have Java on your machine the next step is to add the Clojure and Clojure-contrib directories to your CLASSPATH.

Once you have Clojure installed the next thing to install is lein. It is a Clojure build tool that helps you manage your projects. In my short period of time in the Clojure world lein has been a great tool and I have found it has many useful plugins. The install takes no time at all, just follow the instructions on the project’s page and you will be ready for business. Now that I have Clojure and lein installed I'm ready to start the ‘Hello Clojure Web’ project.

Creating the Hello Clojure Web App

Step number one is to create the project using lein by running the command:

lein new hello-clojure-web

When lein has finished there will be a new directory named hello-clojure-web. When you cd into the directory and do dir or ls you should see a directory structure similar to this:

image

Lein creates a directory structure for our project separating the tests from the source code, a .gitignore file and a project.clj file. The project.clj file it handles project dependencies and sets up variables that are used to describe the project. We will just scratch the surface of the project file in this post.

The project.clj File

In the project.clj file the first line simply defines the name and version of the project. The dependencies section is used to list what libraries the project depends on. For our app we need to add the dependencies to the ring-core and ring-jetty-adapter libraries. To get the exact information I needed to add in the dependencies section I turned to the clojars.org site. The clojars site is a place where you can find open source libraries. It provides you with the exact syntax required to add the library to your project. To see what a clojars page looks like visit the ring/ring-core page. The line below adds the two ring dependencies I need for my project. Dependencies are added by using the libraries name followed by the version you wish to use.

[ring/ring-core "0.3.7"][ring/ring-jetty-adapter "0.3.7"]

After we've added to the Ring dependency our project.clj file should look like:

After adding my dependencies to the project.clj file I need to 'install' them. Lein will do it for me when I run this command:

lein deps

Lein will retrieve the necessary files and place them in the primageoject's lib directory. If all goes well you should see something like the image to the right. If you see an error message text similar to this towards the bottom of the message:

1 required artifact is missing.

for artifact:
org.apache.maven:super-pom:jar:2.0

It usually means that you have misspelled the name of a dependency in the project.clj file. To see it for yourself remove a letter from the dependency we just added, save the file and then re-run the lein deps command.

src/hello-clojure-web/core.clj

When I created the project lein created a core.clj file in the src/hello-clojure-web directory. The only line inside of the file is the project's namespace declaration. My first step was to add a reference to the ring.adapter.jetty library which I will us to run our HTTP service. Next, I added the handler function which handles the web requests. The last line of the file starts the web service passing the handler function to the run-jetty function. Here is the completed hello-clojure-web/core.clj file.

The handler function takes one parameter which is the web request and returns the response. It hanldes all web requests that come on on port 8080 returning the same response for a request at ‘/’ and ‘/this/is/a/long/one’.

In order to test our project out we will use the REPL. Starting the REPL session with lein makes it easier to run our code within the REPL session. To start a REPL session I need to jump back to the command prompt in the project's home directory and run:

lein repl

From within the REPL session enter the following line:

(use 'hello-clojure-web.core)

This will starts up my service which is now listening for requests on port 8080. Next, I fired up Chrome and entered http://localhost:8080. If everything works correctly I should see Hello Clojure Web! If you do not see the text then an error has occurred. Usually the REPL gives an error message that will point you in the right direction.

I want to change the text to reflect the fact I'm using Ring. I'm going to keep the REPL running and go back to the source file. I changed the Hello Clojure Web string to read Hello Ring!, saved it and refreshed the browser but I didn't see the changes. When I stop and restart the REPL. Re-enter the use statement and reload the web page I will see my changes.

In order for me to see my changes without restarting the REPL I need to add a reference to the ring-devel library. Since I do not want this library to be apart of my ‘production’ version I will only add the dependency to my dev environment by making use of the dev dependency tag. My updated project.clj file now looks like this.

After the changes make sure to run lein deps again. You will see in the output of that command it places files in the hello-clojure-web/libs/dev directory in addition to the hello-clojure-web/libs directory.

Now that I have the dependencies taken care of it is time to update the code in the core.clj file. I've wrapped the run-jetty call in a function called boot so I can make use of the wrap-reload function. What this call does is reload the namespace of our application before each request is handled. So now we can make changes to our code and refresh the browser to see them. Here's what the updated code looks like:

imageAs you can see there wasn't much change in the code needed to be able to handle our updates. To see it in action, start up REPL and view the app in the browser. Change the response text and then reload the web page. You should see our updated message. Next I'll describe how to parse parameters from a GET and POST requests.

Retrieving Parameters

In this section I'm going to introduce Compojure, a small, open source web framework. To keep things simple I am going to add the Compojure code to our already existing core.clj file. Before I make changes to core.clj I need to update the project.clj file with the Compojure dependencies.

The Updated project.clj file

I added the compojure lib in the 'normal' dependencies section and in the dev-dependencies I added the reference to the lein-ring plugin. The ring plugin allows me to start ring by running the command: lein ring server. For the ring server command to work I need to tell ring where the handler method is which is done on the last line of the file. Ring knows that app will handle the web requests. I ran lein deps again to update the project's dependencies to include lein-ring.

Now that the project.clj file is updated I need to adjust the ns statement in the core.clj file to include the Compojure libraries:

(ns hello-clojure-web.core 
(:use compojure.core)
(:require [compojure.route :as route]
[compojure.handler :as handler])
(:use ring.middleware.reload)
(:use ring.adapter.jetty))

Nothing special going on here, just a few more libraries to include. Next I setup my routes. Using the defroutes macro I create the routes I want my app to respond to. Compojure will take the route definitions and generate a Ring handler function. The routes are processed from the top down, the first match wins. If a request comes in that doesn’t match the three routes I’ve defined the route/not-found will be called.

My last step is to bind app to the handler/site my-routes function. This binding is used to start up the application. After I have updated the file I can start the app by running:

lein ring server

The command starts up the web app and brings up a browser opening it to http://localhost:3000/. To test my app I wrote a batch script that utilizes curl. It tries my three routes plus a non-existing route to ensure they are handled properly, and it worked!

image

The complete core.clj file:

Summary

The Clojure web world offers frameworks at different levels. You can stay at a relatively low level buy using Ring or if you want something at a little higher level you can use Compojure. I am a Clojure noob and I was able to get a web app up and running in no time. I will be expanding on my Compojure knowledge through a project I am working on with my son. We had originally planned on using Node.js but now that I found Compojure we have decided to go with a Clojure based application. As the project progresses I am sure I will have more Clojure web related posts.

Resources

Clojure, Lein, Ring, Compojure

Code

project.clj core.clj test_clojure_web.bat

Friday, March 18, 2011

Getting vsClojure up and running in VS2010

This is a quick post on how to get the Visual Studio 2010 vsClojure Extension manager up and running.

Step 0. Install The Extension

Fire up Visual Studio and go to the Tools menu. From there select the the ‘Extension Manager..’ option. When the Extension Manager click on the ‘Online Gallery’ bar on the left hand side of the window. Next enter vsClojure on the upper right corner of the window. Your window should look, something like this:

image

Now click on the download button and follow the directions.  When the extension has been installed you will need to restart visual studio if it doesn’t do it for you.

Step 1. Create a Clojure Project

When Visual Studio has restarted close any solutions that you my have open and create a new Clojure project. When you do a File|New or Click on the New Project link from the startup page you should see Clojure listed under the ‘Installed Templates’ section on the left:

image

Select Clojure, name the project whatever you want and click the OK button. When the project is created you will have a project with a file named program.clj and a reference to the Clojure.dll file.

image

The first time I installed the extension and created a project the reference to the Clojure.dll was to a dll in a location that did not exist, “\1.2.0\Clojure.dll”. I did a quick search and  found this post and it resolved my issue.  I only had this problem the first time I installed the extension all subsequent installs have worked flawlessly.

Step 2 – Run the Project

Running a Clojure project is done just like running a C# project, by using your f5 key. When I do that I see:

image

If you receive an error when you try and run the project that starts with:

\1.2.0\Clojure.Compile core The system cannot find the path specified. 


Follow these instructions and it should resolve your problem.


Summary


Not an earth shattering blog post by any means but if you are a .NET person looking to expand his/her horizons like myself this may be a way to get you exposed to Clojure While I go through my Clojure book(s) I will be working with both the ‘real’ Clojure (JVM based) and Clojure CLR (since I work in a .NET environment).



Clojure Site, Clojure CLR site and the VS Extension’s site



I have a feeling there will be more Clojure posts in the not too distant future.

Tuesday, March 8, 2011

Getting Started with Node.js

Node.js is a server-side, event-driven environment that I am using to wrap my code generation scripts up and present them as a service.  I wanted a HTTP service that was simple and quick without much ‘fluff’. Node.js definitely comes without ‘fluff.  In this post I’m going to give you a quick overview of Node. It is not a deep dive but a quick example of ‘normal’ web requests.

The Setup

One thing I need to point out that Node.js is primarily a linux/unix/bsd solution. Supposedly you can run it on windows but it is not recommended. In my development environment I am running it on a Ubuntu 10.04 VM. I installed node and its package management system (npm) by following these instructions. Since the instructions are clear I won’t duplicate them here. After node is installed it is time for a quick test.

Hello World Node.js Style

Actually I didn’t write my own ‘Hello World’ I just copied the one from the node.js home page. Here’s what it looks like:

The code is pretty straight forward. The first line creates a the http object that we’ll use to create our HTTP server. Next, the script creates a web server object that takes in a function that is added to the request event queue. In the body of the function the first line creates the response’s header. The second line sends our Hello, World statement back to the browser. Lastly, the http server object’s listen method is called to tell the server to listen on the port 8124 on the local address.
To start the server I simply type:
node hello-world.js
Once the server has started the console.log message is printed which shows that the service is open for business. The hello world script works but it will send the hello world message to any GET request it receives on the port, http://localhost:8124 , http://localhost:8124/rob/was/here, etc all return the same message. You can set up 'straight' node.js to respond to different urls but I found an easier way to do it using express.js

Introducing Express.js

Express.js is a package that will turn our node.js script into something that looks like the JavaScript version of Sinatra. Before I show you what the code looks you need to install express.js.

Installation

If you followed the instructions for installing node.js to the letter you’ve already installed the package manager (npm). If you skipped the npm install earlier, install npm now. To install express simple run this from the command line:
npm install express
That’s it. Now we can use it to help us build out our service.

Hello World – Express.js version

Here’s our hello world service with express:

The first line is similar to the pure node.js one except that I create the app object after ‘requiring’ the library. The next line is where the express.js goodness kicks in. The line is is telling the server that whenever you receive an HTTP GET request for the url ‘/’ run the function that is passed into the app.get method call. Now, If start the service and run:
curl http://localhost:8124
I will see 'Hello World' written to STDOUT. If I tack on /Rob to the end of the URL I will receive an error that states:
Cannot GET /Rob

Retrieving Parameters (GET version)

So what if I want to pass the string Rob in as a parameter, how would I do that with express.js? It is pretty easy. Here is an updated version of the code that supports passing in a name as a parameter.

As you can see there isn’t much to adding parameters. A few things I’d like to point out are that the ? after the parameter name means that the parameter is not required. If one is passed it will be used. If no value is passed in we will still respond to the / request. Parameters are accessed by making referencing:
req.params.<variable name here>
That’s great but how do I do POST requests with express.js?

Retrieving Parameters (POST version)

How do you respond to a POST request? I’m sure you’ve probably already figured that out but I’ll show you the code to handle a post:

The app.post method is almost the same as the app.get method. If you look at the parameters to the fs.writeFile method you will notice the one visible difference in this code snippet, the parameters are accessed via the req.body object. I’m going to start the service and then call it with the following command:
curl -d "path=/tmp/blog.txt&content=Hi, Rob\n" http://localhost:8124/savefile
When I run that I get the following error:

Why did I receive this error? Out of the box Express.js doesn’t know how to parse the variables from a POST. In order to access the POST variables with express we need to add a piece of middle ware one line to our script:
app.use(express.bodyDecoder());
app.use(express.bodyParser());
Updated after updated Express.js - Thanks Douglas

Now express.js will be able to parse the parameters and store them in the req.body object. If I re-start the service and run the curl statement I should see the statement ‘File Saved!’ and have a text file at /tmp/blog.txt with the content ‘Hi, Rob’. Handling POST requests are almost as easy as handling GETs.
The full hello-world-express.js script:

Summary

This only scratches the surface as far as node.js goes. There are all kinds of packages available for node ones like express, view engines, low-level functionality, etc. In my project I’m using node.js as a middle man that has access to Riak, via raik-js), run my code generation scripts, and manage the code that is generated be the scripts. Due to Node's simplicity, I have been able to concentrate on the functionality that I’m trying to implement and not messing with server configurations.

Tuesday, March 1, 2011

Instantiating a Ruby Class that is a Member of a Module from C# (a work around in 2 parts)

Recently I was experimenting with calling my generator ruby scripts from within an ASP.NET MVC 3 project and  I ran into a problem when I attempted to instantiate a class that is a member of a module.  I was sure others had ran into this issue so I hit the internet to see what others have done to get around this issue.  In this blog post I’ll lay out what my issue was and how I found the work around for it.

The Code

Here’s a scaled down version of the ruby class layout that I’m attempting to instantiate:

I took the guts out of the methods since they aren't important. The key here is that the class is in a module. The C# code that I’m trying to instantiate the ruby class in looks like this:

I’m not going to get into the nuts and bolts of how to call into ruby from C# but I am going to give you a quick overview of what the code is doing here.  The first line creates the object we need to call into ruby. I then set up the search path so all the required files can be found.  The next step is to execute the script that has the class I want to instantiate.  Once I have the object I want to execute the run method on the object and return the results.

Line #9 in the C# snippet is where the error was thrown.  It would complain about not being able to find the object.  I tried to use the full name, Generator::CmdLine, and just the class name CmdLine with the same result. After that I went to Google. Everything I found said that a class within a module couldn’t be instantiated from within C#. I found that a bit odd since modules are all over ruby so I turned to StackOverflow.com. 

The Workaround

I posted the question on StackOverflow,   Instantiating a ruby class that is in a module from within C#.  I figured if I’ve run across this problem someone else probably has as well. Within less than 24 hours Shay Friedman author of IronRuby Unleashed had answered my question. Here is what he suggested:

This method is to be placed at the bottom of the cmd_line.rb file outside of the module so it is visible from within the C# code. In the C# code I change the line #9 from the C# code snippet above to this:

Now I call the hack method from C# to get access to the Generator::CmdLine object. The work around got me past the issue I was having and I was able to continue on with my research.

Summary

Having the ability to create objects from ruby classes in C# code is nice but it is not fully functional at this point in time.  However, using resources such as StackOverflow can help you find ways around some of the limitations that currently exist.  I’m also thankful for people like Shay Friedman who take time out of their busy day to help the likes of me. 

This little adventure also has me wondering how many people out there are instantiating objects from Python or Ruby in production or in their day to day work environments.  If you are leave a comment with a brief description of how you are using it and what you think about it.