Git Product home page Git Product logo

swagger-gradle-plugin's Introduction

Swagger Gradle Plugin CircleCI Download

This plugin was based on kongchen's swagger-maven-plugin

This enables your Swagger-annotated project to generate Swagger specs and customizable, templated static documents during the gradle build phase. Unlike swagger-core, swagger-gradle-plugin does not actively serve the spec with the rest of the application; it generates the spec as a build artifact to be used in downstream Swagger tooling.

N.B This plugin is tested against the latest of each major Gradle version from 3.x onwards. The reason for 3.x, is that 3.2 was the first that supported Kotlin, therefore keeping tests simpler. This does not mean that this plugin won't work with earlier versions, just your mileage may vary.

Features

Usage

Import the plugin in your project by adding following configuration:

Gradle version >= 2.1

build.gradle (Groovy DSL)

plugins {
    id 'com.benjaminsproule.swagger' version '1.0.8'
}

build.gradle.kts (Kotlin DSL)

plugins {
    id("com.benjaminsproule.swagger") version "1.0.8"
}

Gradle versions < 2.1

buildscript {
  repositories {
    maven {
      url 'https://plugins.gradle.org/m2/'
    }
  }
  dependencies {
    classpath 'gradle.plugin.com.benjaminsproule:swagger-gradle-plugin:1.0.0'
  }
}

apply plugin: 'com.benjaminsproule.swagger'

swagger {
    apiSource {
        ...
    }
}

One apiSource can be considered as a version of APIs of your service.

You can specify several apiSources. Generally, one is enough.

swagger {
    apiSource {
        ...
    }
    apiSource {
        ...
    }
}

Configuration for swagger

name description
apiSources List of apiSource closures. One apiSource can be considered as a version of APIs of your service. You can specify several apiSource closures, though generally one is enough.

Configuration for apiSource

name description
springmvc Tell the plugin your project is a JAX-RS(false) or a SpringMvc(true) project
locations required Classes containing Swagger's annotation @Api, or packages containing those classes can be configured here, using ; as the delimiter.
schemes The transfer protocol of the API. Values MUST be from the list: "http", "https", "ws", "wss".
host The host (name or ip) serving the API. This MUST be the host only and does not include the scheme nor sub-paths. It MAY include a port. The host does not support path templating.
basePath The base path on which the API is served, which is relative to the host. The value MUST start with a leading slash (/). The basePath does not support path templating.
descriptionFile A Path to file with description to be set to Swagger Spec 2.0's info Object
info required The basic information of the api, using same definition as Swagger Spec 2.0's info Object
securityDefinitions You can put your security definitions here, see more details below
security A declaration of which security schemes are applied for the API as a whole. security requirement see more details below
templatePath The path of a handlebars template file, see more details below.
outputPath The path of the generated static document, not existed parent directories will be created. If you don't want to generate a static document, just don't set it.
outputFormats The format types of the generated swagger spec. Valid values are json, yaml or both (as a list, e.g. ['json']). The json format is default.
shouldSortArrays JSON arrays will be sorted instead of being written in the order of appearance. Default is false.
swaggerDirectory The directory of generated swagger.json file. If null, no swagger.json will be generated.
swaggerFileName The filename of generated filename.json file. If null, swagger.json will be generated.
swaggerApiReader If not null, the value should be a full name of the class extending com.github.kongchen.swagger.docgen.reader.ClassSwaggerReader. This allows you to flexibly implement/override the reader's implementation. Default is com.github.kongchen.swagger.docgen.reader.JaxrsReader. More details below
attachSwaggerArtifact If enabled, the generated swagger.json file will be attached as a gradle artifact. The swaggerFileName will be used as an artifact classifier. Default is false.
modelSubstitute The model substitute file's path, see more details below
typesToSkip Nodes of class names to explicitly skip during parameter processing. More details below
apiModelPropertyAccessExclusionsList Allows the exclusion of specified @ApiModelProperty fields. This can be used to hide certain model properties from the swagger spec. More details below
jsonExampleValues If true, all example values in @ApiModelProperty will be handled as json raw values. This is useful for creating valid examples in the generated json for all property types, including non-string ones.
modelConverters List of custom implementations of io.swagger.converter.ModelConverter that should be used when generating the swagger files. More details below
excludePattern Regex of files that will be excluded from the swagger documentation. The default is .*\\.pom so it ignores all pom files.
tagStrategy Default no. class use class name if no tags are set to group operations specific to controller. (currently only springmvc)
expandSuperTypes Default true. You can skip the scan of super types (parent class, interfarce)

If you'd like to generate a template-driven static document, such as markdown or HTML documentation, you'll need to specify a handlebars template file in templatePath. The value for templatePath supports 2 kinds of path:

  1. Resource in classpath. You should specify a resource path with a classpath: prefix. e.g:

    1. classpath:/markdown.hbs
    2. classpath:/templates/hello.html
  2. Local file's absolute path. e.g:

    1. ${project.rootDir}/src/main/resources/markdown.hbs
    2. ${project.rootDir}/src/main/resources/template/hello.html

There's a standalone project for the template files, fetch them and customize it for your own project.

There're 3 types of security definitions according to Swagger Spec: basic, apiKey and oauth2.

You can define multi definitions here, but you should fully follow the spec.

Basic - Security Definitions

You can define a basic definition like this:

securityDefinition {
    // `name` can be used refer to this security schemes from elsewhere
    name = 'MyBasicAuth'
    type = 'basic'
}

ApiKey - Security Definitions

You can also define a ApiKey definition like this:

swagger {
    apiSource {
        ...
        securityDefinition {
            // `name` can be used refer to this security schemes from elsewhere
            name = 'ApiKeyAuth'
            type = 'apiKey'
            // The location of the API key. Valid values are "query" or "header".
            keyLocation = 'header'
            // The name of the header
            keyName = 'X-API-Key'
        }
    }
}

Oauth2 - Security Definitions

You can also define a Oauth2 definition like this:

swagger {
    apiSource {
        ...
        securityDefinition {
            // `name` can be used refer to this security schemes from elsewhere
            name = 'OAuth2Authentication'
            type = 'oauth2'
            // The flow used by the OAuth2 security scheme
            flow = 'accessCode'
            authorizationUrl = 'https://somewhere.com/authorization'
            tokenUrl = 'https://somewhere.com/token'
            scope {
                name = 'read:model'
                description = 'Read the details of the model'
            }
        }
    }
}

Json - Security Definitions

It is also possible to define several definitions in a json file and specify the json path like this:

securityDefinition {
    json = 'securityDefinition.json'
}

Alternatively, specify the absolute file path to the json definition file:

securityDefinition {
    json = "${project.projectDir}/securityDefinition.json"
}

The securityDefinition.json file should also follow the spec, one sample file like this:

{
  "api_key": {
    "type": "apiKey",
    "name": "api_key",
    "in": "header"
  },
  "petstore_auth": {
    "type": "oauth2",
    "authorizationUrl": "http://swagger.io/api/oauth/dialog",
    "flow": "implicit",
    "scopes": {
      "write:pets": "modify pets in your account",
      "read:pets": "read your pets"
    }
  }
}

