From 6e98fe9cc475ed433256dbddcf0ea10fcfe6f1f1 Mon Sep 17 00:00:00 2001 From: Chris Vogel Date: Thu, 31 Mar 2016 23:05:05 -0500 Subject: [PATCH 1/2] Look for parameter annotations on parent classes/interfaces. This is a fix for issue #1506. Reader got parameter annotations from a child method, ignoring any on a parent class or interface. This fix will look for annotation on the parent class or interface, if it exists. Credit mohitmutha with the fix. I just implemented it and created the pull request. --- .../java/io/swagger/util/ReflectionUtils.java | 29 +++++++++++++++++++ .../main/java/io/swagger/jaxrs/Reader.java | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/modules/swagger-core/src/main/java/io/swagger/util/ReflectionUtils.java b/modules/swagger-core/src/main/java/io/swagger/util/ReflectionUtils.java index e23ed79072..9f4d64c839 100644 --- a/modules/swagger-core/src/main/java/io/swagger/util/ReflectionUtils.java +++ b/modules/swagger-core/src/main/java/io/swagger/util/ReflectionUtils.java @@ -1,6 +1,8 @@ package io.swagger.util; import com.fasterxml.jackson.databind.type.TypeFactory; + +import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -209,7 +211,34 @@ public static A getAnnotation(Class cls, Class anno } return annotation; } + + public static Annotation[][] getParameterAnnotations(Method method) { + Annotation[][] methodAnnotations = method.getParameterAnnotations(); + Method overriddenmethod = getOverriddenMethod(method); + + if (overriddenmethod != null) { + Annotation[][] overriddenAnnotations = overriddenmethod + .getParameterAnnotations(); + for (int i = 0; i < methodAnnotations.length; i++) { + List types = new ArrayList(); + for (int j = 0; j < methodAnnotations[i].length; j++) { + types.add(methodAnnotations[i][j].annotationType()); + } + for (int j = 0; j < overriddenAnnotations[i].length; j++) { + if (!types.contains(overriddenAnnotations[i][j] + .annotationType())) { + methodAnnotations[i] = ArrayUtils.add( + methodAnnotations[i], + overriddenAnnotations[i][j]); + } + } + + } + } + return methodAnnotations; + } + /** * Checks if the type is void. * diff --git a/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/Reader.java b/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/Reader.java index 38839cd4a8..5b8abdaf15 100644 --- a/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/Reader.java +++ b/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/Reader.java @@ -858,7 +858,7 @@ private Operation parseMethod(Class cls, Method method, List globa } Type[] genericParameterTypes = method.getGenericParameterTypes(); - Annotation[][] paramAnnotations = method.getParameterAnnotations(); + Annotation[][] paramAnnotations = ReflectionUtils.getParameterAnnotations(method); for (int i = 0; i < genericParameterTypes.length; i++) { final Type type = TypeFactory.defaultInstance().constructType(genericParameterTypes[i], cls); List parameters = getParameters(type, Arrays.asList(paramAnnotations[i])); From 00c7f4a8d03cabeee818594ae496009aa29b05f2 Mon Sep 17 00:00:00 2001 From: Jan Hoeve Date: Tue, 12 Apr 2016 13:40:53 +0200 Subject: [PATCH 2/2] Fixed issue 1746 - Api and ApiImplicitParam annotations not read when they are in a parent of the resource class Also credit to mohitmutha for finding a solution to a similar problem and captdestrukto to provide a pull request for that one --- .../main/java/io/swagger/jaxrs/Reader.java | 4 ++-- .../src/test/java/io/swagger/ReaderTest.java | 22 +++++++++++++++++++ ...esourceWithAnnotationsOnlyInInterface.java | 20 +++++++++++++++++ ...rceWithAnnotationsOnlyInInterfaceImpl.java | 9 ++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 modules/swagger-jaxrs/src/test/java/io/swagger/resources/ResourceWithAnnotationsOnlyInInterface.java create mode 100644 modules/swagger-jaxrs/src/test/java/io/swagger/resources/ResourceWithAnnotationsOnlyInInterfaceImpl.java diff --git a/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/Reader.java b/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/Reader.java index 5b8abdaf15..bc6c032ebd 100644 --- a/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/Reader.java +++ b/modules/swagger-jaxrs/src/main/java/io/swagger/jaxrs/Reader.java @@ -187,7 +187,7 @@ private Swagger read(Class cls, String parentPath, String parentMethod, boole String[] produces = new String[0]; final Set globalSchemes = EnumSet.noneOf(Scheme.class); - Api api = (Api) cls.getAnnotation(Api.class); + Api api = ReflectionUtils.getAnnotation(cls, Api.class); boolean hasPathAnnotation = (ReflectionUtils.getAnnotation(cls, javax.ws.rs.Path.class) != null); boolean hasApiAnnotation = (api != null); @@ -410,7 +410,7 @@ private Swagger read(Class cls, String parentPath, String parentMethod, boole } private void readImplicitParameters(Method method, Operation operation) { - ApiImplicitParams implicitParams = method.getAnnotation(ApiImplicitParams.class); + ApiImplicitParams implicitParams = ReflectionUtils.getAnnotation(method, ApiImplicitParams.class); if (implicitParams != null && implicitParams.value().length > 0) { for (ApiImplicitParam param : implicitParams.value()) { Parameter p = readImplicitParam(param); diff --git a/modules/swagger-jaxrs/src/test/java/io/swagger/ReaderTest.java b/modules/swagger-jaxrs/src/test/java/io/swagger/ReaderTest.java index 53835c140b..07609e96b5 100644 --- a/modules/swagger-jaxrs/src/test/java/io/swagger/ReaderTest.java +++ b/modules/swagger-jaxrs/src/test/java/io/swagger/ReaderTest.java @@ -3,6 +3,7 @@ import io.swagger.jaxrs.Reader; import io.swagger.models.Operation; import io.swagger.models.Swagger; +import io.swagger.models.Tag; import io.swagger.models.parameters.*; import io.swagger.resources.*; import org.testng.annotations.Test; @@ -316,6 +317,27 @@ public void scanDeclaredExceptionsAndCombineWithMethodResponsesClassLevel() { } + @Test(description = "scan resource (impl) which has the Api annotations only declared in its interface") + public void scanApiAnnotationWhichAreOnlyPresentInInterfaceAndNotInImplementation() { + Swagger swagger = getSwagger(ResourceWithAnnotationsOnlyInInterfaceImpl.class); + assertNotNull(swagger); + + final List tags = swagger.getTags(); + assertEquals(tags.size(), 1); + assertEquals(tags.get(0).getName(), "someTag"); + } + + @Test(description = "scan resource (impl) which has the ApiParam annotations only declared in its interface") + public void scanApiImplicitParamAnnotationWhichAreOnlyPresentInInterfaceAndNotInImplementation() { + Swagger swagger = getSwagger(ResourceWithAnnotationsOnlyInInterfaceImpl.class); + assertNotNull(swagger); + + List parameters = getGet(swagger, "/pet/randomPet").getParameters(); + assertNotNull(parameters); + assertEquals(parameters.size(), 1); + assertEquals(parameters.get(0).getName(), "petImplicitIdParam"); + } + private Swagger getSwagger(Class cls) { return new Reader(new Swagger()).read(cls); } diff --git a/modules/swagger-jaxrs/src/test/java/io/swagger/resources/ResourceWithAnnotationsOnlyInInterface.java b/modules/swagger-jaxrs/src/test/java/io/swagger/resources/ResourceWithAnnotationsOnlyInInterface.java new file mode 100644 index 0000000000..160538b0c2 --- /dev/null +++ b/modules/swagger-jaxrs/src/test/java/io/swagger/resources/ResourceWithAnnotationsOnlyInInterface.java @@ -0,0 +1,20 @@ +package io.swagger.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("/pet") +@Api(tags = "someTag") +public interface ResourceWithAnnotationsOnlyInInterface { + + @GET + @Path("/randomPet") + @ApiOperation(value = "getRandomPet") + @ApiImplicitParams({ @ApiImplicitParam(name = "petImplicitIdParam", paramType = "query", dataType = "string") }) + String getRandomPet(); +} diff --git a/modules/swagger-jaxrs/src/test/java/io/swagger/resources/ResourceWithAnnotationsOnlyInInterfaceImpl.java b/modules/swagger-jaxrs/src/test/java/io/swagger/resources/ResourceWithAnnotationsOnlyInInterfaceImpl.java new file mode 100644 index 0000000000..4900e3cacc --- /dev/null +++ b/modules/swagger-jaxrs/src/test/java/io/swagger/resources/ResourceWithAnnotationsOnlyInInterfaceImpl.java @@ -0,0 +1,9 @@ +package io.swagger.resources; + +public class ResourceWithAnnotationsOnlyInInterfaceImpl implements ResourceWithAnnotationsOnlyInInterface { + + @Override + public String getRandomPet() { + return "No pet today.."; + } +}