Swagger With Play2


What is Swagger :

Swagger is very powerful tool for REST API description and API documentation.Swagger API gives a Swagger GUI for humans to learn and test your API.It’s 100% open source.The goal of Swagger is to enable client and documentation systems to update at the same pace as the server. The documentation of methods, parameters, and models are tightly integrated into the server code, allowing APIs to always stay in sync.
In this post I’m going to show step by step instruction how to setup Swagger UI with Play Framework.
How to Use Swagger Api In Our Project:-

———————————————————————————————————————–
Step-1: Installing swagger-play2 plugin:

Just Add Swagger dependency to your project’s dependencies (most likely in build.sbt)

libraryDependencies ++= Seq(
//other dependencies
"com.wordnik" %% "swagger-play2" % "1.3.8",
//other dependencies
)

—————————————————————————————————————————–
Step-2 :For Swagger UI

2.1:Download Swagger UI:

Download Swagger UI and put all these files in [project_root_dir]/public/swagger
—————————————————————————————————————————–
Step-2.2:For Getting swagger home page:

Copy index.html in [project_root_dir]/app/views and rename it in swagger.scala.html
———————————————————————————————————–
Step-2.3: Modify Swagger.scala.html:

Follow next three steps for modifying swagger.scala.html
a): Introduce one import statement in swagger.scala.html:

Add following line on the top of the file:

@import play.api.Play.current

b) Update all src location in swagger.scala.html:
Update all src location .After updating all of them would be like this:

<script src='/assets/swagger/lib/backbone-min.js' type='text/javascript'></script>

c) Update some java script code in swagger.scala.html:

Update JavaScript code snippet by injecting there some Play Template code:

