{"id":17782,"date":"2013-10-04T01:00:41","date_gmt":"2013-10-03T22:00:41","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=17782"},"modified":"2013-10-03T09:16:01","modified_gmt":"2013-10-03T06:16:01","slug":"swagger-make-developers-love-working-with-your-rest-api","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html","title":{"rendered":"Swagger: make developers love working with your REST API"},"content":{"rendered":"<p>As <a href=\"https:\/\/jax-rs-spec.java.net\/\">JAX-RS<\/a> API is evolving, with version <b>2.0<\/b> released earlier this year under <a href=\"http:\/\/jcp.org\/en\/jsr\/detail?id=339\">JSR-339<\/a> umbrella, it&#8217;s becoming even more easy to create <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> services using excellent <a href=\"http:\/\/www.java.com\/en\/\">Java<\/a> platform.<\/p>\n<p>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 <a href=\"http:\/\/jcp.org\/en\/jsr\/detail?id=339\">JSR-339<\/a> doesn&#8217;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 <a href=\"https:\/\/github.com\/wordnik\/swagger-core\">Swagger<\/a>.<\/p>\n<p>Essentially, <a href=\"https:\/\/github.com\/wordnik\/swagger-core\">Swagger<\/a> does a simple but very powerful thing: with a bit of additional annotations it generates the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> API descriptions (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">HTTP<\/a> methods, path \/ query \/ form parameters, responses, <a href=\"http:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">HTTP<\/a> error codes, &#8230;) and even provides a simple <a href=\"https:\/\/github.com\/wordnik\/swagger-ui\">web UI<\/a> to play with <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> calls to your APIs (not to mention that all this metadata is available over <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> as well).<\/p>\n<p>Before digging into implementation details, let&#8217;s take a quick look what <a href=\"https:\/\/github.com\/wordnik\/swagger-core\">Swagger<\/a> is from API consumer prospective. Assume you have developed a great <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> service to manage people. As a good citizen, this <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> service is feature-complete and provides following functionality:<\/p>\n<ul>\n<li>lists all people (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">GET<\/a>)<\/li>\n<li>looks up person by e-mail (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">GET<\/a>)<\/li>\n<li>adds new person (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">POST<\/a>)<\/li>\n<li>updates existing person (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">PUT<\/a>)<\/li>\n<li>and finally removes person (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">DELETE<\/a>)<\/li>\n<\/ul>\n<p>Here is the same API from <a href=\"https:\/\/github.com\/wordnik\/swagger-core\">Swagger<\/a>&#8216;s perspective:<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-frontpage.png\"><img decoding=\"async\" class=\"aligncenter size-medium wp-image-17800\" alt=\"swagger-frontpage\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-frontpage-300x114.png\" width=\"300\" height=\"114\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-frontpage-300x114.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-frontpage-1024x389.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-frontpage.png 1263w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>It looks quite pretty. Let&#8217;s do more and call our <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> service from <a href=\"https:\/\/github.com\/wordnik\/swagger-ui\">Swagger UI<\/a>, here this awesome framework really shines. The most complicated use-case is adding new person (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">POST<\/a>) so this one will be looked closely.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-post.png\"><img decoding=\"async\" class=\"aligncenter size-medium wp-image-17802\" alt=\"swagger-post\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-post-300x133.png\" width=\"300\" height=\"133\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-post-300x133.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-post-1024x456.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-post.png 1203w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>As you can see on the snapshot above, every piece of <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> service call is there:<\/p>\n<ul>\n<li>description of the service<\/li>\n<li>relative context path<\/li>\n<li>parameters (form \/ path \/ query), required or optional<\/li>\n<li><a href=\"http:\/\/en.wikipedia.org\/wiki\/Hypertext_Transfer_Protocol\">HTTP<\/a> status codes: <b>201 CREATED<\/b> and <b>409 CONFLICT<\/b><\/li>\n<li>ready to go <b>Try it out!<\/b> to call <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> service immediately (with out-of-the box parameters validation)<\/li>\n<\/ul>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-response.png\"><img decoding=\"async\" class=\"aligncenter size-medium wp-image-17803\" alt=\"swagger-response\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-response-300x238.png\" width=\"300\" height=\"238\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-response-300x238.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-response-1024x815.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-response.png 1206w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>To complete the demo part, let me show yet another example, where <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST <\/a>resource is being involved (in our case, it&#8217;s a simple class <b>Person<\/b>). <a href=\"https:\/\/github.com\/wordnik\/swagger-core\">Swagger<\/a> is able to provide its properties and meaningful description together with expected response content type(s).<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-get.png\"><img decoding=\"async\" class=\"aligncenter size-medium wp-image-17804\" alt=\"swagger-get\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-get-300x169.png\" width=\"300\" height=\"169\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-get-300x169.png 300w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-get-1024x578.png 1024w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2013\/10\/swagger-get.png 1206w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>Looks nice! Moving on to the next part, it&#8217;s all about implementation details. <a href=\"https:\/\/github.com\/wordnik\/swagger-core\">Swagger<\/a> supports seamless integration with <a href=\"https:\/\/jax-rs-spec.java.net\/\">JAX-RS<\/a> services, with just couple of additional annotations required on top of existing ones. Firstly, every single <a href=\"https:\/\/jax-rs-spec.java.net\/\">JAX-RS<\/a> service which supposed to be documented should be annotated with <b>@Api<\/b> annotation, in our case:<\/p>\n<pre class=\" brush:java\">@Path( \"\/people\" ) \r\n@Api( value = \"\/people\", description = \"Manage people\" )\r\npublic class PeopleRestService {\r\n    \/\/ ...\r\n}<\/pre>\n<p>Next, the same approach is applicable to <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> service operations: every method which supposed to be documented should be annotated with <b>@ApiOperation<\/b> annotation, and optionally with <b>@ApiResponses\/@ApiResponse<\/b>. If it accepts parameters, those should be annotated with <b>@ApiParam<\/b> annotation. Couple of examples here:<\/p>\n<pre class=\" brush:java\">@Produces( { MediaType.APPLICATION_JSON } )\r\n@GET\r\n@ApiOperation( \r\n    value = \"List all people\", \r\n    notes = \"List all people using paging\", \r\n    response = Person.class, \r\n    responseContainer = \"List\"\r\n)\r\npublic Collection&lt; Person &gt; getPeople(  \r\n        @ApiParam( value = \"Page to fetch\", required = true ) \r\n        @QueryParam( \"page\") @DefaultValue( \"1\" ) final int page ) {\r\n    \/\/ ...\r\n}<\/pre>\n<p>And another one:<\/p>\n<pre class=\" brush:java\">@Produces( { MediaType.APPLICATION_JSON } )\r\n@Path( \"\/{email}\" )\r\n@GET\r\n@ApiOperation( \r\n    value = \"Find person by e-mail\", \r\n    notes = \"Find person by e-mail\", \r\n    response = Person.class \r\n)\r\n@ApiResponses( {\r\n    @ApiResponse( code = 404, message = \"Person with such e-mail doesn't exists\" )    \r\n} )\r\npublic Person getPeople( \r\n        @ApiParam( value = \"E-Mail address to lookup for\", required = true ) \r\n        @PathParam( \"email\" ) final String email ) {\r\n    \/\/ ...\r\n}<\/pre>\n<p><a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> resource classes (or model classes) require special annotations: <b>@ApiModel<\/b> and <b>@ApiModelProperty<\/b>. Here is how our <b>Person<\/b> class looks like:<\/p>\n<pre class=\" brush:java\">@ApiModel( value = \"Person\", description = \"Person resource representation\" )\r\npublic class Person {\r\n    @ApiModelProperty( value = \"Person's first name\", required = true ) \r\n    private String email;\r\n    @ApiModelProperty( value = \"Person's e-mail address\", required = true ) \r\n    private String firstName;\r\n    @ApiModelProperty( value = \"Person's last name\", required = true ) \r\n    private String lastName;\r\n\r\n    \/\/ ...\r\n}<\/pre>\n<p>The last steps is to plug in <a href=\"https:\/\/github.com\/wordnik\/swagger-core\">Swagger<\/a> into <a href=\"https:\/\/jax-rs-spec.java.net\/\">JAX-RS<\/a> application. The example I have developed uses <a href=\"http:\/\/projects.spring.io\/spring-framework\/\">Spring Framework<\/a>, <a href=\"http:\/\/cxf.apache.org\/\">Apache CXF<\/a>, <a href=\"https:\/\/github.com\/wordnik\/swagger-ui\">Swagger UI<\/a> and embedded <a href=\"http:\/\/www.eclipse.org\/jetty\/\">Jetty<\/a> (complete project is available on <a href=\"https:\/\/github.com\/reta\/jax-rs-2.0-swagger\">Github<\/a>). Integrating <a href=\"https:\/\/github.com\/wordnik\/swagger-core\">Swagger<\/a> is a matter of adding configuration bean (<b>swaggerConfig<\/b>), one additional <a href=\"https:\/\/jax-rs-spec.java.net\/\">JAX-RS<\/a> service (<b>apiListingResourceJson<\/b>) and two <a href=\"https:\/\/jax-rs-spec.java.net\/\">JAX-RS<\/a> providers (<b>resourceListingProvider<\/b> and <b>apiDeclarationProvider<\/b>).<\/p>\n<pre class=\" brush:java\">package com.example.config;\r\n\r\nimport java.util.Arrays;\r\n\r\nimport javax.ws.rs.ext.RuntimeDelegate;\r\n\r\nimport org.apache.cxf.bus.spring.SpringBus;\r\nimport org.apache.cxf.endpoint.Server;\r\nimport org.apache.cxf.jaxrs.JAXRSServerFactoryBean;\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.context.annotation.Bean;\r\nimport org.springframework.context.annotation.Configuration;\r\nimport org.springframework.context.annotation.DependsOn;\r\nimport org.springframework.core.env.Environment;\r\n\r\nimport com.example.resource.Person;\r\nimport com.example.rs.JaxRsApiApplication;\r\nimport com.example.rs.PeopleRestService;\r\nimport com.example.services.PeopleService;\r\nimport com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;\r\nimport com.wordnik.swagger.jaxrs.config.BeanConfig;\r\nimport com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider;\r\nimport com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON;\r\nimport com.wordnik.swagger.jaxrs.listing.ResourceListingProvider;\r\n\r\n@Configuration\r\npublic class AppConfig {\r\n    public static final String SERVER_PORT = \"server.port\";\r\n    public static final String SERVER_HOST = \"server.host\";\r\n    public static final String CONTEXT_PATH = \"context.path\";  \r\n\r\n    @Bean( destroyMethod = \"shutdown\" )\r\n    public SpringBus cxf() {\r\n        return new SpringBus();\r\n    }\r\n\r\n    @Bean @DependsOn( \"cxf\" )\r\n    public Server jaxRsServer() {\r\n        JAXRSServerFactoryBean factory = RuntimeDelegate.getInstance().createEndpoint( jaxRsApiApplication(), JAXRSServerFactoryBean.class );\r\n        factory.setServiceBeans( Arrays.&lt; Object &gt;asList( peopleRestService(), apiListingResourceJson() ) );\r\n        factory.setAddress( factory.getAddress() );\r\n        factory.setProviders( Arrays.&lt; Object &gt;asList( jsonProvider(), resourceListingProvider(), apiDeclarationProvider() ) );\r\n        return factory.create();\r\n    }\r\n\r\n    @Bean @Autowired\r\n    public BeanConfig swaggerConfig( Environment environment ) {\r\n        final BeanConfig config = new BeanConfig();\r\n\r\n        config.setVersion( \"1.0.0\" );\r\n        config.setScan( true );\r\n        config.setResourcePackage( Person.class.getPackage().getName() );\r\n        config.setBasePath( \r\n            String.format( \"http:\/\/%s:%s\/%s%s\",\r\n                environment.getProperty( SERVER_HOST ),\r\n                environment.getProperty( SERVER_PORT ),\r\n                environment.getProperty( CONTEXT_PATH ),\r\n                jaxRsServer().getEndpoint().getEndpointInfo().getAddress() \r\n            ) \r\n        );\r\n\r\n        return config;\r\n    }\r\n\r\n    @Bean\r\n    public ApiDeclarationProvider apiDeclarationProvider() {\r\n        return new ApiDeclarationProvider();\r\n    }\r\n\r\n    @Bean\r\n    public ApiListingResourceJSON apiListingResourceJson() {\r\n        return new ApiListingResourceJSON();\r\n    }\r\n\r\n    @Bean\r\n    public ResourceListingProvider resourceListingProvider() {\r\n        return new ResourceListingProvider();\r\n    }\r\n\r\n    @Bean \r\n    public JaxRsApiApplication jaxRsApiApplication() {\r\n        return new JaxRsApiApplication();\r\n    }\r\n\r\n    @Bean \r\n    public PeopleRestService peopleRestService() {\r\n        return new PeopleRestService();\r\n    }\r\n\r\n    \/\/ ... \r\n}<\/pre>\n<p>In order to get rid of any possible hard-coded configuration, all parameters are passed through named properties (<b>SERVER_PORT<\/b>, <b>SERVER_HOST<\/b> and <b>CONTEXT_PATH<\/b>). <a href=\"https:\/\/github.com\/wordnik\/swagger-core\">Swagger<\/a> exposes additional <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> endpoint to provide API documentation, in our case it is accessible at: <b>http:\/\/localhost:8080\/rest\/api\/api-docs<\/b>. It is used by <a href=\"https:\/\/github.com\/wordnik\/swagger-ui\">Swagger UI<\/a> which itself is embedded into final <b>JAR<\/b> archive and served by <a href=\"http:\/\/www.eclipse.org\/jetty\/\">Jetty<\/a> as static web resource.<\/p>\n<p>The final piece of the puzzle is to start embedded <a href=\"http:\/\/www.eclipse.org\/jetty\/\">Jetty<\/a> container which glues all those parts together and is encapsulated into <b>Starter<\/b> class:<\/p>\n<pre class=\" brush:java\">package com.example;\r\n\r\nimport org.apache.cxf.transport.servlet.CXFServlet;\r\nimport org.eclipse.jetty.server.Server;\r\nimport org.eclipse.jetty.server.handler.HandlerList;\r\nimport org.eclipse.jetty.servlet.DefaultServlet;\r\nimport org.eclipse.jetty.servlet.ServletContextHandler;\r\nimport org.eclipse.jetty.servlet.ServletHolder;\r\nimport org.eclipse.jetty.util.resource.Resource;\r\nimport org.springframework.core.io.ClassPathResource;\r\nimport org.springframework.web.context.ContextLoaderListener;\r\nimport org.springframework.web.context.support.AnnotationConfigWebApplicationContext;\r\n\r\nimport com.example.config.AppConfig;\r\n\r\npublic class Starter {\r\n    private static final int SERVER_PORT = 8080;\r\n    private static final String CONTEXT_PATH = \"rest\";\r\n\r\n    public static void main( final String[] args ) throws Exception {\r\n        Resource.setDefaultUseCaches( false );\r\n\r\n        final Server server = new Server( SERVER_PORT );  \r\n        System.setProperty( AppConfig.SERVER_PORT, Integer.toString( SERVER_PORT ) );\r\n        System.setProperty( AppConfig.SERVER_HOST, \"localhost\" );\r\n        System.setProperty( AppConfig.CONTEXT_PATH, CONTEXT_PATH );    \r\n\r\n        \/\/ Configuring Apache CXF servlet and Spring listener  \r\n        final ServletHolder servletHolder = new ServletHolder( new CXFServlet() );      \r\n        final ServletContextHandler context = new ServletContextHandler();   \r\n        context.setContextPath( \"\/\" );\r\n        context.addServlet( servletHolder, \"\/\" + CONTEXT_PATH + \"\/*\" );     \r\n        context.addEventListener( new ContextLoaderListener() ); \r\n\r\n        context.setInitParameter( \"contextClass\", AnnotationConfigWebApplicationContext.class.getName() );\r\n        context.setInitParameter( \"contextConfigLocation\", AppConfig.class.getName() );\r\n\r\n        \/\/ Configuring Swagger as static web resource\r\n        final ServletHolder swaggerHolder = new ServletHolder( new DefaultServlet() );\r\n        final ServletContextHandler swagger = new ServletContextHandler();\r\n        swagger.setContextPath( \"\/swagger\" );\r\n        swagger.addServlet( swaggerHolder, \"\/*\" );\r\n        swagger.setResourceBase( new ClassPathResource( \"\/webapp\" ).getURI().toString() );\r\n\r\n        final HandlerList handlers = new HandlerList();\r\n        handlers.addHandler( context );\r\n        handlers.addHandler( swagger );\r\n\r\n        server.setHandler( handlers );\r\n        server.start();\r\n        server.join(); \r\n    }\r\n}<\/pre>\n<p>Couple of comments make thing a bit more clear: our <a href=\"https:\/\/jax-rs-spec.java.net\/\">JAX-RS<\/a> services will be available under <b>\/rest\/*<\/b> context path while <a href=\"https:\/\/github.com\/wordnik\/swagger-ui\">Swagger UI<\/a> is available under <b>\/swagger<\/b> context path. The one important note concerning <b>Resource.setDefaultUseCaches( false )<\/b>: because we are serving static web content from <b>JAR<\/b> file, we have to set this property to <b>false<\/b> as workaround for this <a href=\"http:\/\/jira.codehaus.org\/browse\/JETTY-1471\">bug<\/a>.<\/p>\n<p>Now, let&#8217;s build and run our <a href=\"https:\/\/jax-rs-spec.java.net\/\">JAX-RS<\/a> application by typing:<\/p>\n<pre class=\" brush:java\">mvn clean package\r\njava -jar target\/jax-rs-2.0-swagger-0.0.1-SNAPSHOT.jar<\/pre>\n<p>In a second, <a href=\"https:\/\/github.com\/wordnik\/swagger-ui\">Swagger UI<\/a> should be available in your browser at: <a href=\"http:\/\/localhost:8080\/swagger\/\">http:\/\/localhost:8080\/swagger\/<\/a><\/p>\n<p>As a final note, there are a lot more to say about <a href=\"https:\/\/github.com\/wordnik\/swagger-core\">Swagger<\/a> but I hope this simple example shows the way to make our <a href=\"http:\/\/en.wikipedia.org\/wiki\/Representational_state_transfer\">REST<\/a> services self-documented and easily consumable with minimal efforts. Many thanks to <a href=\"http:\/\/swagger.wordnik.com\/\">Wordnik<\/a> team for that.<\/p>\n<ul>\n<li>Source code is available on <a href=\"https:\/\/github.com\/reta\/jax-rs-2.0-swagger\">Github<\/a>.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<div style=\"border: 1px solid #D8D8D8; background: #FAFAFA; width: 100%; padding-left: 5px;\"><b><i>Reference: <\/i><\/b><a href=\"http:\/\/aredko.blogspot.com\/2013\/09\/swagger-make-developers-to-love-working.html\">Swagger: make developers love working with your REST API<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\">JCG partner<\/a> Andrey Redko at the <a href=\"http:\/\/aredko.blogspot.com\/\">Andriy Redko {devmind} <\/a> blog.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>As JAX-RS API is evolving, with version 2.0 released earlier this year under JSR-339 umbrella, it&#8217;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 &hellip;<\/p>\n","protected":false},"author":141,"featured_media":112,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[439,54],"class_list":["post-17782","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-jax-rs","tag-restful-web-services"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Swagger: make developers love working with your REST API<\/title>\n<meta name=\"description\" content=\"As JAX-RS API is evolving, with version 2.0 released earlier this year under JSR-339 umbrella, it&#039;s becoming even more easy to create REST services using\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Swagger: make developers love working with your REST API\" \/>\n<meta property=\"og:description\" content=\"As JAX-RS API is evolving, with version 2.0 released earlier this year under JSR-339 umbrella, it&#039;s becoming even more easy to create REST services using\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2013-10-03T22:00:41+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Andrey Redko\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andrey Redko\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html\"},\"author\":{\"name\":\"Andrey Redko\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\"},\"headline\":\"Swagger: make developers love working with your REST API\",\"datePublished\":\"2013-10-03T22:00:41+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html\"},\"wordCount\":804,\"commentCount\":3,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"keywords\":[\"JAX-RS\",\"RESTful Web Services\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html\",\"name\":\"Swagger: make developers love working with your REST API\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"datePublished\":\"2013-10-03T22:00:41+00:00\",\"description\":\"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\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/enterprise-java-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"java-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/10\\\/swagger-make-developers-love-working-with-your-rest-api.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Swagger: make developers love working with your REST API\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/771a6504862edc45322776832cbce413\",\"name\":\"Andrey Redko\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g\",\"caption\":\"Andrey Redko\"},\"description\":\"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\\\/EE, C#\\\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).\",\"sameAs\":[\"http:\\\/\\\/aredko.blogspot.com\\\/\",\"http:\\\/\\\/ca.linkedin.com\\\/in\\\/aredko\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/andrey-redko\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Swagger: make developers love working with your REST API","description":"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","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html","og_locale":"en_US","og_type":"article","og_title":"Swagger: make developers love working with your REST API","og_description":"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","og_url":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2013-10-03T22:00:41+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","type":"image\/jpeg"}],"author":"Andrey Redko","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Andrey Redko","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html"},"author":{"name":"Andrey Redko","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413"},"headline":"Swagger: make developers love working with your REST API","datePublished":"2013-10-03T22:00:41+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html"},"wordCount":804,"commentCount":3,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","keywords":["JAX-RS","RESTful Web Services"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html","url":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html","name":"Swagger: make developers love working with your REST API","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","datePublished":"2013-10-03T22:00:41+00:00","description":"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","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/enterprise-java-logo.jpg","width":150,"height":150,"caption":"java-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2013\/10\/swagger-make-developers-love-working-with-your-rest-api.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Swagger: make developers love working with your REST API"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/771a6504862edc45322776832cbce413","name":"Andrey Redko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/16419ce8394173028eddaeb992859862bab50cfcf74589fa9bb9a3dd8bb27518?s=96&d=mm&r=g","caption":"Andrey Redko"},"description":"Andriy is a well-grounded software developer with more then 12 years of practical experience using Java\/EE, C#\/.NET, C++, Groovy, Ruby, functional programming (Scala), databases (MySQL, PostgreSQL, Oracle) and NoSQL solutions (MongoDB, Redis).","sameAs":["http:\/\/aredko.blogspot.com\/","http:\/\/ca.linkedin.com\/in\/aredko"],"url":"https:\/\/www.javacodegeeks.com\/author\/andrey-redko"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/17782","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/141"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=17782"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/17782\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/112"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=17782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=17782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=17782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}