SlideShare ist ein Scribd-Unternehmen logo
1 von 60
Downloaden Sie, um offline zu lesen
API First
with Play and Swagger
THEN
Java Developer
LATER
Enterprise
Architect
NOW
Scala Consultant
TWITTER
@slavaschmidt
MAIL
slavaschmidt@gmx.de
THEN
Java Developer
LATER
Enterprise
Architect
NOW
Scala Consultant
TWITTER
@ZALANDO
MAIL
slavaschmidt@gmx.de
NOW
Scala Consultant
@ZALANDO
@ZALANDO
@ZALANDO
@ZALANDO
•Autonomy
•Small in size
•Full responsibility
•One or more components
•Autonomy
•Full responsibility
•One system boundary
API First
Document and
peer review API
before writing a
single line of code
Ideally, generate either
your server interfaces
or your test data (or
both) from the spec
Specification
Server Implementation
Review
Client Implementation
MisinterpretationMisrepresentation
+ API First
REST
???
What is REST’s central distinguishing feature?
… its emphasis on a uniform interface between
components
Roy Thomas Fielding
remaining the same in all cases and at all
times
British Dictionary
uniform
How do we combine “same” and “changing” ?
???
REST
• Client-Server
• Stateless
• Cacheable
• Layered System
• Uniform Interface
• Identification of resources
• Manipulation of resources through these representations
• Self-descriptive messages
• Hypermedia as the engine of application state
implementation details
Server
Client/Server
Protocol
Architecture
Hexagonal Architecture
The 1968/69 NATO

Software Engineering
Conference
aka Ports and Adapters
Chris Fidao
https://www.youtube.com/watch?v=6SBjKOwVq0o
Hexagonal Architecture
Hexagonal Architecture
Hexagonal Architecture
Transport
Transport
Validations
Validations
Model
Model
DRY
DRY
Most people take DRY to mean you shouldn't duplicate code.
That's not its intention. The idea behind DRY is far grander
than that. DRY says that every piece of system knowledge
should have one authoritative, unambiguous representation.
Dave Thomas
Getting real…
• Easy to use
• Human readable
• Widest adoption
• Open Source
• Scala and Java
• Dynamic recompilation / Hot reload
• Asynchronous IO
• Easy to use
• URI path definitions (supports parameterisation and templating)
• URI parameter definitions
• Response definitions
• Scheme definitions
• MIME type definitions
• Primitive datatypes
• Complex datatypes
• Structural constraints
• Value constraints
• Security constraints
• Tags
• Vendor extensions
Specification
URLs
Verbs
Parameters
Security
Definitions
Specification
URLs
Verbs
Parameters
Security
Definitions Validations
Model
Test Data
Validations
Play Routes
Marshallers
Tests
Controllers
DEMO
Architecture
AST
Play
Akka HTTP
Swagger
RAML
Apiary
Blueprint
…
…
…
Generated code
Metadata
swagger: "2.0"

info:

version: 1.0.0

title: Swagger Petstore

description: A sample API that uses a petstore as an example to
demonstrate features in the swagger-2.0 specification

termsOfService: http://swagger.io/terms/

contact:

name: Swagger API Team

email: foo@example.com

url: http://madskristensen.net

license:

name: MIT

url: http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT

host: petstore.swagger.io

basePath: /api

schemes:

- http

consumes:

- application/json

produces:

- application/json
URL Prefix
Definitions
definitions:

Pet:

allOf:

- $ref: '#/definitions/NewPet'

- required:

- id

properties:

id:

type: integer

format: int64

NewPet:

required:

- name 

properties:

name:

type: string

tag:

type: string 

Error:

required:

- code

- message

properties:

code:

type: integer

format: int32

message:

type: string
object definitions {

trait NewPetDef {

def name: String

def tag: Option[String]

}

case class Pet(

id: Option[Long],

name: String,

tag: Option[String]

) extends NewPetDef

case class NewPet(

name: String,

tag: Option[String]

) extends NewPetDef

case class Error(

code: Int,

message: String

)

}
Test data
definitions:

Pet:

allOf:

- $ref: '#/definitions/NewPet'

- required:

- id

properties:

id:

type: integer

format: int64

NewPet:

required:

- name 

properties:

name:

type: string

tag:

type: string 

Error:

required:

- code

- message

properties:

code:

type: integer

format: int32

message:

