I have a REST service I want to document for my client developing team.
So I added some Links
from Spring-Hateoas
to my resources API, and plugged into it swagger-springmvc
@Api...
annotations to document everything and make a good API reference for my Angular team to be able to understand my REST service.
The problem is that swagger
is unable to discover what links are possible, and just give me a big array of Links
without saying their possible values.
Here is a (simple) example. Swagger detects :
Model Schema
CollectionListResource {
collections (array[CollectionResource]): All available collections,
links (array[Link]): Relations for next actions
}
CollectionResource {
collectionId (string): Collection Unique Id,
name (string): Human readable collection name,
links (array[Link]): Relations for next actions
}
Link {
rel (string, optional),
templated (boolean, optional),
href (string, optional)
}
And I get in fact in HAL :
{"collections":
[{"collectionId":"5370a206b399c65f05a7c59e",
"name":"default",
"_links":{ [
"self":{
"href":"http://localhost:9080/collections/5370a206b399c65f05a7c59e"
},
"delete":{
"href":"http://localhost:9080/collections/5370a206b399c65f05a7c59e"
}
]}
}, ...]}
I've tried to extend Link
and ResourceSupport
to have annoted version of them but this lead me to nowhere.
Is there a way/tool I could use to generate a good API doc telling that a self
relation is to get the content, and a delete
relation is to delete the collection ?
I liked swagger for its good UI, but I don't mind changing my documentation tool if its help having the doc really complete.
I could eventually think of changing spring-hateoas for another link generator, but I'm not sure there is a better tool available right now.
Swagger-UI as such is not hypermedia aware; or atleast its limited in that it can ONLY navigate from top level apis to api listings. That has not changed much in v2.0 of the spec either, with the notable addition of linking to external documents for out of band documentation.
What you need is a hybrid of the HAL browser and the swagger-ui. As you rightly pointed out, there is a semantic gap between the word "delete" and what it means in the context of a collection resource. HAL uses a combination of curies and optionally a profile document ALPS to bridge this gap. Curies are nothing but namespaced versions of linked relations so that they dont collide with other domains. Restful Web APIs is a great resource to learn more about these ideas and how to design media types. The spring data rest project also has a great example of how to achieve that.
Below is an example that demonstrates and combines these approaches.
{"collections":
[{"collectionId":"5370a206b399c65f05a7c59e",
"name":"default",
"curies": [
{
"name": "sw",
"href": "http://swagger.io/rels/{rel}",
"templated": true
},
{
"name": "iana",
"href": "http://tools.ietf.org/html/rfc5023",
"templated": false
},
{
"name": "col",
"href": "http://localhost:9080/collections/{rel}",
"templated": false
}
],
"_links":{ [
"self":{
"href":"http://localhost:9080/collections/5370a206b399c65f05a7c59e"
},
"sw:operation":{
"href":"http://localhost:9080/api-docs/collections#delete"
},
"sw:operation":{
"href":"http://localhost:9080/api-docs/collections#search"
},
"sw:operation":{
"href":"http://localhost:9080/api-docs/collections#update"
},
"iana:edit":{
"href":"http://localhost:9080/collections/5370a206b399c65f05a7c59e"
},
"col:delete": {
"href":"http://localhost:9080/collections/5370a206b399c65f05a7c59e"
}
]}
}, ...]}
So from most generic to most specific, the solution (in that order) is
I know this doesn't answer your question precisely, and the tools in this space are still evolving. Hope this helps.
DISCLAIMER: I'm one of the core maintainers of springfox which is a spring integration solution that makes it easy to provide swagger service descriptions. So any feedback on how you'd like it to solve this problem is very welcome!