Tag Archives: Grails app

In this article, we will learn how to integrate Swagger-UI with Grails application. Basically ‘SwaggerUI’ is used to serve documentation of a REST API. It describes and visualises RESTful web services, not only that it will help to expose the REST APIs to end users. With Swagger-UI we can represent our APIs in graphical representation. In this article, we are going to integrate Swagger-UI into sample-oauth2-app. Our aim is to see the following pages.

swagger-ui-5

swagger-ui-6

Here are the steps to integrate Swagger-UI:

  1. Add swagger dependencies
  2. Configure the Swagger
  3. Writing a controller that enables the swagger into action
  4. Annotate API with swagger annotations
  5. Add swagger UI plugin

1. Add Swagger Dependencies

In this initial step, we need to add swagger dependencies in grails-app/conf/BuildConfig.grooy

compile "io.swagger:swagger-core:1.5.3"
compile "io.swagger:swagger-jaxrs:1.5.3"

2.Configure the Swagger

Swagger’s BeanConfig class allows you to set various properties for Swagger’s initialization. Configure the BeanConfig class in resource.groovy

Method Property Name Purpose
setTitle(String) title Sets the title of the application.
setDescription(String) description Sets the description of the application.
setTermsOfServiceUrl(String) termsOfServiceUrl Sets the URL of the application’s Terms of Service.
setContact(String) contact Sets the contact information for the application.
setLicense(String) license Sets the license of the application
setLicenseUrl(String) licenseUrl Sets the license URL of the application.
setVersion(String) version Sets the version of the API.
setBasePath(String) basePath Sets the basePath for the API calls.
setApiReader(String) apiReader Sets an API Reader class for Swagger.
setFilterClass(Sting) filterClass Sets a security filter for Swagger’s documentation.
setResourcePackage(String) resourcePackage Sets which package(s) Swagger should scan to pick up resources. If there’s more than one package, it can be a list of comma-separated packages
setScan(boolean) scan When set to true, Swagger will build the documentation
import io.swagger.jaxrs.config.BeanConfig
beans = {
    swaggerConfig(BeanConfig) {
        def serverUrl = grailsApplication.config.grails.serverURL.toString()
        def hostName = serverUrl.substring(serverUrl.indexOf("://")+3)
        resourcePackage = 'com.nbos.core'
        host = hostName
        basePath = "/api"
        version = 'v0' // Default "1".
        title = 'Core Registration API, Version V0' // Default: App Name.
        description = 'API for Accessing secured resources'
        contact = 'webservices@nbostech.com'
        license = ''
        licenseUrl = ''
    }
}

3. Writing a Controller that Enables the Swagger into Action

After the configuration, we have to write controller to get the swagger into action

package com.nbos.apidoc
import org.codehaus.groovy.grails.web.mapping.LinkGenerator

class ApiDocController {
    LinkGenerator grailsLinkGenerator
    def apiDocService
    def index = {
        String basePath = grailsLinkGenerator.serverBaseURL
        render(view: 'index', model: [apiDocsPath: "${basePath}/api/swagger-json"])
    }
    def swaggerJson = {
        render apiDocService.generateJSON()
    }
}

Map these actions in URL mappings.groovy

