Swagger 2.0 support in Grails 3+ (3.0.11) not work

2019-03-22 02:36发布

问题:

I am running Grails 3.0.11 and want to create Swagger-documentation for my REST endpoints. I added the SwaggyDoc-plugin to the dependencies in my build.gradle script by adding:

compile "org.grails.plugins:swaggydoc:0.26.0".

In IntelliJ I see the Swaggydoc-dependency added to my list of libraries.

After starting my Grails-application via the grails run-app command and opening my application by entering http://localhost:8080/api/ I get an 404 error telling the page does not exist.

Do I need to configure something more or to run something special to generate documentation? I already tried to open a ticket in the Git-project and contacting the author with no succes.

Update1: there seems to be a Grails 3-plugin (found at Versioneye?) which I added:

compile "org.grails.plugins:swaggydoc-grails3:0.26.0"

It does work half, by default some sort of Pet-demo is visible and it is failing on constraints in a domain and enums. Doesn't seem to work very well actually.

Update2: As pointed out by Dilip Krishnan I tried to use SpringFox, first I added the dependencies to my Gradle build file:

compile("io.springfox:springfox-swagger2:2.3.1")
compile("io.springfox:springfox-swagger-ui:2.3.1")

Then I added a new class called ApiDocumentationConfiguration with the following code:

 @Configuration
 @EnableSwagger2
 public class ApiDocumentationConfiguration {
 @Bean
 public Docket documentation() { 
    return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.any())
            .paths(PathSelectors.any())
            .build();
 }

 @Bean
 public UiConfiguration uiConfig() {
    return UiConfiguration.DEFAULT;
 }

 private ApiInfo metadata() {
    return new ApiInfoBuilder()
           .title("My awesome API")
            .description("Some description")
            .version("1.0")
            .contact("my-email@domain.org")
            .build();
 }
}

My Grails resources file contains the following code:

beans = {
    apiDocumentationConfiguration(ApiDocumentationConfiguration)
}

Last step was starting the application and trying to load the end point which shows the Swagger front end:

http://localhost:8080/swagger-ui.html

It behind the scenes tries to load an other end point (containing the JSON I guess?) which loads

http://localhost:8080/v2/api-docs

This does show JSON data and I get end points for things like a basic error controller, health mvc, metrics mvc et cetera. But not my own annotated user controller which is annotated like follows:

@Api(value = "users", description = "Endpoint for user management")
class UserController { 

    // GET all users
    @ApiOperation(value = "doStuff", nickname = "doStuff", response = User.class)
    def index() {
        respond User.list()
    }
}

Seems I am almost there, but still missing something, is my annotation wrong or doesn't it scan my controllers?

Update3: in contact with one of the authors of SpringFox (Dilip Krishnan) to add support for Grails 3+ to SpringFox, see ticket. The reason it doesn't currently work is because SpringFox looks at MVC annotation, an adapter needs to be written to retrieve the endpoints from the controllers in Grails.

回答1:

I have successfully used swaggydocs in both 2.4.x projects and 3.1.4. In order to make it work in 3.x (tested on 3.1.4) you have to add

    compile "org.grails.plugins:swaggydoc-grails3:0.26.0"

to gradle dependencies section. That makes swaggy available in your project.

Then add annotations to your controllers

@Api("test methods")
class TestController {
@ApiOperation(value = "some method description")
@ApiResponses([
        @ApiResponse(code = 405, message = "Bad method. Only POST is allowed"),
        @ApiResponse(code = 401, message = "Unauthorized"),
        @ApiResponse(code = 400, message = "Invalid request json")
])
def testGetMethod() {
    render([status: "OK"] as JSON)
}

Then mark your methods allowedMethods as follows

class TestController {
static allowedMethods = [testGetMethod: "GET", testPostMethod: "POST"]

NOTE this is really important - otherwise swaggy will mark every your method as GET. Swaggy doesn't respect neither httpMethod in ApiOperation annotation nor http method in url mappings.

Finally add your controller to urlmappings as swaggy checks url mappings to look for URLS. Note camelCase!

//NOTE small camelCase
//swaggy won't see urls correctly if you start controller name with capital letter
"/api/test/"(controller: "test", action: "testGetMethod")
"/api/test/"(controller: "test", action: "testPostMethod")

You can also add some api info in application.yml

swaggydoc:
    contact: rafal@pydyniak.pl
    description: sample swaggy app

You can find sample app (with dummy methods but point was to make swaggy work) at my github https://github.com/RafalPydyniak/Swaggy-example. Also there are some more docs on how to use this api on http://rahulsom.github.io/swaggydoc/. I just wanted to show you how to install it (as it's quite tricky to make everything work)

Hope it helps!



回答2:

I followed the same 2 steps: 1) add swagger2 dependencies 2) provide configuation The problem is that sprinfox does not scan grails url mappings (see https://github.com/springfox/springfox/issues/1169#issuecomment-252259284) To fix that I added standard spring annotations:

@Controller()
@RequestMapping(value="/path")

on the controller and

@RequestMapping(value="/resource")

on the method. After that sprinfox started to pick up my documentation.