Search code examples
javaspring-bootswagger-uiswagger-2.0springfox

How to arrange the order of Docket's groupName displayed in Swagger UI


I'm setting two different Docket API in one spring boot application. I gave one Docket "Test" groupName and leave the other, so it ended up as "default" in the Swagger UI.

My question is, how to arrange the order of these Dockets in the UI.

At first, I thought it was arranged alphabetically, but it's not. I keep changing the name, but the order is unknown.

    @Bean
    public Docket myAPI(){
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage("anything"))
            .paths(PathSelectors.regex("/v1/anything.*"))
            .build()
            .apiInfo(apiInfo());
        buildGlobalParameter(docket);
        buildGlobalResponseMessage(docket);
        return docket;
    }

    @Bean
    public Docket testAPI(){
        Docket tDocket = new Docket(DocumentationType.SWAGGER_2)
            .groupName("Test Card")
            .select()
            .apis(RequestHandlerSelectors.basePackage("anything"))
            .paths(PathSelectors.regex("/v1/anything2*"))
            .build()
            .apiInfo(apiTestInfo());
        buildGlobalParameter(tDocket);
        buildGlobalResponseMessage(tDocket);
        return tDocket;
    }

https://i.sstatic.net/bAmNm.jpg

I am sorry, I cannot post the image yet, so I am leaving the direct URL.

When I run the spring boot application, I want the default Swagger UI's displayed to be the "default" one.


Solution

  • Dockets are indeed sorted alphabetically - so are the dockets from your example. If the group names of dockets are "Test" and "default", the dockets will be displayed on the Swagger UI page also in that order. In case the name of your explicitly named docket was "test" (instead of "Test" or "Test Card"), then they would be displayed like you expected.

    The reason for that behavior is that strings are by default compared using String.compareTo(String) method which is case-sensitive - considering that, as the first characters of docket names from your example are 'T' and 'd', docket with name "Test" should really appear before the one with the name "default" because their Unicode values are 84 and 100, respectively.

    On the other hand, the answer for your question is unfortunately negative - especially if you are using Swagger2 or older. There is proposal/pull-request for removing docket sorting and that change will be included in Swagger3 (according to the response of the current main contributor of Springfox to the shared pull-request). For now you have 3 dirty options to achieve that dockets are displayed in wanted order:

    • add corresponding number as prefix to the each docket group name - using this approach you should also define explicit name for your default docket, so its name could be like "1 default" and the name of other docket would be "2 Test". If you'll have more than 9 dockets, keep in mind adding leading zero(es) in case that immediately after prefix/number is located a character with Unicode value higher than 58 (for whitespace from this example is not necessary since its value is 32)
    • add corresponding number of spaces as prefix to the each docket group name (the higher the amount, the later the position will be) - this is actually pretty good workaround since leading spaces will do the trick for ordering dockets in desired order, but they will be trimmed before displaying so the drop-down menu on the Swagger UI won't be weird-looking. If you are having many dockets and it is hassle to manually insert specific amount of spaces in string literal of each group name, you can use some of the solutions for character repetition from here
    • if you can't wait for Swagger3 and previous options seem too dirty or as partial workarounds for you, you can extract some component classes from Swagger2 and adapt them accordingly, so the dockets wouldn't be displayed in the drop-down menu sorted alphabetically, but rather in the same order as they were defined/injected with the @Bean annotation. On the previously-mentioned pull-request and in its comments you can find what minor changes have to be done. Except exporting 2 mentioned classes to your project, you'll also have to extract corresponding used classes with non-public access modifier. Note: if you'll do everything right, you should end up with exactly 5 classes. Also, don't forget to annotate extracted and customized @Component classes with the @Primary annotation!