> grails url-mappings-report
Dynamic Mappings
 |    *     | /oauth/authorize                                          | Action: (default action)                 |
 |    *     | /oauth/token                                              | Action: (default action)                 |
 |    *     | /${controller}/${action}?/${id}?(.${format)?              | Action: (default action)                 |
 |    *     | /                                                         | View:   /index                           |
 |    *     | ERROR: 500                                                | View:   /error                           |

Controller: apiDoc
 |    *     | /api/info                                                 | Action: index                            |
 |    *     | /api/swagger-json                                         | Action: swaggerJson                      |

Controller: dbdoc
 |    *     | /dbdoc/${section}?/${filename}?/${table}?/${column}?      | Action: (default action)                 |

Controller: sample
 |    *     | /api/sample/securedWithClientOAuth                        | Action: securedWithClientOAuth           |
 |    *     | /api/sample/securedWithUserOAuth                          | Action: securedWithUserOAuth             |

For Swagger to actually produce the documentation, you must setScan(true). The BeanConfig should be called when your application starts up. Invoke the BeanConfig in service class

package com.care.apidoc
import io.swagger.jaxrs.config.BeanConfig
import io.swagger.util.Json;
import grails.transaction.Transactional

@Transactional
class ApiDocService {

    def swaggerConfig

    /*
     * generates SWAGGer JSON
     */
    def generateJSON() {

        String[] schemes = ["http"] as String[]
        swaggerConfig.setSchemes(schemes)
        swaggerConfig.setScan(true)
        def swagger = swaggerConfig.getSwagger()

        Json.mapper().writeValueAsString(swagger);
    }
}

4. Annotate API with Swagger Annotations

We are annotating the SampleController APIs with Swagger annotations, that will help to generate SwaggerJson.

package com.nbos.core
import grails.plugin.springsecurity.annotation.Secured
import io.swagger.annotations.Api
import io.swagger.annotations.ApiOperation

import javax.ws.rs.GET
import javax.ws.rs.Path
import javax.ws.rs.Produces

@Path("/sample")
@Api(value = "auth", description = "Secured Access Using tokens")
@Produces(["application/json", "application/xml"])
class SampleController {

    static responseFormats = ['json', 'xml']

    @GET
    @Path("/securedWithClientOAuth")
    @ApiOperation(value = "Secured Access Using client tokens", httpMethod = "GET" )
    @Secured("#oauth2.isClient()")
    def securedWithClientOAuth() {
        def map=['sucsess':'AuthenticationSucces','message':'Client is authenticated successfully']
        respond map
    }
    @GET
    @Path("/securedWithUserOAuth")
    @ApiOperation(value = "Secured access using user token", httpMethod = "GET" )
    @Secured("#oauth2.isUser()")
    def securedWithUserOAuth(){
        def map=['sucsess':'AuthenticationSucces','message':'User is authenticated successfully']
        respond map
    }
}

5. Add swagger UI plugin

Lastly, we need to add Swagger UI plug. You can Download swagger UI, copy and paste it in folder/web app. Now write the index.html apidoc/index.gsp

Swagger UI

    %{--<!-- TODO: move these to use asset-pipeline -->--}%

    <script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2/lib', file: 'jquery-1.8.0.min.js')}"></script><script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2/lib', file: 'jquery.slideto.min.js')}"></script><script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2/lib', file: 'jquery.wiggle.min.js')}"></script><script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2/lib', file: 'jquery.ba-bbq.min.js')}"></script><script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2/lib', file: 'handlebars-2.0.0.js')}"></script><script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2/lib', file: 'underscore-min.js')}"></script><script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2/lib', file: 'backbone-min.js')}"></script><script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2', file: 'swagger-ui.js')}"></script><script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2/lib', file: 'highlight.7.3.pack.js')}"></script><script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2/lib', file: 'marked.js')}"></script><script src="${resource(dir: 'vendor/swagger-ui/2.1.4-M2/lib', file: 'swagger-oauth.js')}"></script>%{--<!-- enabling this will enable oauth2 implicit scope support -->--}% %{--<script></script>--}%<script>// <![CDATA[         $(function () {             window.swaggerUi = new SwaggerUi({                 url: "${apiDocsPath}",                 dom_id: "swagger-ui-container",                 supportedSubmitMethods: ['get', 'post', 'put', 'delete'],                 onComplete: function(swaggerApi, swaggerUi){                     if(typeof initOAuth == "function") {                         /*                          initOAuth({                          clientId: "your-client-id",                          realm: "your-realms",                          appName: "your-app-name"                          });                          */                     }                     $('pre code').each(function(i, e) {                         hljs.highlightBlock(e)                     });                 },                 onFailure: function(data) {                     console.log("Unable to Load SwaggerUI");                 },                 docExpansion: "none"             });             $('#input_apiKey').change(function() {                 var key = $('#input_apiKey')[0].value;                 if(key && key.trim() != "") {                     swaggerUi.api.clientAuthorizations.add("key", new SwaggerClient.ApiKeyAuthorization("Authorization", "Bearer " + key, "header"));                 }             })             window.swaggerUi.load();         });      // ]]></script></pre>
<div id="header">
<div class="swagger-ui-wrap">
<a id="logo" href="http://swagger.io">swagger</a>
<form id="api_selector">
<div class="input"><input id="input_baseUrl" name="baseUrl" type="text" placeholder="http://example.com/api" /></div>
<div class="input"><input id="input_apiKey" name="apiKey" type="text" placeholder="access_token" /></div>
<div class="input"><a id="explore" href="#">Explore</a></div>
</form>
</div>
</div>
<div id="message-bar" class="swagger-ui-wrap"></div>
<div id="swagger-ui-container" class="swagger-ui-wrap"></div>
<pre>

 

Now we all are set. Run the server.

> grails run-app

Go to browser and try to access “http://localhost:8080/sample-oauth2-app/api/info”. You will see above screens on the browser.