Reputation: 1421
I have openapi 3.0 specification in yaml format and my application that generates code from it. Everything works fine except generation of swagger ui. I use spring-fox for its generation, but it seems like it generates swagger ui 2.0 version from controllers, that are generated from openapi specification.
How can I generate swagger ui directly from my 3.0 spec and not from controllers, that are generated from 3.0 openapi spec?
Upvotes: 9
Views: 9488
Reputation: 1421
Well I have solved the problem (the solution is pretty cumbersome though).
First of all I added swagger ui webjar -
<plugin>
<!-- Download Swagger UI webjar. -->
<artifactId>maven-dependency-plugin</artifactId>
<version>${maven-dependency-plugin.version}</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.webjars</groupId>
<artifactId>swagger-ui</artifactId>
<version>${swagger-ui.version}</version>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Then I transform my yaml specification to json format and copy it to swagger-ui webjar directory:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>4.0.0-beta3</version>
<executions>
<execution>
<id>generate-spec</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${openapi-spec-file-location}</inputSpec>
<validateSpec>true</validateSpec>
<generatorName>openapi</generatorName>
<output>${project.build.directory}/classes/META-INF/resources/webjars/swagger-ui/${swagger-ui.version}</output>
</configuration>
</execution>
</executions>
</plugin>
Next we need to set specification path in swagger-ui. According to swagger-ui API we can pass spec
JSON variable instead of url. So to initialize this spec
variable and to edit swagger ui rendering I use replacer plugin in maven:
<plugin>
<!-- Replace the OpenAPI specification example URL with the local one. -->
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>replace</goal>
</goals>
</execution>
</executions>
<configuration>
<includes>
<!-- Static index html with swagger UI rendering and OAS in JSON format. -->
<include>${project.build.directory}/classes/META-INF/resources/webjars/swagger-ui/${swagger-ui.version}/index.html</include>
<include>${project.build.directory}/classes/META-INF/resources/webjars/swagger-ui/${swagger-ui.version}/openapi.json</include>
</includes>
<regexFlags>
<regexFlag>CASE_INSENSITIVE</regexFlag>
<regexFlag>MULTILINE</regexFlag>
</regexFlags>
<replacements>
<!-- This replacement imports spec json variable into static html page. -->
<replacement>
<token><script></token>
<value><script src="./openapi.json"> </script><script></value>
</replacement>
<!-- This part replaces url input variable with spec variable. -->
<replacement>
<token>url:\s"https:\/\/petstore\.swagger\.io\/v2\/swagger\.json"</token>
<value>spec: spec</value>
</replacement>
<replacement>
<!-- This replacement initializes spec variable, that will be passed to swagger ui index.html. -->
<token>^\{</token>
<value>spec = {</value>
</replacement>
</replacements>
</configuration>
</plugin>
So at this step after build we got static resource with swagger ui. Last thing to do is to serve it with Spring.
@Configuration
@EnableWebMvc
public class SwaggerConfiguration implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/swagger-ui/3.22.0/");
}
//this method was introduced just for convenient swagger ui access. Without it swagger ui can be accessed with /index.html GET call
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/swagger-ui.html").setViewName("forward:/index.html");
}
}
So this is it. It would be great if you comment this answer and point on how to simplify this procedure.
Upvotes: 13