tag:blogger.com,1999:blog-24590200984366610332024-03-13T07:45:10.494-07:00Jeroen VloothuisJeroen Vloothuishttp://www.blogger.com/profile/05816895705516300335noreply@blogger.comBlogger1125tag:blogger.com,1999:blog-2459020098436661033.post-18202127552577820002010-07-23T13:50:00.000-07:002010-07-25T03:25:59.330-07:00Deploying a Clojure web-application as a WAR fileAfter working my way trough several tutorials, a <a href="http://pragprog.com/titles/shcloj/programming-clojure">book on Clojure</a> and the <a href="http://clojure.org/API">API docs</a> I managed to produce a web-application using <a href="http://weavejester.github.com/compojure/">Compojure</a>. If you're like me and made it this far you might be wondering; how do I deploy my application?<br />
<br />
This post will walk you through deploying your application as a <a href="http://en.wikipedia.org/wiki/WAR_%28Sun_file_format%29">WAR file</a> on <a hef="http://tomcat.apache.org/" href="">Apache Tomcat 6</a> using the <a href="http://httpd.apache.org/">Apache HTTP Server</a> as proxy complete with virtual hosting and static file serving. The chosen operating system is <a href="http://www.ubuntu.com/">Ubuntu</a>, keep this in mind if your system differs. <a href="http://www.debian.org/">Debian</a> / Ubuntu might have some different locations / tools for managing Apache and Tomcat.<br />
<br />
<h2>Step 1, creating a WAR file</h2><br />
<br />
To create the WAR file we will use <a href="http://github.com/technomancy/leiningen">Leiningen</a> and the <a href="http://github.com/alienscience/leiningen-war">leiningen-war plugin</a>. Open your project.clj file and add the following; <i>uk.org.alienscience/leiningen-war "0.0.3"</i> to; <i>:dev-dependencies</i>. My <i>project.clj</i> looks like:<br />
<br />
<pre>(defproject myapp "1.0.0-SNAPSHOT"
;; Removed some lines for clarity
:dev-dependencies [[swank-clojure "1.2.0"]
[uk.org.alienscience/leiningen-war "0.0.3"]]
;; The rest of your config
:namespaces [myapp.servlet])
</pre><br />
<br />
Please lookup the <a href="http://clojars.org/uk.org.alienscience/leiningen-war">most recent available version on Clojars</a> before copying the code.<br />
<br />
This plugin will create a WAR file when we run: <i>lein uberwar</i>. Before we can do this we need to create a servlet class. Add a file called <i>servlet.clj</i> to your project in <i>src/myapp/servlet.clj</i> (change myapp as needed).<br />
<br />
Within this file add the following lines:<br />
<br />
<pre>(ns myapp.servlet
(:gen-class :extends javax.servlet.http.HttpServlet)
(:require [compojure.route :as route])
(:use ring.util.servlet
[myapp.core :only [application]]))
(defservice application)
</pre><br />
<br />
In this case "application" should be the name you chose in <i>core.clj</i> for your defroutes. If you want to have Ring middle-ware as well either wrap it here or create a "def" which you can reference instead.<br />
<br />
Now you can compile the servlet class with: <i>lein compile</i>. Before the WAR file can be created a <em>web.xml</em> file also needs to be setup. Create a file called <em>src/web.xml</em> with the following contents. <br />
<br />
<pre><?xml version="1.0" encoding="ISO-8859-1"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>My App</display-name>
<servlet>
<servlet-name>myapp</servlet-name>
<servlet-class>myapp.servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myapp</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
</pre><br />
Create the WAR with: <i>lein uberwar</i>. Using <i>uberwar</i> makes sure all your dependencies are included.<br />
<br />
<h2>Step 2, getting the packages</h2><br />
I will be assuming you already have a working Java installation. Enter the following command line to install the dependencies:<br />
<br />
<pre>sudo apt-get install tomcat6 apache2</pre><br />
<br />
<h2>Step 3, configure Tomcat</h2><br />
Since I want my application to be available at mydomain.example.com I need to setup Tomcat for virtual hosting. To do this open <i>/etc/tomcat6/server.xml</i>. Search for the <i>&lthost name="..</i> and add one below like:<br />
<br />
<pre><Host name=" com="" appbase="myapp">
unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false"></pre><br />
<br />
<br />
You will also need to enable the connector for the AJP protocol. This will be used for interaction between Tomcat and Apache. To do this uncomment the line which says; <i><Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /></i><br />
<br />
Your web-application needs to be placed in a new directory within the Tomcat installation (as defined with "appBase"). Create this directory with the following commands:<br />
<br />
<pre>sudo mkdir /var/lib/tomcat6/myapp
sudo chown tomcat6:tomcat6 /var/lib/tomcat6/myapp</pre><br />
<br />
<h2>Step 4, configuring Apache</h2><br />
<br />
Apache has a module specifically designed for proxy-ing traffic to Tomcat. To enable this module run: <i>sudo a2enmod proxy_ajp</i>. Now we can create a virtual host configuration file.<br />
<br />
Using your editor of choice open: <i>/etc/apache2/site-available/myapp.example.com</i>. Paste in something like:<br />
<br />
<pre><VirtualHost *:80>
ServerName myapp.example.com
ErrorLog /var/log/apache2/myapp.error.log
CustomLog /var/log/apache2/myapp.log combined
Alias /static/ "/var/myapp/static/"
<Directory /var/myapp/static/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<Proxy *>
AddDefaultCharset Off
Order deny,allow
Allow from all
</Proxy>
ProxyPass /static !
ProxyPass / ajp://localhost:8009/
ProxyPassReverse / ajp://localhost:8009/
</VirtualHost>
</pre><br />
<br />
The <i>/var/myapp/static</i> directory will contain the applications static files. You can put this anywhere you want as long as it's readable for Apache.<br />
<br />
Now enable the virtual host with: <i>sudo a2ensite myapp.example.com</i>.<br />
<br />
<h2>Step 5, install application and load</h2><br />
<br />
All we have to do now is to install the WAR file. Copy or move the WAR file created in step 1 to <i>/var/lib/tomcat6/myapp/ROOT.war</i>. Make sure it's name will be <i>ROOT.war</i>. This tells Tomcat to use it to "mount" you application on <i>/</i>. Otherwise it will mount it on <i>/name-of-warfile</i>.<br />
<br />
The last step is to restart all Tomcat and Apache:<br />
<br />
<pre>sudo /etc/init.d/tomcat6 restart
sudo /etc/init.d/apache2 restart</pre><br />
<br />
If everything went well you should now be able to visit myapp.example.com to see your application. To diagnose any problems look in the files specified in <i>/var/log/tomcat6/catalina.out</i> and the ones specified in your Apache virtual host.Jeroen Vloothuishttp://www.blogger.com/profile/05816895705516300335noreply@blogger.com1