From 3b15de3d3cd18bc718bc7a7ababafa23237212c1 Mon Sep 17 00:00:00 2001 From: Teodora Onaca Date: Tue, 5 Apr 2016 11:58:48 +0200 Subject: [PATCH 1/8] Added new blog post --- _posts/2016-04-05-generate-swagger.md | 177 ++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 _posts/2016-04-05-generate-swagger.md diff --git a/_posts/2016-04-05-generate-swagger.md b/_posts/2016-04-05-generate-swagger.md new file mode 100644 index 0000000..c8833ad --- /dev/null +++ b/_posts/2016-04-05-generate-swagger.md @@ -0,0 +1,177 @@ + +--- +layout: post +title: Generating Swagger from your API +subtitle: How to quickly generate the swagger documentation from your existing API. +category: howto +tags: [devops] +author: teodora_onaca +author_email: teodora.onaca@haufe-lexware.com +header-img: "images/bg-post.old.jpg" +--- + +If you already have an existing API and you just want to generate the swagger documentation from it, there are a couple easy steps to make it work. First off, you should be familiar with Swagger and, in particular, with [swagger-core](https://github.com/swagger-api/swagger-core). Assuming that you coded your REST API using JAX-RS, based on which was your library of choice (Jersey or RESTEasy), there are several [guides](https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-JAX-RS-Project-Setup-1.5.X) available to get you set up very fast. + +In our case, working with RESTEasy, it was a matter of adding the maven dependencies: + + + + io.swagger + swagger-jaxrs + 1.5.8 + + + + io.swagger + swagger-jaxrs + 1.5.8 + + + +Note: please make sure to set the jar version to the latest one available, so that the latest bug fixes are included. + +In order to hook up swagger-core in the application, there are multiple solutions, the easiest of which is to just use a custom `Application` subclass. + + + + public class SwaggerTestApplication extends Application { + + public SwaggerTestApplication() { + BeanConfig beanConfig = new BeanConfig(); + beanConfig.setVersion("1.0"); + beanConfig.setSchemes(new String[] { "http" }); + beanConfig.setTitle("My API"); + beanConfig.setBasePath("/TestSwagger"); + beanConfig.setResourcePackage("com.haufe.demo.resources"); + beanConfig.setScan(true); + } + + @Override + public Set> getClasses() { + HashSet> set = new HashSet>(); + + set.add(Resource.class); + + set.add(io.swagger.jaxrs.listing.ApiListingResource.class); + set.add(io.swagger.jaxrs.listing.SwaggerSerializers.class); + + return set; + } + } + + +Once this is done, you can access the generated `swagger.json` or `swagger.yaml` at the location: `http(s)://server:port/contextRoot/swagger.json` or `http(s)://server:port/contextRoot/swagger.yaml`. + +Note that the `title` element for the API is mandatory, so a missing one will generate an invalid swagger file. Also, any misuse of the annotations will generate an invalid swagger file. Any existing bugs of swagger-core will have the same effect. + +In order for a resource to be documented, other than including it in the list of classes that need to be parsed, it has to be annotated with @Api. You can check the [documentation](https://github.com/swagger-api/swagger-core/wiki/Annotations-1.5.X) for the existing annotations and use any of the described fields. + +A special case, that might give you some head aches, is the use of subresources. The REST resource code usually goes something like this: + + + @Api + @Path("resource") + public class Resource { + + @Context + ResourceContext resourceContext; + + @GET + @Produces("application/json") + @ApiOperation(value = "Returns something") + public String getResource() { + return "GET"; + } + + @POST + @Produces("application/json") + public String postResource(String something) { + return "POST" + something; + } + + @Path("/{subresource}") + @ApiOperation(value = "Returns a subresource") + public SubResource getSubResource() { + return resourceContext.getResource(SubResource.class); + } + + } + + + @Api + public class SubResource { + + @PathParam("subresource") + private String subresourceName; + + @GET + @Produces("application/json") + @ApiOperation(value = "Returns subresource something") + public String getSubresource() { + return "GET " + subresourceName; + } + + + @POST + @Produces("application/json") + @ApiOperation(value = "Posts subresource something") + public String postSubresource(String something) { + return "POST " + subresourceName + something; + } + } + + +The swagger parser works like a charm if it finds the @Path and @GET and @POST annotations where it thinks they should be. In the case depicted above, the subresource is returned from the parent resource and does not have a @Path annotation at the class level. A lower version of swagger-core will generate an invalid swagger file, so please use the latest version for a correct code generation. If you want to make you life a bit harder and you have a path that goes deeper, something like /resource/{subresource}/{subsubresource}, things might get a bit more complicated. + +In the Subresource class, you might have a @PathParam for holding the value of the {subresource}. The Subsubresource class might want to do the same. In this case, the generated swagger file will contain the same parameter twice, which results in an invalid swagger file. It will look like this: + + parameters: + - name: "subresource" + in: "path" + required: true + type: "string" + - name: "subsubresource" + in: "path" + required: true + type: "string" + - in: "body" + name: "body" + required: false + schema: + type: "string" + - name: "subresource" + in: "path" + required: true + type: "string" + + +In order to fix this, use `@ApiParam(hidden=true)` for the subresource `@PathParam` in the `Subsubresource` class. See below. + + + @Api + public class SubSubResource { + + @ApiParam(hidden=true) + @PathParam("subresource") + private String subresourceName; + + @PathParam("subsubresource") + private String subsubresourceName; + + @GET + @Produces("application/json") + @ApiOperation(value = "Returns subsubresource something") + public String getSomethingw() { + return "GET " + subresourceName + "/" + subsubresourceName; + } + + @POST + @Produces("application/json") + @ApiOperation(value = "Posts subsubresource something") + public String postSomethingw(String something) { + return "POST " + subresourceName + "/" + subsubresourceName + " " +something; + } + } + + +There might be more tips and tricks that you will discover once you start using the annotations for your API, but it will not be a slow learning curve and once you are familiar with swagger (both spec and core) you will be able to document your API really fast. \ No newline at end of file From d47c6b97084c1b3ccabe55719d8e69852c78a0a6 Mon Sep 17 00:00:00 2001 From: Teodora Onaca Date: Tue, 5 Apr 2016 12:05:26 +0200 Subject: [PATCH 2/8] Update 2016-04-05-generate-swagger.md --- _posts/2016-04-05-generate-swagger.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/_posts/2016-04-05-generate-swagger.md b/_posts/2016-04-05-generate-swagger.md index c8833ad..1b224b1 100644 --- a/_posts/2016-04-05-generate-swagger.md +++ b/_posts/2016-04-05-generate-swagger.md @@ -1,5 +1,4 @@ - ---- +--- layout: post title: Generating Swagger from your API subtitle: How to quickly generate the swagger documentation from your existing API. @@ -8,7 +7,7 @@ tags: [devops] author: teodora_onaca author_email: teodora.onaca@haufe-lexware.com header-img: "images/bg-post.old.jpg" ---- +--- If you already have an existing API and you just want to generate the swagger documentation from it, there are a couple easy steps to make it work. First off, you should be familiar with Swagger and, in particular, with [swagger-core](https://github.com/swagger-api/swagger-core). Assuming that you coded your REST API using JAX-RS, based on which was your library of choice (Jersey or RESTEasy), there are several [guides](https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-JAX-RS-Project-Setup-1.5.X) available to get you set up very fast. @@ -174,4 +173,4 @@ In order to fix this, use `@ApiParam(hidden=true)` for the subresource `@PathPar } -There might be more tips and tricks that you will discover once you start using the annotations for your API, but it will not be a slow learning curve and once you are familiar with swagger (both spec and core) you will be able to document your API really fast. \ No newline at end of file +There might be more tips and tricks that you will discover once you start using the annotations for your API, but it will not be a slow learning curve and once you are familiar with swagger (both spec and core) you will be able to document your API really fast. From 4e54bc8b48ec3c8a193808d6b462610288f8a280 Mon Sep 17 00:00:00 2001 From: Teodora Onaca Date: Tue, 5 Apr 2016 12:10:14 +0200 Subject: [PATCH 3/8] Update 2016-04-05-generate-swagger.md --- _posts/2016-04-05-generate-swagger.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_posts/2016-04-05-generate-swagger.md b/_posts/2016-04-05-generate-swagger.md index 1b224b1..abec152 100644 --- a/_posts/2016-04-05-generate-swagger.md +++ b/_posts/2016-04-05-generate-swagger.md @@ -3,10 +3,10 @@ layout: post title: Generating Swagger from your API subtitle: How to quickly generate the swagger documentation from your existing API. category: howto -tags: [devops] +tags: [dev] author: teodora_onaca author_email: teodora.onaca@haufe-lexware.com -header-img: "images/bg-post.old.jpg" +header-img: "images/bg-post.jpg" --- If you already have an existing API and you just want to generate the swagger documentation from it, there are a couple easy steps to make it work. First off, you should be familiar with Swagger and, in particular, with [swagger-core](https://github.com/swagger-api/swagger-core). Assuming that you coded your REST API using JAX-RS, based on which was your library of choice (Jersey or RESTEasy), there are several [guides](https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-JAX-RS-Project-Setup-1.5.X) available to get you set up very fast. From c7302ca93ce2b7d4c965eaaea1c9040e40a634d4 Mon Sep 17 00:00:00 2001 From: Teodora Onaca Date: Tue, 5 Apr 2016 12:11:53 +0200 Subject: [PATCH 4/8] Update 2016-04-05-generate-swagger.md --- _posts/2016-04-05-generate-swagger.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/_posts/2016-04-05-generate-swagger.md b/_posts/2016-04-05-generate-swagger.md index abec152..fde62b5 100644 --- a/_posts/2016-04-05-generate-swagger.md +++ b/_posts/2016-04-05-generate-swagger.md @@ -32,7 +32,7 @@ Note: please make sure to set the jar version to the latest one available, so th In order to hook up swagger-core in the application, there are multiple solutions, the easiest of which is to just use a custom `Application` subclass. - +```java public class SwaggerTestApplication extends Application { public SwaggerTestApplication() { @@ -58,7 +58,7 @@ In order to hook up swagger-core in the application, there are multiple solution } } - +``` Once this is done, you can access the generated `swagger.json` or `swagger.yaml` at the location: `http(s)://server:port/contextRoot/swagger.json` or `http(s)://server:port/contextRoot/swagger.yaml`. Note that the `title` element for the API is mandatory, so a missing one will generate an invalid swagger file. Also, any misuse of the annotations will generate an invalid swagger file. Any existing bugs of swagger-core will have the same effect. @@ -67,7 +67,7 @@ In order for a resource to be documented, other than including it in the list of A special case, that might give you some head aches, is the use of subresources. The REST resource code usually goes something like this: - +```java @Api @Path("resource") public class Resource { @@ -118,7 +118,7 @@ A special case, that might give you some head aches, is the use of subresources. return "POST " + subresourceName + something; } } - +``` The swagger parser works like a charm if it finds the @Path and @GET and @POST annotations where it thinks they should be. In the case depicted above, the subresource is returned from the parent resource and does not have a @Path annotation at the class level. A lower version of swagger-core will generate an invalid swagger file, so please use the latest version for a correct code generation. If you want to make you life a bit harder and you have a path that goes deeper, something like /resource/{subresource}/{subsubresource}, things might get a bit more complicated. @@ -146,7 +146,7 @@ In the Subresource class, you might have a @PathParam for holding the value of t In order to fix this, use `@ApiParam(hidden=true)` for the subresource `@PathParam` in the `Subsubresource` class. See below. - +```java @Api public class SubSubResource { @@ -171,6 +171,6 @@ In order to fix this, use `@ApiParam(hidden=true)` for the subresource `@PathPar return "POST " + subresourceName + "/" + subsubresourceName + " " +something; } } - +``` There might be more tips and tricks that you will discover once you start using the annotations for your API, but it will not be a slow learning curve and once you are familiar with swagger (both spec and core) you will be able to document your API really fast. From b2ca524cd7da39b9bb4044b58919af40991ea053 Mon Sep 17 00:00:00 2001 From: Teodora Onaca Date: Tue, 5 Apr 2016 12:12:42 +0200 Subject: [PATCH 5/8] Update 2016-04-05-generate-swagger.md --- _posts/2016-04-05-generate-swagger.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_posts/2016-04-05-generate-swagger.md b/_posts/2016-04-05-generate-swagger.md index fde62b5..a8005c4 100644 --- a/_posts/2016-04-05-generate-swagger.md +++ b/_posts/2016-04-05-generate-swagger.md @@ -32,7 +32,7 @@ Note: please make sure to set the jar version to the latest one available, so th In order to hook up swagger-core in the application, there are multiple solutions, the easiest of which is to just use a custom `Application` subclass. -```java +``` java public class SwaggerTestApplication extends Application { public SwaggerTestApplication() { @@ -67,7 +67,7 @@ In order for a resource to be documented, other than including it in the list of A special case, that might give you some head aches, is the use of subresources. The REST resource code usually goes something like this: -```java +``` java @Api @Path("resource") public class Resource { @@ -146,7 +146,7 @@ In the Subresource class, you might have a @PathParam for holding the value of t In order to fix this, use `@ApiParam(hidden=true)` for the subresource `@PathParam` in the `Subsubresource` class. See below. -```java +``` java @Api public class SubSubResource { From 9199fd6df8983d6984b2737410211e27ed7f57be Mon Sep 17 00:00:00 2001 From: Teodora Onaca Date: Tue, 5 Apr 2016 12:13:47 +0200 Subject: [PATCH 6/8] Update 2016-04-05-generate-swagger.md --- _posts/2016-04-05-generate-swagger.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_posts/2016-04-05-generate-swagger.md b/_posts/2016-04-05-generate-swagger.md index a8005c4..668afb5 100644 --- a/_posts/2016-04-05-generate-swagger.md +++ b/_posts/2016-04-05-generate-swagger.md @@ -3,7 +3,7 @@ layout: post title: Generating Swagger from your API subtitle: How to quickly generate the swagger documentation from your existing API. category: howto -tags: [dev] +tags: [api] author: teodora_onaca author_email: teodora.onaca@haufe-lexware.com header-img: "images/bg-post.jpg" From 6300be5ea3a649a441db6e7a0abec55ca7094488 Mon Sep 17 00:00:00 2001 From: Teodora Onaca Date: Tue, 5 Apr 2016 12:14:43 +0200 Subject: [PATCH 7/8] Update 2016-04-05-generate-swagger.md --- _posts/2016-04-05-generate-swagger.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_posts/2016-04-05-generate-swagger.md b/_posts/2016-04-05-generate-swagger.md index 668afb5..296f2c4 100644 --- a/_posts/2016-04-05-generate-swagger.md +++ b/_posts/2016-04-05-generate-swagger.md @@ -4,7 +4,7 @@ title: Generating Swagger from your API subtitle: How to quickly generate the swagger documentation from your existing API. category: howto tags: [api] -author: teodora_onaca +author: Tora Onaca author_email: teodora.onaca@haufe-lexware.com header-img: "images/bg-post.jpg" --- From 2c073ef06d027a98b30ca650f38d269d3639cabb Mon Sep 17 00:00:00 2001 From: Teodora Onaca Date: Wed, 6 Apr 2016 13:20:15 +0200 Subject: [PATCH 8/8] Rename 2016-04-05-generate-swagger.md to 2016-04-07-generate-swagger.md --- ...6-04-05-generate-swagger.md => 2016-04-07-generate-swagger.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename _posts/{2016-04-05-generate-swagger.md => 2016-04-07-generate-swagger.md} (100%) diff --git a/_posts/2016-04-05-generate-swagger.md b/_posts/2016-04-07-generate-swagger.md similarity index 100% rename from _posts/2016-04-05-generate-swagger.md rename to _posts/2016-04-07-generate-swagger.md