Monday, September 30, 2013

Swagger: make developers love working with your REST API

As JAX-RS API is evolving, with version 2.0 released earlier this year under JSR-339 umbrella, it's becoming even more easy to create REST services using excellent Java platform.

But with great simplicity comes great responsibility: documenting all these APIs so other developers could quickly understand how to use them. Unfortunately, in this area developers are on their own: the JSR-339 doesn't help much. For sure, it would be just awesome to generate verbose and easy to follow documentation from source code, and not asking someone to write it along the development process. Sounds unreal, right? In certain extent, it really is, but help is coming in a form of Swagger.

Essentially, Swagger does a simple but very powerful thing: with a bit of additional annotations it generates the REST API descriptions (HTTP methods, path / query / form parameters, responses, HTTP error codes, ...) and even provides a simple web UI to play with REST calls to your APIs (not to mention that all this metadata is available over REST as well).

Before digging into implementation details, let's take a quick look what Swagger is from API consumer prospective. Assume you have developed a great REST service to manage people. As a good citizen, this REST service is feature-complete and provides following functionality:

It looks quite pretty. Let's do more and call our REST service from Swagger UI, here this awesome framework really shines. The most complicated use-case is adding new person (POST) so this one will be looked closely.

As you can see on the snapshot above, every piece of REST service call is there:

To complete the demo part, let me show yet another example, where REST resource is being involved (in our case, it's a simple class Person). Swagger is able to provide its properties and meaningful description together with expected response content type(s).

Looks nice! Moving on to the next part, it's all about implementation details. Swagger supports seamless integration with JAX-RS services, with just couple of additional annotations required on top of existing ones. Firstly, every single JAX-RS service which supposed to be documented should be annotated with @Api annotation, in our case:

Next, the same approach is applicable to REST service operations: every method which supposed to be documented should be annotated with @ApiOperation annotation, and optionally with @ApiResponses/@ApiResponse. If it accepts parameters, those should be annotated with @ApiParam annotation. Couple of examples here:

The last steps is to plug in Swagger into JAX-RS application. The example I have developed uses Spring Framework, Apache CXF, Swagger UI and embedded Jetty (complete project is available on Github). Integrating Swagger is a matter of adding configuration bean (swaggerConfig), one additional JAX-RS service (apiListingResourceJson) and two JAX-RS providers (resourceListingProvider and apiDeclarationProvider).

In order to get rid of any possible hard-coded configuration, all parameters are passed through named properties (SERVER_PORT, SERVER_HOST and CONTEXT_PATH). Swagger exposes additional REST endpoint to provide API documentation, in our case it is accessible at: http://localhost:8080/rest/api/api-docs. It is used by Swagger UI which itself is embedded into final JAR archive and served by Jetty as static web resource.

The final piece of the puzzle is to start embedded Jetty container which glues all those parts together and is encapsulated into Starter class:

Couple of comments make thing a bit more clear: our JAX-RS services will be available under /rest/* context path while Swagger UI is available under /swagger context path. The one important note concerning Resource.setDefaultUseCaches( false ): because we are serving static web content from JAR file, we have to set this property to false as workaround for this bug.

As a final note, there are a lot more to say about Swagger but I hope this simple example shows the way to make our REST services self-documented and easily consumable with minimal efforts. Many thanks to Wordnik team for that.

Couple of questions: * is it possible to export all generated documentation to the company official portal? Or to access the documentation the app should be up and running.* Does this library knows something about API versioning?

Thank you very much for your comments. Swagger does support the security in some extent as covered in this manual: https://github.com/wordnik/swagger-core/wiki/authorizations (personally, I haven't used this feature yet but it's a very important use case to cover).

Thanks a lot for your comments. Yes, Swagger does have a Maven plugin and can generate API documentation at build time (https://github.com/kongchen/swagger-maven-plugin). With respect to API versioning, Swaggers support API version (https://github.com/wordnik/swagger-core/wiki/API-Declaration) though its usage is somewhat limited and is up to developer.

Thanks a lot for your comments. Unfortunately, I do not have hands-on experience with Apache Camel and cannot answer your question. However, if you could outline some details about the problem you are having, I might suggest to try something out.

Thank you very much for your comment. To answer your question, it is quite easy, in class AppConfig, line 54, replace please String.format( "http://%s:%s/%s%s", with String.format( "https://%s:%s/%s%s", (or better just parametrize the protocol as well). Hope it helps!

Nice post. I have no experience with creating/deploying/documenting an API. I was wondering if you could help me with intefrating swagger into an Eclipse project that has already been started for me by my internship. They have created a REST Api and they want us to use swagger for documentation/annotation. I am completely lost at what to do. I have done some research, but can't seem to find anything on using it with an eclipse project.

Unfortunately I cannot do that. It belongs to a company I am working at for an internship this summer. Im just trying to figure out what files i need to put into my project and where. Even some sort of direction would be appreciated.

Gotcha, no problem. Let me try to guide you through than. So Swagger consist of two parts (as for this blog post concerns): API description and UI (optional). API description part in general depends on what kind of REST framework you are using, could you please hint me with that? Swagger UI is simple, self-contained and could be just pulled from GitHub: https://github.com/swagger-api/swagger-ui. It is a static set of web resources. So I think once we figure out the API part, we can glue everything together. Waiting for your response!

Yes, I have the swagger files downloaded from GitHub. We are using Jersey and it looks like Spring as well. This is the first time I have ever worked on a web service / servlet, or API so this is all new to me, kinda confused as to what Jersey and Spring does exactly but I can certainly read up on that on my own. If it helps at all I'm using Eclipse to work on the project and it is a DynamicWeb project. The API has already been written, me and my partner just have to go through and annotate the stuff so that we can use the UI for deployment.

hello Andi,great article , more over it is exactly what i have been looking for.Ran into a jetty issue while running it. so updated the jetty version to 9.1 to get it working.Now when I try to look for localhost:8080/swagger i am getting 404. My rest API is just coming fine and the document also. But not sure how to resolve the 404.

Thank you very much for your comment. Yes, you are right, I updated Jetty to 9.1+ and there is 404 returned. It seems like the handlers are managed a bit differently by Jetty now, could you please just change the order of handlers in Starter.java like that, instead of:handlers.addHandler( context );handlers.addHandler( swagger );

I have created a sample, Jersey 2.0 based project branch for you on GitHub: https://github.com/reta/jax-rs-2.0-swagger/tree/jersey-2.0

It is a little bit hard to figure out how exactly you run your application but I hope it will give you a basic idea. The key class is JaxRsApiApplication which extends Jersey's ResourceConfig class and register appropriate Swagger (and JAX-RS beans). Once you run the Starter class in Eclipse, you should be able to open Swagger UI on http://localhost:8080/swagger. Please give it a try and let me know it was helpful or not.

Sorry it has taken me a while to get back to you. I have sucessfuly deployed my swagger project and documented two API's. Horray! I was wondering if you know anything about using Basic Auth with swagger-UI? Currently when I hit the "try it out!" button when testing the api I have to login to access the API, I am trying to set it up so that a header is sent so that I don't have to log in everytime. I have looked at the documentation, but everything I have tried so far has been unsucessful.

Glad to hear you pulled it off! I haven't used Basic Auth with Swagger UI yet, but it seems like it could be added manually (some JavaScript coding required). There is an issue to watch: https://github.com/swagger-api/swagger-ui/issues/764.

Hi,I'm new to swagger and want to learn it.But i dont know how to get started with it.Please help me with it.Im interested in swagger with jersey at this link https://github.com/reta/jax-rs-2.0-swagger/tree/jersey-2.0.

If i pull the code form github into eclipse what do i have to do to get it runningYour step by step help is highly appreciated.Thanks!

Thanks a lot for your interest. It is very easy: once you pull the code to Eclipse, you just right-click on a project, select [Run As] / [Java Application] and select Starter class. That's it, once run, point your browser at http://localhost:8080/swagger/

Got it, you have two choices here: - right-click on the project, select [Configure], then [Convert To Maven Project] - reimport the project as [Check out Maven Projects from SCM], using the same Github repository

You basically need two update your Jersey configuration (see please JaxRsApiApplication class). It is very hard to give you the right advice because there could quite a few ways to create Jersey applications and integrate them with Swagger. If you could share your project @ Github, I would be happy to help you out.

Submitted PR: https://github.com/HJ786/TutorialsDesk/pull/1Please take a look, it is the easiest way to start playing with Swagger and Swagger UI.Just start with adding more annotations to your Tasks REST service!Thanks!

I did a merge online then pulled the code from github into my project in eclipse.Swagger is still not running at my end on the given URL http://localhost:8080/TutorialsDesk.Rest.CRUDWebServices/swagger-ui/

Hi,To elaborate my problem i would like to mention that in Eclipse in the git repositories window when i right click the project(TutorialsDesk.Rest.CRUDWebServices) and select pull..it says Nothing to update-eveyrthing uptodate.

In the project explorer,when i right click the project(TutorialsDesk.Rest.CRUDWebServices)and select Run As-> Run on Server(select the server) i cannot see swagger changes integrated to it.

Neither can i see the newly added files nor any changes made to my existing files in my project(TutorialsDesk.Rest.CRUDWebServices)under project explorer or git repositories window.

Please check your repo commit history, https://github.com/HJ786/TutorialsDesk/commits/master. I am not sure exactly what you are trying to do but you merged and reverted the merge at least 2 times. Right now there is no changes from PR in your repo. You may reset your HEAD to this commit: https://github.com/HJ786/TutorialsDesk/commit/40cebd3f60121a734c438e1c6258efe21d21a7d8 (please consult Github documentation how to do that, it is very good).

I apologize in advance because I'm not too familiar with creating, working with or documenting an API. Is it possible to use Swagger UI to document a REST API that isn't dependent on a framework? The API I'm trying to document is written in C and according to my coworkers was not developed using a framework. I've done research but I can't seem to figure out how or if it's possible to use Swagger UI to document it. Any help would really be appreciated!

Thank you very much for the comment. Essentially, Swagger is just an API description specification (https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md). If your REST API, written in any language, is able to return its own description according to specification, Swagger UI will be happy to show it off! On the other side, I am not aware of any implementation which could generate the API documentation in C (I would suspect it may be not possible as C has no reflection support). However, the one way to dial with that is by manually creating swagger.json file with API description and returning it from your C API (f.e. /api-specs/swagger.json), that will require some work but I do not see another option at the moment. If your API is not changing, that would be one time thing. I hope it will help.

My apologies for giving you a confusing answer. I would like to disambiguate it a bit: reflection simplifies a lot of things and as such makes certain use cases much simpler to implement. By no means I intended to let you think that "no reflection support would disallow it from generating the documentation", probably more routine work is required.

SEVERE: Servlet [Jersey2Config] in web application [/TutorialsDesk.Rest.CRUDWebServices] threw load() exceptionjava.lang.ClassNotFoundException: io.swagger.jaxrs.config.DefaultJaxrsConfig at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571) at org.apache.catalina.core.DefaultInstanceManager.loadClass(DefaultInstanceManager.java:506) at org.apache.catalina.core.DefaultInstanceManager.loadClassMaybePrivileged(DefaultInstanceManager.java:488) at org.apache.catalina.core.DefaultInstanceManager.newInstance(DefaultInstanceManager.java:115) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1148) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1087) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5266) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5554) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1575) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1565) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)

In the browser when i type the swagger url id saysCan't read swagger JSON from http://localhost:8080/TutorialsDesk.Rest.CRUDWebServices/rest/swagger.json

I just cloned the application, imported it to eclipse and running it has java application with pointing starter class, when i use localhost:808/swagger/ i cannot see anything. web page is empty with just swagger icon on it. Do i need to make any other changes to run this application.

Thanks for your comment. No, you are not supposed to make any changes to have application working. Could you please check the Eclipse console for possible errors. Also, could you please run curl http://localhost:8080/rest/api/api-docs to check if API description is properly returned?

Thanks a bunch for such a great details. It seems like you have run into Jetty bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=418871). Could you please try to update the Jetty version in pom.xml from

Could you suggest me some document or blog if any to learn about swagger from the scratch. I just thinking of doing some simple project to understand these concepts more clearly. but i don't have idea about from where i should start.

As for me, Swagger's Wiki (https://github.com/swagger-api/swagger-core/wiki) is the best source of documentation and samples. In particular, those sections https://github.com/swagger-api/swagger-core/wiki/Annotations, https://github.com/swagger-api/swagger-core/wiki/Java-CXF-Quickstart, https://github.com/swagger-api/swagger-core/wiki/Java-Integrations are very helpful.

Hi Andriy,That was a full fledged example! Followed this and was able to do this successfully. However, I want to know one more thing:If you see petstore example on Swagger UI website (http://petstore.swagger.io/#/, go to pet, then go to Add new pet to the store.), there is a feature in which data Type of a parameter is Model Schema and it is displayed just like the Response class in your example. BUt, if you left click it, the JSON format of the class gets copied to the parameter input value! I just want to know how does this works? Thanks a lot! :)

Thank you for your comment! Yeah, thanks to Swagger, it is very easy to do. There are actually two ways:1. Annotating the parameter itself, f.e. @ApiParam(value = "person") Person person2. Using @ApiImplicitParam / @ApiImplicitParams

In this case, when API parameter is a complex entity (usually passed as HTTP call payload), Swagger UI is going to show its JSON representation, same way you saw it on petstore example. Hope it answers your question!

Hi Andriy,Thanks for the quick answer. Actually I am using Swagger in Groovy Grails. The version of swagger I am using is 1.3.8. I have tried it using @ApiImplicitParam. But it doesnt work. It works only when I write response= ABC.CLASS in @ApiOperation, and then write in @ApiImplicitParam(dataType="ABC"). This solves the problem but is impractical, because response class model schema is also displayed on the screen alongwith data type model schema, which is not good. I think I have to update Swagger to 1.5 since I have found a bug in the previous version. (https://github.com/swagger-api/swagger-core/issues/1149).

Yeah, @ApiImplicitParam needs dataType to be provided as a fully qualified class name. Nevertheless, upgrading to 1.5 is a great idea, it seems like 1.3 won't evolve anymore. Should be very straightforward (the project on Github for this post has a branch for Swagger 1.5 as well, could be helpful for you).

Thanks for the comment! If the project is not Maven-based, you just need to find a way to include Swagger JAR files into the build / classpath (for SBT or Gradle it is as straightforward as just adding dependencies into your build files).

By not JAX-RS based project I mean f.e. just use pure Java servlets or Play! Framework integration, those are not implementations conformant with JAX-RS but Swagger supports it.

Yeah, you right, description_swagger2_web still contains Spring dependencies. Please use https://github.com/apache/cxf/tree/master/distribution/src/main/release/samples/jax_rs/description_swagger2, there is no Spring here but Maven is required for build. CXFNonSpringJaxrsServlet is the good one to use. If you want to get rid of Maven, you still have to have build process in place (other build tools or scripts). I am not sure what is your choice here.

Am using the ant build and below jars for my project.---------------------activation-1.1.jarasm-3.1.jarcxf-2.7.18.jarFastInfoset-1.2.2.jarhttpasyncclient-4.0-beta3.jarhttpclient-4.2.5.jarhttpcore-4.2.4.jarhttpcore-nio-4.2.4.jarjavassist-3.19.0-GA.jarjavax.ws.rs-api-2.0-m10.jarjdom-1.0.jarjettison-1.3.7.jarjunit-4.10.jarlog4j-api-2.4.1.jarlog4j-core-2.4.1.jarlog4j-slf4j-impl-2.1.jarmail-1.4.jarmockito-all-1.10.19.jarneethi-3.0.3.jarorg-apache-commons-lang.jarorg.apache.servicemix.bundles.swagger-jaxrs-1.3.12_2.jarorg.json.jarpowermock-mockito-1.6.2-full.jarreflections-0.9.5.jarrome-0.9.jarscala-library-2.10.0-rc1.jarslf4j.api-1.6.1.jarstax-api-1.0-2.jarswagger-annotations_2.10.0-1.2.0.jarswagger-core_2.10-1.3.12.jarswagger-jaxrs_2.10-1.3.0.jarwsdl4j-1.6.3.jarxmlschema-core-2.1.0.jar---------------------------

Thanks a lot for your comment. Swagger has excellent documentation regarding integration with Jersey, please take a look on it: https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5

Most of the projects are Maven based, so you just do File -> Import -> Existing Maven project in Eclipse and you are good to go.

Certainly, I would be more than happy to help you out if you encounter some issues along the way.

My LinkedIn Profile

About Me

Seasoned software developer with a great passion to code. I am extensively working with JVM platform using Java, Groovy, Scala as well as other languages and technologies (Ruby, Grails, Play!, Akka, MySQL, PostreSQL, MongoDB, Redis, JUnit, ...)