type: string
object generatorDefinitions {



def createPet = _generate(PetGenerator)

def createNewPet = _generate(NewPetGenerator)

def createError = _generate(ErrorGenerator)

// test data generator for /definitions/Pet

val PetGenerator =

for {

id <- Gen.option(arbitrary[Long])

name <- arbitrary[String]

tag <- Gen.option(arbitrary[String])

} yield Pet(id, name, tag)

// test data generator for /definitions/NewPet

val NewPetGenerator =

for {

name <- arbitrary[String]

tag <- Gen.option(arbitrary[String])

} yield NewPet(name, tag)

// test data generator for /definitions/Error

val ErrorGenerator =

for {

code <- arbitrary[Int]

message <- arbitrary[String]

} yield Error(code, message)

def _generate[T](gen: Gen[T]) = (count: Int) =>
for (i <- 1 to count) yield gen.sample

}
Validations'#/definitions/NewPet'

red:

rties:

ype: integer

ormat: int64



s:

string

string 

ge

s:

integer

t: int32

:

string
class PetValidation(instance: Pet) {

import de.zalando.play.controllers.PlayValidations._

val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]

val result = {

val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)

if (errors.nonEmpty) Left(errors) else Right(instance)

}

}





class NewPetValidation(instance: NewPet) {

import de.zalando.play.controllers.PlayValidations._

val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]

val result = {

val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)

if (errors.nonEmpty) Left(errors) else Right(instance)

}

}





class ErrorValidation(instance: Error) {

import de.zalando.play.controllers.PlayValidations._

val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]

val result = {

val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)

if (errors.nonEmpty) Left(errors) else Right(instance)

}

}
Validations
/pets/{id}:

get:

description: Returns a user based
on a single ID, if the user does not
have access to the pet

operationId: find pet by id

parameters:

- name: id

in: path

description: ID of pet to fetch

required: true

type: integer

format: int64

responses:

200:

description: pet response

schema:

$ref: '#/definitions/Pet'

default:

description: unexpected error

schema:

$ref: '#/definitions/Error'
class ValidationForPetexpandedYamlfindPetById(in: (Long)) {

val (id) = in



val idConstraints = new ValidationBase[Long] {

override def constraints: Seq[Constraint[Long]] = Seq()

}



val normalValidations =
Seq(idConstraints.applyConstraints(id))



val containerValidations =
Seq.empty[scala.Either[scala.Seq[ParsingError], String]]



val rightResult = Right((id))



val allValidations = normalValidations ++
containerValidations



val result = {

val errors =
allValidations.filter(_.isLeft).flatMap(_.left.get)

if (errors.nonEmpty) Left(errors) else rightResult

}

}
Tests
"discard invalid data" in new WithApplication {

val genInputs =

for {

id <- arbitrary[Long]

} yield (id)

val inputs = genInputs suchThat { i => new ValidationForPetexpandedYamlfindPetById(i).result !=
Right(i) }

val props = forAll(inputs) { i => testInvalidInput(i) }

checkResult(props)

}
Tests
def testInvalidInput(in: (Long)) = {

val (id) = in

val url = s"""/api/pets/${id}"""

val path = route(FakeRequest(GET, url)).get

val validation = new ValidationForPetexpandedYamlfindPetById(id).result

lazy val validations = validation.left.get flatMap {

_.messages map { m => contentAsString(path).contains(m) ?= true }

}

("given an URL: [" + url + "]") |: all(

status(path) ?= BAD_REQUEST,

contentType(path) ?= Some("application/json"),

validation.isLeft ?= true,

all(validations:_*)

)

}
Controllers
private val findPetByIdResponseMimeType = "application/json"

private val findPetByIdActionSuccessStatus = Status(200)



private type findPetByIdActionRequestType = (Long)

private type findPetByIdActionResultType = Pet

private type findPetByIdActionType = findPetByIdActionRequestType => Either[Throwable, findPetByIdActionResultType]



private def errorToStatusfindPetById: PartialFunction[Throwable, Status] = PartialFunction.empty[Throwable, Status]



def findPetByIdAction = (f: findPetByIdActionType) => (id: Long) => Action {

val result = new ValidationForPetexpandedYamlfindPetById(id).result.right.map {

processValidfindPetByIdRequest(f)

}

implicit val marshaller = parsingErrors2Writable(findPetByIdResponseMimeType)

val response = result.left.map { BadRequest(_) }

response.fold(a => a, c => c)

}



