Unable to link Swagger-ui to my swagger Spring mvc project

10,536

This issue seems old but just to share, with the recent version of swagger-springmvc and springmvc-ui, it has become very easy and less complicated to integrate swagger & swagger-ui with your web service to see in production REST api documentation.

@EnableSwagger annotation is added that enables swagger-springmvc out of the box. The generated swagger json Resource Listing can be accessed at /api-docs.

You may refer to following link for the steps on integrating swagger-springmvc and swagger-ui with your spring mvc project. https://github.com/martypitt/swagger-springmvc

Share:
10,536
Tekateyy
Author by

Tekateyy

Updated on June 17, 2022

Comments

  • Tekateyy
    Tekateyy almost 2 years

    I'm currently creating an API Rest using Eclipse, Spring Framework MVC, and I just added to my project swagger. I can access the json result of swagger but I need to add swagger ui.

    Here are all my files creating for swagger-springmvc:

    WebAppInitializer.java

    public class WebAppInitializer implements WebApplicationInitializer {
    
        private AnnotationConfigWebApplicationContext ctx = null;
    
        @Override
        public void onStartup(final ServletContext sc) throws ServletException {
    
            System.setProperty("spring.profiles.active", "web");
    
            // Create the 'root' Spring application context
            ctx = new AnnotationConfigWebApplicationContext();
            ctx.register(SpringBaseWebConfiguration.class,
                    SpringSwaggerConfiguration.class);
    
            // Manages the lifecycle
            sc.addListener(new ContextLoaderListener(ctx));
            sc.addListener(new ContextCleanupListener());
    
            // Spring WebMVC
            ServletRegistration.Dynamic springWebMvc = sc.addServlet("ws",
                    new DispatcherServlet(ctx));
            springWebMvc.setLoadOnStartup(1);
            springWebMvc.addMapping("/ws/*");
            springWebMvc.setAsyncSupported(true);
        }
    
        @PreDestroy
        protected final void cleanup() {
            if (ctx != null) {
                ctx.close();
            }
        }
    }
    

    SpringSwaggerConfiguration.java

    public class SpringSwaggerConfiguration {
        public static final List<String> DEFAULT_INCLUDE_PATTERNS = Arrays
                .asList(new String[]{"/com/sa/rnd/dark/resources/.*"});
        public static final String SWAGGER_GROUP = "ApiDark";
        public static final String RELATIVE_GROUP = "ApiDark";
        @Autowired
        private SpringSwaggerConfig springSwaggerConfig;
    
    /**
     * Adds the jackson scala module to the MappingJackson2HttpMessageConverter
     * registered with spring Swagger core models are scala so we need to be
     * able to convert to JSON Also registers some custom serializers needed to
     * transform swagger models to swagger-ui required json format
     */
    @Bean
    public JacksonScalaSupport jacksonScalaSupport() {
        final JacksonScalaSupport jacksonScalaSupport = new JacksonScalaSupport();
        // Set to false to disable
        jacksonScalaSupport.setRegisterScalaModule(true);
        return jacksonScalaSupport;
    }
    
    /**
     * Global swagger settings
     */
    @Bean
    public SwaggerGlobalSettings swaggerGlobalSettings() {
        final SwaggerGlobalSettings swaggerGlobalSettings = new SwaggerGlobalSettings();
        swaggerGlobalSettings.setGlobalResponseMessages(springSwaggerConfig
                .defaultResponseMessages());
        swaggerGlobalSettings.setIgnorableParameterTypes(springSwaggerConfig
                .defaultIgnorableParameterTypes());
        return swaggerGlobalSettings;
    }
    
    /**
     * API Info as it appears on the swagger-ui page
     */
    private ApiInfo apiInfo() {
        return new ApiInfo(
                "Swagger Spring MVC for Dark Api",
                "Sample application demonstrating how to use swagger-springmvc in a no-XML environment.",
                "http://en.wikipedia.org/wiki/Terms_of_service",
                "[email protected]", "Apache 2.0",
                "http://www.apache.org/licenses/LICENSE-2.0.html");
    }
    
    /**
     * Configure a SwaggerApiResourceListing for each swagger instance within
     * your app. e.g. 1. private 2. external apis Required to be a spring bean
     * as spring will call the postConstruct method to bootstrap swagger
     * scanning.
     *
     * @return
     */
    @Bean
    public SwaggerApiResourceListing swaggerApiResourceListing() {
        // The group name is important and should match the group set on
        // ApiListingReferenceScanner
        // Note that swaggerCache() is by DefaultSwaggerController to serve the
        // swagger json
        final SwaggerApiResourceListing swaggerApiResourceListing = new SwaggerApiResourceListing(
                springSwaggerConfig.swaggerCache(), SWAGGER_GROUP);
    
        // Set the required swagger settings
        swaggerApiResourceListing
                .setSwaggerGlobalSettings(swaggerGlobalSettings());
    
        // Supply the API Info as it should appear on swagger-ui web page
        swaggerApiResourceListing.setApiInfo(apiInfo());
    
        // Use the default path provider
        swaggerApiResourceListing.setSwaggerPathProvider(springSwaggerConfig
                .defaultSwaggerPathProvider());
    
        // Global authorization - see the swagger documentation
        swaggerApiResourceListing.setAuthorizationTypes(authorizationTypes());
    
        // Sets up an auth context - i.e. which controller request paths to
        // apply global auth to
        swaggerApiResourceListing
                .setAuthorizationContext(authorizationContext());
    
        // Every SwaggerApiResourceListing needs an ApiListingReferenceScanner
        // to scan the spring request mappings
        swaggerApiResourceListing
                .setApiListingReferenceScanner(apiListingReferenceScanner());
        return swaggerApiResourceListing;
    }
    
    @Bean
    /**
     * The ApiListingReferenceScanner does most of the work.
     * Scans the appropriate spring RequestMappingHandlerMappings
     * Applies the correct absolute paths to the generated swagger resources
     */
    public ApiListingReferenceScanner apiListingReferenceScanner() {
        ApiListingReferenceScanner apiListingReferenceScanner = new ApiListingReferenceScanner();
    
        // Picks up all of the registered spring RequestMappingHandlerMappings
        // for
        // scanning
        apiListingReferenceScanner
                .setRequestMappingHandlerMapping(springSwaggerConfig
                        .swaggerRequestMappingHandlerMappings());
    
        // Excludes any controllers with the supplied annotations
        apiListingReferenceScanner.setExcludeAnnotations(springSwaggerConfig
                .defaultExcludeAnnotations());
    
        //
        apiListingReferenceScanner
                .setResourceGroupingStrategy(springSwaggerConfig
                        .defaultResourceGroupingStrategy());
    
        // Path provider used to generate the appropriate uri's
        apiListingReferenceScanner
                .setSwaggerPathProvider(relativeSwaggerPathProvider());
    
        // Must match the swagger group set on the SwaggerApiResourceListing
        apiListingReferenceScanner.setSwaggerGroup(SWAGGER_GROUP);
    
        // Only include paths that match the supplied regular expressions
        apiListingReferenceScanner.setIncludePatterns(DEFAULT_INCLUDE_PATTERNS);
    
        return apiListingReferenceScanner;
    }
    
    private List<AuthorizationType> authorizationTypes() {
        final List<AuthorizationType> authorizationTypes = new ArrayList<>();
        authorizationTypes.add(new BasicAuth());
        return authorizationTypes;
    }
    
    @Bean
    public AuthorizationContext authorizationContext() {
        final List<Authorization> authorizations = newArrayList();
    
        AuthorizationScope authorizationScope = new AuthorizationScope(
                "global", "accessEverything");
    
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[]{authorizationScope};
        authorizations.add(new Authorization("basic", authorizationScopes));
    
        AuthorizationContext authorizationContext = new AuthorizationContext.AuthorizationContextBuilder(
                authorizations).withIncludePatterns(DEFAULT_INCLUDE_PATTERNS)
                .build();
    
        return authorizationContext;
    }
    
    // Relative path example
    @Bean
    public SwaggerApiResourceListing relativeSwaggerApiResourceListing() {
        SwaggerApiResourceListing swaggerApiResourceListing = new SwaggerApiResourceListing(
                springSwaggerConfig.swaggerCache(), RELATIVE_GROUP);
        swaggerApiResourceListing
                .setSwaggerGlobalSettings(swaggerGlobalSettings());
        swaggerApiResourceListing
                .setSwaggerPathProvider(relativeSwaggerPathProvider());
        swaggerApiResourceListing
                .setApiListingReferenceScanner(relativeApiListingReferenceScanner());
        return swaggerApiResourceListing;
    }
    
    @Bean
    public ApiListingReferenceScanner relativeApiListingReferenceScanner() {
    
        ApiListingReferenceScanner apiListingReferenceScanner = 
                new ApiListingReferenceScanner();
    
        apiListingReferenceScanner
                .setRequestMappingHandlerMapping(springSwaggerConfig
                        .swaggerRequestMappingHandlerMappings());
    
        apiListingReferenceScanner.setExcludeAnnotations(springSwaggerConfig
                .defaultExcludeAnnotations());
    
        apiListingReferenceScanner
                .setResourceGroupingStrategy(springSwaggerConfig
                        .defaultResourceGroupingStrategy());
    
        apiListingReferenceScanner
                .setSwaggerPathProvider(relativeSwaggerPathProvider());
    
        apiListingReferenceScanner.setSwaggerGroup(RELATIVE_GROUP);
        apiListingReferenceScanner.setIncludePatterns(DEFAULT_INCLUDE_PATTERNS);
        return apiListingReferenceScanner;
    }
    
    @Bean
    public SwaggerPathProvider relativeSwaggerPathProvider() {
        return new ApiRelativeSwaggerPathProvider();
    }
    
    private class ApiRelativeSwaggerPathProvider extends
            DefaultSwaggerPathProvider {
        @Override
        public String getAppBasePath() {
            return "/ApiDark/ws";
        }
    }
    

    }

    SpringBaseWebConfiguration.java :

    @Configuration
    @ComponentScan(basePackages = {"com.sa.rnd.dark.resources",
            "com.mangofactory.swagger.configuration",
            "com.mangofactory.swagger.controllers"})
    
    @EnableWebMvc
    public class SpringBaseWebConfiguration extends WebMvcConfigurerAdapter {
        private List<HttpMessageConverter<?>> messageConverters;
    
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/**").addResourceLocations("/");
        }
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/api-docs").setViewName("redirect:index.html");
        }
    
        /**
         * The message converters for the content types we support.
         *
         * @return the message converters; returns the same list on subsequent calls
         */
        private List<HttpMessageConverter<?>> getMessageConverters() {
            if (messageConverters == null) {
                messageConverters = new ArrayList<>();
    
                final MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter = new MappingJackson2HttpMessageConverter();
                final ObjectMapper mapper = new ObjectMapper();
                mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
                mapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
                mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,
                        false);
                mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
                        false);
                mappingJacksonHttpMessageConverter.setObjectMapper(mapper);
                messageConverters.add(mappingJacksonHttpMessageConverter);
            }
            return messageConverters;
        }
    
        @Override
        public void configureMessageConverters(
                List<HttpMessageConverter<?>> converters) {
            converters.addAll(getMessageConverters());
        }
    
        @Bean
        public static PropertyPlaceholderConfigurer swaggerProperties() {
            final PropertyPlaceholderConfigurer swaggerProperties = new PropertyPlaceholderConfigurer();
            swaggerProperties.setLocation(new ClassPathResource(
                    "swagger.properties"));
            return swaggerProperties;
        }
    }
    

    Here are my 3 files to add swagger to my project, atm I just decide to check just 1 method which is :

    @Api(description = "CRUD services for containers working with WebDark",
            value = "CRUD Services Containers")
    @RestController
    @RequestMapping(value = "/container", produces = MediaType.APPLICATION_JSON_VALUE)
    public class ContainersResources {
        /**
         * Find all children of a container.
         *
         * @param containerId
         *            ID of the parent container
         * @return ApiResponse
         */
    
    
        @ApiOperation(response = ApiResponse.class,
                value = "Find all children containers of one container",
                notes = "Find all children containers of one container")
        @RequestMapping(method = RequestMethod.GET, value = "/{containerId}")
        @ResponseStatus(HttpStatus.OK)
        public @ResponseBody ApiResponse<List<ContainerModel>> getContainerChildren(
                @ApiParam(required = true, value = "The id of the container parent",
                        name = "containerId")@PathVariable("containerId") final String containerId) {
            ApiResponse<List<ContainerModel>> result = new ApiResponse<>();
            result.setMessage("getContainerChildren  method of new Api Dark");
            result.setSuccess(true);
            result.setTotal(9000);
            return result;
        }
    }
    

    My results : I can access the following url http://localhost:8080/ApiDark/ws/api-docs but I get the json value like :

    {"apiVersion":"1","swaggerVersion":"1.2","authorizations":{"basicAuth":{"type":"basicAuth"}},"info":{"title":"Swagger Spring MVC for Dark Api","description":"Sample application demonstrating how to use swagger-springmvc in a no-XML environment.","termsOfServiceUrl":"http://en.wikipedia.org/wiki/Terms_of_service","contact":"[email protected]","license":"Apache 2.0","licenseUrl":"http://www.apache.org/licenses/LICENSE-2.0.html"}}

    That's why I decided to add swagger-ui. I add the content of dist folder (taken from swagger-ui) to my src/main/webapp folder. And modify the content of index.html to point to my url :

    <script type="text/javascript">
    $(function () {
      window.swaggerUi = new SwaggerUi({
          url: "http://localhost:8080/ApiDark/ws/api-docs.json",
      dom_id: "swagger-ui-container",
    

    But I can't access to swagger-ui interface, I just have the json result... Need help to make it work please !

  • Tekateyy
    Tekateyy almost 10 years
    Thanks, but I found a work-around by redirecting the web.xml to the swagger index.html ;)
  • plzdontkillme
    plzdontkillme about 9 years
    Even though I am using @EnableSwagger, I am seeing the same issue.
  • spiderman
    spiderman over 8 years