Doing More With Springdoc-OpenAPI
Doing More With Springdoc-OpenAPI
Rendering fully qualified names in the generated swagger documentation and global exception handling using controller advice.
Join the DZone community and get the full member experience.Join For Free
In my last recent article we tried out a Spring Boot Open API 3-enabled REST project and explored some of its capabilities namely:
- Automatic JSR-303 related swagger documentation.
- How maven builds properties could be shown as project information in the swagger documentation.
In this continuation we will explore two additional Objectives namely:
- Rendering Fully Qualified names in the generated swagger documentation.
- Global Exception Handling Using Controller Advice and its related swagger documentation.
- Java 8.x.
- Maven 3.x.
The code is loosely based on the last article but there are some differences/additions to the last article. We will start by listing the new code. We will then run the application. As we walk through this tutorial listing the various artifacts we will discuss which code helped in achieving the objectives of this tutorial along with some other details.
The code is a typical java maven project and is laid out as shown below
Listing below the different artifacts one by one. Try following the above layout:
The main improvement is the @PostConstruct init() method which will cause rendering of fully qualified names for java model classes in swagger schemas. Also as noted in the future possibly after a few releases the CustomConverter call can be avoided and FQNs can be enabled by just directly invoking io.swagger.v3.core.jackson.TypeNameResolver.std.setUseFqn(true); For now however we must deal with the CustomConverter.
The key logic is in this line:
The above-discussed code is enough to achieve fully qualified names of java model classes in swagger schemas. In the future, this can be simplified as discussed earlier.
Lets now move on to the main model class — Person.java
The main changes are:
- The addition of a GET method.
- Use of some additional annotations like @Validated, @RequestParam, @NotNull, @NotBlank, @Size
Note: Use of @Validated causes validations to be applied even for the GET method parameter. After the application is complete and running play around with the above annotations. Feel free to remove them and see their effect. The GET URL can always be directly invoked using http://localhost:8080/personByLastName and http://localhost:8080/personByLastName?lastName=12345678901. For now, it's a little early. Let's continue adding remaining artifacts.
Let's discuss Global Exception handling using @ControllerAdvice and how we can achieve corresponding swagger documentation.
When we come to ExceptionHandling in Spring Controllers there are so many Exceptions possible. There may be various validation related exceptions invoked even before the actual controller code is invoked.
The controller itself my have some logic that leads to a business Exception or some Exception because of bad coding. Rather than handling these exceptions in each Controller, we are choosing to duck the Exceptions. We are choosing to centralize the exception handling be it during the controller invocation or before.
Producing below a very rudimentary ControllerAdvice — GlobalControllerAdvice.java which you can later expand upon and improve as needed.
The key thing to remember is to decorate the methods in this class with @org.springframework.web.bind.annotation.ResponseStatus which is the only hint that spring doc Open-API needs for including the appropriate models in its controller method swagger documentation.
For completeness will list below two classes referred to in this GlobalControllerAdvice.java before we attempt to start the application.
ErrorMessage.java also follows:
Let's Not Forget Application.Properties:
That completes all our code for this tutorial. Let's try it out.
mvn clean package from the command prompt or terminal. Then, execute
java -jar target\sample-0.0.1.jar.
You can also launch the application by running the SampleApplication.java class from your IDE.
Now, let's visit the Swagger UI — http://localhost:8080/swagger-ui.html. We can also visit the JSON based API-docs - http://localhost:8080/v3/api-docs. For YAML based API-docs use http://localhost:8080/v3/api-docs.yaml. These URLs are the defaults and can be changed if needed.
General usage of swagger UI is explained in the last article. In case of issues please see the Troubleshooting section at the bottom of this tutorial.
Will focus on this tutorial specific areas.
Now that the application should be running let's visit it.
The swagger UI landing screen — http://localhost:8080/swagger-ui.html.
Note the fully qualified class names.
Now let's see how controller advice has contributed to the swagger documentation.
If we were to click the schema links it will look like this.
So by adding @ResponseStatus to our ControllerAdvice methods, we can see the related schemas associated with the HTTPStatus for each of the REST controller methods documentation. How neat is that?
@ControllerAdvice also has some attributes (e.g. "assignableTypes"), which allow the
@ControllerAdvice to be applied more specifically on Controllers than globally. Currently, that behavior is not there yet, but please expect it to be there when the springdoc-openapi folks release their next version.
With the above, we have completed the two goals we had set out to achieve.
A little manual testing follows.
The Post Method
This method is designed to have automatic validations. That was tested in the last article.
This method is also designed to cause exceptions randomly just to see how the controller's advice is invoked when things go wrong.
Click the green Post button. Then click the Try it out button. Then click the blue execute button.
Note that the validation errors are crisper compared to the last article.
The validation errors are now crisper because of the logic in the controller advice.
Lets now feed it valid input. Showing here valid input for ready reference that can be copy-pasted.
Copy the valid input into the below screen as shown below and press the blue execute button.
This will cause either of the two below responses depending on whether the random exception occurs or not:
Without the exception
When the exception happened
Note again the response for the Http Status code of 500 is formatted as per logic in the ControllerAdvice.
The GET Method
Lets now examine the GET method in our Controller.
Also, note that the controller class is decorated with a @Validated annotation.
There can be a few minor limitations. I will explore one of them without spending too much time on it. As we saw in our last article as of now it does not fully cover all the JSR 303 annotations. There are other issues also some of which are not entirely due to springdoc open API but rather more likely due to the swagger UI project itself.
Let's click the blue GET button followed by the Try it out button.
Let's feed-in 12345678901 for the lastName input field and press the blue Execute button.
There can be some improvement in how the contract expected from the validations is displayed.
As discussed earlier the GET URL can always be directly invoked using http://localhost:8080/personByLastName and http://localhost:8080/personByLastName?lastName=12345678901. Give it a try to see what are the responses. Play with the annotations @Validated, @RequestParam, @NotNull, @NotBlank, @Size and see how the handling or contract changes. A spring developer who also is a user of the generated documentation will expect the documentation to be corresponding to his usage of these and other annotations.
It's possible there are some minor areas where this may not be perfect but the bigger strong vital pieces are all there. It covers openAPI 3, even Webflux, OAuth 2. It's only a question of time when through contributions and feedback this can keep only getting better.
All said and done for a fairly recent API springdoc openAPI has achieved quite a lot very elegantly. Impressive. And it does cover most of the important scenarios thoroughly.
We achieved our objective of realizing FQNs or fully qualified names for java classes and also saw how to integrate the documentation with global exception handling leveraging Controller Advice.
- Ensure prerequisites.
- If using the Eclipse IDE, we might need to do a Maven update on the project after creating all the files.
- In the Swagger UI, if you are unable to access the “Schema” definitions link, it might be because you need to come out of the “try it out “ mode. Click on one or two Cancel buttons that might be visible.
- Ensure you use http://localhost:8080/swagger-ui.html for this tutorial.
Source Code is here: https://github.com/teq-niq/sample/tree/springdoc-openapi-doingmore.
Git Clone URL: https://github.com/teq-niq/sample.git.
Opinions expressed by DZone contributors are their own.