Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to DRY ApiResponses Annotations #690

Closed
todd-richmond opened this issue Sep 24, 2014 · 12 comments
Closed

How to DRY ApiResponses Annotations #690

todd-richmond opened this issue Sep 24, 2014 · 12 comments

Comments

@todd-richmond
Copy link

I have integrated Swagger into our our new Java server app and am trying to come up with a way to eliminate redundant ApiResponse values contained within ApiResponses annotations. I have tried numerous techniques w/o luck and Java does not allow subclassing an annotation, but there must be some way. As an example, returning a 404 is quite common so I'd like a simple annotation such as @ApiResponseNotFound(optionalMessage="x not found").

For a bonus, I'd love @ApiResponseList("400, 404") or equivalent such as @ApiResponses({@ApiResponseNotFound, @ApiResponseArgument})

@ApiResponses(@ApiResponse(code = 404, message = "not found"))

or

@ApiResponses({ @ApiResponses(@ApiResponse(code = 400, message = "invalid argument"), @ApiResponse(code = 404, message = "not found") })

@webron
Copy link
Contributor

webron commented Sep 25, 2014

Unfortunately, that's not really an option, at least not without going into extreme annotation processing (which even then may not offer what you want).

Annotation values are determined at compilation and not runtime, so at most you can have static strings and use those as values for the annotations.

In terms of annotation processing, accepting user-generated annotations won't work as well, as like you said, there's no annotation inheritance.

We could at some point change the @ApiResponse to a java class to allow static initialization, but even if we do end up doing that, it'll only be in a future major version since it'll break backwards compatibility.

@mwhig
Copy link

mwhig commented Oct 2, 2014

Not sure if I misunderstood the question, but can this be achieved by allowing @ApiResponse be a meta-annotation?

//other metas
@Target(ElementType.METHOD, ElementType.ANNOTATION_TYPE)
@ApiResponse

Then we could have user defined annotations like:

@ApiResponse(code="404", message="Resource not found")
public @interface MyResourceNotFound

The annotation processor can then check if the @MyResourceNotFound has @ApiResponse in its meta-annotation "hierarchy".

@webron
Copy link
Contributor

webron commented Oct 3, 2014

@mwhig - thanks for the suggestion, looks interesting, especially as an idea to allow user-created response annotations.

That partially solve the second request from @todd-richmond, but not the first. If I understand correctly, he wants the "message" part to be dynamic - so not just "Resource not found" but rather "{X} not found" where X is replaced by the resource name.

The reason that it only partially solves the second request is that @ApiResponse is currently not used processed from being directly on the method but rather only as an input to @ApiRsponses. The @Target(ElementType.METHOD) is actually a bug and the proper declaration should have been @Target({}). The reason for that is simple - you can't have more than one instance of an annotation on a method, and if you want to include several responses you won't be able to do that (and we don't support it for a single response declaration). Your suggestion may help there, but it would also force the user to create their own annotations which is not necessarily what we want.

@todd-richmond
Copy link
Author

Nope - i don't need var substitution in the default response string. It would definitely be useful to optionally override the entire string so if you want more descriptive "foo not found" instead of plain "not found" you would have to supply it yourself. Default strings can come straight from the RFC spec

@fehguy fehguy modified the milestone: v2.0.0 Dec 23, 2014
@fehguy fehguy added the P3 label Dec 23, 2014
@fehguy
Copy link
Contributor

fehguy commented Mar 11, 2015

With 1.5.x-M1, you can now plug your own annotation processors. While documentation needs to be written, you can follow the swagger-jersey2-jaxrs module as an example, allowing you to create a simple module which is loaded via SPI.

@vhochstein
Copy link

Unfortuenetly, I did not understand your described solution.
Has anyone a link where I can see how I may define my general Response Codes such as 500, 502 which apply for all operations and use them in each operation annotation to avoid the same block of documentation for every operation ?
Thanks a lot in advance.

@todd-richmond
Copy link
Author

an example would definitely help. Our REST API has a global exception handler that we use to catch most issues and translate to HTTP codes in a general manner. As a result, the documented responses would all share the same docs. Ideally I'd like to create a base set of responses for each HTTP command (PUT, PATCH, GET, DELETE...) and then be able to add a few per-route additions

@codenozzle
Copy link

I came across this thread as I too need a way to define our Response Codes once, and use them across the API. We have several response codes (500, 400, 200, etc.) that we don't want to copy/paste all throughout the API. Yes, I could statically define the strings for the responses, but the annotations would still need to be duplicated.

Has anyone figured this out? I don't think I followed what @fehguy was suggesting back in March.

Thank you very much in advance! Love using Swagger!

@jlous
Copy link

jlous commented Feb 9, 2017

If I understand correctly, the swagger json format already supports references that would do the trick. All we need is annotation support for it. Or am I missing something?

@ishener
Copy link

ishener commented Feb 23, 2017

+1

@rob-k
Copy link

rob-k commented Feb 28, 2017

+1
Would be extremely helpful if you added the full spec of the Swagger object (or at least definitions, parameters and responses) to @SwaggerDefinition. Alternatively, as @jlous pointed out, it would be sufficient to give us an option to reference global definitions in @ApiOperation, @ApiParam etc. (e.g. with a field ref), as one can define the global definitions by subclassing ReaderListener as described here: http://swagger.io/customizing-your-auto-generated-swagger-definitions-in-1-5-x/

@rhamedy
Copy link

rhamedy commented Feb 6, 2018

So it is possible to create an a Custom annotation (i.e. GroupedApiResponses) and annotate it with @ApiResponses and then use the custom annotations GroupedAPiResponses on endpoints and works just fine. I have posted an answer in SO about the same.

It saves a lots of repetitive code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants