Playframework and Swagger
PlayframeworkandSwagger
1.PreparetheRESTfulProject(Upgrade)
Downloadthelatestactivatorversionandplaceintheworkingdirectory.
https://www.playframework.com/documentation/2.4.3/ScalaTestingWithScalaTest
SomeChangestoUpgradetheVersion
activator
declare-rapp_version=“1.3.6"
activator.bat
setAPP_VERSION=1.3.6
build.sbt
importplay.sb.PlayScala
…snip...
scalaVersion:="2.10.4"
ivyScala:=ivyScala.valuemap{_.copy(overrideScalaVersion=true)}
libraryDependencies++=Seq(
"org.scalatest"%%"scalatest"%"2.2.5"%"test",
"org.scalatestplus"%%"play"%"1.4.0-M4"%"test"
)
…snip...
project/build.properties
sbt.version=0.13.8
project/plugins.sbt
logLevel:=Level.Warn
addSbtPlugin("com.eed3si9n"%"sbt-assembly"%"0.14.0")
addSbtPlugin("com.github.mpeltonen"%"sbt-idea"%"1.6.0")
resolvers+="Typesaferepository"at"https://repo.typesafe.com/typesafe/releases/"
addSbtPlugin("com.typesafe.play"%"sbt-plugin"%"2.4.3")
test/controllers/BookControllerSpec.scala
packagecontrollers
importplay.api.libs.json.JsValue
importscala.concurrent.Future
importorg.scalatestplus.play._
importplay.api.mvc._
importplay.api.test._
importplay.api.test.Helpers._
classBookControllerSpecextendsPlaySpecwithResults{
classTestController()extendsControllerwithBookController
"BookAPI#listBooks"should{
"sizeshouldbe2"in{
valcontroller=newTestController
valresult:Future[Result]=controller.listBooks.apply(FakeRequest())
valbodyText:JsValue=contentAsJson(result)
bodyTextmustnotbenull
}
}
}
2.PrepareSwagger
Playwithswagger-uiProject
>gitclonehttps://github.com/swagger-api/swagger-ui.git
>npminstall
>gulp
Afterthat,weshouldseethedistributionunderthelistfolder.
CheckifIhaveapachehttpserveronmymachine.
>apachectl-V
Serverversion:Apache/2.4.16(Unix)
Serverbuilt:Jul22201521:03:09
Server'sModuleMagicNumber:20120211:47
Serverloaded:APR1.4.8,APR-UTIL1.5.2
Compiledusing:APR1.4.8,APR-UTIL1.5.2
Architecture:64-bit
ServerMPM:prefork
threaded:no
forked:yes(variableprocesscount)
Servercompiledwith....
-DAPR_HAS_SENDFILE
-DAPR_HAS_MMAP
-DAPR_HAVE_IPV6(IPv4-mappedaddressesenabled)
-DAPR_USE_FLOCK_SERIALIZE
-DAPR_USE_PTHREAD_SERIALIZE
-DSINGLE_LISTEN_UNSERIALIZED_ACCEPT
-DAPR_HAS_OTHER_CHILD
-DAP_HAVE_RELIABLE_PIPED_LOGS
-DDYNAMIC_MODULE_LIMIT=256
-DHTTPD_ROOT="/usr"
-DSUEXEC_BIN="/usr/bin/suexec"
-DDEFAULT_PIDLOG="/private/var/run/httpd.pid"
-DDEFAULT_SCOREBOARD="logs/apache_runtime_status"
-DDEFAULT_ERRORLOG="logs/error_log"
-DAP_TYPES_CONFIG_FILE="/private/etc/apache2/mime.types"
-DSERVER_CONFIG_FILE="/private/etc/apache2/httpd.conf"
StarttheServer
>sudoapachectlstart
Checktheconfiguration
>cat/etc/apache2/httpd.conf
DocumentRoot"/Library/WebServer/Documents"
Copytheswagger-uidirectorythere
>sudocp-r/Users/carl/book/swagger/swagger-ui/dist/*/Library/WebServer/Documents/
Visitswagger-ui
http://localhost/
Puthttp://localhost:8000/api-docsasparameterintheinputbox,wewillhavetheapidoc.
Or
http://localhost/index.html?url=http://localhost:8000/api-docs
Or
http://localhost:8000/assets/lib/swagger-ui/index.html?/url=http://localhost:8000/api-docs
3.AddnotationintheProject
SomeSamplecodesareinsillycat-scalarestprojectversion-1.3.6-swaggerbranch.
build.sbt
importplay.sbt.PlayScala
name:="""sillycat-scalarest"""
version:="1.0"
lazyvalroot=project.in(file(".")).enablePlugins(PlayScala)
scalaVersion:="2.10.4"
ivyScala:=ivyScala.valuemap{_.copy(overrideScalaVersion=true)}
libraryDependencies++=Seq(
"pl.matisoft"%%"swagger-play24"%"1.4",
//forinternalswagger-ui
//"org.reflections"%"reflections"%"0.9.9"notTransitive(),
//"org.webjars"%"swagger-ui"%"2.1.8-M1",
"org.scalatest"%%"scalatest"%"2.2.5"%"test",
"org.scalatestplus"%%"play"%"1.4.0-M4"%"test"
)
forkinrun:=false
conf/routes
#Routes
#Thisfiledefinesallapplicationroutes(Higherpriorityroutesfirst)
#~~~~
#Mapstaticresourcesfromthe/publicfoldertothe/assetsURLpath
GET/assets/*filecontrollers.Assets.versioned(path="/public",file)
#APIRoutes
GET/pingcontrollers.PingPongController.ping()
GET/api/v1/bookcontrollers.BookController.listBooks
POST/api/v1/bookcontrollers.BookController.saveBook
GET/api/v1/book/:idcontrollers.BookController.getBook(id:String)
PUT/api/v1/book/:idcontrollers.BookController.updateBook(id:String)
DELETE/api/v1/book/:idcontrollers.BookController.deleteBook(id:String)
#SwaggerAPI
GET/api-docs/api/[email protected](path="/api/v1")
app/controllers/PingPongController.scala
packagecontrollers
importplay.api.mvc.{Action,Controller}
importcom.wordnik.swagger.annotations.{Api,ApiModel,ApiModelProperty,ApiOperation,ApiParam,ApiResponse,ApiResponses}
@Api(value="/api/v1",description="OperationswithClassifier")
objectPingPongControllerextendsController{
@ApiOperation(value="Pings",
notes="Returnspong",
response=classOf[String],
httpMethod="GET",
produces="text",
position=1)
@ApiResponses(Array(
newApiResponse(code=200,message="Successfulping",response=classOf[String])
)
)
defping=Action{
Ok("pong")
}
}
ErrorMessage
XMLHttpRequestcannotloadhttp://localhost:8000/string.No'Access-Control-Allow-Origin'headerispresentontherequestedresource.Origin'http://localhost'isthereforenotallowedaccess.TheresponsehadHTTPstatuscode404.
Solution:
http://enable-cors.org/server.html
https://www.playframework.com/documentation/2.4.3/CorsFilter
FilterClassapp/Filters.scala
importjavax.inject.Inject
importplay.api.http.HttpFilters
importplay.filters.cors.CORSFilter
classFilters@Inject()(corsFilter:CORSFilter)extendsHttpFilters{
deffilters=Seq(corsFilter)
}
Configurationinconf/application.conf
play.filters.cors{
#pathPrefixes=["/some/path",...]
allowedOrigins=["http://localhost","http://sillycat.ddns.net"]
allowedHttpMethods=["GET","POST","PUT"]
#allowedHttpHeaders=["Accept"]
#preflightMaxAge=3days
}
4.PlayframeworkDeployment
Buildthebinary
>sbtdist
Runthebinary
>bin/sillycat-scalarest-Dconfig.file=conf/application.conf-Dhttp.port=8000-Dhttp.address=0.0.0.0
Needtousethesameuiversion
>gitcheckouttags/v2.1.8-M1
References:
Playframework
Swagger
https://github.com/matiwinnetou/swagger-play24
http://swagger.io/getting-started/
https://github.com/swagger-api/swagger-ui