This section details how to provide and expose metadata about the REST API using Swagger.
We are often required to document APIs for users and customers. When documenting an API, depending on the tools we use, we often get a few extras such as the ability to generate client code from the API metadata or even the generation of integrated test harnesses for the API.
There isn't yet a recognized and universal standard for the format of the API metadata. This lack of standards leads to a quite a few different solutions on the market for the REST documentation.
We have chosen Swagger here because it has the largest and the most active community. It has existed since 2011, and it offers a very nice UI/test harness and great configuration by default.
This section details what can be done and also what we have done in the code base of the checked-out v4.x.x branch.
swagger-springmvc
project (version 0.9.5) to cloudstreetmarket-core and cloudstreetmarket-parent:<dependency> <groupId>com.mangofactory</groupId> <artifactId>swagger-springmvc</artifactId> <version>${swagger-springmvc.version}</version> </dependency>
configuration
class has been created:@Configuration @EnableSwagger //Loads the beans required by the framework public class SwaggerConfig { private SpringSwaggerConfig springSwaggerConfig; @Autowired public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) { this.springSwaggerConfig = springSwaggerConfig; } @Bean public SwaggerSpringMvcPlugin customImplementation(){ return new SwaggerSpringMvcPlugin( this.springSwaggerConfig) .includePatterns(".*") .apiInfo(new ApiInfo( "Cloudstreet Market / Swagger UI", "The Rest API developed with Spring MVC Cookbook [PACKT]", "", "[email protected]", "LGPL", "http://www.gnu.org/licenses/gpl-3.0.en.html" )); } }
dispatch-context.xml
:<bean class="com.mangofactory.swagger.configuration.SpringSwaggerConfig"/> <bean class="edu.zc.csm.api.swagger.SwaggerConfig"/> <context:property-placeholder location="classpath*:/META-INF/properties/swagger.properties" />
src/main/resources/META-INF/properties
with the content:documentation.services.version=1.0 documentation.services.basePath=http://localhost:8080/api
IndexController
:@Api(value = "indices", description = "Financial indices") @RestController @RequestMapping(value="/indices", produces={"application/xml", "application/json"}) public class IndexController extends CloudstreetApiWCI { @RequestMapping(method=GET) @ApiOperation(value = "Get overviews of indices", notes = "Return a page of index-overviews") public Page<IndexOverviewDTO> getIndices( @ApiIgnore @PageableDefault(size=10, page=0, sort={"dailyLatestValue"}, direction=Direction.DESC) Pageable pageable){ return marketService.getLastDayIndicesOverview(pageable); } @RequestMapping(value="/{market}", method=GET) @ApiOperation(value = "Get overviews of indices filtered by market", notes = "Return a page of index-overviews") public Page<IndexOverviewDTO> getIndicesPerMarket( @PathVariable MarketCode market, @ApiIgnore @PageableDefault(size=10, page=0, sort={"dailyLatestValue"}, direction=Direction.DESC) Pageable pageable){ return marketService.getLastDayIndicesOverview(market, pageable); } @RequestMapping(value="/{market}/{index}/histo", method=GET) @ApiOperation(value = "Get historical-data for one index", notes = "Return a set of historical-data from one index") public HistoProductDTO getHistoIndex( @PathVariable("market") MarketCode market, @ApiParam(value="Index code: ^OEX") @PathVariable("index") String indexCode,@ApiParam(value="Start date: 2014-01-01") @RequestParam(value="fd",defaultValue="") Date fromDate, @ApiParam(value="End date: 2020-12-12") @RequestParam(value="td",defaultValue="") Date toDate, @ApiParam(value="Period between snapshots") @RequestParam(value="i",defaultValue="MINUTE_30") QuotesInterval interval){ return marketService.getHistoIndex(indexCode, market, fromDate, toDate, interval); } }
dispatch-context.xml
again in order for the Spring MVC to open access to static files in the project:<!-- Serve static content--> <mvc:default-servlet-handler/>
http://localhost:8080/api/index.html
brings up the Swagger UI documentation portal:More than just a REST documentation repository, it is also a handy test harness:
Swagger has its own controller that publishes the metadata of our API. The Swagger UI targets this metadata, parses it, and represents it as a usable interface.
On the server side, with the com.mangofactory/swagger-springmvc
dependency added to the swagger-springmvc
project and with the presented SwaggerConfig
class, the library creates a controller on the root path: /api-docs
and publishes the entire metadata there for the REST API.
If you visit http://localhost:8080/api/api-docs
, you will reach the root of our REST API documentation:
This content is the exposed metadata that implements the Swagger specification. The metadata is a navigable structure. Links to other parts of the metadata can be found in the <path>
nodes of the XML content.
The Swagger UI is only made of static files (CSS, HTML, JavaScript, and so on). The JavaScript logic implements the Swagger specification and recursively parses the entire exposed metadata. It then dynamically builds the API documentation website and test harness that we have presented, digging out every single endpoint and its metadata.
In this section, we suggest you to look further into Swagger and its Spring MVC project implementation.
Visit the framework's website and its specification: http://swagger.io.
The swagger-springmvc project is changing as it is becoming part of a bigger project named SpringFox. SpringFox now also supports the second version of the Swagger specification. We recommend you to visit their current reference document:
http://springfox.github.io/springfox/docs/current
They also provide a migration guide to move from the swagger specification 1.2 (that we have implemented here) to the swagger specification 2.0:
https://github.com/springfox/springfox/blob/master/docs/transitioning-to-v2.md
This section guides you toward alternative tools and specification to Swagger: