Search code examples
springspring-bootjax-rsswagger-uiswagger-2.0

Swagger 2 (Spring fox) adds 'es' to my API's


I was just trying to integrate Swagger into my Spring Boot (JAX-RS) project built with Gradle.I was able to generate a docker (Swagger UI) for the same as following : Swagger UI Docker

I have configured my swagger with the default settings as follows :

package com.abc;

import lombok.extern.slf4j.Slf4j;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

@EnableAutoConfiguration
@SpringBootApplication
@EnableMongoRepositories
@Slf4j
@Import({springfox.documentation.spring.data.rest.configuration.SpringDataRestConfiguration.class,springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration.class})
@EnableSwagger2
public class ServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceApplication.class, args);
    }

    public static void run(String[] args) throws Exception{
        log.info("Started application on: 8080");
    }
}

As we can see in the image for GET Events API the docker shows /eventses .. So from where it has added es to /events API which is written as :

@GET
public HashMap<String, Object> getEventList(@DefaultValue("1") @QueryParam("page") int page,
        @DefaultValue("10") @QueryParam("rpp") int rpp, @QueryParam("events") String eventIds) {
    HashMap<String, Object> eventsResultMap= new HashMap<String, Object>();

    List<Events> events = null;

    if (eventIds != null && eventIds.length() > 0) {
        List<String> eventsIdList = Arrays.asList(eventIds.split(","));
        log.info("" + eventsIdList);
        events = eventService.getEvents(eventsIdList);
    } else {
        events = eventService.getEvents(page - 1, rpp);
    }
    eventsResultMap.put("EVENTS", events);

    HashMap<String, Object> recordsMetaMap = new HashMap<String, Object>();
    recordsMetaMap.put("total", eventService.totalCount());
    recordsMetaMap.put("page", page);
    recordsMetaMap.put("rpp", rpp);
    eventsResultMap.put("_metadata", recordsMetaMap);
    log.info("The events you have queried for are:" + eventsResultMap);
    return eventsResultMap;
}

Please, guide me where I am doing wrong.What custom configs need to be done.

I have taken Reference from spring official documentation.


Solution

  • If you are using a jax-rs implementation with spring boot, you should use swagger-core jax-rs libraries rather than spring fox. Swagger team has provided very detailed instructions here on how to configure your application for different implementations like jersey, rest-easy etc. I found it very easy to integrate for jersey 2.x.

    To make your swagger documentation rich, you should try to provide as much meta data as you can using different swagger annotations as documented here. Swagger makes great use of these annotations combined with jax-rs annotations in some cases (E.g. QueryParam vs PathParam identification).

    If you let me know which jax-rs implementation you are using, I might be able to provide you some sample configuration.

    Edit:

    For Jersey 2.x you will need to add something like this in your Jersey Configuration class (which extends org.glassfish.jersey.server.ResourceConfig):

    @Bean
    public BeanConfig swaggerConfig() {
    
        register(ApiListingResource.class);
        register(SwaggerSerializers.class);
    
        BeanConfig config = new BeanConfig();
        config.setConfigId("your-config-id");
        config.setTitle( "Your Title" );
        config.setSchemes(new String[] { "https", "http" });
        config.setBasePath("your application base path E.g. /api");
        config.setResourcePackage("package to be scanned E.g. com.example");
        config.setPrettyPrint(true);
        config.setScan(true);
        return config;
    }
    

    Other than that, you will need to annotate your endpoint(service) classes with swagger annotations. E.g.

    @Path("/material")
    @Service
    @Api(value = "Material")
    public class MaterialEndpoint {
    
        @POST
        @ApiOperation(value = "Create Material")
        @ApiResponses(value = { @ApiResponse(code = 201, message = "Success", response = CreateMaterialResponse.class),
                                @ApiResponse(code = 409, message = "Failure", response = ErrorResponse.class) })
        public Response createMaterial(CreateMaterialRequest createMaterialRequest){
    // Code goes here
       }
    
    }
    

    And your entities with swagger annotations. It is upto you how rich you want your swagger documentation to be. Depending on that you can choose to annotate more or less classes.