4

JaxRs アノテーション付きサービスに Swagger アノテーションを追加しています。

私は次のものを持っています:

(^{
 GET true
 Path "/{who}"
 ApiOperation {:value "Get a hello" :notes "simple clojure GET"}
 Produces ["text/plain; charset=UTF-8"]
 ApiResponses {:value [(ApiResponse {:code 200 :message "yay!"})]}

}

生成されたクラスを逆コンパイルすると、注釈は次のようになります。

@ApiResponses({@com.wordnik.swagger.annotations.ApiResponse(code=200L, message="yay!")})
@Produces({"text/plain; charset=UTF-8"})
@ApiOperation(value="Get a hello", notes="simple clojure GET")
@Path("/{who}")
@GET(true)

最初の注釈コード = 200L であることに注意してください

実行時には、この値は int でなければならず、これを実現する方法がわかりません

私が試したら

ApiResponses {:value [(ApiResponse {:code (int 200) :message "yay!"})]}

コンパイル エラーが発生します (maven swagger プラグインを使用)

Exception in thread "main" java.lang.ClassCastException: clojure.lang.Var cannot be cast to java.lang.Class, compiling:(pocclj/resourceclj.clj:14)

私が試してみました

(def success (int 200))
 ...
ApiResponses {:value [(ApiResponse {:code success :message "yay!"})]}

このコンパイルエラーが発生します:

Exception in thread "main" java.lang.IllegalArgumentException: Unsupported annotation value: success of class class java.lang.Integer, compiling:(pocclj/resourceclj.clj:14)

私は他の多くのもの(derefなど)を試しましたが、秘密のソースを見つけることができません.

私はclojureにかなり慣れていないので、これに関する助けを切望しています。

前もって感謝します

マーティン

4

2 に答える 2

0

ApiResponse についても、アノテーションについてもあまり知りませんが、いくつかのマクロ ( ) がアノテーションを生成しているようで、int としてdeftype?表示する必要があります。200Clojure にはリテラルがないintため、Integer オブジェクトをマクロに直接渡す唯一の方法は、それを呼び出す他のマクロを使用することです。これを良い方法で行うことは実際には不可能です。私の知る限り、を使用するかeval、特に int リテラルを対象にして非常に狭くする必要があります。ソリューションのスケッチを次に示します。

user> (use 'clojure.walk)
user> (defmacro with-int-literals [named-ints & body]
        (prewalk-replace (into {}
                               (for [[k v] (partition 2 named-ints)]
                                 [k (int v)]))
                         `(do ~@body)))

user> (map class (second (macroexpand-1 '(with-int-literals [x 100, y 200] [x y]))))
(java.lang.Integer java.lang.Integer)

したがって、フォーム全体deftype(またはこれらの注釈を生成するマクロ) をwith-int-literalsフォームでラップすると、long の代わりに整数を生成できます。これが機能するかどうかは実際にはわかりません。おそらく、何らかの理由で基本的に int を処理できないアノテーション プロセッサに何かがあるのでしょう。しかし、少なくともこの方法では、int を提供して、最善を尽くすことができます。

編集

「通常の」コードではなく、実際にはメタデータで int リテラルが必要なため、実際には関心prewalkのあるデータを調べません。適切な方法でメタデータを扱うのバージョンを作成し、walkここで prewalk の代わりにそれを使用する必要があります。

于 2013-08-18T07:11:54.063 に答える
0

「:code」のタイプを正しく設定しています。独立してテストできるもの:

user> (def something ^{:ApiResponses {:code (int 200) :message "yay!"}} {:some :data :goes :here})
#'user/something

user> (meta something)
{:ApiResponses {:code 200, :message "yay!"}}

user> (-> (meta something) :ApiResponses :code type)
java.lang.Integer

また、キャストがないと、メタデータに間違った型が含まれます。

user> (def something-wrong ^{:ApiResponses {:code 200 :message "yay!"}} {:some :data :goes :here})
#'user/something-wrong

user> (meta something)
{:ApiResponses {:code 200, :message "yay!"}}

user> (-> (meta something-wrong) :ApiResponses :code type)
java.lang.Long

ApiResponse例外から、おそらくへの呼び出しがクラッシュしているように見えます。ApiResponse が S 式ではなく数値を期待するマクロである場合、これを適切に処理していないことがわかります。それが関数である場合は、クラッシュしている理由を調べる必要があります。

ApiResponse のスタブ実装を提供すると、うまくいきます。

user> (definterface Fooi (Something []))
user.Fooi

user> (def ApiResponse identity)
#'user/ApiResponse

user> (deftype Foo []
        Fooi
        (Something
          ^{GET true
            Path "/{who}"
            ApiOperation {:value "Get a hello" :notes "simple clojure GET"}
            Produces ["text/plain; charset=UTF-8"]
            ApiResponses {:value [(ApiResponse {:code (int 200) :message "yay!"})]}}
          [this] (identity this)))
user.Foo
于 2013-08-16T21:17:11.037 に答える