2. @johannes_fiala#Devoxx #Swagger
Enhance REST APIs
• Add API documentation (like WSDL schema)
• Describes the Service/request/response/models
• + add description for others to understand
• In a standardized way = according to Swagger Spec.
• Using a standardized structure, datatype names, references to
models, …
3. @johannes_fiala#Devoxx #Swagger
Enhance REST APIs
Benefits
• Makes the payload predictable
• Allows to use tools using the Swagger-standard
• Use Swagger-UI for exploring the API
• Generate client code with Swagger-Codegen
• Get Code completion for 20+ programming languages
• Ship SDKs in target languages
• Get correct datatypes in client code
• Get Enum support
• Get Compile-time checking of consistency
4. @johannes_fiala#Devoxx #Swagger
How to enhance REST APIs?
• Ask API provider to provide Swagger apidocs
• If using Spring: Springfox-libraries
• If not: see Swagger-Spring integrations
• If not possible:
• Create Swagger apidocs on your own
• Demo Today: Facebook Graph API
• Other REST-API‘s you‘d like to have enhanced?
• Google Maps API?
• ???
5. @johannes_fiala#Devoxx #Swagger
In the next few minutes you‘ll learn
…
• Introduction to Springfox/Swagger-Codegen
• Basic overview of Facebook Graph API
• Step-by-step Demo of using Swagger-Codegen to extract
Metadata & add them to the model
• Extract standard apidocs for Facebook
• Learn about using Swagger-Codegen
• Support of Bean Validation API: add
@NotNull/@Min/@Max by adding your own
BuilderPlugins
6. @johannes_fiala#Devoxx #Swagger
Technology stack
• Spring
• Spring Boot for fast start
• also possible: Spring REST/MVC
• Springfox
• For generating the api-docs
• Swagger UI
• For accessing the api using a browser
• Swagger Codegen commandline
• For generating client code stubs
10. @johannes_fiala#Devoxx #Swagger
Swagger Codegen
• io.swagger.codegen.DefaultGenerator.generate():
• Reads api-docs in json syntax
• Scans each model
• Scans all the model properties
• Then compiles language-specific Mustache templates using a
language-specific Configuration class
• Language specific configuration:
• io.swagger.codegen.languages.*
• Mustache files: src/main/resources
12. @johannes_fiala#Devoxx #Swagger
Facebook Graph API
• Basic docs:
https://developers.facebook.com/docs/graph-
api/overview
• Graph API Explorer:
https://developers.facebook.com/tools/explorer
• Nice for basic testing
• Retrieve your access token
13. @johannes_fiala#Devoxx #Swagger
Extract metadata from the Facebook
Graph API
• Facebook Graph API url:
https://graph.facebook.com/v2.5/microsoft?access_token
=... &fields=name,about,mission
• Get field metadata: add parameter „&metadata=1“
15. @johannes_fiala#Devoxx #Swagger
Extract metadata from the Facebook
Graph API
• Target: Provide Swagger apidocs for Facebook API
• Read metadata
• Add description to fields
• Map field types to standard datatypes
• Add Enumerations
• Swagger Codegen has the Model data available during
processing and can be extended
• Alternative: Json transformation from metadata to
Swagger api
17. @johannes_fiala#Devoxx #Swagger
Preparation work
• Modules of the swagger-springfox-demo:
• Swagger-codegen-2.1.3-facebook
• The customized Swagger-codegen code for Facbeook
• User-rest-service-2.2.2-facebook
• The Spring Boot REST-API application
• User-rest-service-2.2.2-facebook-client-java-codegen
• The generated client stubs
19. @johannes_fiala#Devoxx #Swagger
Define the server proxy
• ConnectorUserFacebookController:
• Uses basic FacebookUser-model (with 2 attributes)
• No need to recode representation class
• Connects to Facebook using Spring Rest
• Try it using Swagger-UI
22. @johannes_fiala#Devoxx #Swagger
Add metadata fields to Swagger-
Codegen
• Add fields listed in metadata
• Add field description
• Map FB field type to Swagger standard datatype
• Extract Enumerations out of description
• Add JSR-303 @NotNull, (@Min, @Max)
• + ???
• Add further Bean Validation Annotations (e.g. Size)?
• Further suggestions?
23. @johannes_fiala#Devoxx #Swagger
Add metadata fields to Swagger-
Codegen
• Important class: DefaultGenerator
• Line: Model model = definitions.get(name);
String access_token =„…";
String url = "https://graph.facebook.com/pivotalsoftware?access_token=" + access_token + "&metadata=1";
FacebookUser user = readJsonFromUrl(url);
for (FacebookField field : user.getMetadata().getFields()) {
propName = field.getName();
// add new virtual fields from Facebook to the model
virtualProperty = new StringProperty();
virtualProperty.setName(propName);
virtualProperty.setDescription(field.getDescription());
model.getProperties().put(propName, virtualProperty);
}
24. @johannes_fiala#Devoxx #Swagger
Add metadata fields to Swagger-
Codegen
• Map Facebook datatypes to Swagger datatypes
// Examples of data type mappings from Facebook-Datatypes to Swagger-Model-Datatypes
if ("bool".equals(field.getType())) {
virtualProperty = new BooleanProperty();
} else if ("unsigned int32".equals(field.getType())){
virtualProperty = new IntegerProperty();
} else {
virtualProperty = new StringProperty();
}
25. @johannes_fiala#Devoxx #Swagger
Add metadata fields to Swagger-
Codegen
• Extract Enum datatypes (e.g. attire)
• Description: "Dress code of the business. Applicable to Restaurants or Nightlife.
Can be one of Casual, Dressy or Unspecified“
StringProperty myStringProperty = (StringProperty)virtualProperty;
String myEnumValues = StringUtils.substringAfter(field.getDescription(), "Can be one of");
myEnumValues = StringUtils.replace(myEnumValues, " or ", ", ");
String[] enumValues = StringUtils.split(myEnumValues);
for (String myEnum : enumValues) {
myStringProperty._enum(myEnum );
}
27. @johannes_fiala#Devoxx #Swagger
View the generated code
• The FacebookUser now has all fields of the Graph API!
@ApiModel(description = "")
public class FacebookUser {
/**
* Information about the Page
**/
@ApiModelProperty(value = "Information about the Page")
@JsonProperty("about")
public String getAbout() {
return about;
}
…
31. @johannes_fiala#Devoxx #Swagger
Adding a custom language
• See JavaFacebookClientCodegen
• Defines template-directory is JavaFacebook
• Now we can modify the Model
• Add @NotNull
• Add @Min, @Max
33. @johannes_fiala#Devoxx #Swagger
Get Swagger apidocs
• Get Swagger apidocs
• Access FB through Proxy using Swagger-UI
• See model definitions in the browser
• Replace the model class „FacebookUser“
• Restart Spring Boot
• Inspect the updated model using the Swagger-UI
http://localhost:8080/swagger/index.html
35. @johannes_fiala#Devoxx #Swagger
Wrapup
• Learned:
• You are able to add fields dynamically to a model class during
client-code-generation, add datatype-mapping and enums
• You are able to access the Facebook Graph API directly
• You are able to add custom languages
• Benefits:
• You can generate client code for every language supported by
Swagger-Codegen
• You have code completion for all model attributes!
36. @johannes_fiala#Devoxx #Swagger
Possible improvements
• Structures (e.g. Location) are currently not part of the
Facebook metadata and need to be created manually as
representation classes
• Some fields are only accessible with specific
permissions, but that‘s also not visible in the metadata
• See Helper-class AssembleFieldsUtil for details
• JSR-303 support needs further improvement
• @Min/@Max, @Size, …
37. @johannes_fiala#Devoxx #Swagger
Support for Beans Validation API
(JSR 303)
• Not yet implemented
• See Issue for discussion:
https://github.com/springfox/springfox/issues/356
• Can be done using extensions (Plugin Builders)
38. @johannes_fiala#Devoxx #Swagger
Support for Beans Validation API
How to add it yourself:
• Using „Plugins“ you can override/add to the behaviour of
Builders for Parameters/the Model
• Add a component implementing the Plugin-Interface,
e.g. ModelPropertyBuilderPlugin
• You get access to the processing context
• You can query for annotations there
• Examples: @NotNull, @Min/@Max
39. @johannes_fiala#Devoxx #Swagger
Support for Beans Validation API
Further available plugins
• Available Plugins for Model/Parameters:
• ModelBuilderPlugin
• ModelPropertyBuilderPlugin
• ParameterBuilderPlugin
40. @johannes_fiala#Devoxx #Swagger
Fine-Tuning Spring Boot
• Spring Boot adds /error path automatically
• Get rid of it using
new Docket(…)…
.apis(Predicates.not(RequestHandlerSelectors.basePack
age("org.springframework.boot")))
41. @johannes_fiala#Devoxx #Swagger
Hot Deploy using Spring Loaded
• Allows hot deploy
• for adding new methods etc.
• Add JVM parameters:
• -javaagent:/path_to_spring-loaded/springloaded-
1.2.4.RELEASE.jar -noverify
• https://github.com/spring-projects/spring-loaded
• http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-hotswapping