Swagger

Swagger is a specification which allows you to quickly define the functionality of a REST API using JSON documents. But it’s more than
just a spec. It provides automatic generation of interactive API docs, client-side code generation in multiple languages, and server-side code generation
in Java and Scala.

It’s not easy to describe, but it is easy to understand once you see it. Take a look at the Swagger demo app now:

Our application can also take any incoming ?name=foo parameter off the query string, and make it available to this action as the variable name, then filter the FlowerData list for matching results. If you point your browser at
http://localhost:8080/flowers?name=rose,
you’ll see only the roses.

Swagger: a quick introduction

Making an API’s methods, parameters, and responses visible, in an engaging,
easy to understand way, can transform the process of building REST APIs.

Scalatra’s Swagger support allows you to auto-generate runnable documentation
for a REST API - the API’s name, what resources it offers, available methods
and their parameters, and return values.

Swagger spec files

Before we see the auto-generation of Swagger spec files, though, it makes sense
to understand what’s being generated.

If you want to, you can write a Swagger JSON file by hand. A Swagger API
description for our FlowersController might look like this:

{"swagger":"2.0","info":{"title":"The Flowershop API","version":"1","description":"Docs for the Flowers API","termsOfService":"http://scalatra.org","contact":{"name":"apiteam@scalatra.org"},"license":{"name":"MIT","url":"http://opensource.org/licenses/MIT"}},"paths":{"/flowers/":{"get":{"operationId":"getFlowers","summary":"Show all flowers","tags":["Flowers"],"deprecated":false,"parameters":[{"name":"name","description":"A name to search for","required":false,"in":"query","type":"string"}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/Flower"}}}}}},"/flowers/{slug}":{"get":{"operationId":"findBySlug","summary":"Find by a flower by its slug","tags":["Flowers"],"deprecated":false,"parameters":[{"name":"slug","description":"Slug of flower that needs to be fetched","required":true,"in":"path","type":"string"}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/Flower"}},"404":{"description":"Slug Not Found"}}}}},"definitions":{"Flower":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}},"required":["slug","name"]}},"securityDefinitions":{}}

This file describes what APIs we’re offering and details of each API such as the
paths of those APIs, required and optional parameters, and other information.

This JSON file can then be offered to a standard HTML/CSS/JavaScript client,
called the swagger-ui, to make it easy for people to browse the docs. If
you write them by hand, you can simply put them on any HTTP server, point the
swagger-ui client at them, and start viewing the runnable documentation.

Generating API clients

You also get the ability to generate client and server code in multiple
languages, using the swagger-codegen project.

You may want to take a moment to view the Swagger Pet Store example.
Click on the route definitions to see what operations are available for each
resource. You can use the web interface to send live test queries to the API,
and view the API’s response to each query.

Click on the “raw” link next to each API description, and you’ll see the
Swagger spec file for the API.

Scalatra’s Swagger integration

Scalatra’s Swagger integration allow you to annotate the code within your RESTful
API in order to automatically generate Swagger spec files. This means that once
you annotate your API methods, you get documentation and client code generation
for free.

Dependencies

First, add the Swagger dependency to your project/build.scala file, then restart your
app to grab the new jars:

"org.scalatra" %% "scalatra-swagger" % "2.6.4",

You’ll now need to import Scalatra’s Swagger support into your FlowersController:

// Swagger support
import org.scalatra.swagger._

Auto-generating the resources.json spec file

Any Scalatra application which uses Swagger support must implement a Swagger
controller. Those JSON specification files, which we’d otherwise need to write
by hand, need to be served by something, after all. Let’s add a standard Swagger
controller to our application. Drop this code into a new file next to your
FlowersController.scala. You can call it FlowersSwagger.scala:

This controller will automatically produce Swagger-compliant JSON specs for
every annotated API method in your application.

The rest of your application doesn’t know about it yet, though. In order to
get everything set up properly, you’ll need to change your ScalatraBootstrap
file so that the container knows about this new servlet. Currently it looks
like this:

Note that the context.mount(new FlowersController, "/flowers", "flowers") has a second
parameter: in Scalatra 2.3.x, Swagger requires a name parameter to be present so that it
can generate its documentation properly. The name should always be the same as the
controller's mount path, minus the leading "/".

Adding SwaggerSupport to the FlowersController

You’ll need to enable Swagger on your FlowersController.

Let’s add the SwaggerSupport trait to the FlowersController, and also make it
aware of Swagger in its constructor.

In order to make our application compile again, we’ll need to add a name and
description to our FlowersController. This allows Swagger to inform clients
what our API is called, and what it does. You can do this by adding the following
code to the body of the FlowersController class:

protected val applicationDescription = "The flowershop API. It exposes operations for browsing and searching lists of flowers, and retrieving single flowers."

That’s pretty much it for Swagger setup. Now we can start documenting our API’s methods.

Annotating API methods

Swagger annotations are quite simple. You decorate each of your routes with a bit of
information, and Scalatra generates the spec file for your route.

Make sure you initialize the val for your apiOperation before attempting to
use it in as part of a route definition! Otherwise you'll get a 503 error
when attempting to hit your route.

Let’s go through the annotations in detail.

The summary and notes should be human-readable messages that you intend to be read by developers of API clients. The summary is a short description, while the notes should offer a longer description and include any noteworthy features which somebody might otherwise miss.

The operationId is intended as a machine-readable key which can be used by client code to identify this API action - it’ll be used, for instance, by swagger-ui to generate JavaScript method names. You can call it whatever you want, but make sure you don’t include any spaces in it, or client code generation will probably fail - so “getFlowers” or “get_flowers” is fine, “get flowers” isn’t.

The responseClass is essentially a type annotation, so that clients know what data types to expect back. In this case, clients should expect a List of Flower objects.

The parameters details any parameters that may be passed into this route, and whether they’re supposed to be part of the path, post params, or query string parameters. In this case, we define an optional query string parameter called name, which matches what our action expects.

Lastly, the endpoint annotation defines any special parameter substitution or additional route information for this method. This particular route is pretty straightforward, so we can leave this blank.

The Swagger annotations here are mostly similar to those for the get("/") route. There are a few things to note.

The endpoint this time is defined as {slug}. The braces tell Swagger that it should substitute the contents of a path param called {slug} into any generated routes (see below for an example). Also note that this time, we’ve defined a ParamType.Path, so we’re passing the slug parameter as part of the path rather than as a query string. Since we haven’t set the slug parameter as required = false, as we did for the name parameter in our other route, Swagger will assume that slugs are required.

Now let’s see what we’ve gained.

Adding Swagger support to our application, and the Swagger annotations to our FlowersController, means we’ve got some new functionality available. Check the following URL in your browser:

You should see an auto-generated Swagger API document (in this case, there’s only one, but there could be multiple APIs defined by our application and they’d all be noted here):

{"swagger":"2.0","info":{"title":"The Flowershop API","version":"1","description":"Docs for the Flowers API","termsOfService":"http://scalatra.org","contact":{"name":"apiteam@scalatra.org"},"license":{"name":"MIT","url":"http://opensource.org/licenses/MIT"}},"paths":{"/flowers/":{"get":{"operationId":"getFlowers","summary":"Show all flowers","tags":["Flowers"],"deprecated":false,"parameters":[{"name":"name","description":"A name to search for","required":false,"in":"query","type":"string"}],"responses":{"200":{"description":"OK","schema":{"type":"array","items":{"$ref":"#/definitions/Flower"}}}}}},"/flowers/{slug}":{"get":{"operationId":"findBySlug","summary":"Find by a flower by its slug","tags":["Flowers"],"deprecated":false,"parameters":[{"name":"slug","description":"Slug of flower that needs to be fetched","required":true,"in":"path","type":"string"}],"responses":{"200":{"description":"OK","schema":{"$ref":"#/definitions/Flower"}},"404":{"description":"Slug Not Found"}}}}},"definitions":{"Flower":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"}},"required":["slug","name"]}},"securityDefinitions":{}}

Browsing your API using swagger-ui

If you browse to http://petstore.swagger.io/, you’ll see the default Swagger demo application - a Pet Store - and you’ll be able to browse its documentation. One thing which may not be immediately obvious is that you can use this app to browse our local Flower Shop as well.

Paste your Swagger resource descriptor URL - http://localhost:8080/api-docs/swagger.json - into the URL field, then press the “Explore” button. You’ll be rewarded with a fully Swaggerized view of your API documentation. Try clicking on the “GET /flowers” route to expand the operations underneath it, and then entering the word “rose” into the input box for the “name” parameter. You’ll be rewarded with JSON output for the search method we defined earlier.

It's very important to get the api-docs path correct when you browse your docs in swagger-ui. Be careful: there's no trailing slash on http://localhost:8080/api-docs,
and the docs won't work if you accidentally add one.

Also note that the swagger-ui responds to input validation: you can’t try out the /flowers/{slug} route without entering a slug, because we’ve marked that as a required parameter in our Swagger annotations. Note that when you enter a slug such as “yellow-tulip”, the "{slug}" endpoint annotation on this route causes the swagger-ui to fire the request as /flowers/yellow-tulip.

If you want to host your own customized version of the docs, you can of course just download the swagger-ui code from Github and drop it onto any HTTP server.

A note on cross-origin security

Interestingly, you are able to use the remotely-hosted documentation browser at http://petstore.swagger.io to browse an application on http://localhost. Why is this possible? Shouldn’t JavaScript security restrictions have come into play here?

The reason it works is that Scalatra has Cross-Origin Resource Sharing (CORS) support mixed into its SwaggerSupport trait, allowing cross-origin JavaScript requests by default for all requesting domains. This makes it easy to serve JS API clients - but if you want, you can lock down requests to specific domains using Scalatra’s CorsSupport trait. See the Scalatra Helpers documentation for more.