Note: It is only possible to define the OAuth2 type in a json file and not directly in the gradle configuration.

Allows to set a security requirement on the whole API. This can be done with multiple security requirements applied as AND or OR values. See https://swagger.io/docs/specification/2-0/authentication/ The key of the security requirement has to match a name from a securityDefinition.

security = [ [ ApiKeyAuth : [] ] ]

Use BasicAuth with ApiKey or OAuth2 with given scopes (basic(name: MyBasicAuth) && apiKey(name: MyApiKey)) || oauth2(name: MyOAuth2)

security = [ [ MyBasicAuth : [], MyApiKey : [] ], [ MyOAuth2 : [ 'scope1', 'scope2' ] ] ]

You can instruct swagger-gradle-plugin to use a custom swagger api reader rather than use the default by adding the following to your build.gradle:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.custom:swagger-api-reader:1.0.0'
    }
}
...
swagger {
    apiSource {
        ...
        swaggerApiReader = [ 'com.custom.swagger.ApiReader' ]
    }
}

It is important to note that the class has to be available in the buildscript's classpath.

Throughout the course of working with Swagger, you may find that you need to substitute non-primitive objects for primitive objects. This is called model substituion, and it is supported by swagger-gradle-plugin. In order to configure model substitution, you'll need to create a model substitute file. This file is a simple text file containing n lines, where each line tells swagger-gradle-plugin to substitutes a model class with the supplied substitute. These two classes should be seperated by a colone (:).

Sample model substitution

com.foo.bar.PetName : java.lang.String

The above model substitution configuration would tell the plugin to substitute com.foo.bar.PetName with java.lang.String. As a result, the generated swagger.json would look like this ...

 "definitions" : {
    "Pet" : {
      "properties" : {
        ...
        "petName" : {
          "type" : "string"
        }
        ...
      }
    }

... instead of like this:

 "definitions" : {
    "Pet" : {
      "properties" : {
        ...
        "petName" : {
          "$ref" : "#/definitions/PetName"
        }
        ...
      }
    }

The model substitution file will be read by getClass().getResourceAsStream, so please note the path you configured.

You can instruct swagger-gradle-plugin to skip processing the parameters of certain types by adding the following to your build.gradle: // TODO: Not fully supported yet

typesToSkip = [
    'com.foobar.skipper.SkipThisClassPlease',
    'com.foobar.skipper.AlsoSkipThisClassPlease'
]

You can instruct swagger-gradle-plugin to use a custom model converter rather than use the default by adding the following to your build.gradle:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.custom:model-converter:1.0.0'
    }
}
...
swagger {
    apiSource {
        ...
        modelConverters = [ 'com.custom.model.Converter' ]
    }
}

It is important to note that the class has to be available in the buildscript's classpath.

If you'd like to exclude certain @ApiModelPropertys based on their access values, you may do so by adding the following as a child node of apiSource in your build.gradle:

apiModelPropertyAccessExclusionsList = [
    'secret-property'
]

The above setting would prevent internalThing from appearing in the swagger spec output, given this annotated model:

...
    @ApiModelProperty(name = "internalThing", access = "secret-property")
    public String getInternalThing() {
        return internalThing;
    }
...

Note: In order to use apiModelPropertyAccessExclusionsList, you must specify both the name and access fields of the property you wish to exclude.

Generating the swagger documentation

To generate the swagger documentation, you need to run ./gradlew generateSwaggerDocumentation.

N.B In previous versions (< 0.1.0) the task was swagger, but this caused a conflict with another plugin, swagger-codegen, (issue #8).

Skipping generating the swagger documentation

To skip generating the swagger documentation, you need to include the property swagger.skip (e.g. ./gradlew clean build -Pswagger.skip)

Install/Deploy swagger.json

You can instruct swagger-gradle-plugin to deploy the generated swagger.json by adding the following to your build.gradle:

attachSwaggerArtifact = true

The above setting attaches the generated file to Gradle for install/deploy purpose with swaggerDirectory's name as classifier and the outputFormat as type.

Please note that when using the maven-publish plugin instead of the maven plugin, the classifier must be specified in the configuration as it uses a different mechanism for the classifier. This is especially important when using multiple apiSource closures. Example:

publishing {
    publications {
        maven(MavenPublication) {
            artifact source: "${swaggerDirectory}/publicApiSwagger.json", classifier: 'publicApiSwagger'
            artifact source: "${swaggerDirectory}/privateApiSwagger.json", classifier: 'privateApiSwagger'
        }
    }
    repositories {
        maven {
            url "https://path/to/repo"
        }
    }
}
swagger {
     apiSource {
         attachSwaggerArtifact = true
         locations = ['com.benjaminsproule.public']
         swaggerDirectory = "${swaggerDirectory}"
         swaggerFileName = 'publicSwagger'
     }
     apiSource {
         attachSwaggerArtifact = true
         locations = ['com.benjaminsproule.private']
         swaggerDirectory = "${swaggerDirectory}"
         swaggerFileName = 'privateSwagger'
     }
}

Example

build.gradle (Groovy DSL)

plugins {
    id "com.benjaminsproule.swagger" version "1.0.0"
}

swagger {
    apiSource {
        springmvc = true
        locations = [ 'com.wordnik.swagger.sample' ]
        schemes = [ 'http', 'https' ]
        host = 'www.example.com:8080'
        basePath = '/api'
        info {
            title = 'Swagger Gradle Plugin Sample'
            version = 'v1'
            // use markdown here because I'm using markdown for output,
            // if you need to use html or other markup language, you need to use your target language
            description = 'This is a sample.'
            termsOfService = 'http://www.example.com/termsOfService'
            contact {
                email = '[email protected]'
                name = 'Name'
                url = 'http://www.example.com'
            }
            license {
                url = 'http://www.apache.org/licenses/LICENSE-2.0.html'
                name = 'Apache 2.0'
            }
        }
        securityDefinition {
            name = 'basicAuth'
            type = 'basic'
        }
        securityDefinition {
            json = 'securityDefinition.json'
        }
        /**
            Support classpath or file absolute path here.
            1) classpath e.g: "classpath:/markdown.hbs", "classpath:/templates/hello.html"
            2) file e.g: "${project.rootDir}/src/main/resources/markdown.hbs", "${project.rootDir}/src/main/resources/template/hello.html"
        **/
        templatePath = "${project.rootDir}/src/test/resources/strapdown.html.hbs"
        outputPath = "${project.rootDir}/generated/document.html"
        swaggerDirectory = "${project.rootDir}/generated/swagger-ui"
        swaggerApiReader = 'com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader'
        modelConverters = [ 'io.swagger.validator.BeanValidator' ]
        attachSwaggerArtifact = true
    }
}

build.gradle.kts (Kotlin DSL)

plugins {
    id("com.benjaminsproule.swagger") version "1.0.0"
}

swagger {
    apiSource(closureOf<ApiSourceExtension> {
        springmvc = true
        locations = listOf("com.wordnik.swagger.sample"]
        schemes = listOf("http", "https")
        host = "www.example.com:8080"
        basePath = "/api"
        info(closureOf<InfoExtension> {
            title = "Swagger Gradle Plugin Sample"
            version = "v1"
            // use markdown here because I"m using markdown for output,
            // if you need to use html or other markup language, you need to use your target language
            description = "This is a sample."
            termsOfService = "http://www.example.com/termsOfService"
            contact(closureOf<ContactExtension> {
                email = "[email protected]"
                name = "Name"
                url = "http://www.example.com"
            })
            license(closureOf<LicenseExtension> {
                url = "http://www.apache.org/licenses/LICENSE-2.0.html"
                name = "Apache 2.0"
            })
        })
        securityDefinition(closureOf<SecurityDefinitionExtension> {
            name = "basicAuth"
            type = "basic"
        })
        securityDefinition(closureOf<SecurityDefinitionExtension> {
            json = "securityDefinition.json"
        }
        /**
            Support classpath or file absolute path here.
            1) classpath e.g: "classpath:/markdown.hbs", "classpath:/templates/hello.html"
            2) file e.g: "${project.rootDir}/src/main/resources/markdown.hbs", "${project.rootDir}/src/main/resources/template/hello.html"
        **/
        templatePath = "${project.rootDir}/src/test/resources/strapdown.html.hbs"
        outputPath = "${project.rootDir}/generated/document.html"
        swaggerDirectory = "${project.rootDir}/generated/swagger-ui"
        swaggerApiReader = "com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader"
        modelConverters = listOf("io.swagger.validator.BeanValidator")
        attachSwaggerArtifact = true
    })
}

swagger-gradle-plugin's People

Contributors

aferg avatar anver-trip avatar audi-trip avatar copa2 avatar delego-wlritchi avatar dependabot-preview[bot] avatar dependabot[bot] avatar fmotrifork avatar franzwong avatar gigasproule avatar groboclown avatar iautushka avatar istomisgood avatar klu2 avatar mousecage avatar orevial avatar radcortez avatar renovate[bot] avatar set321go avatar swurzinger avatar terziele avatar thenorthernpole avatar theosotr avatar thorin avatar vladiatro avatar wakingrufus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swagger-gradle-plugin's Issues

Refactor away the maven swagger plugin code

I keep running into issues that are in the maven-swagger-plugin which seems to have a low level of maintenance and a number of open issues. I decided to bite the bullet and merge the two plugins.

I started by bringing all the code from the maven-swagger-plugin and then spent some time refactoring the java code into groovy. I have been adding tests and refactoring the gradle-swagger-plugin along the way.

I have added the jacoco plugin to the build but I didn't bring any of the tests from the maven-swagger-plugin because they were generally terrible, I have added quite a few tests around the model objects for the plugin and some tests around skipping and artifact generation.

This is still a WIP (hence the 🍌 ' s) I am going to continue adding tests, especially for the spring generation as there are currently none. Let me know if your interested in this work. I plan to move across to this for my projects and it would be great if it becomes part of your project but I can understand that it's a significant departure from the current plugin.

https://github.com/set321go/swagger-gradle-plugin/tree/remove-kongchen-dependency

Getting java.lang.ClassNotFoundException: javax.servlet.http.HttpServletRequest when generating swagger json

Spring Boot 1.5.2.RELEASE
Spring MVC

stacktrace

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':ingress:generateSwaggerDocumentation'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:69)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:66)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:203)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:185)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:66)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:50)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
        at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
