kongchen / swagger-maven-plugin

JAX-RS & SpringMVC supported maven build plugin, helps you generate Swagger JSON and API document in build phase.
http://kongchen.github.io/swagger-maven-plugin/
Apache License 2.0
761 stars 451 forks source link

Generate Swagger json without annotations #206

Open yissachar opened 9 years ago

yissachar commented 9 years ago

I am using this with a Jersey project and it seems odd that I am forced to double annotate all my methods; once for Jersey and once for Swagger. I am not using any of the additional documentation that Swagger provides - I am simply using Api and ApiOperation annotations to indicate the methods that are part of my API. As far as I can tell it should be possible to do this by just looking at the Jersey Path annotations.

Is this use case not supported? It's not the end of the world if I have to double annotate everything but it just seems silly.

tedleman commented 9 years ago

+1

If you are trying to onboard legacy service implementations to swagger, going back and annotating everything can be a pain...and really isn't necessary for basic documentation needs.

I've done some work locally to make this possible for spring mvc projects, using a POM configuration boolean "requireSwaggerAnnotations = false", and created an extension of the spring reader which works without swagger annotations. It's most likely possible to do the same with the jaxrs reader, but this is a pretty big design decision that is up to @who and @kongchen .

ShijunK commented 8 years ago

Ok, it seems the Reader from latest swagger-jaxrs(1.5.4) can use JAX-RS annotations to generate swagger spec, as long as you put one class level annotation '@Api' there.

I think a better approach is to have 'swagger-maven-plugin' to support Reader from swagger-jaxrs, instead of sub class com.github.kongchen.swagger.docgen.reader.ClassSwaggerReader. No point to include swagger-maven-plugin in dependencies, just for a customized reader.

sample code for using swagger-jaxrs reader:

package com.github.kongchen.swagger.docgen.reader;

import com.github.kongchen.swagger.docgen.GenerateException;
import com.github.kongchen.swagger.docgen.LogAdapter;
import com.wordnik.jaxrs.SubResource;
import edu.emory.mathcs.backport.java.util.Collections;
import io.swagger.jaxrs.Reader;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import org.testng.annotations.Test;

import java.util.Map;
import java.util.Set;

import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;

public class JaxrsReaderTest {

    @Test
    public void testRead() throws Exception {
        LogAdapter LOG = null;
        JaxrsReader reader = new JaxrsReader(new Swagger(), LOG);

        Swagger swagger = reader.read(SubResource.class);
        Map<String, Path> paths = swagger.getPaths();

        assertThat(paths, is(nullValue()));
    }

    @Test
    public void testMyRead() throws Exception {
        MyReader reader = new MyReader();

        Swagger swagger = reader.read(Collections.singleton(SubResource.class));
        Map<String, Path> paths = swagger.getPaths();

        assertThat(paths.keySet().toArray(new String[2]), is(new String[]{"/resources", "/resources/sub"}));
    }

    public static class MyReader implements ClassSwaggerReader {

        @Override
        public Swagger read(Set<Class<?>> classes) throws GenerateException {
            Reader reader = new Reader(null);
            return reader.read(classes);
        }
    }
}

package com.wordnik.jaxrs;

import io.swagger.annotations.Api;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

@Path("/resources")
@Api(value = "/resources")
public class SubResource {

    @GET
    public Response resources() {
        return Response.ok().build();
    }

    @Path("/sub")
    @GET
    public Response sub() {
        return Response.ok().build();
    }
}
RawToast commented 8 years ago

+1 As ShijunK states, this is already possible. It's pretty easy to achieve in using a jax-rs-doclet in Maven/Dropwizard. Since Dropwizard is based on Jersey, I would imagine it would be possible in your case.

ketanprajapati88 commented 4 years ago

+1

If you are trying to onboard legacy service implementations to swagger, going back and annotating everything can be a pain...and really isn't necessary for basic documentation needs.

I've done some work locally to make this possible for spring mvc projects, using a POM configuration boolean "requireSwaggerAnnotations = false", and created an extension of the spring reader which works without swagger annotations. It's most likely possible to do the same with the jaxrs reader, but this is a pretty big design decision that is up to @who and @kongchen .

@tedleman , can you share your implementation with customized spring reader worked for you? I also wanted to generated swagger YAML but do not want to go back to add annotations.

ketanprajapati88 commented 4 years ago

@who , @kongchen , this looks obvious requirement to support, are there any existing implementation available or any future plan to support this? My legacy code has @Path annotations from Javax.wa.rs.** and dont wanted to put another @Api annotations.

ketanprajapati88 commented 4 years ago

Ok, it seems the Reader from latest swagger-jaxrs(1.5.4) can use JAX-RS annotations to generate swagger spec, as long as you put one class level annotation '@Api' there.

I think a better approach is to have 'swagger-maven-plugin' to support Reader from swagger-jaxrs, instead of sub class com.github.kongchen.swagger.docgen.reader.ClassSwaggerReader. No point to include swagger-maven-plugin in dependencies, just for a customized reader.

sample code for using swagger-jaxrs reader:

package com.github.kongchen.swagger.docgen.reader;

import com.github.kongchen.swagger.docgen.GenerateException;
import com.github.kongchen.swagger.docgen.LogAdapter;
import com.wordnik.jaxrs.SubResource;
import edu.emory.mathcs.backport.java.util.Collections;
import io.swagger.jaxrs.Reader;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import org.testng.annotations.Test;

import java.util.Map;
import java.util.Set;

import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.assertThat;

public class JaxrsReaderTest {

    @Test
    public void testRead() throws Exception {
        LogAdapter LOG = null;
        JaxrsReader reader = new JaxrsReader(new Swagger(), LOG);

        Swagger swagger = reader.read(SubResource.class);
        Map<String, Path> paths = swagger.getPaths();

        assertThat(paths, is(nullValue()));
    }

    @Test
    public void testMyRead() throws Exception {
        MyReader reader = new MyReader();

        Swagger swagger = reader.read(Collections.singleton(SubResource.class));
        Map<String, Path> paths = swagger.getPaths();

        assertThat(paths.keySet().toArray(new String[2]), is(new String[]{"/resources", "/resources/sub"}));
    }

    public static class MyReader implements ClassSwaggerReader {

        @Override
        public Swagger read(Set<Class<?>> classes) throws GenerateException {
            Reader reader = new Reader(null);
            return reader.read(classes);
        }
    }
}

package com.wordnik.jaxrs;

import io.swagger.annotations.Api;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;

@Path("/resources")
@Api(value = "/resources")
public class SubResource {

    @GET
    public Response resources() {
        return Response.ok().build();
    }

    @Path("/sub")
    @GET
    public Response sub() {
        return Response.ok().build();
    }
}

@ShijunK , can you share your complete working example including pom.xml if any customized approach worked for you? I am not sure how to customize Readers to use swagger-jaxrs library and don't have much resources to figure out.