My question is related to the one posted here.
I had to rephrase my question as I felt the earlier one was too verbose. Having a go at it again!
I have a REST API which returns a list of Assets, and it's coded like this:
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAllAssets() {
List<Asset> assets = new ArrayList<Asset>();
for(int i=1; i<11; i++) {
assets.add(new Asset(i));
}
return RestResponse.create(Status.OK, "10 assets Fetched successfully!", assets);
}
The response it generates is something like this:
{
"message":"10 assets Fetched successfully!",
"content": [{
"id":"1",
"type":"LPTP",
"owner":"Ram",
"serialNo":"WDKLL3234K3",
"purchasedOn":"01 Jan 2017"
},
{
"id":"2",
"type":"LPTP",
"owner":"Ram",
"serialNo":"WDKLL3234K3",
"purchasedOn":"01 Jan 2017"
},
...
]
}
I have over 60 services in my application which follow the same response template:
{
"message":"Message the service wants to send to the client",
"content": {
....
Entity returned by the service
....
}
}
The following is the RestResponse POJO that represents our Response Template:
public class RestResponse {
private String message;
private Object content;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getContent() {
return content;
}
public void setContent(Object content) {
this.content = content;
}
private RestResponse(String message, Object content) {
this.message = message;
this.content = content;
}
public static Response create(Response.Status status, String message, Object content) {
return Response.status(status).entity(new RestResponse(message, content)).build();
}
}
Now we're documenting all our APIs using Swagger, and have run into a problem.
Since we're returning the RestResponse
class for all our APIs, I wrote the following annotation for my operation:
@ApiOperation(value="Fetches all available assets", response=RestResponse.class, responseContainer="List")
What Swagger does, is in the Definition schema for the RestResponse class looks like this:
"definitions": {
"RestResponse": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"content": {
"type": "object"
}
}
}
}
Here, I do not get any information or schema about the properties of the object inside the content
property.
I understand it's because Swagger doesn't work with Generic Objects.
So if I change my @ApiOperation
annotation to the one below:
@ApiOperation(value="Fetches all available assets", response=Asset.class, responseContainer="List")
In the above case, Swagger describes the properties of the Asset
entity, but obviously, the message
property (of my response template), is missing.
My problem is I want to have both. The content
property of my response template can be any entity.
So, can I set response=Asset.class
and instruct Swagger to enclose Asset
to the RestResponse
content
property before it documents it? Or any other way in which I can achieve this?
Hope I'm precise this time!
Thanks, Sriram Sridharan.
Edit - After I tried out Marc Nuri's suggestion
I created a similar RestServiceResponse.class
with a generic object, and set the responseReference
attribute for my @ApiOperation
to RestServiceResponse<Asset>
. And below is the JSON I got.
{
"swagger": "2.0",
"info": {
"version": "1.0.0",
"title": ""
},
"host": "localhost:7070",
"basePath": "/assets/rest",
"tags": [
{
"name": "Assets"
}
],
"schemes": [
"http"
],
"paths": {
"/assets/{id}": {
"get": {
"tags": [
"Assets"
],
"summary": "Fetches information about a single asset",
"description": "",
"operationId": "fetchAssetDetail",
"produces": [
"application/json"
],
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/RestServiceResponse<Asset>"
}
}
}
}
}
}
}
As you can see, the Definitions
section is missing altogether. Am I missing something?
I have my project in GitHub, in case you need to see the whole code. Please help me.