Caused by: java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest
        at com.benjaminsproule.swagger.gradleplugin.reader.SpringMvcApiReader.generateResourceMap(SpringMvcApiReader.groovy:444)
        at com.benjaminsproule.swagger.gradleplugin.reader.SpringMvcApiReader.read(SpringMvcApiReader.groovy:52)
        at com.benjaminsproule.swagger.gradleplugin.reader.ClassSwaggerReader$read.call(Unknown Source)
        at com.benjaminsproule.swagger.gradleplugin.docgen.AbstractSwaggerLoader.loadDocuments(AbstractSwaggerLoader.groovy:31)
        at com.benjaminsproule.swagger.gradleplugin.docgen.AbstractSwaggerLoader$loadDocuments.call(Unknown Source)
        at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.processSwaggerPluginExtension(GenerateSwaggerDocsTask.groovy:73)
        at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.generateSwaggerDocuments(GenerateSwaggerDocsTask.groovy:52)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:228)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:221)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:210)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:621)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:604)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
        ... 14 more
Caused by: java.lang.ClassNotFoundException: javax.servlet.http.HttpServletRequest
        ... 29 more

generateSwaggerDocumentation throws a warning

On building, everything works, but the following warning gets thrown.

Task :redacted:generateSwaggerDocumentation
Gradle now uses separate output directories for each JVM language, but this build assumes a single directory for all classes from a source set. This behaviour has been deprecated and is scheduled to be removed in Gradle 5.0
at org.gradle.api.internal.tasks.DefaultSourceSetOutput.getClassesDir(DefaultSourceSetOutput.java:80)
at org.gradle.api.internal.tasks.DefaultSourceSetOutput_Decorated.getClassesDir(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at org.codehaus.groovy.runtime.metaclass.MultipleSetterProperty.getProperty(MultipleSetterProperty.java:49)
at org.gradle.internal.metaobject.BeanDynamicObject$MetaClassAdapter.getProperty(BeanDynamicObject.java:228)
at org.gradle.internal.metaobject.BeanDynamicObject.tryGetProperty(BeanDynamicObject.java:171)
at org.gradle.internal.metaobject.CompositeDynamicObject.tryGetProperty(CompositeDynamicObject.java:55)
at org.gradle.internal.metaobject.AbstractDynamicObject.getProperty(AbstractDynamicObject.java:59)
at org.gradle.api.internal.tasks.DefaultSourceSetOutput_Decorated.getProperty(Unknown Source)
at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:50)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296)
at com.benjaminsproule.swagger.gradleplugin.extension.ApiSourceExtension.prepareClassLoader(ApiSourceExtension.groovy:78)
at com.benjaminsproule.swagger.gradleplugin.extension.ApiSourceExtension.getValidClasses(ApiSourceExtension.groovy:85)
at com.github.kongchen.swagger.docgen.mavenplugin.ApiSource.setHostFromAnnotation(ApiSource.java:209)
at com.github.kongchen.swagger.docgen.mavenplugin.ApiSource.getHost(ApiSource.java:296)
at com.github.kongchen.swagger.docgen.AbstractDocumentSource.(AbstractDocumentSource.java:91)
at com.github.kongchen.swagger.docgen.mavenplugin.MavenDocumentSource.(MavenDocumentSource.java:28)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:255)
at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.processSwaggerPluginExtension(GenerateSwaggerDocsTask.groovy:61)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210)
at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:52)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:154)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.generateSwaggerDocuments(GenerateSwaggerDocsTask.groovy:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:46)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:784)
at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:751)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:121)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:110)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)
at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:60)
at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:97)
at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:87)
at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:626)
at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:581)
at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.lang.Thread.run(Thread.java:748)

Is there a planned fix for this? It doesn't break anything yet, but it's getting on my nerves and is a problem if I were to upgrade to gradle 5.

Adding dependency

Been trying to use this plugin, I have followed your example to try and add it to my build.gradle file.

When I run it I get an error saying it cannot find the plugin.