private def processValidfindPetByIdRequest(f: findPetByIdActionType)(request: findPetByIdActionRequestType) = {

val callerResult = f(request)

val status = callerResult match {

case Left(error) => (errorToStatusfindPetById orElse defaultErrorMapping)(error)

case Right(result) => findPetByIdActionSuccessStatus

}

implicit val findPetByIdWritableJson = anyToWritable[findPetByIdActionResultType](findPetByIdResponseMimeType)

status(callerResult)

}
Skeletons
class PetexpandedYaml extends PetexpandedYamlBase {



// handler for GET /pets

def findPets = findPetsAction { in : (Option[Seq[String]], Option[Int]) =>

val (tags, limit) = in

???

}



// handler for POST /pets

def addPet = addPetAction { in : (NewPet) =>

val (pet) = in

???

}



// handler for GET /pets/{id}

def findPetById = findPetByIdAction { in : (Long) =>

val (id) = in

???

}



// handler for DELETE /pets/{id}

def deletePet = deletePetAction { in : (Long) =>

val (id) = in

???

}

}
http://github.com/zalando/play-swagger
Questions?

Weitere ähnliche Inhalte

Was ist angesagt?

Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017Mike Nakhimovich
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: RebirthJohn De Goes
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)Yeshwanth Kumar
 
Testing Java Code Effectively - BaselOne17
Testing Java Code Effectively - BaselOne17Testing Java Code Effectively - BaselOne17
Testing Java Code Effectively - BaselOne17Andres Almiray
 
RIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWTRIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWTMichael Galpin
 
RESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP FrameworkRESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP FrameworkBo-Yi Wu
 
How Testability Inspires AngularJS Design / Ran Mizrahi
How Testability Inspires AngularJS Design / Ran MizrahiHow Testability Inspires AngularJS Design / Ran Mizrahi
How Testability Inspires AngularJS Design / Ran MizrahiRan Mizrahi
 
Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Ahmed Moawad
 
Moderne backends mit dem aktor programmiermodell
Moderne backends mit dem aktor programmiermodellModerne backends mit dem aktor programmiermodell
Moderne backends mit dem aktor programmiermodellDamir Dobric
 
2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & WebpackCodifly
 
Arrays &amp; functions in php
Arrays &amp; functions in phpArrays &amp; functions in php
Arrays &amp; functions in phpAshish Chamoli
 
Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)James Titcumb
 
What you need to know about Lambdas - Jamie Allen
What you need to know about Lambdas - Jamie AllenWhat you need to know about Lambdas - Jamie Allen
What you need to know about Lambdas - Jamie Allenjaxconf
 
Spring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffSpring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffJAX London
 
JavaCro 2014 Scala and Java EE 7 Development Experiences
JavaCro 2014 Scala and Java EE 7 Development ExperiencesJavaCro 2014 Scala and Java EE 7 Development Experiences
JavaCro 2014 Scala and Java EE 7 Development ExperiencesPeter Pilgrim
 
Clean up your code with C#6
Clean up your code with C#6Clean up your code with C#6
Clean up your code with C#6Rui Carvalho
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJosé Paumard
 

Was ist angesagt? (20)

Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017Intro to GraphQL on Android with Apollo DroidconNYC 2017
Intro to GraphQL on Android with Apollo DroidconNYC 2017
 
Scalaz Stream: Rebirth
Scalaz Stream: RebirthScalaz Stream: Rebirth
Scalaz Stream: Rebirth
 
RESTful API using scalaz (3)
RESTful API using scalaz (3)RESTful API using scalaz (3)
RESTful API using scalaz (3)
 
Testing Java Code Effectively - BaselOne17
Testing Java Code Effectively - BaselOne17Testing Java Code Effectively - BaselOne17
Testing Java Code Effectively - BaselOne17
 
RIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWTRIAs Done Right: Grails, Flex, and EXT GWT
RIAs Done Right: Grails, Flex, and EXT GWT
 
Refactoring
RefactoringRefactoring
Refactoring
 
RESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP FrameworkRESTful API Design & Implementation with CodeIgniter PHP Framework
RESTful API Design & Implementation with CodeIgniter PHP Framework
 
How Testability Inspires AngularJS Design / Ran Mizrahi
How Testability Inspires AngularJS Design / Ran MizrahiHow Testability Inspires AngularJS Design / Ran Mizrahi
How Testability Inspires AngularJS Design / Ran Mizrahi
 
Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2Exploring Angular 2 - Episode 2
Exploring Angular 2 - Episode 2
 
Moderne backends mit dem aktor programmiermodell
Moderne backends mit dem aktor programmiermodellModerne backends mit dem aktor programmiermodell
Moderne backends mit dem aktor programmiermodell
 
2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack2018 05-16 Evolving Technologies: React, Babel & Webpack
2018 05-16 Evolving Technologies: React, Babel & Webpack
 
Second Level Cache in JPA Explained
Second Level Cache in JPA ExplainedSecond Level Cache in JPA Explained
Second Level Cache in JPA Explained
 
