Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure deftype calling function in the same namespace throws "java.lang.IllegalStateException: Attempting to call unbound fn:"

I'm placing Clojure into an existing Java project which heavily uses Jersey and Annotations. I'd like to be able to leverage the existing custom annotations, filters, etc of the previous work. So far I've been roughly using the deftype approach with javax.ws.rs annotations found in Chapter 9 of Clojure Programming.

(ns my.namespace.TestResource
  (:use [clojure.data.json :only (json-str)])
  (:import [javax.ws.rs DefaultValue QueryParam Path Produces GET]
           [javax.ws.rs.core Response]))

;;My function that I'd like to call from the resource.
(defn get-response [to]
  (.build
    (Response/ok
      (json-str {:hello to}))))

(definterface Test
  (getTest [^String to]))

(deftype ^{Path "/test"} TestResource [] Test
  (^{GET true
     Produces ["application/json"]}
  getTest
  [this ^{DefaultValue "" QueryParam "to"} to]
  ;Drop out of "interop" code as soon as possible
  (get-response to)))

As you can see from the comments, I'd like to call functions outside the deftype, but within the same namespace. At least in my mind, this allows me to have the deftype focus on interop and wiring up to Jersey, and the application logic to be separate (and more like the Clojure I want to write).

However when I do this I get the following exception:

java.lang.IllegalStateException: Attempting to call unbound fn: #'my.namespace.TestResource/get-response

Is there something unique about a deftype and namespaces?

like image 924
bdaniels Avatar asked Jun 08 '12 17:06

bdaniels


1 Answers

... funny my hours on this problem did not yield an answer until after I asked here :)

It looks like namespace loading and deftypes was addressed in this post. As I suspected the deftype does not automatically load the namespace. As found in the post, I was able to fix this by adding a require like this:

(deftype ^{Path "/test"} TestResource [] Test
  (^{GET true
     Produces ["application/json"]}
    getTest
    [this ^{DefaultValue "" QueryParam "to"} to]
    ;Drop out of "interop" code as soon as possible
    (require 'my.namespace.TestResource) 
    (get-response to)))
like image 126
bdaniels Avatar answered Nov 05 '22 21:11

bdaniels