"Could not find com.benjaminsproule:swagger-gradle-plugin:0.0.3"

Any ideas?

HttpServletRequest/HttpServletResponse parameters are not allowed

When I use a method with
javax/servlet/http/HttpServletRequest
javax/servlet/http/HttpServletResponse
as na input parmeter the swagger.json is not generated for this controller.

gradle output:

:generateSwaggerDocumentation
Gradle now uses separate output directories for each JVM language, but this build assumes a single directory for all classes from a source set. This behaviour has been deprecated and is scheduled to be removed in Gradle 5.0
javax/servlet/http/HttpServletRequest
javax/servlet/http/HttpServletResponse
javax/servlet/http/HttpServletResponse
javax/servlet/http/HttpServletRequest

Method with annotations:

    @ApiOperation(value = "provide options", tags = {"options"}, notes = "Get possible options")
    @RequestMapping(value = {"/{type}", "/v1/{type}"}, method = RequestMethod.OPTIONS, produces = "application/json")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates the option request was successfully performed.")
    })
    @SuppressWarnings("unchecked")
    public void options(@ApiParam(name = "type", value = "type", required = true) @PathVariable(name = "type") String pathType,
                        HttpServletResponse response) throws IOException {
        response.addHeader(HttpHeaders.ALLOW, "GET, OPTIONS, DELETE, PUT, POST");
    }

Is there any problem with annotations?

Could not find method findProperty() for arguments [swagger.skip]

Hi,

I am new to swagger and gradle. I was facing the issue on running the below command.

./gradlew generateSwaggerDocumentation

I got the below error

  • What went wrong:
    Could not evaluate onlyIf predicate for task ':generateSwaggerDocumentation'.

Could not find method findProperty() for arguments [swagger.skip] on root project .

Can someone help

Generated tags regression after updating plugin from 1.0.0 to 1.0.2

Gradle version 4.5.1
Spring MVC

After plugin upgrade the generated "tags" section no longer contains the description property.

Output before:

  "host" : "localhost:8081",
  "tags" : [ {
    "name" : "customers",
    "description" : "Operations related to customers"
  }, {
    "name" : "faqs",
    "description" : "Operations for FAQs"
  }, {
...

Output after:

  "tags" : [ {
    "name" : "customers"
  }, {
    "name" : "faqs"
  }, {
...

The definition in the Customers controller:

@RestController
@RequestMapping( value = "/customers", produces = APPLICATION_JSON_UTF8_VALUE )
@Api( value = "/customers", description = "Operations related to customers",
      authorizations = { @Authorization( value = "dezideoauth",
              scopes = { @AuthorizationScope( scope = "read", description = "" ),
                         @AuthorizationScope( scope = "write", description = "" ) } ) } )
public class CustomerController

Maybe it is possible to compare the generated output of some complex examples to a known output during testing, to avoid introducing regressions like this.

apiSource.outputFormats changed behavior after upgrading from 1.0.0 to 1.0.2

Gradle version: 4.5.1

Error:

* What went wrong:
A problem occurred evaluating project ':contact-center-service'.
> Cannot cast object 'json,yaml' with class 'java.lang.String' to class 'java.util.List'

Changing to:
outputFormats = ['json','yaml']

Gets things going again. I think that the 'new' syntax is more natural, but if the change is intentional then the README should be updated.

Also specifying outputFormats = ['json,yaml'] results in a successful run with no output generated. Perhaps the input could be verified to help users.

Document task name change

I think its good you've given your task a better name but I only figured out what the problem was when I looked at the closed issues (#8).

Something on the readme would be helpful

Could not set unknown property 'swaggerFilename'

No problem when I don't put swaggerFilename="something"

But when I put it into apiSource, this message pops up:

Could not set unknown property 'swaggerFilename' for com.benjaminsproule.swagger.gradleplugin.extension.ApiSourceExtension(apiModelPropertyAccessExclusionsList:null, typesToSkipList:null, attachSwaggerArtifact:false) of type com.benjaminsproule.swagger.gradleplugin.extension.ApiSourceExtension.

apiSource {
    springmvc = false
    locations = [ 'abcdefg' ]
    info {
        title = 'Swagger Gradle Plugin Sample'
        version = 'v1'
        description = 'This is a sample.'
    }
    outputFormats="yaml"
    swaggerDirectory = "${project.rootDir}/generated/swagger-ui"
    swaggerFilename = "swagger123"
}

version: 0.1.2

Can't discover JSON security definition file when in project resources

The following configuration results in JSON parse error which is caused by inability to discover the file service-security.json. The problem is present in all cases with file placed either in main/resources, main/java or at project's root.
Further debugging reveals that the classloader used when the plugin executes has no access to the project's files, be it resources or Java source files.

Code in build.gradle:

swagger {
    apiSource {
        locations = ['my.package']
        basePath = '/api'
        info {
            title = "Service API"
            version = project.version
        }
        jsonExampleValues = true 
        swaggerDirectory = "${project.buildDir}/generated/docs/"
        outputFormats = "json,yaml"
        securityDefinition {
            json = "/service-security.json" // attempted with and without the leading slash 
        }
    }
}

Model substitutions fail - ModelModifier loads classes with the default classloader

Here's an excerpt from my Gradle config (anonymized):

plugins {
    id 'com.benjaminsproule.swagger' version '1.0.2'
}
swagger {
    apiSource {
        locations = ['com.example.api']
        schemes = ['https']
        basePath = '/api'
        info {
            title = 'Example API'
            version = project.version
            description = 'An example API'
        }
        outputFormats = ['json', 'yaml']
        modelSubstitute = "/swagger-substitutions.txt"
        swaggerDirectory = "$projectDir/build/swagger"
        swaggerFileName = 'swagger'
    }
}

The content of buildSrc/src/main/resources/swagger-substitutions.txt:

java.math.BigDecimal : java.lang.String
com.example.model.Foo : java.lang.String
com.example.model.Bar : com.example.codec.Baz

And here's the task output:

> Task :generateSwaggerDocumentation 
Problem with loading class: com.example.model.Foo. Mapping from: com.example.model.Foo to: java.lang.String will be ignored.
Problem with loading class: com.example.model.Bar. Mapping from: com.example.model.Bar to: com.example.codec.Baz will be ignored.
Problem with loading class: com.example.codec.Baz. Mapping from: com.example.model.Bar to: com.example.codec.Baz will be ignored.

Ultimately, the issue is that the classes are not available on the buildscript classpath, so ModelModifier's Class.forName fails. This issue did not occur in 0.1.9.

One possible solution would be to load classes using the same classloading logic as is used in the ClassFinder. I think that care might need to be taken here since the JavaType instances will have to be the same for map lookups to work - thus, the two probably need to use the same classloader.

Another solution might be for ModelModifier to track classes by fully qualified name rather than by resolving them to JavaType objects. I'm not clear on the internals of this plugin, so I'm not sure if this is in line with the grand design or not.

Improve samples

The sample is very basic and could do with showing more variations. At least have Spring annotation and JAX-RS annotation samples.

SecurityDefinition as header cannot be specified in build.gradle

I would love to use the "simple" way of defining a securityDefinition in my build.gradle file:

securityDefinition {
    name = 'MyBasicAuth'
    type = 'basic'
}

My security demands a JWT token set as a header with name=Authorization.

In Json i can define this like this:

{"jwt": { "type": "apiKey", "name": "Authorization", "in": "header" }}

This is not possible in the gradle syntax used now. As the "key" called "name" is used for the name of the entire securitySchemes and I need to set a name for the header aswell.

securityDefinition {
    name = 'jwt'
    name..?? = 'Authorization'
    type = 'apiKey'
    keyLocation = 'header'
}

In swagger YAML this would look like this:

components:
  securitySchemes:
    jwt:
      type: apiKey
      in: header
      name: Authorization

Cannot generate Swagger from Groovy or Kotlin

I'm having problems generating Swagger where the APIs are written in a language other than Java - namely Groovy or Kotlin

In these cases the generated classes are written to build/classes/kotlin/main or build/classes/groovy/main.

When I run the swagger-gradle-plugin, it seems that it cannot find the Kotlin or Groovy classes. I get an error like this:

could not create Dir using directory from url file:/Users/dcp65/projects/myproject/build/classes/java/main. skipping.

Is there any way to override the build path?

I was able to generate Swagger from Groovy until upgrading swagger-gradle-plugin to 1.0.0, so perhaps something changed when the dependency on kongchen was removed.

Null Pointer Exception when running generateSwaggerDocumentation

I'm getting following warning when running generateSwaggerDocumentation command:

could not create Dir using directory from url file:/home/myproject/build/classes/kotlin/main. skipping.
java.lang.NullPointerException
	at org.reflections.vfs.Vfs$DefaultUrlTypes$3.matches(Vfs.java:239)
	at org.reflections.vfs.Vfs.fromURL(Vfs.java:98)
	at org.reflections.vfs.Vfs.fromURL(Vfs.java:91)
	at org.reflections.Reflections.scan(Reflections.java:237)
	at org.reflections.Reflections.scan(Reflections.java:204)
	at org.reflections.Reflections.<init>(Reflections.java:129)
	at org.reflections.Reflections.<init>(Reflections.java:170)
	at sun.reflect.GeneratedConstructorAccessor127.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
	at org.codehaus.groovy.reflection.CachedConstructor.doConstructorInvoke(CachedConstructor.java:77)
	at org.codehaus.groovy.runtime.callsite.ConstructorSite.callConstructor(ConstructorSite.java:45)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:255)
	at com.benjaminsproule.swagger.gradleplugin.extension.ApiSourceExtension.getValidClasses(ApiSourceExtension.groovy:84)
	at com.github.kongchen.swagger.docgen.mavenplugin.ApiSource.setHostFromAnnotation(ApiSource.java:218)
	at com.github.kongchen.swagger.docgen.mavenplugin.ApiSource.getHost(ApiSource.java:305)
	at com.github.kongchen.swagger.docgen.AbstractDocumentSource.<init>(AbstractDocumentSource.java:86)
	at com.github.kongchen.swagger.docgen.mavenplugin.MavenDocumentSource.<init>(MavenDocumentSource.java:28)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
	at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
	at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.processSwaggerPluginExtension(GenerateSwaggerDocsTask.groovy:73)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
	at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.generateSwaggerDocuments(GenerateSwaggerDocsTask.groovy:51)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.doExecute(DefaultTaskClassInfoStore.java:142)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:135)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:122)
	at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:762)
	at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:729)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:121)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:110)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)
	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
	at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:97)
	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:87)
	at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:625)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:580)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.lang.Thread.run(Thread.java:748)
