In my last article, I gave a quick introduction to Swagger in the Spring realm. Also, we saw how the additional Maven artifact "spring-swagger-simplified" automatically leverages the validation constraint annotations used by Spring and enriches the Swagger models and Swagger UI.
Below, for a quick recap, we look at the automatic model enhancements amongst other things we had discussed in the previous article.
In this article, we will go deeper into various Swagger and Spring topics to elaborate on the value provided by the additional "spring-swagger-simplified" jar. We will then understand how to use Swagger apiInfo and manage global Spring exception handling with Swagger. Finally, we will see how the Maven artifact "spring-swagger-simplified" can be helpful in the global exception handling-related Swagger documentation.
Let's get started in the same way as last time.
We are going to refer to the following sources as starting points: Swagger 2 documentation for Spring REST API, Building a RESTful Web Service, and the previous article, Simplified Spring Swagger.
Let's repeat the steps from the last article (a reference to the completed code is also provided at the end of this article).
We need to apply two changes.
In pom.xml, please use the latest version 1.0.4 (use whatever is the latest) for spring-swagger-simplified.
Also, we are going to enhance SwaggerConfig.java by adding the below bean.
Also, we need to add these imports:
Lets now use this bean.
Below, we have the complete modified SwaggerConfig.java with an additional reference to the above bean:
As you can see, the apiInfo() bean is being passed on to docket.apiInfo(). [See line number 49 above]. Make sure you are doing the same else copy from the above SwaggerConfig.java
Let's rebuild, restart the application, and visit: http://localhost:8080/swagger-ui.html.
For now, let's comment out our dependency spring-swagger-simplified in the pom.xml using <! and -->
We will now discuss Global Exception handling using @ControllerAdvice.
Let's start by modifying the PersonController we had created last time.
Let's rebuild and rerun the application.
We are trying to simulate some complex logic that causes the controller to throw exceptions at times. Since we don't have complex real logic, we are using Random and expecting the controller to fail at times. We can test this by repeatedly invoking the execution.
Before getting around to that, you might have noticed that the Swagger UI has reverted to its default by not showing full package names after we commented out our dependency "spring-swagger-simplified."
This can even confuse Swagger if two models have the same name but different packages. While this behavior can certainly be altered by writing more Swagger configuration code, it's one of the details already taken care of by the artifact — spring-swagger-simplified — the artifact which we have currently commented out. It doesn't affect us as of now because we do not, as of yet, have two models with the same class name in different packages.
Also, you might have noticed the model has been stripped of the extra information it was showing: no min max, etc.
Let's get back to invoking the controller and seeing what happens when it fails by invoking it repeatedly.
Let's fill up valid data (keep it handy say in notepad to copy from when needed): image 13
Now, press the execute button until we get an error response, as shown here:
This is all very nice. What if you wanted to send out your own representation of the message? What if you wanted to create a log reference id and convey it in response so that you can leverage the reported log reference id and correlate quickly with server back end logs on the server? Let's say we want to do all of this in a centralized manner.
That's where @ControllerAdvice comes in. Time for some more code.
A few more related classes referred by the ControllerAdvice follow.
Let's restart the application and try again repeatedly until we get the problem response.
Yes, it works. But there is an issue. What is this "undocumented" text? Let's look at what our Swagger UI is showing as the default response codes for our controller.
Where is the documentation in above regarding the "Problem" model we are using when reporting exceptions? Also, what about customizing the above-listed codes and details? Yes, it's possible in different ways.
Let's edit our SwaggerConfig.java and add some new code:
Also, please add the following imports:
Below, we show the completed SwaggerConfig.java with an additional invocation of the changeGlobalResponses() method:
As can be seen above, when building the docket, we are changing the global responses in line 45. Make sure you are doing the same, or else copy from the above SwaggerConfig.java
Slightly better. All it proves so far is that we can customize the response codes by one centralized means. (There are multiple means). But where is the Problem model documented?
You might have also noticed this annoying message that has been flashing whenever we enter the controller.
It's basically complaining that under model definitions, there is no model named Problem or ErrorMessage.
There is only a Person model. Again, there are multiple means of introducing the "Problem" model into our model definitions.
Let's do a few changes.
Firstly, let's edit our pom.xml and uncomment our artifact we had previously commented.
Secondly, let's edit our SwaggerConfig slightly using the method "resolveName."
From:
Let's change it to:
That's because spring-swagger-simplified also forces Swagger to use fully qualified names for the classes.
Let's build and restart. This is what we see now:
Now, let's look at our response codes for the controller.
How did this happen? The spring-swagger-simplified artifact also detects @ControllerAdvice decorated classes and can derive the needed models automatically.
Our automatic min, max, etc. is also back in the model definitions, as shown below. (You can verify by clicking on the "Model" link in above screen — next to "Example Value")
Of course, you can inspect the model definitions in various other places also in the Swagger UI with the same automatic detail of min, max, and other constraints, which cause tighter contracts between APIs.
Note: We just leveraged standard javax.validation.constraints annotations. We did not clutter our code with swagger annotations to convey these constraints information in swagger documentation.
That concludes this tutorial.
Again, this was only a brief introduction to the capabilities of this jar along with being a tutorial on Swagger apiInfo and Spring Global Exception handling integration with Swagger. For a more complete understanding of the various features, please try out this more detailed example project with many more features — https://bitbucket.org/tek-nik/simplified-swagger-examples/.
We will next discuss the usage of Swagger in OAuth space along with Spring and spring-swagger-simplified. With this, we will start covering the various other spring and swagger integration topics one by one and the role of spring-swagger-simplified jar.
Stay tuned!.
Meanwhile, the complete code for this article can be found here, i.e. in branch "doingmore."