Расширение класса службы Dropwizard в Clojure

Я уже давно использую Dropwizard для написания RESTful API в Scala, и мне бы очень хотелось использовать его в Clojure.

Что я пытаюсь сделать, так это создать подкласс com.yammer.dropwizard.Service, который я могу создать и запустить в своем -main, и я изо всех сил пытаюсь это сделать.

Насколько я знаю, мои варианты:

  1. gen-class в ns объявлении. Невозможно, потому что я хочу построить макросы (например, defservice), которые я не могу использовать в объявлении ns. Разве что есть какой-то способ сгенерировать что-то во время выполнения и передать его compile, но это похоже на грязный хак.
  2. gen-class снаружи ns. Несмотря на некоторый код, который я нашел, кажется, что это не работает на все. Вот простой пример:

    user> (gen-class :name foo :extends Object)
    nil
    user> (foo.)
    Unable to resolve classname: foo
     [Thrown class java.lang.IllegalArgumentException]
    

    Я знаю, что gen-class работает только во время компиляции. Я поместил это в файл и поместил (foo. в свой -main, и я получил то же самое исключение.

  3. proxy. Это кажется наиболее перспективным, и это работает для простых случаев, но не для расширения класса Service Dropwizard:

    user> (proxy [Object] [])
    #<Object$0 user.proxy$java.lang.Object$0@249faafc>
    user> (import [com.yammer.dropwizard Service])
    com.yammer.dropwizard.Service
    user> (proxy [Service] ["x"])
    java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
      [Thrown class java.lang.ClassCastException]
    

    Я думаю, что это может быть связано с тем, что Service принимает параметр типа, но я не смог найти никакой информации об этом в Clojure. То, что я нашел, казалось, указывало на то, что они имели значение только для javac и игнорировались Clojure. Так что, возможно, я ошибаюсь в том, почему это происходит.

  4. deftype. Не работает, потому что Service — это класс, а deftype работает только с интерфейсами и протоколами.

Я думаю, что я на правильном пути, но упускаю некоторые тонкости того, как работают gen-class и/или proxy, а документация Clojure чрезвычайно лаконична. Как я могу расширить этот класс Java в Clojure?


person ieure    schedule 26.01.2012    source источник
comment
Clojure обычно может проксировать объект, который принимает общие параметры (попробуйте (proxy [java.util.ArrayList] [])). Ваша текущая проблема связана с реализацией com.yammer.dropwizard.AbstractService и особенно с вызовом getConfigurationClass внутри конструктора. На первый взгляд иерархия классов Dropwizard кажется очень странной.   -  person ponzao    schedule 27.01.2012


Ответы (1)


Я бы сказал, используйте вариант 1, но если я не истолкую ваше описание неправильно, это звучит так, как будто вы пытаетесь написать код внутри формы пространства имен? Это не то, что вы хотите. Когда вы добавляете gen-класс в форму пространства имен, класс Java будет сгенерирован для всего этого пространства имен. Затем вы можете переопределить методы, назвав свои функции в этом ns с префиксом - (или выберите другой и используйте :method-prefix).

Вот пример. Я недостаточно знаю о библиотеках, которые вы используете для тестирования этих классов, но они должны быть как минимум похожими:

(ns com.myapp.MyService
  (:gen-class
   :extends com.yammer.dropwizard.Service
   :exposes-methods {someSuperClassMethod someLocalAlias}))

;; now just write your code as normal, note that
;; you can access super-class methods with the exposes-methods
;; map above!

;; prefix your overriden methods with -

(defn -overriddenMethod
  [params]
  ... )

Надеюсь, это поможет!

person jaley    schedule 26.01.2012
comment
Основная проблема заключается в том, что для этого требуется, чтобы авторы сервисов добавляли шаблонный код в свой (ns…). Я хочу, чтобы defservice генерировал соответствующий gen-class (или что-то еще). Я предполагаю, что этот метод был бы приемлем, если бы он был единственным, который работал бы, но это далеко не то, что я хочу. - person ieure; 27.01.2012