could not create Vfs.Dir from url. ignoring the exception and continuing
org.reflections.ReflectionsException: could not create Vfs.Dir from url, no matching UrlType was found [file:/home/myproject/build/classes/kotlin/main]
either use fromURL(final URL url, final List<UrlType> urlTypes) or use the static setDefaultURLTypes(final List<UrlType> urlTypes) or addDefaultURLTypes(UrlType urlType) with your specialized UrlType.
	at org.reflections.vfs.Vfs.fromURL(Vfs.java:109)
	at org.reflections.vfs.Vfs.fromURL(Vfs.java:91)
	at org.reflections.Reflections.scan(Reflections.java:237)
	at org.reflections.Reflections.scan(Reflections.java:204)
	at org.reflections.Reflections.<init>(Reflections.java:129)
	at org.reflections.Reflections.<init>(Reflections.java:170)
	at sun.reflect.GeneratedConstructorAccessor127.newInstance(Unknown Source)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
	at org.codehaus.groovy.reflection.CachedConstructor.doConstructorInvoke(CachedConstructor.java:77)
	at org.codehaus.groovy.runtime.callsite.ConstructorSite.callConstructor(ConstructorSite.java:45)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:255)
	at com.benjaminsproule.swagger.gradleplugin.extension.ApiSourceExtension.getValidClasses(ApiSourceExtension.groovy:84)
	at com.github.kongchen.swagger.docgen.mavenplugin.ApiSource.setHostFromAnnotation(ApiSource.java:218)
	at com.github.kongchen.swagger.docgen.mavenplugin.ApiSource.getHost(ApiSource.java:305)
	at com.github.kongchen.swagger.docgen.AbstractDocumentSource.<init>(AbstractDocumentSource.java:86)
	at com.github.kongchen.swagger.docgen.mavenplugin.MavenDocumentSource.<init>(MavenDocumentSource.java:28)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
	at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:263)
	at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.processSwaggerPluginExtension(GenerateSwaggerDocsTask.groovy:73)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite$PogoCachedMethodSiteNoUnwrapNoCoerce.invoke(PogoMetaMethodSite.java:210)
	at org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite.callCurrent(PogoMetaMethodSite.java:59)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:166)
	at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.generateSwaggerDocuments(GenerateSwaggerDocsTask.groovy:51)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.doExecute(DefaultTaskClassInfoStore.java:142)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:135)
	at org.gradle.api.internal.project.taskfactory.DefaultTaskClassInfoStore$StandardTaskAction.execute(DefaultTaskClassInfoStore.java:122)
	at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:762)
	at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:729)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:121)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:110)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:92)
	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:70)
	at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:62)
	at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
	at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:97)
	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:87)
	at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
	at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:248)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199)
	at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:241)
	at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:230)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:625)
	at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:580)
	at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
	at java.lang.Thread.run(Thread.java:748)

It might be (probably is) related to issue in org.reflections. What is weird, is that running generateSwaggerDocumentation causes all subfolders in build/classes/kotlin to disappear.

I'm running Gradle 4.2.1. My swagger plugin config is as follows:

swagger {
    apiSource {
        springmvc = false
        locations = swaggerLocation
        schemes = ['http','https']
        basePath = '/'
        info {
            title = swaggerTitle
            description = hasProperty("swaggerDescription") ? swaggerDescription : swaggerTitle
            version = 'NaN'
        }
        templatePath = "${rootDir}/additions/api-doc-template/strapdown.html.hbs"
        outputPath = "${rootDir}/build/swagger/${project.name}/document.html"
        swaggerDirectory = "${rootDir}/build/swagger/${project.name}/swagger-ui"
        attachSwaggerArtifact = true
    }
}

unknown property "classesDirs"

