Monday, May 27, 2013

SoapUI + Swagger = true!

Since I published the original version of the soapui-swagger-plugin in late 2012, Swagger has continued to gain traction within the API community. For those of you not familiar with Swagger, it's a metadata format for describing the ins and outs of a REST API - much like WSDL is for SOAP APIs - have a look at the Swagger website to learn more.

The initial version of the plugin allowed you to import Swagger definitions into SoapUI - making it extremely easy to send ad-hoc requests, create functional tests, load tests and API monitors for the Swagger-described API (and all for free!). When discussing the plugin with some users at APIStrat earlier this year, they requested the possibility to be able to export Swagger definitions as well, i.e. if you have a REST API defined in SoapUI - they wanted to be able to generate a corresponding Swagger definition that they (for example) could use with swagger-ui to provide your customers an online tool for trying out your API.

Obviously I couldn't resist the challenge, and although its taken me some time I'm happy to finally announce version 0.2 of the plugin that does exactly that; exports Swagger definitions for any REST API defined in SoapUI - which has some cool usage scenarios. Let's dive in.

REST APIs in SoapUI


Despite its contextually unfortunate name - SoapUI has had good support for testing REST APIs since 2008 (!). REST support was initially modeled around the WADL specification (an initial attempt at providing metadata for REST APIs) - fortunately the object model in Swagger plays pretty well with WADL, which makes the Swagger import/export feature in the plugin play seamlessly with SoapUIs REST support.

Exporting Swagger Definitions


Exporting Swagger definitions using the plugin is straightforward; make sure you have at least one REST API defined in your SoapUI project and right-click the project node in the SoapUI navigator; the popup menu now has an "Export Swagger" menu option:



Select it to bring up the following dialog:


The settings are as follows:

  • APIs : select which REST APIs in your project that you want to include in the generated Swagger definition
  • Target Folder : where to generate the files
  • API Version : the value for the api-version property in the generated definitions
  • Base Path: the base path that the generated resource listing will be hosted on. This is important to get right as API declarations are resolved relative to this (see example below)
  • Format : which format to use; Swagger technically supports both json and xml, although I would guess 99% of its users are using json at this time :-)

Press the OK button when you've set the options as desired; SoapUI will work a little and prompt you with the path of the generated Swagger resource listing. This is ready to go; feed it into any other tool that supports Swagger - for example you can use swagger-ui to provide a nice online UI for exploring the described API (see example below).

Usage Scenarios


Although the primary usage scenario may be the one described further down in this post - generating Swagger definitions for hosting them with swagger-ui - you could of course use the export feature of the plugin for things like:

  • WADL to Swagger conversion; if you have API definitions in WADL format you can simply import them into SoapUI (using the regular Add WADL functionality) and then export them as Swagger definitions with this Plugin
  • Swagger-creation; if you need a visual tool to build Swagger definitions "from scratch" you can use SoapUI to define your REST API which you can then export.


Hosting Swagger definitions with SoapUI


One thing you might want to do is provide your API users with a nice browser-based UI for trying out your API - which is precisely what the swagger-ui project is for (also from the Swagger folks). You can download swagger-ui from GitHub and just open it from your local file system in your browser - which will start you with something like:

(by default it displays the sample petstore Swagger definition)

Now how do you get swagger-ui to read the resource-listing generated by SoapUI? Unfortunately swagger-ui doesn't support file-based URLs so we need to do a bit of trickery with SoapUI to expose our Swagger for swagger-ui; the MockService functionality in SoapUI can be used as a miniature web-server, which is just what we need here (if you have a local web server running you can of course use that instead).

Start by creating a MockService in your SoapUI project via the Project menus "New MockService" option. Once created - double-click it to open the MockService window and select the "Options" button - which will bring up the following dialog:




Set the docroot to point at the folder where you generated the Swagger definition, configure the port as desired (so it doesn't collide with anything else you might be hosting on your machine), press OK and start the MockService with the "Run" button in the top-left corner of the MockService window. You now have a mini webserver running, ready to serve any documents you have in the specified docroot folder, but before we can use swagger-ui with it we need to make sure the MockService adds some HTTP Headers that swagger-ui expects. Select the "OnRequest Script" tab in the MockService window and enter the following:

mockRequest.httpResponse.addHeader( "Access-Control-Allow-Origin", "*" )
mockRequest.httpResponse.addHeader( "Access-Control-Allow-Methods", "GET, POST, DELETE, PUT" )
mockRequest.httpResponse.addHeader( "Access-Control-Allow-Headers", "Content-Type, api_key, Authorization" )

In SoapUI, this looks as follows;




Let's go back to the dialog for Exporting Swagger definitions and configure it accordingly:




Please note that Base Path configuration above matches the local ip that the MockService is running on (so the path can be resolved) and the Target Folder is the same as the docroot for the MockService configured above. Once exported we're all set; open a web-browser and enter "http://127.0.0.1:8181/api-docs.json" (change the port accordingly) - which should bring up the Swagger resource listing we generated above;




Now back to swagger-ui; paste the same endpoint in the URL field and press the "Explore"; swagger-ui will work a bit and presto, you should get something like the following;



Awesome - we've created Swagger definitions for some of the Google Maps APIs and can now do some simple API invocation from within swagger-ui!

Changes to the Import Swagger feature


The "Import Swagger" feature has been improved a little since last; the dialog invoked by the corresponding menu item now looks as follows:




Here you can now specify to import Swagger API Declarations directly (instead of always having to provide a Resource Listing) - which can come in handy for some of the API-mgmt platforms out there that provide API Declarations directly (APIHub for example).

A bonus under the hood: swagger4j


Version 0.2 of this plugin needed a more robust way to read and write Swagger definitions than the groovy scripts that were used in version 0.1 to just read them. I've separated this into a separate java library - swagger4j - which has no dependencies on SoapUI whatsoever and can as such used within any Java program that needs to read or write Swagger definitions. It's open-source (Apache licensed) and available over at GitHub - check it out, and don't hesitate to give me feedback so I can improve that as well.

Installation


Installing the plugin is straight forward; download it from sourceforge or build it yourself with maven (it's on GitHub). The download from sourceforge contains the required dependencies - all you have to do is unzip it into your SoapUI/bin folder.If you build it manually you will have to add these dependencies yourself to the SoapUI/bin/ext folder:


Next Steps

So what's next? You tell me! Please get in touch if you want to see any specific fixes, improvements, etc - I'd love to hear from you.

Thanks,

/Ole