Arrays &amp; functions in php
Arrays &amp; functions in phpArrays &amp; functions in php
Arrays &amp; functions in php
 
Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)Diving into HHVM Extensions (PHPNW Conference 2015)
Diving into HHVM Extensions (PHPNW Conference 2015)
 
What you need to know about Lambdas - Jamie Allen
What you need to know about Lambdas - Jamie AllenWhat you need to know about Lambdas - Jamie Allen
What you need to know about Lambdas - Jamie Allen
 
Thinking Beyond ORM in JPA
Thinking Beyond ORM in JPAThinking Beyond ORM in JPA
Thinking Beyond ORM in JPA
 
Spring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard WolffSpring Day | Spring and Scala | Eberhard Wolff
Spring Day | Spring and Scala | Eberhard Wolff
 
JavaCro 2014 Scala and Java EE 7 Development Experiences
JavaCro 2014 Scala and Java EE 7 Development ExperiencesJavaCro 2014 Scala and Java EE 7 Development Experiences
JavaCro 2014 Scala and Java EE 7 Development Experiences
 
Clean up your code with C#6
Clean up your code with C#6Clean up your code with C#6
Clean up your code with C#6
 
JAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) BridgeJAX-RS and CDI Bike the (Reactive) Bridge
JAX-RS and CDI Bike the (Reactive) Bridge
 

Ähnlich wie API first with Swagger and Scala by Slava Schmidt

What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?Nikita Popov
 
Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"Fwdays
 
Getting to Grips with SilverStripe Testing
Getting to Grips with SilverStripe TestingGetting to Grips with SilverStripe Testing
Getting to Grips with SilverStripe TestingMark Rickerby
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Michelangelo van Dam
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Shinya Ohyanagi
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Michelangelo van Dam
 
Improving Correctness with Types
Improving Correctness with TypesImproving Correctness with Types
Improving Correctness with TypesIain Hull
 
"Scala in Goozy", Alexey Zlobin
"Scala in Goozy", Alexey Zlobin "Scala in Goozy", Alexey Zlobin
"Scala in Goozy", Alexey Zlobin Vasil Remeniuk
 
Test driven development with behat and silex
Test driven development with behat and silexTest driven development with behat and silex
Test driven development with behat and silexDionyshs Tsoumas
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceMaarten Balliauw
 
Scala for Java Programmers
Scala for Java ProgrammersScala for Java Programmers
Scala for Java ProgrammersEric Pederson
 
Introduction to Client-Side Javascript
Introduction to Client-Side JavascriptIntroduction to Client-Side Javascript
Introduction to Client-Side JavascriptJulie Iskander
 
SystemVerilog OOP Ovm Features Summary
SystemVerilog OOP Ovm Features SummarySystemVerilog OOP Ovm Features Summary
SystemVerilog OOP Ovm Features SummaryAmal Khailtash
 
Lambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive CodeLambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive CodeIan Robertson
 
Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018
Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018 Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018
Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018 Codemotion
 

Ähnlich wie API first with Swagger and Scala by Slava Schmidt (20)

What's new in PHP 8.0?
What's new in PHP 8.0?What's new in PHP 8.0?
What's new in PHP 8.0?
 
Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"Nikita Popov "What’s new in PHP 8.0?"
Nikita Popov "What’s new in PHP 8.0?"
 
ppopoff
ppopoffppopoff
ppopoff
 
Getting to Grips with SilverStripe Testing
Getting to Grips with SilverStripe TestingGetting to Grips with SilverStripe Testing
Getting to Grips with SilverStripe Testing
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
 
Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2Zend Framework Study@Tokyo #2
Zend Framework Study@Tokyo #2
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
Structure on a freeform world
Structure on a freeform worldStructure on a freeform world
Structure on a freeform world
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Einführung in TypeScript
Einführung in TypeScriptEinführung in TypeScript
Einführung in TypeScript
 
Improving Correctness with Types
Improving Correctness with TypesImproving Correctness with Types
Improving Correctness with Types
 
"Scala in Goozy", Alexey Zlobin
"Scala in Goozy", Alexey Zlobin "Scala in Goozy", Alexey Zlobin
"Scala in Goozy", Alexey Zlobin
 
Test driven development with behat and silex
Test driven development with behat and silexTest driven development with behat and silex
Test driven development with behat and silex
 
behat
behatbehat
behat
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to Space
 
Scala for Java Programmers
Scala for Java ProgrammersScala for Java Programmers
Scala for Java Programmers
 
Introduction to Client-Side Javascript
Introduction to Client-Side JavascriptIntroduction to Client-Side Javascript
Introduction to Client-Side Javascript
 