Hello
I tried to use this plugin (which seems great) but I have a problem related to gradle more than the plugin itself but the documentaton doesn't talk about that:

* What went wrong:
Execution failed for task ':generateSwaggerDocumentation'.
> Could not get unknown property 'classesDirs' for main classes of type org.gradle.api.internal.tasks.DefaultSourceSetOutput.

Any idea of solution ?

I simply copied the swagger {} example.

Re-work security definitions logic

Currently, the security definitions logic only allows for 1 security definition and doesn't really work with OAuth (unless using JSON).

To make this more self-enclosed (rather than requiring JSON for this), the Swagger spec should be configurable from within the Gradle config.

generateSwaggerDocumentation fails with org.yaml:snakeyaml >= 1.20

When issuing the generateSwaggerDocumentation task with org.yaml:snakeyaml >= 1.20, a java.lang.NoSuchMethodError is thrown.

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':generateSwaggerDocumentation'. at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:103) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:73) at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51) at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59) at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54) at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59) at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101) at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44) at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91) at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54) at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43) at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker$1.run(DefaultTaskGraphExecuter.java:256) at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336) at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328) at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:249) at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter$EventFiringTaskWorker.execute(DefaultTaskGraphExecuter.java:238) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.processTask(DefaultTaskPlanExecutor.java:123) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.access$200(DefaultTaskPlanExecutor.java:79) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:104) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:98) at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.execute(DefaultTaskExecutionPlan.java:663) at org.gradle.execution.taskgraph.DefaultTaskExecutionPlan.executeWithTask(DefaultTaskExecutionPlan.java:597) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$TaskExecutorWorker.run(DefaultTaskPlanExecutor.java:98) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) Caused by: java.lang.NoSuchMethodError: org.yaml.snakeyaml.events.MappingStartEvent.<init>(Ljava/lang/String;Ljava/lang/String;ZLorg/yaml/snakeyaml/error/Mark;Lorg/yaml/snakeyaml/error/Mark;Ljava/lang/Boolean;)V at com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.writeStartObject(YAMLGenerator.java:450) at com.fasterxml.jackson.core.base.GeneratorBase.writeStartObject(GeneratorBase.java:286) at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:151) at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480) at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319) at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1396) at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:1120) at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:993) at com.fasterxml.jackson.databind.ObjectWriter$writeValueAsString.call(Unknown Source) at com.benjaminsproule.swagger.gradleplugin.generator.SwaggerSpecGenerator.generate(SwaggerSpecGenerator.groovy:76) at com.benjaminsproule.swagger.gradleplugin.generator.Generator$generate.call(Unknown Source) at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.processSwaggerPluginExtension(GenerateSwaggerDocsTask.groovy:76) at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.generateSwaggerDocuments(GenerateSwaggerDocsTask.groovy:52) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:46) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26) at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:788) at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:755) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:124) at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:336) at org.gradle.internal.progress.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:328) at org.gradle.internal.progress.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:199) at org.gradle.internal.progress.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:110) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:113) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:95)

Plugin does not seem to pick up changes due to gradle caching or something

Hi,

I have noticed that the plugin does not seem to pick up changes in the source files after a successful build.

Executing: gradlew clean gSD generates a new swagger.json, but the contents are stale (identical to the previous run). If I run the command as gradlew --no-daemon clean gSD the expected (updated) result is generated.

This happens with gradle 4.1 and 4.2.1 (and possibly others, I just tried the previous version to confirm that it was not introduced in 4.2.1).

I'm not entirely sure, but I guess that some gradle task definition magic is incorrect as the gradle team seems to have been focusing on more aggressive caching in the 4.x series.

Multiple models with same name results in nondeterministic swagger file generation

I located a very interesting issue in the current implementation.

If the application that we generate swagger documentations for has multiple models with the same class name, it will result in that the swagger file generated will only contain one of the models. It seems random which of the models are chosen for the swagger generation.

This can happen if you have two different input model and output models with same name. Or to models with same name in different versions:

 com.xxxxxx.v1.canonical.Pet
 com.xxxxxx.v2.canonical.Pet

The plugin should handle this in some way. I see a couple of different options.

  1. Prefix models with package until all names are unique
  2. Add a running number to the model name for duplicate models
  3. Throw an exception and not create any swagger docs if there are different models with same name

Best,
Frederik

Task is slow

When running the generateSwaggerDocumentation task it takes a long time. It looks like this is because Reflections is scanning the world!

> Task :authtoken-rest:generateSwaggerDocumentation
Putting task artifact state for task ':authtoken-rest:generateSwaggerDocumentation' into context took 0.0 secs.
Executing task ':authtoken-rest:generateSwaggerDocumentation' (up-to-date check took 0.0 secs) due to:
  Task has not declared any outputs.
Resolving dependency management for configuration 'runtime' of project 'authtoken-rest'
Excluding []
Gradle now uses separate output directories for each JVM language, but this build assumes a single directory for all classes from a source set. This behaviour has been deprecated and is scheduled to be removed in Gradle 5.0
Reflections took 2 ms to scan 2 urls, producing 13 keys and 20 values 
Reflections took 4027 ms to scan 294 urls, producing 14115 keys and 76380 values 
Reflections took 4054 ms to scan 294 urls, producing 14115 keys and 76380 values 
Reflections took 4016 ms to scan 294 urls, producing 14115 keys and 76380 values 
Reflections took 4019 ms to scan 294 urls, producing 14115 keys and 76380 values 
Reflections took 3919 ms to scan 294 urls, producing 14115 keys and 76380 values 
Reflections took 4311 ms to scan 294 urls, producing 14115 keys and 76380 values 

I suspect was caused by gradle i'm running the latest 4.1 in this project but i have seen this issue with all projects running 4+

property swaggerFileName is not supported

The Maven plugin (https://github.com/kongchen/swagger-maven-plugin/blob/master/README.md) has a property swaggerFileName that, along with swaggerDirectory controls where the swagger output json file ends up (by default, a file called swagger.json)

However this property is not exposed & implemented in the gradle wrapper, see:
https://github.com/gigaSproule/swagger-gradle-plugin/blob/master/src/main/groovy/com/benjaminsproule/swagger/gradleplugin/GenerateSwaggerDocsTask.groovy#L89

Swagger 2 is not supported

Hey there,

I'm trying to use the plugin with Swagger 2 annotations (io.swagger.core.v3:swagger-annotations:2.0.0-rc4 package) but the plugin doesn't seem to pick up the resource file. It works using the annotations from Swagger 1.5. is this supported? If yes, how do I enable it?

Thanks!

Reduce dependencies

Hi,
Thanks for developing the plugin!
I have one request, though: The plugin adds a project dependency to swagger-core which itself depends on quite heavy libraries like guava. Any chance to "reduce" the added project dependency to swagger-annotations since I don't see any necessity to add a dependency to swagger-core in a project using the plugin.

Error in Springmvc project: AnnotatedElementUtils.findMergedAnnotation()

When enabling version 1.0.2 of this plugin in our spring boot app, we get the following error:

        at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.generateSwaggerDocuments(GenerateSwaggerDocsTask.groovy:59)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:228)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:221)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:210)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:621)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:604)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
        ... 60 more
