Permalink
Browse files

Merge pull request #1 from dlebrero/master

ServletContextListener to run clojure functions at startup/shutdown
  • Loading branch information...
2 parents b91a417 + 6a57f97 commit 1b6a91090b5ae7b0eb69559946a0186a23cbfbe0 @laurentpetit committed Sep 20, 2012
View
@@ -2,24 +2,26 @@
Allows you to embed ring handlers in existing java web applications without having to add an AOT phase to your build process, by providing you with a generic way to declare servlets in your web.xml, and where the clojure ring handler is located.
-##Example
+It also provides a ServletContextListener which can be configured to run a function when the web app is initialized and destroyed.
-### Add the Ring java servlet dependency to your project
-Add this project as a dependency of your project. By means of transitive dependencies magic, you''ll need to add no other dependency.
+##Setup
+Add this project as a dependency of your project. By means of transitive dependencies magic, you'll need to add no other dependency.
ring-java-servlet is distributed on clojars.org as a maven artifact, with following coordinates:
* groupId=org.lpetit.ring
* artifactId=ring-java-servlet
-* version=0.1.0 (as of the time where this README was last updated)
+* version=0.2.0 (as of the time where this README was last updated)
ring-java-servlet artifacts are currently only available on clojars.org
+##Ring handler example
+
### Create your Ring handler
Write a clojure ring handler and place it somewhere in your source/resources folder (so that your build system adds it to the webapp classpath, e.g. places it in WEB-INF/classes folder of your webapp) :
; file lpetit.ring_test.clj
- (ns lpetit.ring-test
+ (ns lpetit.ring-test)
(defn hello [req]
{:status 200
:headers {"Content-Type" "text/html"}
@@ -41,5 +43,36 @@ Write a clojure ring handler and place it somewhere in your source/resources fol
</servlet-mapping>
### Test it
-That''s all. Next time you build your webapp and start it, you should see a "Hello world from ring java servlet" welcome message at http://the-server:the-port/<your-webapp-context>/foo.some-extension
+That's all. Next time you build your webapp and start it, you should see a "Hello world from ring java servlet" welcome message at http://the-server:the-port/<your-webapp-context>/foo.some-extension
+
+##ServletContextListener example
+
+### Create startup and shutdown functions
+Any clojure function with one parameter can be used as the startup or shutdown function. The RingServletContextListener will pass the ServletContext to the function. There is also a small utility function to convert the context parameters to a clojure map.
+
+ ; file lpetit.ring_test.clj
+ (ns lpetit.context-test
+ (:require [org.lpetit.ring.servlet.util :as util]))
+
+ (defn start-up [ctx]
+ (println "Starting app with params: " (util/context-params ctx)))
+
+ (defn shutdown [ctx]
+ (println "Stopping app with params: " (util/context-params ctx)))
+
+
+### Declare the ServletContextListener in your web.xml
+
+Specify which funtions to run at start/stop with the `context-init` and `context-destroy` context parameters. Both parameters are optional.
+ <context-param>
+ <param-name>context-init</param-name>
+ <param-value>lpetit.context-test/start-up</param-value>
+ </context-param>
+ <context-param>
+ <param-name>context-destroy</param-name>
+ <param-value>lpetit.context-test/shutdown</param-value>
+ </context-param>
+ <listener>
+ <listener-class>org.lpetit.ring.servlet.RingServletContextListener</listener-class>
+ </listener>
View
@@ -1,6 +1,8 @@
-(defproject org.lpetit.ring/ring-java-servlet "0.1.0"
+(defproject org.lpetit.ring/ring-java-servlet "0.2.0"
:description "Ring generic servlet for using ring without AOT."
:url "http://github.com/laurentpetit/ring-java-servlet"
- :dependencies [[ring/ring-servlet "0.3.5" :exclusions [javax.servlet/servlet-api]]]
- :dev-dependencies [[javax.servlet/servlet-api "2.5"]]
- :aot [org.lpetit.ring.servlet.RingHttpServlet])
+ :dependencies [[ring/ring-servlet "1.1.0" :exclusions [javax.servlet/servlet-api]]]
+ :profiles {:provided
+ {:dependencies
+ [[javax.servlet/servlet-api "2.5"]]}}
+ :aot [org.lpetit.ring.servlet.RingHttpServlet org.lpetit.ring.servlet.RingServletContextListener])
@@ -1,17 +1,17 @@
(ns org.lpetit.ring.servlet.RingHttpServlet-impl
(:require [ring.util.servlet :as s])
+ (:use org.lpetit.ring.servlet.util)
(:import org.lpetit.ring.servlet.RingHttpServlet))
(defn -initState [] [[] (atom {})])
(defn -init-void [this]
- (let [[n h] (map symbol ((juxt namespace name) (symbol (.getInitParameter this "handler"))))]
- (require n)
- (swap!
+ (let [resolved-fn (require-and-resolve (.getInitParameter this "handler"))]
+ (swap!
(.state this)
assoc
:service-fn
- (s/make-service-method (ns-resolve (the-ns n) h)))))
+ (s/make-service-method resolved-fn))))
(defn -service [this req resp]
((-> this .state deref :service-fn) this req resp))
@@ -0,0 +1,19 @@
+(ns org.lpetit.ring.servlet.RingServletContextListener
+ (:use org.lpetit.ring.servlet.util)
+ (:gen-class :implements [javax.servlet.ServletContextListener])
+ (:import [javax.servlet ServletContextEvent]))
+
+(defn run [contextEvent symbol-str]
+ (let [ctx (.getServletContext contextEvent)]
+ (if-let [the-fn (.getInitParameter ctx symbol-str)]
+ (let [resolved-fn (require-and-resolve the-fn)]
+ (resolved-fn ctx)))))
+
+(defn -contextInitialized [this ^ServletContextEvent contextEvent]
+ (run contextEvent "context-init"))
+
+(defn -contextDestroyed [this ^ServletContextEvent contextEvent]
+ (run contextEvent "context-destroy"))
+
+
+
@@ -0,0 +1,13 @@
+(ns org.lpetit.ring.servlet.util
+ (:import [javax.servlet ServletContext]))
+
+(defn require-and-resolve [symbol-str]
+ (let [[n h] (map symbol ((juxt namespace name) (symbol symbol-str)))]
+ (require n)
+ (ns-resolve (the-ns n) h)))
+
+(defn context-params [^ServletContext ctx]
+ "Given a servlet context, it returns a map with all the context parameters. Keys are keywords."
+ (into {} (for [param (enumeration-seq (.getInitParameterNames ctx))
+ :let [value (.getInitParameter ctx param)]]
+ [(keyword param) value])))

0 comments on commit 1b6a910

Please sign in to comment.