SystemVerilog OOP Ovm Features Summary
SystemVerilog OOP Ovm Features SummarySystemVerilog OOP Ovm Features Summary
SystemVerilog OOP Ovm Features Summary
 
Lambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive CodeLambda Chops - Recipes for Simpler, More Expressive Code
Lambda Chops - Recipes for Simpler, More Expressive Code
 
Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018
Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018 Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018
Enrique Amodeo | Graphql + Microservices = Win! | Codemotion Madrid 2018
 

Mehr von JavaDayUA

STEMing Kids: One workshop at a time
STEMing Kids: One workshop at a timeSTEMing Kids: One workshop at a time
STEMing Kids: One workshop at a timeJavaDayUA
 
Flavors of Concurrency in Java
Flavors of Concurrency in JavaFlavors of Concurrency in Java
Flavors of Concurrency in JavaJavaDayUA
 
What to expect from Java 9
What to expect from Java 9What to expect from Java 9
What to expect from Java 9JavaDayUA
 
Continuously building, releasing and deploying software: The Revenge of the M...
Continuously building, releasing and deploying software: The Revenge of the M...Continuously building, releasing and deploying software: The Revenge of the M...
Continuously building, releasing and deploying software: The Revenge of the M...JavaDayUA
 
The Epic Groovy Puzzlers S02: The Revenge of the Parentheses
The Epic Groovy Puzzlers S02: The Revenge of the ParenthesesThe Epic Groovy Puzzlers S02: The Revenge of the Parentheses
The Epic Groovy Puzzlers S02: The Revenge of the ParenthesesJavaDayUA
 
20 Years of Java
20 Years of Java20 Years of Java
20 Years of JavaJavaDayUA
 
How to get the most out of code reviews
How to get the most out of code reviewsHow to get the most out of code reviews
How to get the most out of code reviewsJavaDayUA
 
Unlocking the Magic of Monads with Java 8
Unlocking the Magic of Monads with Java 8Unlocking the Magic of Monads with Java 8
Unlocking the Magic of Monads with Java 8JavaDayUA
 
Virtual Private Cloud with container technologies for DevOps
Virtual Private Cloud with container technologies for DevOpsVirtual Private Cloud with container technologies for DevOps
Virtual Private Cloud with container technologies for DevOpsJavaDayUA
 
JShell: An Interactive Shell for the Java Platform
JShell: An Interactive Shell for the Java PlatformJShell: An Interactive Shell for the Java Platform
JShell: An Interactive Shell for the Java PlatformJavaDayUA
 
Interactive Java Support to your tool -- The JShell API and Architecture
Interactive Java Support to your tool -- The JShell API and ArchitectureInteractive Java Support to your tool -- The JShell API and Architecture
Interactive Java Support to your tool -- The JShell API and ArchitectureJavaDayUA
 
MapDB - taking Java collections to the next level
MapDB - taking Java collections to the next levelMapDB - taking Java collections to the next level
MapDB - taking Java collections to the next levelJavaDayUA
 
Save Java memory
Save Java memorySave Java memory
Save Java memoryJavaDayUA
 
Design rationales in the JRockit JVM
Design rationales in the JRockit JVMDesign rationales in the JRockit JVM
Design rationales in the JRockit JVMJavaDayUA
 
Next-gen DevOps engineering with Docker and Kubernetes by Antons Kranga
Next-gen DevOps engineering with Docker and Kubernetes by Antons KrangaNext-gen DevOps engineering with Docker and Kubernetes by Antons Kranga
Next-gen DevOps engineering with Docker and Kubernetes by Antons KrangaJavaDayUA
 
Apache Cassandra. Inception - all you need to know by Mikhail Dubkov
Apache Cassandra. Inception - all you need to know by Mikhail DubkovApache Cassandra. Inception - all you need to know by Mikhail Dubkov
Apache Cassandra. Inception - all you need to know by Mikhail DubkovJavaDayUA
 
Solution Architecture tips & tricks by Roman Shramkov
Solution Architecture tips & tricks by Roman ShramkovSolution Architecture tips & tricks by Roman Shramkov
Solution Architecture tips & tricks by Roman ShramkovJavaDayUA
 
Testing in Legacy: from Rags to Riches by Taras Slipets
Testing in Legacy: from Rags to Riches by Taras SlipetsTesting in Legacy: from Rags to Riches by Taras Slipets
Testing in Legacy: from Rags to Riches by Taras SlipetsJavaDayUA
 
Reactive programming and Hystrix fault tolerance by Max Myslyvtsev
Reactive programming and Hystrix fault tolerance by Max MyslyvtsevReactive programming and Hystrix fault tolerance by Max Myslyvtsev
Reactive programming and Hystrix fault tolerance by Max MyslyvtsevJavaDayUA
 