Caused by: groovy.lang.MissingMethodException: No signature of method: static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation() is applicable for argument types: (java.lang.reflect.Method, java.lang.Class) values: [public abstract java.util.List our.org.OurClass.ourMethod(java.util.UUID,org.joda.time.DateTime,org.joda.time.DateTime), ...]
        at com.benjaminsproule.swagger.gradleplugin.reader.SpringMvcApiReader.analyzeController(SpringMvcApiReader.groovy:378)
        at com.benjaminsproule.swagger.gradleplugin.reader.SpringMvcApiReader.generateResourceMap(SpringMvcApiReader.groovy:437)
        at com.benjaminsproule.swagger.gradleplugin.reader.SpringMvcApiReader.read(SpringMvcApiReader.groovy:52)
        at com.benjaminsproule.swagger.gradleplugin.reader.ClassSwaggerReader$read.call(Unknown Source)
        at com.benjaminsproule.swagger.gradleplugin.docgen.AbstractSwaggerLoader.loadDocuments(AbstractSwaggerLoader.groovy:31)
        at com.benjaminsproule.swagger.gradleplugin.docgen.AbstractSwaggerLoader$loadDocuments.call(Unknown Source)
        at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.processSwaggerPluginExtension(GenerateSwaggerDocsTask.groovy:73)
        at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.generateSwaggerDocuments(GenerateSwaggerDocsTask.groovy:52)
        ... 68 more

we have the springmvc = true option in the config.
we are using spring boot 1.4.7.RELEASE
and spring 4.3.12.RELEASE

I have tried gradle versions 2.14.1 and 4.5.1

Get `ClassNotFoundException` after `gradle clean`

When performing gradle clean and then gradle swagger a ClassNotFoundException is thrown. If gradle swagger is then run again, it works fine.

When running gradle clean swagger there are no exceptions thrown.

apiSource.securityDefinition changed behavior after upgrade from 1.0.0 to 1.0.2

Gradle 4.5.1

Having:

securityDefinition {
        json = '/securityDefinition.json'
}

Like mentioned various places in the README, has stopped working after upgrading to 1.0.2.
Previously it would successfully include the file from src/main/resources/securityDefinition.json, now the plugin fails with:

> Ambiguous method overloading for method com.fasterxml.jackson.databind.ObjectMapper#readTree.
  Cannot resolve which method to invoke for [null] due to overlapping prototypes between:
        [class com.fasterxml.jackson.core.JsonParser]
        [class [B]
        [class java.io.File]
        [class java.io.InputStream]
        [class java.io.Reader]
        [class java.lang.String]
        [class java.net.URL]

This is the same error as one gets if the plugin cannot locate the file specified.

Changing to:

securityDefinition {
        json = 'securityDefinition.json'
}

Gets things running again.

I also tried with absolute paths like mentioned in the README without any success (there is also an example with "${basedir}/..." which probably should be "${projectDir}/...") but none of the absolute paths are working (this may also have been the case pre 1.0.2 as I just tried it out now)

Definitions in generated swagger.json contains more than model types

This seems to have crept in since I upgraded from 0.1.9 to 1.0.2.

Previously, the 'definitions' section of my generated swagger.json only included classes from my project's 'api-model' module.

Now, a host of unrelated classes, that should never be exposed in API documentation, are appearing.

I have now rolled back to 0.1.9 and I'm only seeing the expected definition classes.

Plugin has side-effect w/ Gradle daemon

When using the Gradle daemon (default on newer Gradle versions) the plugin has some odd side effects. Once a class is loaded once for analysis by the plugin it won't be loaded again on subsequent builds, so changes won't be picked up.

Workaround: running Gradle with --no-daemon fixes the issue

One possible solution would be to create a new, isolated classloader an run the plugin in that, as shown here: https://discuss.gradle.org/t/how-to-separate-gradle-plugin-dependencies-and-project-dependencies/15515/4

Update README to explain how to use custom model converters, API readers, etc.

Currently, it's not obvious how to use custom classes as part of this plugin, such as custom model converters and API readers. All that is required is to add the classes to the classpath for the buildscript, e.g. to use io.swagger.validator.BeanValidator for the model converter:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'io.swagger:swagger-hibernate-validations:1.5.18'
    }
}

Swagger attachSwaggerArtifact don´t deploy JSON type object as described

As described :

You can instruct swagger-gradle-plugin to deploy the generated swagger.json by adding the following to your build.gradle:
swaggerDirectory = '${project.rootDir}/swagger-ui'
attachSwaggerArtifact = true
The above setting attaches the generated file to Gradle for install/deploy purpose with swagger-ui as classifier and json as type

task Added ability to attach swagger artifact:
GenerateSwaggerDocsTask.groovy:

project.task('createSwaggerArtifact', type: Jar, dependsOn: project.tasks.classes) {

                    classifier = classifierName
                from swaggerFile

}

Swagger.json for Spring RestControllers is not generated

At first I thought my configuration is somewhat wrong. So I've taken the sample directory and generated swagger.json - worked perfectly. Then I changed the controller to Spring-ish, not JAX-RS:

package com.benjaminsproule.sample;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Api(value = "/sample", description = "Sample REST for Integration Testing")
public class SampleResource {
    @RequestMapping("/sample")
    @ApiOperation(value = "Return hello message", response = String.class)
    public String home() {
        return "{\"Hello\": \"World!\"}";
    }
}

And suddenly the swagger.json does not contain paths section whatsoever. I even changed the configuration:

swagger {
    apiSource {
        springmvc = true
        swaggerApiReader = 'com.github.kongchen.swagger.docgen.reader.SpringMvcApiReader'
        //...
    }
}

But it didn't help. Also tried without swaggerApiReader - no luck here either. So my question is - how to generate the swagger.json for Spring controllers?

Gradle 4.0 warnings about getClassesDir() when generating swagger docs with sourceSets

since upgrading to gradle 4.2.1 I have been seeing these warnings:

"Gradle now uses separate output directories for each JVM language, but this build assumes a single directory for all classes from a source set. This behaviour has been deprecated and is scheduled to be removed in Gradle 5.0"

...
at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.getClasspath(GenerateSwaggerDocsTask.groovy:193)
at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.processSwaggerPluginExtension(GenerateSwaggerDocsTask.groovy:64)
...

It looks like classesDir is now a collection (classesDirs), and the legacy behavior is to get the first element of the list.

modelSubstitute file is null

when I put a file called "models.txt" in my project's "src/main/resources" and set the modelSubstitute configuration to "/models.txt", I get the following error:

Caused by: java.lang.NullPointerException: Cannot invoke method eachLine() on null object
        at com.benjaminsproule.swagger.gradleplugin.docgen.EnvironmentConfigurer.configureModelModifiers(EnvironmentConfigurer.groovy:87)
        at com.benjaminsproule.swagger.gradleplugin.docgen.EnvironmentConfigurer$configureModelModifiers.call(Unknown Source)
        at com.benjaminsproule.swagger.gradleplugin.docgen.LoaderFactory.configureGeneratorEnvironment(LoaderFactory.groovy:17)
        at com.benjaminsproule.swagger.gradleplugin.docgen.LoaderFactory.loader(LoaderFactory.groovy:8)
        at com.benjaminsproule.swagger.gradleplugin.docgen.LoaderFactory$loader.call(Unknown Source)
        at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.processSwaggerPluginExtension(GenerateSwaggerDocsTask.groovy:70)
        at com.benjaminsproule.swagger.gradleplugin.GenerateSwaggerDocsTask.generateSwaggerDocuments(GenerateSwaggerDocsTask.groovy:52)
        ... 83 more

