nerdErg / swagger4jaxrs

This is a Grails plugin that adds Swagger support to document REST APIs of any Grails projects that use the Grails JAX-RS (JSR 311) plugin.
Apache License 2.0
10 stars 10 forks source link

Models are missing in the API, Response Class and Model are empty in Swagger UI #11

Open christianjunk opened 10 years ago

christianjunk commented 10 years ago

It seems that the models section is missing in the API. That leads the Swagger UI to display an 'empty' Response Class definition:

screen shot 2013-11-08 at 10 55 32

Compared to the online demo (http://petstore.swagger.wordnik.com/api/api-docs/pet)

screen shot 2013-11-08 at 10 59 54

Could you verify this behaviour? Is this a Grails specific issue?

Best regards, Christian

aruizca commented 10 years ago

Hi ,@christianjunk I think is up to you to document that using the Swagger Annotations. It won't show that out of the box.

Cheers,

pikazlou commented 10 years ago

I've struggled today with this issue. No annotations should be required to generate model. This is really a bug in swagger4jaxrs (at least with swagger-jaxrs_2.10 - swagger-core_2.10 combination) ! Please fix it!

1) At first I tried to use my own POJO, created in grails application. I've tried both groovy and java POJO, placed it everywhere under grails-app, src/groovy, src/java. But everytime the result was as per issue reporter: something like "gpts.model.Pet" in the models. Swagger annotations had no effect.

2) Then I tried using third party POJO class from dependency jar, and it rendered properly in models!

3) So I started to debug model resolution. I've found that all model classes are loaded by com.wordnik.swagger.core.SwaggerContext, which uses a list of classloaders. In my case the list had only one classloader: org.codehaus.groovy.grails.cli.support.GrailsRootLoader. This classloader cannot load any classes, created within grails app (ClassNotFoundException). But it can load any classes from dependency jars! This makes sense, because the main classloader for grails app is org.codehaus.groovy.grails.compiler.GrailsClassLoader. So why SwaggerContext wasn't using it? If you inspect the code, you can see, that SwaggerContext adds its class classloader to the list during static initialization. And it seems, that because SwaggerContext is loaded from dependency jar, its classloader is GrailsRootLoader and not GrailsClassLoader.

So I ended up with a temporary hack: added

def init = { servletContext ->
        SwaggerContext.registerClassLoader(this.getClass().getClassLoader())

to BootStrap init method.

This way I get both GrailsRootLoader and GrailsClassLoader in SwaggerContext's list and my POJO from grails app can be resolved.

Unfortunately, with this hack I have to use Java POJO, because when using Groovy POJO, properties are recursively iterated, resulting in a bunch of reflection/groovy classes dumped into model.

So my POJO:

public class Pet {
    private int number;
    private String name;
... (getters, setters)
}

My resource:

    @GET
    @Path("/getPet")
    @ApiOperation(value = "Request pet", notes = "Request pet by id", response=Pet.class)
    @Produces(MediaType.APPLICATION_JSON)
    Response getPet(
            @ApiParam(value = "id of requested pet") @QueryParam('id') Integer id) {
...

And voila! image

Of course adding annotations like @ApiModel and @ApiModelProperty with some info creates additional description on UI, but this is optional.

aruizca commented 10 years ago

Hi @pikazlou

Thank you very much for taking the time to find out what the problem is. At first glance it looks to me that the it is a Swagger-jaxrs and swagger-core issue. What do you think we should do to address this? I can add the bootstrap hack in the plugin, but that does not solve the problem completely. Should we open and issue in the project?

Maybe using metaprogramming we could add support for Groovy POJOs. What do you think?

Cheers, Angel.

aaron-brown commented 10 years ago

I recommend loading the ClassLoader in the bean declaration in the Swagger4jaxrsGrailsPlugin class, if you do so.

Doing so in a boot-strap is cumbersome and will make it harder to maintain, and technically it may load up later than you expect in the Spring bootstrap.

As far as why it is not loading POGOs, I am not certain. Would have to research.

rorybeling commented 9 years ago

Im having the precise same issue as described above, any progress been made in making @ApiModel annotation work?

aruizca commented 9 years ago

Hi @rorybeling! I have not work on it because I am not sure how to solve it. The main problem is that the Swagger API does not support POGOs only POJOs. Any ideas about how to add support for POGOs?

Pull requests are welcomed! :-)

CrossfireCurt commented 9 years ago

Eeek, yeah, this is a pretty big problem for me as well. I was super excited to see that there was a swagger plugin for grails but this issues makes it completely useless for me. I'd like to use swagger-codegen with it, but can't because it cannot generate the models :(