Spark-driven audience counting by Boris Trofimov
Spark-driven audience counting by Boris TrofimovSpark-driven audience counting by Boris Trofimov
Spark-driven audience counting by Boris TrofimovJavaDayUA
 

Mehr von JavaDayUA (20)

STEMing Kids: One workshop at a time
STEMing Kids: One workshop at a timeSTEMing Kids: One workshop at a time
STEMing Kids: One workshop at a time
 
Flavors of Concurrency in Java
Flavors of Concurrency in JavaFlavors of Concurrency in Java
Flavors of Concurrency in Java
 
What to expect from Java 9
What to expect from Java 9What to expect from Java 9
What to expect from Java 9
 
Continuously building, releasing and deploying software: The Revenge of the M...
Continuously building, releasing and deploying software: The Revenge of the M...Continuously building, releasing and deploying software: The Revenge of the M...
Continuously building, releasing and deploying software: The Revenge of the M...
 
The Epic Groovy Puzzlers S02: The Revenge of the Parentheses
The Epic Groovy Puzzlers S02: The Revenge of the ParenthesesThe Epic Groovy Puzzlers S02: The Revenge of the Parentheses
The Epic Groovy Puzzlers S02: The Revenge of the Parentheses
 
20 Years of Java
20 Years of Java20 Years of Java
20 Years of Java
 
How to get the most out of code reviews
How to get the most out of code reviewsHow to get the most out of code reviews
How to get the most out of code reviews
 
Unlocking the Magic of Monads with Java 8
Unlocking the Magic of Monads with Java 8Unlocking the Magic of Monads with Java 8
Unlocking the Magic of Monads with Java 8
 
Virtual Private Cloud with container technologies for DevOps
Virtual Private Cloud with container technologies for DevOpsVirtual Private Cloud with container technologies for DevOps
Virtual Private Cloud with container technologies for DevOps
 
JShell: An Interactive Shell for the Java Platform
JShell: An Interactive Shell for the Java PlatformJShell: An Interactive Shell for the Java Platform
JShell: An Interactive Shell for the Java Platform
 
Interactive Java Support to your tool -- The JShell API and Architecture
Interactive Java Support to your tool -- The JShell API and ArchitectureInteractive Java Support to your tool -- The JShell API and Architecture
Interactive Java Support to your tool -- The JShell API and Architecture
 
MapDB - taking Java collections to the next level
MapDB - taking Java collections to the next levelMapDB - taking Java collections to the next level
MapDB - taking Java collections to the next level
 
Save Java memory
Save Java memorySave Java memory
Save Java memory
 
Design rationales in the JRockit JVM
Design rationales in the JRockit JVMDesign rationales in the JRockit JVM
Design rationales in the JRockit JVM
 
Next-gen DevOps engineering with Docker and Kubernetes by Antons Kranga
Next-gen DevOps engineering with Docker and Kubernetes by Antons KrangaNext-gen DevOps engineering with Docker and Kubernetes by Antons Kranga
Next-gen DevOps engineering with Docker and Kubernetes by Antons Kranga
 
Apache Cassandra. Inception - all you need to know by Mikhail Dubkov
Apache Cassandra. Inception - all you need to know by Mikhail DubkovApache Cassandra. Inception - all you need to know by Mikhail Dubkov
Apache Cassandra. Inception - all you need to know by Mikhail Dubkov
 
Solution Architecture tips & tricks by Roman Shramkov
Solution Architecture tips & tricks by Roman ShramkovSolution Architecture tips & tricks by Roman Shramkov
Solution Architecture tips & tricks by Roman Shramkov
 
Testing in Legacy: from Rags to Riches by Taras Slipets
Testing in Legacy: from Rags to Riches by Taras SlipetsTesting in Legacy: from Rags to Riches by Taras Slipets
Testing in Legacy: from Rags to Riches by Taras Slipets
 
Reactive programming and Hystrix fault tolerance by Max Myslyvtsev
Reactive programming and Hystrix fault tolerance by Max MyslyvtsevReactive programming and Hystrix fault tolerance by Max Myslyvtsev
Reactive programming and Hystrix fault tolerance by Max Myslyvtsev
 
Spark-driven audience counting by Boris Trofimov
Spark-driven audience counting by Boris TrofimovSpark-driven audience counting by Boris Trofimov
Spark-driven audience counting by Boris Trofimov
 

Kürzlich hochgeladen

From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfEnterprise Knowledge
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 

Kürzlich hochgeladen (20)

From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 