$(function () {
var url = window.location.search.match(/url=([^&]+)/);
 if (url && url.length > 1) {
url = url[1];
} else {
url = "@{s"${current.configuration.getString("swagger.api.basepath")
.getOrElse("http://localhost:9000")}/api-docs.json"}"
}.......

——————————————————————————————————-
Step-3 : Import following for decorating our action :

For necessary annotation to decorate action,use following import:

import com.wordnik.swagger.annotations._
import javax.ws.rs._

It’s time to decorate REST endpoints with appropriate annotations:


@Api(value = "/hello", description = "Operation like GET,POST and Upload Image")
object Hello extends Controller {

val messageForm = Form(
    tuple(
      "nick_name" -> nonEmptyText,
      "address" -> nonEmptyText))

/*
* Following is a Get method that returns a greeting Hello Guest
* */
@ApiOperation(
nickname = "Message",
value = "Return message",
notes = "Check message",
httpMethod = "GET")
@ApiResponses(Array(
new ApiResponse(code = 200, message = "Success"),
new ApiResponse(code = 400, message = "Bad Request"),
new ApiResponse(code = 500, message = "DB connection error")))
def getHello = Action {  implicit request =>
Ok("Hello Guest!")
}

/*
* following is a POST method that takes a parameter @name and return a greeting with name,nickname and address.
* */

@ApiOperation(
nickname = "PostHello",
value = "It returns a greeting with your name",
notes = "Post Method",
httpMethod = "POST")
@ApiImplicitParams(Array(
new ApiImplicitParam(value = "Data For Post Hello", required = true, dataType = "string", paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "Success"),
new ApiResponse(code = 400, message = "Bad Request"),
new ApiResponse(code = 500, message = "DB connection error")))
def postHello(@ApiParam(value = "name", required = true)@PathParam(value = "name") name: String) = Action {  implicit request =>
messageForm.bindFromRequest.fold(
formWithErrors =>
BadRequest("Some error in form submission" + formWithErrors),
 receiptDetail => {
val nickname = receiptDetail._1
val address = receiptDetail._2
Ok("Hello " + name + "!" + "" + "your nick name is " + nickname + "and" + "address is " + address)

})
}

/* It takes an image as well as @nick_name and @address*/

@ApiOperation(
nickname = "imageUpload",
value = "image uploading based on image and other data",
notes = "image upload",
httpMethod = "POST",
consumes = "multipart/form-data", produces = "multipart/form-data")
@ApiImplicitParams(Array(
new ApiImplicitParam(value = "Query string", name = "image", required = true, paramType = "form", dataType = "file"), new ApiImplicitParam(name = "receiptForms", value = "Query strings", required = true, paramType = "body")))
@ApiResponses(Array(
new ApiResponse(code = 200, message = "Success"),
new ApiResponse(code = 400, message = "Bad Request"),
new ApiResponse(code = 500, message = "DB connection error")))
def upload = Action(parse.multipartFormData) { implicit request =>
request.body.file("image").map {  image =>
val file = new File(s"/tmp/${image.filename}")
image.ref.moveTo(file)
//Perform your logic for image
}
Ok("Successfully uploaded")

}

——————————————————————————————————–
Step-4 :Modification in routes.scala

Step-4.1: Add a route in routes.scala for listing end points :

In routes file ,put following URI in order to list all REST endpoints in a project:

GET /api-docs.json controllers.ApiHelpController.getResources

————————————————————————————————————-
Step-4.2 : Add Swagger api-docs routes for each end points in routes.scala:
Modify routes file again but now for a particular endpoint:

GET /api-docs.json/hello controllers.ApiHelpController.getResource(path = "/hello")
GET /hello controllers.Hello.getHello()
POST /hello/:name controllers.Hello.postHello(name:String)
POST /hello/upload/image controllers.Hello.upload()

—————————————————————————————————
Step-4.3 : Add a route in routes.scala for getting swagger UI :

finally add following routes


GET /swagger controllers.Application.swagger

—————————————————————————————————————————-
Step-5 Add an Action in Application.scala for getting Swagger-GUI :

Add an action which will be responsible for Swagger UI display:

object Application extends Controller {

def swagger = Action {
request =>
Ok(views.html.swagger())
}

}

————————————————————————————————————————–
Step-6:Add application URL for Swagger GUI in application.conf:

Add default application URL in application.config


swagger.api.basepath=http://localhost:9000

———————————————————————————————————————-

#Verify the Swagger API Configuration :
Check Swagger-api’s configuration at – http://localhost:9000/api-docs.json
If all things went good then there would be response like this :
{“apiVersion”:”beta”,”swaggerVersion”:”1.2″,”apis”:[{“path”:”/hello”,”description”:”Some operation like GET,POST and Upload Image”}]}

Check following image:

SwaggerApiDocResponse

http://localhost:9000/api-docs.json – doesn’t respond than something went wrong.

#How to run my swagger UI:
Run your project with all services(if exists) after it
check the Swagger API Docs at http://localhost:9000/swagger
SwaggerUI

There is only one link named hello because in routes.scala,there was one route named hello.

Just click on hello link and see all your rest api link associated with hello.

SwaggerRoutesLink

#How to check Api Response:

There are 3 routes.

Just click POST/hello/{name} :-   It takes name as a query parameter and nick_name and address as a Json. Click on Try it out!  and check next image:

SwaggerPOSTResponse

#For Image Upload :

For uploading an image as well as send data through form.

SwaggerUploadImage

Github link for demo project : Swagger_Play

Advertisements
This entry was posted in Play Framework, Scala, Swagger and tagged , , , , , . Bookmark the permalink.

6 Responses to Swagger With Play2

  1. John Sullivan says:

    If you are using Scala 2.11.6, Play v2.4.x you will need to have these items.
    build.conf:
    “io.swagger” %% “swagger-play2” % “1.5.0”

    application.conf:
    play.modules.enabled += “play.modules.swagger.SwaggerModule”

    Without the line in application.conf you will get a NPE when trying to access the /api-docs.json

    • bvizy says:

      Thank you John!

      If you get a play.modules.swagger.SwaggerModule not found message, make sure you replace the double quotes with “plain” double quotes (do not copy-past the above lines).

  2. harshvs20 says:

    Do you have something for Play2.5 ?
    the import @import play.api.Play.current is deprecated and this is not working anymore.

  3. HOw to fixed this,
    object wordnik is not a member of package com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s