How can I define a clojure type that implements the servlet interface?
- by Rob Lachlan
I'm attempting to use deftype (from the bleeding-edge clojure 1.2 branch) to create a java class that implements the java Servlet interface. I would expect the code below to compile (even though it's not very useful).
(ns foo [:import [javax.servlet Servlet ServletRequest ServletResponse]])
(deftype servlet []
javax.servlet.Servlet
(service [this
#^javax.servlet.ServletRequest request
#^javax.servlet.ServletResponse response]
nil))
But it doesn't compile. The compiler produces the message:
Mismatched return type: service, expected: void, had: java.lang.Object
[Thrown class java.lang.IllegalArgumentException]
Which doesn't make sense to me, because I'm returning nil. So the fact that the return type of the method is void shouldn't be a problem. For instance, for the java.util.Set interface:
(deftype bar [#^Number n] java.util.Set (clear [this] nil))
compiles without issue.
So what am I doing wrong with the Servlet interface?
To be clear:
I know that the typical case is to subclass one of the servlet abstract classes rather than implement this interface directly, but it should still be possible to do this.
Stack Trace:
The stack trace for the (deftype servlet... is:
Mismatched return type: service, expected: void, had: java.lang.Object
[Thrown class java.lang.IllegalArgumentException]
Restarts:
0: [ABORT] Return to SLIME's top level.
Backtrace:
0: clojure.lang.Compiler$NewInstanceMethod.parse(Compiler.java:6461)
1: clojure.lang.Compiler$NewInstanceExpr.build(Compiler.java:6119)
2: clojure.lang.Compiler$NewInstanceExpr$DeftypeParser.parse(Compiler.java:6003)
3: clojure.lang.Compiler.analyzeSeq(Compiler.java:5289)
4: clojure.lang.Compiler.analyze(Compiler.java:5110)
5: clojure.lang.Compiler.analyze(Compiler.java:5071)
6: clojure.lang.Compiler.eval(Compiler.java:5347)
7: clojure.lang.Compiler.eval(Compiler.java:5334)
8: clojure.lang.Compiler.eval(Compiler.java:5311)
9: clojure.core$eval__4350.invoke(core.clj:2364)
10: swank.commands.basic$eval_region__673.invoke(basic.clj:40)
11: swank.commands.basic$eval_region__673.invoke(basic.clj:31)
12: swank.commands.basic$eval__686$listener_eval__687.invoke(basic.clj:54)
13: clojure.lang.Var.invoke(Var.java:365)
14: foo$eval__2285.invoke(NO_SOURCE_FILE)
15: clojure.lang.Compiler.eval(Compiler.java:5343)
16: clojure.lang.Compiler.eval(Compiler.java:5311)
17: clojure.core$eval__4350.invoke(core.clj:2364)
18: swank.core$eval_in_emacs_package__320.invoke(core.clj:59)
19: swank.core$eval_for_emacs__383.invoke(core.clj:128)
20: clojure.lang.Var.invoke(Var.java:373)
21: clojure.lang.AFn.applyToHelper(AFn.java:169)
22: clojure.lang.Var.applyTo(Var.java:482)
23: clojure.core$apply__3776.invoke(core.clj:535)
24: swank.core$eval_from_control__322.invoke(core.clj:66)
25: swank.core$eval_loop__324.invoke(core.clj:71)
26: swank.core$spawn_repl_thread__434$fn__464$fn__465.invoke(core.clj:183)
27: clojure.lang.AFn.applyToHelper(AFn.java:159)
28: clojure.lang.AFn.applyTo(AFn.java:151)
29: clojure.core$apply__3776.invoke(core.clj:535)
30: swank.core$spawn_repl_thread__434$fn__464.doInvoke(core.clj:180)
31: clojure.lang.RestFn.invoke(RestFn.java:398)
32: clojure.lang.AFn.run(AFn.java:24)
33: java.lang.Thread.run(Thread.java:637)