Hello Clojure Servlet

175 views
Skip to first unread message

Craig McDaniel

unread,
Aug 26, 2008, 2:46:16 PM8/26/08
to Clojure
Here is a simple "hello world" servlet project that runs under
Tomcat. It may be useful to others. Note: This code works with the
20080612 Clojure release, but doesn't seem to find the doGet method
when using the current SVN release.

*** Instructions ***

1. Edit build.properties in user home to specify Tomcat parameters
catalina.home, manager.username, and manager.password.

2. Edit build.properties in project home to specify where clojure.jar
and genclass.clj reside.

3. ant install

4. Go to http://localhost:8080/hello-clojure/hello

*** File List ***

./src/mypkg/HelloServlet.clj
./build.properties
./build.xml
./gen-classes.clj
./web/WEB-INF/web.xml

*** gen-classes.clj ***

(def genclass-file (first *command-line-args*))
(def build-dir (second *command-line-args*))
(load-file genclass-file)
(clojure/gen-and-save-class build-dir
'mypkg.HelloServlet
:extends javax.servlet.http.HttpServlet)

*** HelloServlet.clj ***

(clojure/in-ns 'mypkg.HelloServlet)
(clojure/refer 'clojure)

(import '(java.io PrintWriter))

(defn doGet [this request response]
(.setContentType response "text/html")
(let [out (PrintWriter. (.getWriter response))]
(doto out
(println "<html>")
(println "<head>")
(println "<title>Hello World!</title>")
(println "</head>")
(println "<body>")
(println "<h1>Hello World...from Clojure!</h1>")
(println (str "17 + 3 = " (+ 17 3)))
(println "</body>")
(println "</html>"))))


*** build.properties ***

clojure.jar=${user.home}/clojure/clojure.jar
genclass.clj=${user.home}/clojure/src/genclass.clj

*** web.xml ***

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app 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"
version="2.4">

<display-name>Hello, World Clojure Application</display-name>
<description>
This is a simple web application with a source code organization
based on the recommendations of the Application Developer's Guide.
</description>

<servlet>
<servlet-name>HelloClojure</servlet-name>
<servlet-class>mypkg.HelloServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>HelloClojure</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>

</web-app>

*** build.xml ***

<project name="servlet-test" default="clojure.gen" basedir=".">

<!--
include the following in your build.properties file:
* clojure.jar - full path of clojure.jar
* genclass.clj - full path of genclass.clj
-->
<property file="build.properties"/>

<!--
include the following in your ~/build.properties file:
* catalina.home
* manager.username
* manager.password
-->
<property file="${user.home}/build.properties"/>

<property name="app.name" value="hello-clojure"/>
<property name="app.path" value="/${app.name}"/>
<property name="app.version" value="0.1-dev"/>
<property name="build.home" value="${basedir}/build"/>
<property name="dist.home" value="${basedir}/dist"/>
<property name="docs.home" value="${basedir}/docs"/>
<property name="manager.url" value="http://localhost:8080/manager"/
>
<property name="src.home" value="${basedir}/src"/>
<property name="web.home" value="${basedir}/web"/>


<path id="compile.classpath">
<!-- the main clojure jar -->
<pathelement location="${clojure.jar}"/>
<!-- Include all elements that Tomcat exposes to applications -->
<fileset dir="${catalina.home}/bin">
<include name="*.jar"/>
</fileset>
<pathelement location="${catalina.home}/lib"/>
<fileset dir="${catalina.home}/lib">
<include name="*.jar"/>
</fileset>
</path>

<!-- custom ant tasks -->
<taskdef resource="org/apache/catalina/ant/catalina.tasks"
classpathref="compile.classpath"/>

<!--
The "prepare" target is used to create the "build" destination
directory, and copy the static contents of your web application
to it. If you need to copy static files from external
dependencies, you can customize the contents of this task.

Normally, this task is executed indirectly when needed.
-->
<target name="prepare">
<tstamp/>
<!-- Create build directories as needed -->
<mkdir dir="${build.home}"/>
<mkdir dir="${build.home}/WEB-INF"/>
<mkdir dir="${build.home}/WEB-INF/classes/mypkg/test"/>
<!-- Copy static content of this web application -->
<copy todir="${build.home}">
<fileset dir="${web.home}"/>
</copy>
<!-- Copy external dependencies as required -->
<mkdir dir="${build.home}/WEB-INF/lib"/>
<copy todir="${build.home}/WEB-INF/lib" file="${clojure.jar}"/>
</target>

<!--
The clojure.gen target generates class files from *.clj files
-->
<target name="clojure.gen" depends="prepare">
<!-- Generate java class from clj file -->
<mkdir dir="${build.home}/WEB-INF/classes"/>
<java classname="clojure.lang.Script"
classpathref="compile.classpath">
<arg value="gen-classes.clj"/>
<arg value="--"/>
<arg value="${genclass.clj}"/>
<arg value="${build.home}/WEB-INF/classes"/>
</java>
<!-- Copy application resources -->
<copy todir="${build.home}/WEB-INF/classes">
<fileset dir="${src.home}" excludes="**/*.java"/>
</copy>
</target>

<!--
The "dist" target creates a binary distribution of your
application in a directory structure ready to be archived in a
tar.gz or zip file.
-->
<target name="dist" depends="clojure.gen"
description="Create binary distribution">
<mkdir dir="${dist.home}"/>
<!-- Create application JAR file -->
<jar jarfile="${dist.home}/${app.name}-${app.version}.war"
basedir="${build.home}"/>
<!-- Copy additional files to ${dist.home} as necessary -->
</target>

<!--
The "clean" target deletes any previous "build" and "dist"
directory,
so that you can be ensured the application can be built from
scratch.
-->
<target name="clean" description="clean up" >
<delete dir="${build.home}"/>
<delete dir="${dist.home}"/>
</target>

<!--
The "all" target is a shortcut for running the "clean" target
followed by the "compile" target, to force a complete recompile.
-->
<target name="all" depends="clean,clojure.gen"
description="Clean build and dist directories, then
clojure.gen"/>


<!--
The "install" target tells the specified Tomcat 6 installation
to dynamically install this web application and make it
available for execution. It does *not* cause the existence of
this web application to be remembered across Tomcat restarts; if
you restart the server, you will need to re-install all this web
application.

If you have already installed this application, and simply want
Tomcat to recognize that you have updated Java classes (or the
web.xml file), use the "reload" target instead.

NOTE: This target will only succeed if it is run from the same
server that Tomcat is running on.

NOTE: This is the logical opposite of the "remove" target.
-->
<target name="install" depends="clojure.gen"
description="Install application to servlet container">
<deploy url="${manager.url}"
username="${manager.username}"
password="${manager.password}"
path="${app.path}"
localWar="file://${build.home}"/>
</target>

<!--
The "list" target asks the specified Tomcat 6 installation to
list the currently running web applications, either loaded at
startup time or installed dynamically. It is useful to
determine whether or not the application you are currently
developing has been installed.
-->
<target name="list"
description="List installed applications on servlet
container">
<list url="${manager.url}"
username="${manager.username}"
password="${manager.password}"/>
</target>

<!--
The "reload" signals the specified application Tomcat 6 to shut
itself down and reload. This can be useful when the web
application context is not reloadable and you have updated
classes or property files in the /WEB-INF/classes directory or
when you have added or updated jar files in the /WEB-INF/lib
directory.

NOTE: The /WEB-INF/web.xml web application configuration file is
not reread on a reload. If you have made changes to your web.xml
file you must stop then start the web application.
-->
<target name="reload" depends="clojure.gen"
description="Reload application on servlet container">
<reload url="${manager.url}"
username="${manager.username}"
password="${manager.password}"
path="${app.path}"/>
</target>

<!--
The "remove" target tells the specified Tomcat 6 installation to
dynamically remove this web application from service.

NOTE: This is the logical opposite of the "install" target.
-->
<target name="remove"
description="Remove application on servlet container">
<undeploy url="${manager.url}"
username="${manager.username}"
password="${manager.password}"
path="${app.path}"/>
</target>

</project>
Reply all
Reply to author
Forward
0 new messages