Skip to content

IllegalArgumentException when using schema.core/pred in a defschema #102

@psarando

Description

@psarando

When trying to use schema.core/pred in a compojure-api swagger schema, like this

(defn non-blank-string? [s]
  (and (string? s) (not (blank? s))))
(def NonBlankString
  (describe (s/pred non-blank-string?) "A non-blank string."))
(s/defschema Paths
  {:paths (describe [NonBlankString] "A list of paths")})

we are getting the following exception when opening the swagger docs URL:
java.lang.IllegalArgumentException: Looks like you're trying to define two models with the same name (Paths), but different properties: {:paths [(pred #<core$non_blank_string_QMARK_ blargh.core$non_blank_string_QMARK_@7038a5b7>)]} & {:paths [(pred #<core$non_blank_string_QMARK_ blargh.core$non_blank_string_QMARK_@1707caf0>)]} This might happen if you anonymously manipulate a named schema (see #39). Extract to another named schema or use schema-tools.core -transformers.

The following simple lein app reproduces this error, by running
lein do clean, deps, uberjar
java -jar target/uberjar/blargh-0.1.0-SNAPSHOT-standalone.jar
then navigating a browser to http://localhost:31300

project.clj

(defproject blargh "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [metosin/compojure-api "0.20.1"]
                 [ring "1.3.2"]]
  :main ^:skip-aot blargh.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all}})

src/blargh/core.clj

(ns blargh.core
  (:gen-class)
  (:use [clojure.string :only [blank?]]
        [compojure.api.sweet]
        [compojure.api.legacy]
        [ring.util.response :only [redirect]])
  (:require [ring.adapter.jetty :as jetty]
            [schema.core :as s]))

(defn non-blank-string? [s]
  (and (string? s) (not (blank? s))))

;; This definition causes an IllegalArgumentException when bringing up the Swagger UI.
(def NonBlankString
  (describe (s/pred non-blank-string?) "A non-blank string."))

;; This definition causes a "No matching ctor" error.
#_(def NonBlankString
  (describe (s/both String (s/pred (complement blank?))) "A non-blank string."))

(s/defschema Paths
  {:paths (describe [NonBlankString] "A list of paths")})

(defn- success-response*
  [body]
  {:status  200
   :body    body
   :headers {"Content-Type" "application/json"}})

(defroutes* all-routes
  (POST* "/frobnicate" [:as {:keys [uri]}]
         :body [body (describe Paths "The paths to frobnicate.")]
         :return Paths
         :summary "Frobnicate Paths"
         :description "Frobnicates a list of paths in a superior fashion using an influx
         modulator."
         (success-response* body)))

(defapi app
  (swagger-ui "/api")
  (swagger-docs
   {:info {:title "The Superior Frobnication Influx Service."
           :description "Documentation for the Superior Frobnication Influx Service."
           :version "42"}})
  (GET "/" [] (redirect "/api"))
  (GET "/favicon.ico" [] {:status 404})
  all-routes)

(defn -main
  [& args]
  (jetty/run-jetty app {:port 31300}))

Note that when using the commented out definition of NonBlankString, the following exception is thrown at start-up instead:
java.lang.IllegalArgumentException: No matching ctor found for class clojure.core$complement$fn__4082
This looks similar to the issue discussed here: http://stackoverflow.com/questions/19427303/inconsistency-in-clojure-functions-in-macros-and-illegalargumentexception

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions