Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Let me write your Networking Code

Let me write your Networking Code

Let me write your networking code
=====

When writing networking code, you want to make sure the code between the client and server implementation is consistent. After spending hours defining the APIs with your backend engineers, you’ll probably need to spend even more time implementing those details over to your code (and guess what… your backend engineers will be doing the same!). This process is boring, time consuming, and prone to errors.

Wouldn’t it be cool if this process were automated? If you could have classes and interfaces that mirror your API definition? And if they were automatically tested and ready to use out of the box?

It can be done! At Yelp, we define our APIs using Swagger Specs and we successfully automated the generation of our networking code for both servers and clients (iOS & Android). On Android, we generate Kotlin Data Classes and Retrofit APIs that mirror our spec files and are ready to use for all engineers. In this talk, we will explore how we set up our code generation pipeline and how you can start doing it, too.

Nicola Corti

April 02, 2019
Tweet

More Decks by Nicola Corti

Other Decks in Technology

Transcript

  1. LET ME WRITE YOUR NETWORKING CODE Nicola Corti Android Infra

    Engineer @cortinico Community Lover
 (GDG Pisa - Kotlin Hamburg) ! ✈
  2. Open API The Specification Swagger The Tooling Define the API

    in a JSON/YAML files Build infrastructure around them SWAGGER Swagger & Open API
  3. !!--- swagger: '2.0' info: description: 'This is a sample server

    Petstore server' version: 1.0.0 title: Swagger Petstore
  4. !!--- swagger: '2.0' info: description: 'This is a sample server

    Petstore server' version: 1.0.0 title: Swagger Petstore contact: email: [email protected]
  5. !!--- swagger: '2.0' info: description: 'This is a sample server

    Petstore server' version: 1.0.0 title: Swagger Petstore contact: email: [email protected] license: name: Apache 2.0 url: http:!//!!www.apache.org/licenses/LICENSE-2.0.html
  6. !!--- swagger: '2.0' info: description: 'This is a sample server

    Petstore server' version: 1.0.0 title: Swagger Petstore contact: email: [email protected] license: name: Apache 2.0 url: http:!//!!www.apache.org/licenses/LICENSE-2.0.html host: petstore.swagger.io
  7. !!--- swagger: '2.0' info: description: 'This is a sample server

    Petstore server' version: 1.0.0 title: Swagger Petstore contact: email: [email protected] license: name: Apache 2.0 url: http:!//!!www.apache.org/licenses/LICENSE-2.0.html host: petstore.swagger.io basePath: "/v2"
  8. !!--- swagger: '2.0' info: description: 'This is a sample server

    Petstore server' version: 1.0.0 title: Swagger Petstore contact: email: [email protected] license: name: Apache 2.0 url: http:!//!!www.apache.org/licenses/LICENSE-2.0.html host: petstore.swagger.io basePath: "/v2" schemes: - https - http
  9. basePath: “/v2" schemes: - https - http definitions: Pet: type:

    object properties: id: type: integer format: int64

  10. basePath: “/v2" schemes: - https - http definitions: Pet: type:

    object properties: id: type: integer format: int64 name: type: string
  11. basePath: “/v2" schemes: - https - http definitions: Pet: type:

    object properties: id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string
  12. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string 

  13. properties: id: type: integer format: int64 name: type: string photoUrls:

    type: array items: type: string status: type: string 

  14. properties: id: type: integer format: int64 name: type: string photoUrls:

    type: array items: type: string status: type: string description: pet status in the store 

  15. properties: id: type: integer format: int64 name: type: string photoUrls:

    type: array items: type: string status: type: string description: pet status in the store enum: - available - sold 

  16. properties: id: type: integer format: int64 name: type: string photoUrls:

    type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: 

  17. properties: id: type: integer format: int64 name: type: string photoUrls:

    type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category"
  18. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" 

  19. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" 
 Category:
  20. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" 
 Category: type: object
  21. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" 
 Category: type: object properties: id: type: integer format: int64
  22. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" 
 Category: type: object properties: id: type: integer format: int64 name: type: string
  23. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json
  24. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters:
  25. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId
  26. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path
  27. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return
  28. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true
  29. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer
  30. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64
  31. - name: petId in: path description: ID of pet to

    return required: true type: integer format: int64
  32. - name: petId in: path description: ID of pet to

    return required: true type: integer format: int64 responses:
  33. - name: petId in: path description: ID of pet to

    return required: true type: integer format: int64 responses: '200':
  34. - name: petId in: path description: ID of pet to

    return required: true type: integer format: int64 responses: '200': description: successful operation
  35. - name: petId in: path description: ID of pet to

    return required: true type: integer format: int64 responses: '200': description: successful operation '404':
  36. - name: petId in: path description: ID of pet to

    return required: true type: integer format: int64 responses: '200': description: successful operation '404': description: Pet not found
  37. - name: petId in: path description: ID of pet to

    return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "" '404': description: Pet not found
  38. - name: petId in: path description: ID of pet to

    return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found
  39. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found
  40. public Pet getPet(final String id) { String https_url = "https:!//petstore.swagger.io/v2/pet/"

    + id; URL url; try { url = new URL(https_url); HttpsURLConnection con = (HttpsURLConnection) url.openConnection(); if (con !!= null) { BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream())); String response = ""; String input; while ((input = br.readLine()) !!= null) { System.out.println(input); response += input; } br.close(); JSONObject object = new JSONObject(response); Pet result = new Pet(); result.setId(object.getInt("id")); result.setName(object.getString("name")); result.setStatus(object.getString("status")); JSONArray photos = object.getJSONArray("photoUrls"); List<String> photoArrays = new ArrayList!<>(); for (int i = 0; i < photos.length(); i!++) { photoArrays.add(photos.getString(i)); } result.setPhotoUrls(photoArrays); JSONArray tags = object.getJSONArray("tags"); List<String> tagArrays = new ArrayList!<>(); for (int i = 0; i < tags.length(); i!++) { tagArrays.add(tags.getString(i)); } result.setTags(tagArrays); System.out.println(result); System.out.println(result.getId()); System.out.println(result.getName()); System.out.println(result.getPhotoUrls().get(0)); System.out.println(result.getStatus()); System.out.println(result.getTags().get(0)); return result; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JSONException e) { e.printStackTrace(); } return null; } public class Pet { private Integer id; private String name; private List<String> photoUrls = null; private List<String> tags = null; private String status; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getPhotoUrls() { return photoUrls; } public void setPhotoUrls(List<String> photoUrls) { this.photoUrls = photoUrls; } public List<String> getTags() { return tags; } public void setTags(List<String> tags) { this.tags = tags; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } } fun getPet(id: String): Pet? { val https_url = "https:!//petstore.swagger.io/v2/pet/$id" val url: URL try { url = URL(https_url) val con = url.openConnection() as HttpsURLConnection val br = BufferedReader(InputStreamReader(con.inputStream)) var response = "" var input: String? = br.readLine() while (input !!= null) { println(input) response += input input = br.readLine() } br.close() val parsedObject = JSONObject(response) val photos = parsedObject.getJSONArray("photoUrls") val photoArrays = ArrayList<String>() for (i in 0 until photos.length()) { photoArrays.add(photos.getString(i)) } val tags = parsedObject.getJSONArray("tags") val tagArrays = ArrayList<String>() for (i in 0 until tags.length()) { tagArrays.add(tags.getString(i)) } val result = Pet( id = parsedObject.getInt("id"), name = parsedObject.getString("name"), status = parsedObject.getString("status"), photoUrls = photoArrays, tags = tagArrays ) println(result) println(result.id) println(result.name) println(result.photoUrls!!![0]) println(result.status) println(result.tags!!![0]) return result } catch (e: MalformedURLException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() } catch (e: JSONException) { e.printStackTrace() } return null } data class Pet( var id: Int?, var name: String?, var photoUrls: List<String>?, var tags: List<String>?, var status: String? ) data class Tag(var id: Int?, var name: String?) fun getPet(id: String): Pet? { val https_url = "https:!//petstore.swagger.io/v2/pet/$id" val url: URL try { url = URL(https_url) val con = url.openConnection() as HttpsURLConnection val br = BufferedReader(InputStreamReader(con.inputStream)) var response = "" var input: String? = br.readLine() while (input !!= null) { println(input) response += input input = br.readLine() } br.close() val moshi = Moshi.Builder().build() val jsonAdapter = moshi.adapter<Pet>(Pet!::class.java) val pet = jsonAdapter.fromJson(response) println(pet) return pet } catch (e: MalformedURLException) { e.printStackTrace() } catch (e: IOException) { e.printStackTrace() } return null } data class Pet( var id: Int?, var name: String?, var photoUrls: List<String>?, var tags: List<Tag>?, var status: String? ) data class Tag(var id: Int?, var name: String?) fun getPet(id: String): Pet? { val client = OkHttpClient.Builder().build() val request = Request.Builder().url("https:!//petstore.swagger.io/v2/pet/$id").build() client.newCall(request).execute().use { val moshi = Moshi.Builder().build() val jsonAdapter = moshi.adapter<Pet>(Pet!::class.java) val pet = jsonAdapter.fromJson(it.body()!?.string()!!!) println(pet) return pet } } data class Pet( var id: Int?, var name: String?, var photoUrls: List<String>?, var tags: List<Tag>?, var status: String? ) data class Tag(var id: Int?, var name: String?)
  41. r.io/v2/pet/$id" tpsURLConnection eader(con.inputStream)) (Pet!::class.java) nse) g?) fun getPet(id: String): Pet?

    { val client = OkHttpClient.Builder().build() val request = Request.Builder().url("https:!//petstore.swagger.io/v2/pet/$id").build() client.newCall(request).execute().use { val moshi = Moshi.Builder().build() val jsonAdapter = moshi.adapter<Pet>(Pet!::class.java) val pet = jsonAdapter.fromJson(it.body()!?.string()!!!) println(pet) return pet } } data class Pet( var id: Int?, var name: String?, var photoUrls: List<String>?, var tags: List<Tag>?, var status: String? ) data class Tag(var id: Int?, var name: String?)
  42. r.io/v2/pet/$id" tpsURLConnection eader(con.inputStream)) (Pet!::class.java) nse) g?) fun getPet(id: String): Pet?

    { val client = OkHttpClient.Builder().build() val request = Request.Builder().url("https:!//petstore.swagger.io/v2/pet/$id").build() client.newCall(request).execute().use { val moshi = Moshi.Builder().build() val jsonAdapter = moshi.adapter<Pet>(Pet!::class.java) val pet = jsonAdapter.fromJson(it.body()!?.string()!!!) println(pet) return pet } } data class Pet( var id: Int?, var name: String?, var photoUrls: List<String>?, var tags: List<Tag>?, var status: String? ) data class Tag(var id: Int?, var name: String?) interface PetInterface { @GET("pet/{id}") fun getPet(@Path("id") id: String?) : Call<Pet> } .getPet(“42")
  43. On Github: swagger-api/swagger-codegen Generator & Templates Several templates already available

    Command line tool SWAGGER CODEGEN Swagger Codegen java -jar swagger-codegen-cli-2.3.1.jar generate \ -i swagger.yaml \ --api-package com.yelp.codegen.sample.api \ --model-package com.yelp.codegen.sample.model \ --group-id com.yelp.codegen.sample \ --artifact-id sample-codegen \ --artifact-version 0.0.1 \ -l spring \ -o sample-codegen
  44. {{#model}}{{#description}} /** * {{description}} **/{{/description}} @ApiModel(description = "{{{description}}}") public class

    {{classname}} {{#parent}}extends {{{parent}}}{{/parent}} { {{#vars}}{{#isEnum}} public enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} {{•}}, {{/values}}{{/allowableValues}} }; @SerializedName("{{baseName}}") private {{{datatypeWithEnum}}} {{name}} = {{{defaultValue}}};{{/isEnum}}{{^isEnum}} @SerializedName("{{baseName}}") private {{{datatype}}} {{name}} = {{{defaultValue}}};{{/isEnum}}{{/vars}} {{#vars}} /**{{#description}} * {{{description}}}{{/description}}{{#minimum}} * minimum: {{minimum}}{{/minimum}}{{#maximum}} * maximum: {{maximum}}{{/maximum}} **/ @ApiModelProperty({{#required}}required = {{required}}, {{/required}}value = "{{{description}}}") public {{{datatypeWithEnum}}} {{getter}}() { return {{name}}; } public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { this.{{name}} = {{name}}; }
  45. {{#model}}{{#description}} /** * {{description}} **/{{/description}} @ApiModel(description = "{{{description}}}") public class

    {{classname}} {{#parent}}extends {{{p {{#vars}}{{#isEnum}} public enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} {{•}}, {{/valu }; @SerializedName("{{baseName}}") private {{{datatypeWithEnum}}} {{name}} = {{{def
  46. {{#model}}{{#description}} /** * {{description}} **/{{/description}} @ApiModel(description = "{{{description}}}") public class

    {{classname}} {{#parent}}extends {{{p {{#vars}}{{#isEnum}} public enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} {{•}}, {{/valu }; @SerializedName("{{baseName}}") private {{{datatypeWithEnum}}} {{name}} = {{{def
  47. Plug it inside your gradle build Input/Output aware Simpler API

    for the developer SWAGGER GRADLE CODEGEN Yelp/swagger-gradle-codegen A Gradle Plugin
  48. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string description: pet status in the store enum: - available - sold category: $ref: “#/definitions/Category" 
 Category: type: object properties: id: type: integer format: int64 name: type: string
  49. Category: type: object properties: id: type: integer format: int64 name:

    type: string data class Category( var id, var name )
  50. Category: type: object properties: id: type: integer format: int64 name:

    type: string data class Category( var id: Long, var name: String )
  51. Category: type: object properties: id: type: integer format: int64 name:

    type: string data class Category( var id: Long?, var name: String? )
  52. Category: type: object properties: id: type: integer format: int64 name:

    type: string data class Category( var id: Long? = null, var name: String? = null )
  53. Category: type: object properties: id: type: integer format: int64 name:

    type: string data class Category( @Json(name = "id") var id: Long? = null, @Json(name = "name") var name: String? = null )
  54. Category: type: object properties: id: type: integer format: int64 name:

    type: string import com.squareup.moshi.Json data class Category( @Json(name = "id") var id: Long? = null, @Json(name = "name") var name: String? = null )
  55. Category: type: object description: properties: id: type: integer description: format:

    int64 name: type: string description: import com.squareup.moshi.Json data class Category( @Json(name = "id") var id: Long? = null, @Json(name = "name") var name: String? = null )
  56. Category: type: object description: A Category used to group pets

    properties: id: type: integer description: Unique ID of the Category format: int64 name: type: string description: Name of this category import com.squareup.moshi.Json data class Category( @Json(name = "id") var id: Long? = null, @Json(name = "name") var name: String? = null )
  57. Category: type: object description: A Category used to group pets

    properties: id: type: integer description: Unique ID of the Category format: int64 name: type: string description: Name of this category import com.squareup.moshi.Json /** * A Category used to group pets * @property id Unique ID of the Category * @property name Name of this category */ data class Category( @Json(name = "id") var id: Long? = null, @Json(name = "name") var name: String? = null )
  58. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" 

  59. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" 
 package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } }
  60. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" 
 package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } }
  61. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" 
 package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } }
  62. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" 
 package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } }
  63. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" 
 package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } }
  64. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" 
 package com.yelp.codegen.samples.models import com.squareup.moshi.Json data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } }
  65. definitions: Pet: type: object required: - name - photoUrls properties:

    id: type: integer format: int64 name: type: string photoUrls: type: array items: type: string status: type: string enum: - available - sold category: $ref: “#/definitions/Category" 
 package com.yelp.codegen.samples.models import com.squareup.moshi.Json /** * Represents a specific Pet in the store * @property category Optional category of the pet * @property id Unique ID of this Pet * @property name Name of this specific pet * @property photoUrls Photo URLs for this Pet on the bucket * @property status Pet status in the store */ data class Pet ( @Json(name = "name") var name: String, @Json(name = "photoUrls") var photoUrls: List<String>, @Json(name = "category") var category: Category? = null, @Json(name = "id") var id: Long? = null, @Json(name = "status") var status: Pet.StatusEnum? = null ) { /** * Pet status in the store * Values: AVAILABLE, SOLD */ enum class StatusEnum(val value: String){ @Json(name = "available") AVAILABLE("available"), @Json(name = "sold") SOLD("sold") } }
  66. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found
  67. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { }
  68. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { fun getPetById() }
  69. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { fun getPetById( @retrofit2.http.Path("petId") petId: Long ) }
  70. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { @GET("/pet/{petId}") fun getPetById( @retrofit2.http.Path("petId") petId: Long ) }
  71. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { @GET("/pet/{petId}") fun getPetById( @retrofit2.http.Path("petId") petId: Long ): Single<Pet> }
  72. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { @Headers( "X-Operation-ID: getPetById" ) @GET("/pet/{petId}") fun getPetById( @retrofit2.http.Path("petId") petId: Long ): Single<Pet> }
  73. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found interface DefaultApi { /** * Find pet by ID * Returns a single pet * @param petId ID of pet to return (required) */ @Headers( "X-Operation-ID: getPetById" ) @GET("/pet/{petId}") fun getPetById( @retrofit2.http.Path("petId") petId: Long ): Single<Pet> }
  74. paths: /pet/{petId}: get: summary: Find pet by ID description: Returns

    a single pet operationId: getPetById produces: - application/json parameters: - name: petId in: path description: ID of pet to return required: true type: integer format: int64 responses: '200': description: successful operation schema: $ref: "#/definitions/Pet" '404': description: Pet not found package com.yelp.codegen.generatecodesamples.apis import com.yelp.codegen.generatecodesamples.models.Pet import io.reactivex.Single import retrofit2.http.GET import retrofit2.http.Headers interface DefaultApi { /** * Find pet by ID * Returns a single pet * @param petId ID of pet to return (required) */ @Headers( "X-Operation-ID: getPetById" ) @GET("/pet/{petId}") fun getPetById( @retrofit2.http.Path("petId") petId: Long ): Single<Pet> }
  75. Build an app module with specs locally Build a pure-Kotlin

    module with a specs locally Build a library project that contains your models/apis Integrate your library with your CI system SWAGGER GRADLE CODEGEN Yelp/swagger-gradle-codegen Use cases
  76. buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"

    } } generateSwagger { inputFile = file("../sample_specs.json") outputDir = file("./src/main/java/") }
  77. buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"

    } } generateSwagger { platform = "kotlin" packageName = "com.yelp.codegen.samples" specName = "petstore" specVersion = "1.0.0" inputFile = file("../sample_specs.json") outputDir = file("./src/main/java/") }
  78. buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"

    } } generateSwagger { platform = "kotlin" packageName = "com.yelp.codegen.samples" specName = "petstore" specVersion = "1.0.0" inputFile = file("../sample_specs.json") outputDir = file("./src/main/java/") }
  79. buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"

    } } generateSwagger { platform = "kotlin" packageName = "com.yelp.codegen.samples" specName = "petstore" specVersion = "1.0.0" inputFile = file("../sample_specs.json") outputDir = file("./src/main/java/") }
  80. buildscript { repositories { gradlePluginPortal() } dependencies { classpath "com.yelp.codegen:plugin:1.0.0"

    } } generateSwagger { platform = "kotlin" packageName = "com.yelp.codegen.samples" specName = "petstore" specVersion = "1.0.0" inputFile = file("../sample_specs.json") outputDir = file("./src/main/java/") } preBuild.dependsOn(tasks.getByName(“generateSwagger"))
  81. e pet of pet to return (required) ion-ID: getPetById") ")

    trofit2.http.Path("petId") petId: Long): Single<Pet> eup.moshi.Json "name") var name: String, "photoUrls") var photoUrls: List<String>, "category") var category: Category? = null, "id") var id: Long? = null, "status") var status: Pet.StatusEnum? = null tatusEnum(val value: String){ me = "available") AVAILABLE("available"), me = "sold") SOLD("sold")
  82. Breaking changes Defining names Accessing the Raw Response SWAGGER GRADLE

    CODEGEN Yelp/swagger-gradle-codegen Challenges interface DefaultApi { /** * Find the owner of a pet. !*/ @GET("/pet/owner") fun getPetById( @retrofit2.http.Path("name") name: String @retrofit2.http.Path("surname") surname: String ): Single<Owner> } interface DefaultApi { /** * Find the owner of a pet. !*/ @GET("/pet/owner") fun getPetById( @retrofit2.http.Path("surname") surname: String @retrofit2.http.Path("name") name: String ): Single<Owner> } data class IdToPredictedBizInfoForPhotoUploadSuggestionMapToBusinessReviewMap( !!... ) interface DefaultApi { /** * Find the owner of a pet. !*/ @GET("/pet/owner") fun getPetById( @retrofit2.http.Path("surname") surname: String @retrofit2.http.Path("name") name: String ): Single<Owner> } interface DefaultApi { /** * Find the owner of a pet. !*/ @GET("/pet/owner") fun getPetById( @retrofit2.http.Path("surname") surname: String @retrofit2.http.Path("name") name: String ): Single<Result<Owner!>> }