API first with Swagger and Scala by Slava Schmidt

  • 1. API First with Play and Swagger
  • 8.
  • 9. •Autonomy •Small in size •Full responsibility •One or more components
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 22. API First Document and peer review API before writing a single line of code Ideally, generate either your server interfaces or your test data (or both) from the spec
  • 23.
  • 26. What is REST’s central distinguishing feature? … its emphasis on a uniform interface between components Roy Thomas Fielding remaining the same in all cases and at all times British Dictionary uniform
  • 27. How do we combine “same” and “changing” ?
  • 28. ???
  • 29. REST • Client-Server • Stateless • Cacheable • Layered System • Uniform Interface • Identification of resources • Manipulation of resources through these representations • Self-descriptive messages • Hypermedia as the engine of application state implementation details Server Client/Server Protocol
  • 31. Hexagonal Architecture The 1968/69 NATO Software Engineering Conference
  • 32. aka Ports and Adapters Chris Fidao https://www.youtube.com/watch?v=6SBjKOwVq0o
  • 36.
  • 38. DRY
  • 39. DRY Most people take DRY to mean you shouldn't duplicate code. That's not its intention. The idea behind DRY is far grander than that. DRY says that every piece of system knowledge should have one authoritative, unambiguous representation. Dave Thomas
  • 41. • Easy to use • Human readable • Widest adoption • Open Source • Scala and Java • Dynamic recompilation / Hot reload • Asynchronous IO • Easy to use
  • 42. • URI path definitions (supports parameterisation and templating) • URI parameter definitions • Response definitions • Scheme definitions • MIME type definitions • Primitive datatypes • Complex datatypes • Structural constraints • Value constraints • Security constraints • Tags • Vendor extensions
  • 43.
  • 46. DEMO
  • 50. Metadata swagger: "2.0"
 info:
 version: 1.0.0
 title: Swagger Petstore
 description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
 termsOfService: http://swagger.io/terms/
 contact:
 name: Swagger API Team
 email: foo@example.com
 url: http://madskristensen.net
 license:
 name: MIT
 url: http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT
 host: petstore.swagger.io
 basePath: /api
 schemes:
 - http
 consumes:
 - application/json
 produces:
 - application/json URL Prefix
  • 51. Definitions definitions:
 Pet:
 allOf:
 - $ref: '#/definitions/NewPet'
 - required:
 - id
 properties:
 id:
 type: integer
 format: int64
 NewPet:
 required:
 - name 
 properties:
 name:
 type: string
 tag:
 type: string 
 Error:
 required:
 - code
 - message
 properties:
 code:
 type: integer
 format: int32
 message:
 type: string object definitions {
 trait NewPetDef {
 def name: String
 def tag: Option[String]
 }
 case class Pet(
 id: Option[Long],
 name: String,
 tag: Option[String]
 ) extends NewPetDef
 case class NewPet(
 name: String,
 tag: Option[String]
 ) extends NewPetDef
 case class Error(
 code: Int,
 message: String
 )
 }
  • 52. Test data definitions:
 Pet:
 allOf:
 - $ref: '#/definitions/NewPet'
 - required:
 - id
 properties:
 id:
 type: integer
 format: int64
 NewPet:
 required:
 - name 
 properties:
 name:
 type: string
 tag:
 type: string 
 Error:
 required:
 - code
 - message
 properties:
 code:
 type: integer
 format: int32
 message:
 type: string object generatorDefinitions {
 
 def createPet = _generate(PetGenerator)
 def createNewPet = _generate(NewPetGenerator)
 def createError = _generate(ErrorGenerator)
 // test data generator for /definitions/Pet
 val PetGenerator =
 for {
 id <- Gen.option(arbitrary[Long])
 name <- arbitrary[String]
 tag <- Gen.option(arbitrary[String])
 } yield Pet(id, name, tag)
 // test data generator for /definitions/NewPet
 val NewPetGenerator =
 for {
 name <- arbitrary[String]
 tag <- Gen.option(arbitrary[String])
 } yield NewPet(name, tag)
 // test data generator for /definitions/Error
 val ErrorGenerator =
 for {
 code <- arbitrary[Int]
 message <- arbitrary[String]
 } yield Error(code, message)
 def _generate[T](gen: Gen[T]) = (count: Int) => for (i <- 1 to count) yield gen.sample
 }
  • 53. Validations'#/definitions/NewPet'
 red:
 rties:
 ype: integer
 ormat: int64
 
 s:
 string
 string 
 ge
 s:
 integer
 t: int32
 :
 string class PetValidation(instance: Pet) {
 import de.zalando.play.controllers.PlayValidations._
 val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]
 val result = {
 val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)
 if (errors.nonEmpty) Left(errors) else Right(instance)
 }
 }
 
 
 class NewPetValidation(instance: NewPet) {
 import de.zalando.play.controllers.PlayValidations._
 val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]
 val result = {
 val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)
 if (errors.nonEmpty) Left(errors) else Right(instance)
 }
 }
 
 
 class ErrorValidation(instance: Error) {
 import de.zalando.play.controllers.PlayValidations._
 val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]
 val result = {
 val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)
 if (errors.nonEmpty) Left(errors) else Right(instance)
 }
 }
  • 54. Validations /pets/{id}:
 get:
 description: Returns a user based on a single ID, if the user does not have access to the pet
 operationId: find pet by id
 parameters:
 - name: id
 in: path
 description: ID of pet to fetch
 required: true
 type: integer
 format: int64
 responses:
 200:
 description: pet response
 schema:
 $ref: '#/definitions/Pet'
 default:
 description: unexpected error
 schema:
 $ref: '#/definitions/Error' class ValidationForPetexpandedYamlfindPetById(in: (Long)) {
 val (id) = in
 
 val idConstraints = new ValidationBase[Long] {
 override def constraints: Seq[Constraint[Long]] = Seq()
 }
 
 val normalValidations = Seq(idConstraints.applyConstraints(id))
 
 val containerValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]
 
 val rightResult = Right((id))
 
 val allValidations = normalValidations ++ containerValidations
 
 val result = {
 val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)
 if (errors.nonEmpty) Left(errors) else rightResult
 }
 }
  • 55. Tests "discard invalid data" in new WithApplication {
 val genInputs =
 for {
 id <- arbitrary[Long]
 } yield (id)
 val inputs = genInputs suchThat { i => new ValidationForPetexpandedYamlfindPetById(i).result != Right(i) }
 val props = forAll(inputs) { i => testInvalidInput(i) }
 checkResult(props)
 }
  • 56. Tests def testInvalidInput(in: (Long)) = {
 val (id) = in
 val url = s"""/api/pets/${id}"""
 val path = route(FakeRequest(GET, url)).get
 val validation = new ValidationForPetexpandedYamlfindPetById(id).result
 lazy val validations = validation.left.get flatMap {
 _.messages map { m => contentAsString(path).contains(m) ?= true }
 }
 ("given an URL: [" + url + "]") |: all(
 status(path) ?= BAD_REQUEST,
 contentType(path) ?= Some("application/json"),
 validation.isLeft ?= true,
 all(validations:_*)
 )
 }
  • 57. Controllers private val findPetByIdResponseMimeType = "application/json"
 private val findPetByIdActionSuccessStatus = Status(200)
 
 private type findPetByIdActionRequestType = (Long)
 private type findPetByIdActionResultType = Pet
 private type findPetByIdActionType = findPetByIdActionRequestType => Either[Throwable, findPetByIdActionResultType]
 
 private def errorToStatusfindPetById: PartialFunction[Throwable, Status] = PartialFunction.empty[Throwable, Status]
 
 def findPetByIdAction = (f: findPetByIdActionType) => (id: Long) => Action {
 val result = new ValidationForPetexpandedYamlfindPetById(id).result.right.map {
 processValidfindPetByIdRequest(f)
 }
 implicit val marshaller = parsingErrors2Writable(findPetByIdResponseMimeType)
 val response = result.left.map { BadRequest(_) }
 response.fold(a => a, c => c)
 }
 
 private def processValidfindPetByIdRequest(f: findPetByIdActionType)(request: findPetByIdActionRequestType) = {
 val callerResult = f(request)
 val status = callerResult match {
 case Left(error) => (errorToStatusfindPetById orElse defaultErrorMapping)(error)
 case Right(result) => findPetByIdActionSuccessStatus
 }
 implicit val findPetByIdWritableJson = anyToWritable[findPetByIdActionResultType](findPetByIdResponseMimeType)
 status(callerResult)
 }
  • 58. Skeletons class PetexpandedYaml extends PetexpandedYamlBase {
 
 // handler for GET /pets
 def findPets = findPetsAction { in : (Option[Seq[String]], Option[Int]) =>
 val (tags, limit) = in
 ???
 }
 
 // handler for POST /pets
 def addPet = addPetAction { in : (NewPet) =>
 val (pet) = in
 ???
 }
 
 // handler for GET /pets/{id}
 def findPetById = findPetByIdAction { in : (Long) =>
 val (id) = in
 ???
 }
 
 // handler for DELETE /pets/{id}
 def deletePet = deletePetAction { in : (Long) =>
 val (id) = in
 ???
 }
 }