Am I doing something wrong or is this a bug? There doesn't seem to be unit test coverage on this feature.

Used it for non-spring mvc or jaxrs , it generates spec but it has no data on resources

It looks even though I pass the package information, it does not pick up resources classes and add it to the swagger spec. What could be the reasons that it does not pick up the resources from the given packages.

Here is the swagger spec generated
{
"swagger" : "2.0",
"info" : {
"description" : "This is a sample.",
"version" : "v1",
"title" : "Swagger Gradle Plugin Sample",
"termsOfService" : "http://www.example.com/termsOfService",
"contact" : {
"name" : "Name",
"url" : "http://www.example.com",
"email" : "[email protected]"
},
"license" : {
"name" : "Apache 2.0",
"url" : "http://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"host" : "http://localhost:8080",
"basePath" : "/restTestApp/bookapi",
"schemes" : [ "http", "https" ]
}

Here is the build.gradle file
defaultTasks 'generateSwaggerDocumentation'

// Apply the java plugin to add support for Java
apply plugin: 'java'

repositories {
jcenter()
}

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.benjaminsproule:swagger-gradle-plugin:0.1.9'
}
}
apply plugin: 'com.benjaminsproule.swagger'

dependencies {

compile 'io.swagger:swagger-annotations:1.5.17'	
compile 'io.swagger:swagger-core:1.5.17'
compile 'io.swagger:swagger-jaxrs:1.5.17'
compile 'io.swagger:swagger-models:1.5.17'
compile 'com.google.code.gson:gson:2.8.2'
compile 'com.squareup.okhttp:okhttp:2.7.5'
compile 'com.squareup.okhttp:logging-interceptor:2.7.5'
compile 'joda-time:joda-time:2.9.9'


testCompile 'org.testng:testng:6.13.1'

}

sourceSets {
main {
java {
srcDirs = ['src/main/java', 'books/src/main/java']
}
}

test {
	java{
	    srcDirs = ['src/test']
	}
}

}

swagger {
apiSource {
println 'inside swagger apisource'
springmvc = false
locations = [ 'oracle.igcs.resource' ]
schemes = [ 'http', 'https' ]
host = 'http://localhost:8080'
basePath = '/restTestApp/bookapi'
info {
title = 'Swagger Gradle Plugin Sample'
version = 'v1'
description = 'This is a sample.'
termsOfService = 'http://www.example.com/termsOfService'
contact {
email = '[email protected]'
name = 'Name'
url = 'http://www.example.com'
}
license {
url = 'http://www.apache.org/licenses/LICENSE-2.0.html'
name = 'Apache 2.0'
}
}
/**
Support classpath or file absolute path here.
1) classpath e.g: "classpath:/markdown.hbs", "classpath:/templates/hello.html"
2) file e.g: "${project.rootDir}/src/main/resources/markdown.hbs", "${project.rootDir}/src/main/resources/template/hello.html"
**/

    //templatePath = "${project.rootDir}/src/test/resources/strapdown.html.hbs"
    //outputPath = "${project.rootDir}/generated/document.html"
    swaggerDirectory = "${project.rootDir}/generated/swagger-ui"
    println "${project.rootDir}"
    //swaggerApiReader = 'com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader'
    //modelConverters = [ 'io.swagger.validator.BeanValidator' ]
    // attachSwaggerArtifact = true - WILL BE ADDED IN THE FUTURE
}

}

test {

// enable TestNG support (default is JUnit)
useTestNG()
// listen to events in the test execution lifecycle
beforeTest { descriptor ->
logger.lifecycle("Running test: " + descriptor)
}

Task name "swagger" conflicts with other swagger related plugins

We are using swagger-codegen plugin to generate the REST client and we want to use swagger-gradle-plugin to generate the API Spec which will then be used by swagger-codegen. Since swagger-codegen also has a task name "swagger" there is a conflict and we cannot use the two plugins together. As per the best practices of Gradle plugin development, the task names should be very specific. Can you please update the task name or do you need a PR?

API basic authorization definition

I need to define basic authorization security for my API. As I understand from documentation, I would have to set my Gradle settings file like this:

swagger {
    apiSource {
    ...
        securityDefinition {
            name = 'basicAuth'
            type = 'basic'
       	}
   
}

but this results in error:

No signature of method: com.github.kongchen.swagger.docgen.mavenplugin.SecurityDefinition.setJsonPath() is applicable for argument types: (null) values: [null]

Which it is suppose to be an alternative definition using a file. How do I define a single basic authorization in Gradle settings file?

I am using version 1.5.16.

Thanks.

Error using Custom Model Converter

Hi guys,

I get the follwing error using custom model generator:
Could not find custom model converter com.vig.dummy.wgv.resource.CustomModelConverter
The file file is available on the classpath and implements io.swagger.converter.ModelConverter

I am using the version 1.0.2 with Spring and JaxRs:

Here is my setup:

	swagger {
	    apiSource {
	        springmvc = false
	        locations = [ 
	        	'com.vig.dummy.basis.resource.gf.GeschaeftsfallResource',
	        	'com.vig.dummy.framework.produkt.konfiguration.resources.ProduktKonfigurationResource'
	        ]
	        schemes = ['http']
        host = 'localhost:8080'
        basePath = '/ngwgv'
        info {
            title = 'Vigo Next-Gen API'
            version = '1.0.0'
        }
	    swaggerDirectory = "${project.buildDir}/swagger-ui"
	    modelConverters = [ 'com.vig.dummy.wgv.resource.CustomModelConverter' ]
	    }
	}
	
	build.dependsOn generateSwaggerDocumentation

Can anyone help or is dealing also with this issue ?

Thx for help

Migration from the swagger mavin plugin

Hi Benjamin,

I have been researching for ways to generate swagger documentation during build from our gradle projects but failed to locate any plugin for it. I ended up creating a pom.xml and built/generated the swagger.json using kongchen swagger mavin plugin. Then to my surprise, I came across your recent implementation of this plugin and gave it an immediate try. I used the following minimum settings:

buildscript {
    ...
    dependencies {
        ...
        classpath 'com.benjaminsproule:swagger-gradle-plugin:0.0.1-SNAPSHOT'
    }
}

apply plugin: 'swagger-gradle-plugin'

swagger {
    apiSource {
        locations = 'test.sample.api'
        info {
            title = 'test service'
            version = 'v0.0.1'
            description = 'test service description'
            contact {
                email = '[email protected]'
                name = 'test name'
            }
        }
        swaggerDirectory = '${project.build.directory}/swagger-ui'
        attachSwaggerArtifact = true
    }
}

The project builds but it does not generate the swagger.json file. Is there something wrong with the way I configured the plugin?

Thanks in advance,

--Phu

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.