> simple, you'd be embarrassed to admit that you didn't see WHAT WAS
> STARING YOU IN THE FACE all along?

Don't be too hard on yourself - it takes a while for the clojure
patterns to sink in so you easily spot the simple errors. Best to
throw it out there so someone else can help.

Gen-class is a tricky place to be in the beginning as its syntax and
operation is pretty complex. Coincidentally (as is so often the case
with this forum), I have just been doing something pretty similar to
yourself, so I thought I'd post it to give you (and others) a good
example of interop with gen-class and how I've use it in this case...

(ns timr.TimerTask
  (:import (java.util TimerTask))
  (:gen-class :extends java.util.TimerTask
    :init init
    :constructors {[clojure.lang.Associative][]}
    :state ttmap))

(defn -init
"Note, throws a InvocationTargetException if anythong goes wrong."
  [#^clojure.lang.Associative mp]
  (let [ns-sym (get mp "task-ns" (str *ns*))
        task-fn-nm (get mp "task-fn-nm" 'do-task)
        ns-sym (symbol ns-sym)
        task-ns (find-ns ns-sym)
        task-ns (if (nil? task-ns)
            (let [n (create-ns ns-sym)] (require ns-sym) n)
            task-ns)
        task-fn (get (ns-publics ns-sym) (symbol task-fn-nm))
        ]
    [[] (assoc mp :task-ns task-ns :task-fn task-fn)]))

(defn -run
  [this]
  (let [ttmap (.ttmap this)]
  ((ttmap :task-fn) ttmap)))

The above compiles a clojure class extending java.util.TimerTask, but
passing the "ns name" and "run" function name in a map to the
constructor (java.util.Map or clojure Associative structure). When a
TimerTask object is instantiated, it loads and requires (if necessary)
the ns and determines which fn should be called in run() when the
timer triggers the task. (Note that the ns defaults to the current ns
and the task fn to "do-task"). Note that in this case I don't need to
pass state from one invocation to the next, so I'm just storing a map
in the state and not a ref as in Rich's example at clojure.org.

>From the repl...

(import 'timr.TimerTask)
(defn my-task [mp] (println "Allo..."))
def tt (TimerTask. {"task-fn-nm" "my-task"}))
(doto (java.util.Timer.) (.schedule tt (long 1000) (long 3000)))
Allo...
Allo...
Allo...

So, I can create clojure timer tasks and instantiate them from both
clojure and java, allowing me to easily bring clojure into legacy java
apps with only this boiler-plate being AOT compiled. All my actual
clojure tasks are just clj src files on the class path (makes builds
simpler - clojure does all the work and I have only one compile...
(binding [*compile-path* "WEB-INF/classes"]
   (compile 'timr.TimerTask))

I use a similar technique for extending HttpServlets, ContextListener
(implementations), JSP-clojure bridges, etc, and dynamically invoking
the clojure functions from the jave side and of course the clojure
side!

Hope that gives you some ideas and pointers.

-Rgds, Adrian.


On Fri, Apr 30, 2010 at 8:16 AM, Gregg Williams <greg...@innerpaths.net> wrote:
> Have you ever wanted to abandon a simple program with a bug that has
> been DRIVING YOU CRAZY because it's just got to be something SO
> simple, you'd be embarrassed to admit that you didn't see WHAT WAS
> STARING YOU IN THE FACE all along? Well, this is mine:
>
> (ns org.InfoML.genclassObject
>  (:gen-class
>   :extends [java.lang.Object]
>   :init init
>   :constructors {[] []}
>   :state state))
>
> (defn -init [s]
>  [[] (ref "foo")])
>
>
> (defn -main []
>  (let [x (new org.InfoML.genclassObject)]
>    (println x)))
>
> I'm beyond getting clues that will help me solve my original problem--
> it just bothers me that I can't figure out what's happening.
>
> Whether I compile the org.InfoML package or not, I get the same error
> message:
>
> Exception in thread "main" java.lang.ClassNotFoundException: [java/
> lang/Object] (genclassObject.clj:1)
> ... (a bunch of lines omitted here) ...
> Caused by: java.lang.ClassNotFoundException: [java/lang/Object]
>        at java.lang.Class.forName0(Native Method)
>        at java.lang.Class.forName(Class.java:247)
>        at clojure.lang.RT.classForName(RT.java:1504)
>        at clojure.core$the_class__7054.invoke(genclass.clj:91)
>        at clojure.core$generate_class__7060.invoke(genclass.clj:99)
>        at clojure.core$gen_class__7189.doInvoke(genclass.clj:593)
>        at clojure.lang.RestFn.invoke(RestFn.java:761)
>        at clojure.lang.Var.invoke(Var.java:421)
>        at clojure.lang.AFn.applyToHelper(AFn.java:289)
>        at clojure.lang.Var.applyTo(Var.java:476)
>        at clojure.lang.Compiler.macroexpand1(Compiler.java:4504)
>        at clojure.lang.Compiler.analyzeSeq(Compiler.java:4578)
>        ... 34 more
>
> And what's with the slashes in "[java/lang/Object]"--I've never seen
> that before.
>
> I beg your forbearance in advance. Please, make the pain stop.
>
> PS to Mikel: Regarding my original goal, converting the
> GraphEditor.java program to Clojure, it should be obvious that my
> objective is not simply to get an example program running onscreen.
> Rather, I really want an answer to a specific question. That question
> is, "In Java, I can add new behavior to the constructor of an original
> class that I'm subclassing. And yet, the constructor is a special case
> because its name is the name of the superclass. How can I do the same
> thing in Clojure?" Yes, I'm stubborn. Misguided, too, probably.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to