GN-48 Swagger-Annotations to REST-Services added
diff --git a/pom.xml b/pom.xml index 7893d22..19c59f8 100644 --- a/pom.xml +++ b/pom.xml
@@ -29,6 +29,11 @@ <commons-io.version>2.5</commons-io.version> <gson.version>2.8.0</gson.version> <httpclient.version>4.5.2</httpclient.version> + <swagger-core-version>1.5.15</swagger-core-version> + <swagger-maven-plugin-version>3.1.6</swagger-maven-plugin-version> + <swagger-core-version>1.5.17</swagger-core-version> + <swagger-annotations-version>1.5.13</swagger-annotations-version> + <swagger-jersey2-jaxrs>1.5.10</swagger-jersey2-jaxrs> </properties> <dependencyManagement> @@ -85,6 +90,18 @@ <artifactId>jacoco-maven-plugin</artifactId> <version>${jacoco-maven-plugin.version}</version> </dependency> + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + <version>${swagger-jersey2-jaxrs}</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>com.google.code.findbugs</groupId> + <artifactId>annotations</artifactId> + </exclusion> + </exclusions> + </dependency> </dependencies> <build> @@ -206,6 +223,56 @@ </executions> </plugin> + <plugin> + <groupId>com.github.kongchen</groupId> + <artifactId>swagger-maven-plugin</artifactId> + <version>${swagger-maven-plugin-version}</version> + <configuration> + <skipSwaggerGeneration>false</skipSwaggerGeneration> + <apiSources> + <apiSource> + <springmvc>false</springmvc> + <locations>org.eclipse.openk</locations> + <schemes>http</schemes> + <host>localhost:9010</host> + <basePath>/mics/central</basePath> + <info> + <title>micsCentralService@openK - Backend REST-Service documentation</title> + <version>v1</version> + <description>This documentation contains the description of all used REST services.</description> + <termsOfService> + . + </termsOfService> + <contact> + <email>nn@pta.de</email> + <name></name> + </contact> + <license> + <url>http://www.apache.org/licenses/LICENSE-2.0.html</url> + <name>Apache 2.0</name> + </license> + </info> + <outputFormats>yaml</outputFormats> + <templatePath>${basedir}/templates/strapdown.html.hbs</templatePath> + <outputPath>src/main/swagger/document.html</outputPath> + <swaggerDirectory>src/main/swagger/swagger-ui</swaggerDirectory> + <securityDefinitions> + <securityDefinition> + <json>/securityDefinitions.json</json> + </securityDefinition> + </securityDefinitions> + </apiSource> + </apiSources> + </configuration> + <executions> + <execution> + <phase>compile</phase> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </build>
diff --git a/src/main/java/org/eclipse/openk/resources/MicsCentralResource.java b/src/main/java/org/eclipse/openk/resources/MicsCentralResource.java index 4241164..b1134b6 100644 --- a/src/main/java/org/eclipse/openk/resources/MicsCentralResource.java +++ b/src/main/java/org/eclipse/openk/resources/MicsCentralResource.java
@@ -13,7 +13,13 @@ package org.eclipse.openk.resources; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; import org.apache.log4j.Logger; +import org.eclipse.openk.api.VersionInfo; import org.eclipse.openk.core.common.JsonGeneratorBase; import org.eclipse.openk.core.controller.DispatchController; import org.hibernate.validator.constraints.NotEmpty; @@ -26,6 +32,14 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +@Api(value = "/mics/gridmeasures") +@ApiResponses( value ={ + @ApiResponse(code = 200, message = "OK",response = VersionInfo.class,reference = "#/definitions/VersionInfo"), + @ApiResponse(code = 400, message = "Bad Request"), + @ApiResponse(code = 401, message = "Unauthorized"), + @ApiResponse(code = 404, message = "Not found"), + @ApiResponse(code = 423, message = "Locked"), + @ApiResponse(code = 500, message = "Internal Server Error") } ) @Path("/mics/central") @Produces(MediaType.APPLICATION_JSON) public class MicsCentralResource extends BaseWebService{ @@ -35,22 +49,32 @@ super(logger); } + @ApiOperation(value = "Service Distribution", notes = "This service returns the available distributions for a given cluster") + @ApiResponses( value ={ @ApiResponse(code = 200, message = "OK") } ) @GET @Path("/serviceDistribution/{clustername}") - public Response getServiceDistribution(@PathParam("clustername") @NotEmpty String clustername) { + public Response getServiceDistribution(@ApiParam(name = "clustername", value = "The name of the cluster") + @PathParam("clustername") @NotEmpty String clustername) { return invokeRunnable(() -> new BackendController().readServerDistribution(clustername)); } + @ApiOperation(value = "Health state check", notes = "This service checks if the components of a service are healthy") + @ApiResponses( value ={ @ApiResponse(code = 200, message = "OK") } ) @GET @Path("/serviceHealthState/{clustername}/{servicename}") - public Response getClusterHealthState(@PathParam("clustername") @NotEmpty String clustername, + public Response getClusterHealthState(@ApiParam(name = "clustername", value = "The name of the cluster") + @PathParam("clustername") @NotEmpty String clustername, + @ApiParam(name = "servicename", value = "The name of the service") @PathParam("servicename") @NotEmpty String servicename) { return invokeRunnable(() -> new BackendController().getServiceHealthState(clustername, servicename)); } + @ApiOperation(value = "Dispatcher", notes = "") + @ApiResponses( value ={ @ApiResponse(code = 200, message = "OK") } ) @POST @Path("/dispatch/{clustername}") public Response dispatch(String envelope, + @ApiParam(name = "clustername", value = "The name of the cluster") @PathParam("clustername") @NotEmpty String clustername) { ServiceRequestEnvelope envObj = JsonGeneratorBase.getGson().fromJson(envelope, ServiceRequestEnvelope.class); @@ -62,7 +86,8 @@ } } - + @ApiOperation(value = "Version Information", notes = "This services displays the version infos of this backend and the connected database.") + @ApiResponses( value ={ @ApiResponse(code = 200, message = "OK", response = VersionInfo.class,reference = "#/definitions/VersionInfo") } ) @GET @Path("/versionInfo") public Response getVersionInfo() {
diff --git a/src/main/resources/securityDefinitions.json b/src/main/resources/securityDefinitions.json new file mode 100644 index 0000000..7183dfd --- /dev/null +++ b/src/main/resources/securityDefinitions.json
@@ -0,0 +1,16 @@ +{ + "api_key": { + "type": "apiKey", + "name": "api_key", + "in": "header" + }, + "Existing JWT token": { + "type": "oauth2", + "authorizationUrl": "http://swagger.io/api/oauth/dialog", + "flow": "implicit", + "scopes": { + "scope1": "scope description 1", + "scope2": "scope description 2" + } + } +} \ No newline at end of file
diff --git a/templates/markdown.hbs b/templates/markdown.hbs new file mode 100644 index 0000000..2a7e5cf --- /dev/null +++ b/templates/markdown.hbs
@@ -0,0 +1,107 @@ +#{{#info}}{{title}} + + +## {{join schemes " | "}}://{{host}}{{basePath}} + + +{{description}} + +{{#contact}} +[**Contact the developer**](mailto:{{email}}) +{{/contact}} + +**Version** {{version}} + +[**Terms of Service**]({{termsOfService}}) + +{{#license}}[**{{name}}**]({{url}}){{/license}} + +{{/info}} + +{{#if consumes}}**Consumes:** {{join consumes ", "}}{{/if}} + +{{#if produces}}**Produces:** {{join produces ", "}}{{/if}} + +{{#if securityDefinitions}} +# Security Definitions +{{/if}} +{{> security}} + +# APIs + +{{#each paths}} +## {{@key}} +{{#this}} +{{#get}} +### GET +{{> operation}} +{{/get}} + +{{#put}} +### PUT +{{> operation}} +{{/put}} + +{{#post}} +### POST + +{{> operation}} + +{{/post}} + +{{#delete}} +### DELETE +{{> operation}} +{{/delete}} + +{{#option}} +### OPTION +{{> operation}} +{{/option}} + +{{#patch}} +### PATCH +{{> operation}} +{{/patch}} + +{{#head}} +### HEAD +{{> operation}} +{{/head}} + +{{/this}} +{{/each}} + +# Definitions +{{#each definitions}} +## <a name="/definitions/{{key}}">{{@key}}</a> + +<table border="1"> + <tr> + <th>name</th> + <th>type</th> + <th>required</th> + <th>description</th> + <th>example</th> + </tr> + {{#each this.properties}} + <tr> + <td>{{@key}}</td> + <td> + {{#ifeq type "array"}} + {{#items.$ref}} + {{type}}[<a href="{{items.$ref}}">{{basename items.$ref}}</a>] + {{/items.$ref}} + {{^items.$ref}}{{type}}[{{items.type}}]{{/items.$ref}} + {{else}} + {{#$ref}}<a href="{{$ref}}">{{basename $ref}}</a>{{/$ref}} + {{^$ref}}{{type}}{{#format}} ({{format}}){{/format}}{{/$ref}} + {{/ifeq}} + </td> + <td>{{#required}}required{{/required}}{{^required}}optional{{/required}}</td> + <td>{{#description}}{{{description}}}{{/description}}{{^description}}-{{/description}}</td> + <td>{{example}}</td> + </tr> + {{/each}} +</table> +{{/each}} \ No newline at end of file
diff --git a/templates/operation.hbs b/templates/operation.hbs new file mode 100644 index 0000000..3ad3175 --- /dev/null +++ b/templates/operation.hbs
@@ -0,0 +1,73 @@ +{{#deprecated}}-deprecated-{{/deprecated}} +<a id="{{operationId}}">{{summary}}</a> + +{{description}} + +{{#if externalDocs.url}}{{externalDocs.description}}. [See external documents for more details]({{externalDocs.url}}) +{{/if}} + +{{#if security}} +#### Security +{{/if}} + +{{#security}} +{{#each this}} +* {{@key}} +{{#this}} * {{this}} +{{/this}} +{{/each}} +{{/security}} + +#### Request + +{{#if consumes}} +**Content-Type: ** {{join consumes ", "}}{{/if}} + +##### Parameters +{{#if parameters}} +<table border="1"> + <tr> + <th>Name</th> + <th>Located in</th> + <th>Required</th> + <th>Description</th> + <th>Default</th> + <th>Schema</th> + </tr> + {{/if}} + + {{#parameters}} + <tr> + <th>{{name}}</th> + <td>{{in}}</td> + <td>{{#if required}}yes{{else}}no{{/if}}</td> + <td>{{description}}{{#if pattern}} (**Pattern**: `{{pattern}}`){{/if}}</td> + <td> - </td> + {{#ifeq in "body"}} + <td> + {{#ifeq schema.type "array"}}Array[<a href="{{schema.items.$ref}}">{{basename schema.items.$ref}}</a>]{{/ifeq}} + {{#schema.$ref}}<a href="{{schema.$ref}}">{{basename schema.$ref}}</a> {{/schema.$ref}} + </td> + {{else}} + {{#ifeq type "array"}} + <td>Array[{{items.type}}] ({{collectionFormat}})</td> + {{else}} + <td>{{type}} {{#format}}({{format}}){{/format}}</td> + {{/ifeq}} + {{/ifeq}} + </tr> + {{/parameters}} + {{#if parameters}} +</table> +{{/if}} + + +#### Response + +{{#if produces}}**Content-Type: ** {{join produces ", "}}{{/if}} + + +| Status Code | Reason | Response Model | +|-------------|-------------|----------------| +{{#each responses}}| {{@key}} | {{description}} | {{#schema.$ref}}<a href="{{schema.$ref}}">{{basename schema.$ref}}</a>{{/schema.$ref}}{{#ifeq schema.type "array"}}Array[<a href="{{schema.items.$ref}}">{{basename schema.items.$ref}}</a>]{{/ifeq}}{{^schema}} - {{/schema}}| +{{/each}} \ No newline at end of file
diff --git a/templates/security.hbs b/templates/security.hbs new file mode 100644 index 0000000..94badab --- /dev/null +++ b/templates/security.hbs
@@ -0,0 +1,88 @@ +{{#each securityDefinitions}} +### {{@key}} +{{#this}} +{{#ifeq type "oauth2"}} +<table> + <tr> + <th>type</th> + <th colspan="2">{{type}}</th> + </tr> + {{#if description}} + <tr> + <th>description</th> + <th colspan="2">{{description}}</th> + </tr> + {{/if}} + {{#if authorizationUrl}} + <tr> + <th>authorizationUrl</th> + <th colspan="2">{{authorizationUrl}}</th> + </tr> + {{/if}} + {{#if flow}} + <tr> + <th>flow</th> + <th colspan="2">{{flow}}</th> + </tr> + {{/if}} + {{#if tokenUrl}} + <tr> + <th>tokenUrl</th> + <th colspan="2">{{tokenUrl}}</th> + </tr> + {{/if}} + {{#if scopes}} + <tr> + <td rowspan="3">scopes</td> + {{#each scopes}} + <td>{{@key}}</td> + <td>{{this}}</td> + </tr> + <tr> + {{/each}} + </tr> + {{/if}} +</table> +{{/ifeq}} +{{#ifeq type "apiKey"}} +<table> + <tr> + <th>type</th> + <th colspan="2">{{type}}</th> + </tr> + {{#if description}} + <tr> + <th>description</th> + <th colspan="2">{{description}}</th> + </tr> + {{/if}} + {{#if name}} + <tr> + <th>name</th> + <th colspan="2">{{name}}</th> + </tr> + {{/if}} + {{#if in}} + <tr> + <th>in</th> + <th colspan="2">{{in}}</th> + </tr> + {{/if}} +</table> +{{/ifeq}} +{{#ifeq type "basic"}} +<table> + <tr> + <th>type</th> + <th colspan="2">{{type}}</th> + </tr> + {{#if description}} + <tr> + <th>description</th> + <th colspan="2">{{description}}</th> + </tr> + {{/if}} +</table> +{{/ifeq}} +{{/this}} +{{/each}} \ No newline at end of file
diff --git a/templates/strapdown.html.hbs b/templates/strapdown.html.hbs new file mode 100644 index 0000000..fd359ff --- /dev/null +++ b/templates/strapdown.html.hbs
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<title>API Document</title> + +<xmp theme="united" style="display:none;"> + {{>markdown}} +</xmp> + +<script src="http://strapdownjs.com/v/0.2/strapdown.js"></script> +</html> \ No newline at end of file