diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java index 58be3e69377..4a991727756 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java @@ -18,7 +18,6 @@ package org.openapitools.codegen.languages; import com.samskivert.mustache.Mustache; -import com.samskivert.mustache.Template; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; @@ -41,8 +40,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; -import java.io.IOException; -import java.io.Writer; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; @@ -71,7 +68,7 @@ public class SpringCodegen extends AbstractJavaCodegen public static final String SPRING_BOOT = "spring-boot"; public static final String SPRING_CLOUD_LIBRARY = "spring-cloud"; public static final String IMPLICIT_HEADERS = "implicitHeaders"; - public static final String SWAGGER_DOCKET_CONFIG = "swaggerDocketConfig"; + public static final String OPENAPI_DOCKET_CONFIG = "swaggerDocketConfig"; protected String title = "OpenAPI Spring"; protected String configPackage = "org.openapitools.configuration"; @@ -87,7 +84,7 @@ public class SpringCodegen extends AbstractJavaCodegen protected boolean useTags = false; protected boolean useBeanValidation = true; protected boolean implicitHeaders = false; - protected boolean swaggerDocketConfig = false; + protected boolean openapiDocketConfig = false; protected boolean useOptional = false; public SpringCodegen() { @@ -116,7 +113,7 @@ public class SpringCodegen extends AbstractJavaCodegen cliOptions.add(CliOption.newBoolean(USE_TAGS, "use tags for creating interface and controller classnames")); cliOptions.add(CliOption.newBoolean(USE_BEANVALIDATION, "Use BeanValidation API annotations")); cliOptions.add(CliOption.newBoolean(IMPLICIT_HEADERS, "Use of @ApiImplicitParams for headers.")); - cliOptions.add(CliOption.newBoolean(SWAGGER_DOCKET_CONFIG, "Generate Spring Swagger Docket configuration class.")); + cliOptions.add(CliOption.newBoolean(OPENAPI_DOCKET_CONFIG, "Generate Spring OpenAPI Docket configuration class.")); cliOptions.add(CliOption.newBoolean(USE_OPTIONAL, "Use Optional container for optional parameters")); @@ -235,8 +232,8 @@ public class SpringCodegen extends AbstractJavaCodegen this.setImplicitHeaders(Boolean.valueOf(additionalProperties.get(IMPLICIT_HEADERS).toString())); } - if (additionalProperties.containsKey(SWAGGER_DOCKET_CONFIG)) { - this.setSwaggerDocketConfig(Boolean.valueOf(additionalProperties.get(SWAGGER_DOCKET_CONFIG).toString())); + if (additionalProperties.containsKey(OPENAPI_DOCKET_CONFIG)) { + this.setOpenapiDocketConfig(Boolean.valueOf(additionalProperties.get(OPENAPI_DOCKET_CONFIG).toString())); } typeMapping.put("file", "Resource"); @@ -283,7 +280,7 @@ public class SpringCodegen extends AbstractJavaCodegen supportingFiles.add(new SupportingFile("RFC3339DateFormat.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "RFC3339DateFormat.java")); supportingFiles.add(new SupportingFile("application.properties", - ("src.main.resources").replace(".", java.io.File.separator), "swagger.properties")); + ("src.main.resources").replace(".", java.io.File.separator), "openapi.properties")); } if (library.equals(SPRING_CLOUD_LIBRARY)) { supportingFiles.add(new SupportingFile("apiKeyRequestInterceptor.mustache", @@ -310,7 +307,7 @@ public class SpringCodegen extends AbstractJavaCodegen (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "OpenAPIDocumentationConfig.java")); } } - } else if (this.swaggerDocketConfig && !library.equals(SPRING_CLOUD_LIBRARY) && !this.reactive) { + } else if (this.openapiDocketConfig && !library.equals(SPRING_CLOUD_LIBRARY) && !this.reactive) { supportingFiles.add(new SupportingFile("openapiDocumentationConfig.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "OpenAPIDocumentationConfig.java")); } @@ -378,18 +375,10 @@ public class SpringCodegen extends AbstractJavaCodegen } // add lambda for mustache templates - additionalProperties.put("lambdaEscapeDoubleQuote", new Mustache.Lambda() { - @Override - public void execute(Template.Fragment fragment, Writer writer) throws IOException { - writer.write(fragment.execute().replaceAll("\"", Matcher.quoteReplacement("\\\""))); - } - }); - additionalProperties.put("lambdaRemoveLineBreak", new Mustache.Lambda() { - @Override - public void execute(Template.Fragment fragment, Writer writer) throws IOException { - writer.write(fragment.execute().replaceAll("\\r|\\n", "")); - } - }); + additionalProperties.put("lambdaEscapeDoubleQuote", + (Mustache.Lambda) (fragment, writer) -> writer.write(fragment.execute().replaceAll("\"", Matcher.quoteReplacement("\\\"")))); + additionalProperties.put("lambdaRemoveLineBreak", + (Mustache.Lambda) (fragment, writer) -> writer.write(fragment.execute().replaceAll("\\r|\\n", ""))); } @Override @@ -409,11 +398,7 @@ public class SpringCodegen extends AbstractJavaCodegen } else { co.subresourceOperation = !co.path.isEmpty(); } - List opList = operations.get(basePath); - if (opList == null) { - opList = new ArrayList(); - operations.put(basePath, opList); - } + List opList = operations.computeIfAbsent(basePath, k -> new ArrayList<>()); opList.add(co); co.baseName = basePath; } else { @@ -674,8 +659,8 @@ public class SpringCodegen extends AbstractJavaCodegen this.implicitHeaders = implicitHeaders; } - public void setSwaggerDocketConfig(boolean swaggerDocketConfig) { - this.swaggerDocketConfig = swaggerDocketConfig; + public void setOpenapiDocketConfig(boolean openapiDocketConfig) { + this.openapiDocketConfig = openapiDocketConfig; } @Override diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache index 0a04a112fee..4c9e6271d59 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/apiController.mustache @@ -13,6 +13,9 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +{{/jdk8}} +import org.springframework.web.bind.annotation.RequestMapping; +{{^jdk8}} import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; {{/jdk8}} @@ -39,6 +42,9 @@ import java.util.concurrent.Callable; {{/jdk8}} {{>generatedAnnotation}} @Controller +{{=<% %>=}} +@RequestMapping("${openapi.<%title%>.base-path:<%>defaultBasePath%>}") +<%={{ }}=%> {{#operations}} public class {{classname}}Controller implements {{classname}} { {{#isDelegate}} diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/application.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/application.mustache index 4db5be911cb..726647a19eb 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/application.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/application.mustache @@ -1,5 +1,4 @@ springfox.documentation.swagger.v2.path=/api-docs -server.{{#java8}}servlet.{{/java8}}context-path={{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}} server.port={{serverPort}} spring.jackson.date-format={{basePackage}}.RFC3339DateFormat spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/README.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/README.mustache index f4827164a1e..2f401bb621b 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/README.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/README.mustache @@ -12,7 +12,7 @@ The underlying library integrating OpenAPI to SpringBoot is [springfox](https:// Start your server as an simple java application -{{#reactive}} +{{^reactive}} You can view the api documentation in swagger-ui by pointing to http://localhost:8080/ diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/defaultBasePath.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/defaultBasePath.mustache new file mode 100644 index 00000000000..3c7185bd628 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-boot/defaultBasePath.mustache @@ -0,0 +1 @@ +{{contextPath}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-mvc/defaultBasePath.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-mvc/defaultBasePath.mustache new file mode 100644 index 00000000000..35ec3b9d758 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-mvc/defaultBasePath.mustache @@ -0,0 +1 @@ +/ \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-mvc/openapiUiConfiguration.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-mvc/openapiUiConfiguration.mustache index 09fa3ed0c12..2092ed66ffc 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-mvc/openapiUiConfiguration.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/libraries/spring-mvc/openapiUiConfiguration.mustache @@ -28,7 +28,7 @@ import java.util.List; @Configuration @ComponentScan(basePackages = "{{apiPackage}}") @EnableWebMvc -@PropertySource("classpath:swagger.properties") +@PropertySource("classpath:openapi.properties") @Import(OpenAPIDocumentationConfig.class) public class OpenAPIUiConfiguration extends WebMvcConfigurerAdapter { private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" }; diff --git a/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache b/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache index e576906d5b8..7dd911a1ae5 100644 --- a/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache +++ b/modules/openapi-generator/src/main/resources/JavaSpring/openapiDocumentationConfig.mustache @@ -1,19 +1,24 @@ package {{configPackage}}; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.Paths; +import springfox.documentation.spring.web.paths.RelativePathProvider; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; -{{#useOptional}} +{{#useOptional}} import java.util.Optional; {{/useOptional}} +import javax.servlet.ServletContext; {{>generatedAnnotation}} @Configuration @@ -33,12 +38,15 @@ public class OpenAPIDocumentationConfig { } @Bean - public Docket customImplementation(){ +{{=<% %>=}} + public Docket customImplementation(ServletContext servletContext, @Value("${openapi.<%title%>.base-path:<%>defaultBasePath%>}") String basePath) { +<%={{ }}=%> return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("{{apiPackage}}")) .build() {{#java8}} + .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) {{/java8}} @@ -56,4 +64,25 @@ public class OpenAPIDocumentationConfig { .apiInfo(apiInfo()); } + class BasePathAwareRelativePathProvider extends RelativePathProvider { + private String basePath; + + public BasePathAwareRelativePathProvider(ServletContext servletContext, String basePath) { + super(servletContext); + this.basePath = basePath; + } + + @Override + protected String applicationPath() { + return Paths.removeAdjacentForwardSlashes(UriComponentsBuilder.fromPath(super.applicationPath()).path(basePath).build().toString()); + } + + @Override + public String getOperationPath(String operationPath) { + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("/"); + return Paths.removeAdjacentForwardSlashes( + uriComponentsBuilder.path(operationPath.replaceFirst("^" + basePath, "")).build().toString()); + } + } + } diff --git a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/AnotherFakeApiController.java b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/AnotherFakeApiController.java index a00284b15e7..d0e45c0458b 100644 --- a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/AnotherFakeApiController.java +++ b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/AnotherFakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class AnotherFakeApiController implements AnotherFakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/FakeApiController.java b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/FakeApiController.java index b9cfa40cde3..16d3908be7c 100644 --- a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/FakeApiController.java +++ b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/FakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class FakeApiController implements FakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java index f3b7fa0a14a..709a1981f75 100644 --- a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java +++ b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class FakeClassnameTestApiController implements FakeClassnameTestApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/PetApiController.java index 2afbaa68af5..e6d6429de31 100644 --- a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/PetApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class PetApiController implements PetApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/StoreApiController.java index a56c2f1d774..c4cd0487fb8 100644 --- a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/StoreApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class StoreApiController implements StoreApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/UserApiController.java index 0577fc8f345..07044abe99c 100644 --- a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/api/UserApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class UserApiController implements UserApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java index e5dbf694c6a..3ad72e74828 100644 --- a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java +++ b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java @@ -1,16 +1,22 @@ package org.openapitools.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.Paths; +import springfox.documentation.spring.web.paths.RelativePathProvider; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +import javax.servlet.ServletContext; + @Configuration @EnableSwagger2 @@ -29,14 +35,36 @@ public class OpenAPIDocumentationConfig { } @Bean - public Docket customImplementation(){ + public Docket customImplementation(ServletContext servletContext, @Value("${openapi.openAPIPetstore.base-path:/}") String basePath) { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("org.openapitools.api")) .build() + .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) .apiInfo(apiInfo()); } + class BasePathAwareRelativePathProvider extends RelativePathProvider { + private String basePath; + + public BasePathAwareRelativePathProvider(ServletContext servletContext, String basePath) { + super(servletContext); + this.basePath = basePath; + } + + @Override + protected String applicationPath() { + return Paths.removeAdjacentForwardSlashes(UriComponentsBuilder.fromPath(super.applicationPath()).path(basePath).build().toString()); + } + + @Override + public String getOperationPath(String operationPath) { + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("/"); + return Paths.removeAdjacentForwardSlashes( + uriComponentsBuilder.path(operationPath.replaceFirst("^" + basePath, "")).build().toString()); + } + } + } diff --git a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java index e8aacb697c8..2840efe3f19 100644 --- a/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java +++ b/samples/server/petstore/spring-mvc-j8-async/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java @@ -20,7 +20,7 @@ import java.util.List; @Configuration @ComponentScan(basePackages = "org.openapitools.api") @EnableWebMvc -@PropertySource("classpath:swagger.properties") +@PropertySource("classpath:openapi.properties") @Import(OpenAPIDocumentationConfig.class) public class OpenAPIUiConfiguration extends WebMvcConfigurerAdapter { private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" }; diff --git a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/AnotherFakeApiController.java b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/AnotherFakeApiController.java index a00284b15e7..d0e45c0458b 100644 --- a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/AnotherFakeApiController.java +++ b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/AnotherFakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class AnotherFakeApiController implements AnotherFakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/FakeApiController.java b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/FakeApiController.java index b9cfa40cde3..16d3908be7c 100644 --- a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/FakeApiController.java +++ b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/FakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class FakeApiController implements FakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java index f3b7fa0a14a..709a1981f75 100644 --- a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java +++ b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class FakeClassnameTestApiController implements FakeClassnameTestApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/PetApiController.java index 2afbaa68af5..e6d6429de31 100644 --- a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/PetApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class PetApiController implements PetApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/StoreApiController.java index a56c2f1d774..c4cd0487fb8 100644 --- a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/StoreApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class StoreApiController implements StoreApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/UserApiController.java index 0577fc8f345..07044abe99c 100644 --- a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/api/UserApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class UserApiController implements UserApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java index e5dbf694c6a..3ad72e74828 100644 --- a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java +++ b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java @@ -1,16 +1,22 @@ package org.openapitools.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.Paths; +import springfox.documentation.spring.web.paths.RelativePathProvider; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +import javax.servlet.ServletContext; + @Configuration @EnableSwagger2 @@ -29,14 +35,36 @@ public class OpenAPIDocumentationConfig { } @Bean - public Docket customImplementation(){ + public Docket customImplementation(ServletContext servletContext, @Value("${openapi.openAPIPetstore.base-path:/}") String basePath) { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("org.openapitools.api")) .build() + .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) .apiInfo(apiInfo()); } + class BasePathAwareRelativePathProvider extends RelativePathProvider { + private String basePath; + + public BasePathAwareRelativePathProvider(ServletContext servletContext, String basePath) { + super(servletContext); + this.basePath = basePath; + } + + @Override + protected String applicationPath() { + return Paths.removeAdjacentForwardSlashes(UriComponentsBuilder.fromPath(super.applicationPath()).path(basePath).build().toString()); + } + + @Override + public String getOperationPath(String operationPath) { + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("/"); + return Paths.removeAdjacentForwardSlashes( + uriComponentsBuilder.path(operationPath.replaceFirst("^" + basePath, "")).build().toString()); + } + } + } diff --git a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java index e8aacb697c8..2840efe3f19 100644 --- a/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java +++ b/samples/server/petstore/spring-mvc-j8-localdatetime/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java @@ -20,7 +20,7 @@ import java.util.List; @Configuration @ComponentScan(basePackages = "org.openapitools.api") @EnableWebMvc -@PropertySource("classpath:swagger.properties") +@PropertySource("classpath:openapi.properties") @Import(OpenAPIDocumentationConfig.class) public class OpenAPIUiConfiguration extends WebMvcConfigurerAdapter { private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" }; diff --git a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/AnotherFakeApiController.java b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/AnotherFakeApiController.java index 7f65672fd6d..b2bef577409 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/AnotherFakeApiController.java +++ b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/AnotherFakeApiController.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -20,6 +21,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class AnotherFakeApiController implements AnotherFakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/FakeApiController.java b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/FakeApiController.java index fbc64cebd7b..624be6d6926 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/FakeApiController.java +++ b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/FakeApiController.java @@ -16,6 +16,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -27,6 +28,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class FakeApiController implements FakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java index 0e62baafdcd..1b4e5db5f8b 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java +++ b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -20,6 +21,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class FakeClassnameTestApiController implements FakeClassnameTestApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/PetApiController.java index 30fc3b600f0..20ea8d651a4 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/PetApiController.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -22,6 +23,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class PetApiController implements PetApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/StoreApiController.java index df35dbc4a7f..ba21fb432e8 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/StoreApiController.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -21,6 +22,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class StoreApiController implements StoreApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/UserApiController.java index c8107c570f6..eb642e22c13 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/api/UserApiController.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -21,6 +22,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/}") public class UserApiController implements UserApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java index b36e2ad7d3e..68e2e36f370 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java +++ b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java @@ -1,16 +1,22 @@ package org.openapitools.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.Paths; +import springfox.documentation.spring.web.paths.RelativePathProvider; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +import javax.servlet.ServletContext; + @Configuration @EnableSwagger2 @@ -29,11 +35,12 @@ public class OpenAPIDocumentationConfig { } @Bean - public Docket customImplementation(){ + public Docket customImplementation(ServletContext servletContext, @Value("${openapi.openAPIPetstore.base-path:/}") String basePath) { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("org.openapitools.api")) .build() + .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) .directModelSubstitute(org.threeten.bp.LocalDate.class, java.sql.Date.class) @@ -41,4 +48,25 @@ public class OpenAPIDocumentationConfig { .apiInfo(apiInfo()); } + class BasePathAwareRelativePathProvider extends RelativePathProvider { + private String basePath; + + public BasePathAwareRelativePathProvider(ServletContext servletContext, String basePath) { + super(servletContext); + this.basePath = basePath; + } + + @Override + protected String applicationPath() { + return Paths.removeAdjacentForwardSlashes(UriComponentsBuilder.fromPath(super.applicationPath()).path(basePath).build().toString()); + } + + @Override + public String getOperationPath(String operationPath) { + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("/"); + return Paths.removeAdjacentForwardSlashes( + uriComponentsBuilder.path(operationPath.replaceFirst("^" + basePath, "")).build().toString()); + } + } + } diff --git a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java index c17d539e2fc..d67b926b347 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java +++ b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/OpenAPIUiConfiguration.java @@ -24,7 +24,7 @@ import java.util.List; @Configuration @ComponentScan(basePackages = "org.openapitools.api") @EnableWebMvc -@PropertySource("classpath:swagger.properties") +@PropertySource("classpath:openapi.properties") @Import(OpenAPIDocumentationConfig.class) public class OpenAPIUiConfiguration extends WebMvcConfigurerAdapter { private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" }; diff --git a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/SwaggerUiConfiguration.java b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/SwaggerUiConfiguration.java index 041df1dc441..380983cce8e 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/SwaggerUiConfiguration.java +++ b/samples/server/petstore/spring-mvc/src/main/java/org/openapitools/configuration/SwaggerUiConfiguration.java @@ -24,7 +24,7 @@ import java.util.List; @Configuration @ComponentScan(basePackages = "org.openapitools.api") @EnableWebMvc -@PropertySource("classpath:swagger.properties") +@PropertySource("classpath:openapi.properties") @Import(SwaggerDocumentationConfig.class) public class SwaggerUiConfiguration extends WebMvcConfigurerAdapter { private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" }; diff --git a/samples/server/petstore/springboot-beanvalidation/README.md b/samples/server/petstore/springboot-beanvalidation/README.md index a12a59c79ed..f7a85c93303 100644 --- a/samples/server/petstore/springboot-beanvalidation/README.md +++ b/samples/server/petstore/springboot-beanvalidation/README.md @@ -12,4 +12,7 @@ The underlying library integrating OpenAPI to SpringBoot is [springfox](https:// Start your server as an simple java application +You can view the api documentation in swagger-ui by pointing to +http://localhost:8080/ + Change default port value in application.properties \ No newline at end of file diff --git a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/AnotherFakeApiController.java b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/AnotherFakeApiController.java index 7f65672fd6d..4be8a57963d 100644 --- a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/AnotherFakeApiController.java +++ b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/AnotherFakeApiController.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -20,6 +21,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class AnotherFakeApiController implements AnotherFakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeApiController.java b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeApiController.java index fbc64cebd7b..26af39e6eb1 100644 --- a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeApiController.java +++ b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeApiController.java @@ -16,6 +16,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -27,6 +28,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeApiController implements FakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java index 0e62baafdcd..d10cfe7c51d 100644 --- a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java +++ b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -20,6 +21,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeClassnameTestApiController implements FakeClassnameTestApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/PetApiController.java index 30fc3b600f0..b01cdf874b3 100644 --- a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/PetApiController.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -22,6 +23,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class PetApiController implements PetApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/StoreApiController.java index df35dbc4a7f..34e3cb7d8fc 100644 --- a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/StoreApiController.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -21,6 +22,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class StoreApiController implements StoreApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/UserApiController.java index c8107c570f6..69da699f5ee 100644 --- a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/api/UserApiController.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.context.request.NativeWebRequest; @@ -21,6 +22,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class UserApiController implements UserApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java index b36e2ad7d3e..3307fc00b59 100644 --- a/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java +++ b/samples/server/petstore/springboot-beanvalidation/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java @@ -1,16 +1,22 @@ package org.openapitools.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.Paths; +import springfox.documentation.spring.web.paths.RelativePathProvider; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +import javax.servlet.ServletContext; + @Configuration @EnableSwagger2 @@ -29,11 +35,12 @@ public class OpenAPIDocumentationConfig { } @Bean - public Docket customImplementation(){ + public Docket customImplementation(ServletContext servletContext, @Value("${openapi.openAPIPetstore.base-path:/v2}") String basePath) { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("org.openapitools.api")) .build() + .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) .directModelSubstitute(org.threeten.bp.LocalDate.class, java.sql.Date.class) @@ -41,4 +48,25 @@ public class OpenAPIDocumentationConfig { .apiInfo(apiInfo()); } + class BasePathAwareRelativePathProvider extends RelativePathProvider { + private String basePath; + + public BasePathAwareRelativePathProvider(ServletContext servletContext, String basePath) { + super(servletContext); + this.basePath = basePath; + } + + @Override + protected String applicationPath() { + return Paths.removeAdjacentForwardSlashes(UriComponentsBuilder.fromPath(super.applicationPath()).path(basePath).build().toString()); + } + + @Override + public String getOperationPath(String operationPath) { + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("/"); + return Paths.removeAdjacentForwardSlashes( + uriComponentsBuilder.path(operationPath.replaceFirst("^" + basePath, "")).build().toString()); + } + } + } diff --git a/samples/server/petstore/springboot-beanvalidation/src/main/resources/application.properties b/samples/server/petstore/springboot-beanvalidation/src/main/resources/application.properties index f2f5ff7328b..13b0dc6ab96 100644 --- a/samples/server/petstore/springboot-beanvalidation/src/main/resources/application.properties +++ b/samples/server/petstore/springboot-beanvalidation/src/main/resources/application.properties @@ -1,5 +1,4 @@ springfox.documentation.swagger.v2.path=/api-docs -server.servlet.context-path=/v2 server.port=80 spring.jackson.date-format=org.openapitools.RFC3339DateFormat spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false \ No newline at end of file diff --git a/samples/server/petstore/springboot-delegate-j8/README.md b/samples/server/petstore/springboot-delegate-j8/README.md index a12a59c79ed..f7a85c93303 100644 --- a/samples/server/petstore/springboot-delegate-j8/README.md +++ b/samples/server/petstore/springboot-delegate-j8/README.md @@ -12,4 +12,7 @@ The underlying library integrating OpenAPI to SpringBoot is [springfox](https:// Start your server as an simple java application +You can view the api documentation in swagger-ui by pointing to +http://localhost:8080/ + Change default port value in application.properties \ No newline at end of file diff --git a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/AnotherFakeApiController.java b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/AnotherFakeApiController.java index 50a5978d498..3bc2df15df6 100644 --- a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/AnotherFakeApiController.java +++ b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/AnotherFakeApiController.java @@ -1,9 +1,11 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class AnotherFakeApiController implements AnotherFakeApi { private final AnotherFakeApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApiController.java b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApiController.java index f90d556720e..75c4b5587be 100644 --- a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApiController.java +++ b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeApiController.java @@ -1,9 +1,11 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeApiController implements FakeApi { private final FakeApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java index 334fab72828..6566359e66f 100644 --- a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java +++ b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java @@ -1,9 +1,11 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeClassnameTestApiController implements FakeClassnameTestApi { private final FakeClassnameTestApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/PetApiController.java index d5a156c7cca..a8c8c3765a6 100644 --- a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/PetApiController.java @@ -1,9 +1,11 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class PetApiController implements PetApi { private final PetApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/StoreApiController.java index 679d48ecd9b..d00b4841fc0 100644 --- a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/StoreApiController.java @@ -1,9 +1,11 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class StoreApiController implements StoreApi { private final StoreApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/UserApiController.java index ac8d11dfc90..5bd8c1f9f57 100644 --- a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/api/UserApiController.java @@ -1,9 +1,11 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class UserApiController implements UserApi { private final UserApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java index e5dbf694c6a..77dca61d0e5 100644 --- a/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java +++ b/samples/server/petstore/springboot-delegate-j8/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java @@ -1,16 +1,22 @@ package org.openapitools.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.Paths; +import springfox.documentation.spring.web.paths.RelativePathProvider; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +import javax.servlet.ServletContext; + @Configuration @EnableSwagger2 @@ -29,14 +35,36 @@ public class OpenAPIDocumentationConfig { } @Bean - public Docket customImplementation(){ + public Docket customImplementation(ServletContext servletContext, @Value("${openapi.openAPIPetstore.base-path:/v2}") String basePath) { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("org.openapitools.api")) .build() + .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) .apiInfo(apiInfo()); } + class BasePathAwareRelativePathProvider extends RelativePathProvider { + private String basePath; + + public BasePathAwareRelativePathProvider(ServletContext servletContext, String basePath) { + super(servletContext); + this.basePath = basePath; + } + + @Override + protected String applicationPath() { + return Paths.removeAdjacentForwardSlashes(UriComponentsBuilder.fromPath(super.applicationPath()).path(basePath).build().toString()); + } + + @Override + public String getOperationPath(String operationPath) { + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("/"); + return Paths.removeAdjacentForwardSlashes( + uriComponentsBuilder.path(operationPath.replaceFirst("^" + basePath, "")).build().toString()); + } + } + } diff --git a/samples/server/petstore/springboot-delegate-j8/src/main/resources/application.properties b/samples/server/petstore/springboot-delegate-j8/src/main/resources/application.properties index f2f5ff7328b..13b0dc6ab96 100644 --- a/samples/server/petstore/springboot-delegate-j8/src/main/resources/application.properties +++ b/samples/server/petstore/springboot-delegate-j8/src/main/resources/application.properties @@ -1,5 +1,4 @@ springfox.documentation.swagger.v2.path=/api-docs -server.servlet.context-path=/v2 server.port=80 spring.jackson.date-format=org.openapitools.RFC3339DateFormat spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false \ No newline at end of file diff --git a/samples/server/petstore/springboot-delegate/README.md b/samples/server/petstore/springboot-delegate/README.md index a12a59c79ed..f7a85c93303 100644 --- a/samples/server/petstore/springboot-delegate/README.md +++ b/samples/server/petstore/springboot-delegate/README.md @@ -12,4 +12,7 @@ The underlying library integrating OpenAPI to SpringBoot is [springfox](https:// Start your server as an simple java application +You can view the api documentation in swagger-ui by pointing to +http://localhost:8080/ + Change default port value in application.properties \ No newline at end of file diff --git a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/AnotherFakeApiController.java b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/AnotherFakeApiController.java index fb85017a81e..a1397240205 100644 --- a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/AnotherFakeApiController.java +++ b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/AnotherFakeApiController.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; @@ -19,6 +20,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class AnotherFakeApiController implements AnotherFakeApi { private final AnotherFakeApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiController.java b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiController.java index 446c63d3f55..d18e35cff3e 100644 --- a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiController.java +++ b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeApiController.java @@ -16,6 +16,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; @@ -26,6 +27,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeApiController implements FakeApi { private final FakeApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java index 27ccc2f2ed1..a04a4d61282 100644 --- a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java +++ b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; @@ -19,6 +20,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeClassnameTestApiController implements FakeClassnameTestApi { private final FakeClassnameTestApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/PetApiController.java index 79c2450240e..4e56a593144 100644 --- a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/PetApiController.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; @@ -21,6 +22,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class PetApiController implements PetApi { private final PetApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/StoreApiController.java index c15bb5761e4..4b0fe81cd79 100644 --- a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/StoreApiController.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; @@ -20,6 +21,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class StoreApiController implements StoreApi { private final StoreApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/UserApiController.java index 2abfb197ee3..114cdb93081 100644 --- a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/api/UserApiController.java @@ -10,6 +10,7 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; @@ -20,6 +21,7 @@ import java.util.List; import java.util.Map; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class UserApiController implements UserApi { private final UserApiDelegate delegate; diff --git a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java index b36e2ad7d3e..3307fc00b59 100644 --- a/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java +++ b/samples/server/petstore/springboot-delegate/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java @@ -1,16 +1,22 @@ package org.openapitools.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.Paths; +import springfox.documentation.spring.web.paths.RelativePathProvider; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +import javax.servlet.ServletContext; + @Configuration @EnableSwagger2 @@ -29,11 +35,12 @@ public class OpenAPIDocumentationConfig { } @Bean - public Docket customImplementation(){ + public Docket customImplementation(ServletContext servletContext, @Value("${openapi.openAPIPetstore.base-path:/v2}") String basePath) { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("org.openapitools.api")) .build() + .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) .directModelSubstitute(org.threeten.bp.LocalDate.class, java.sql.Date.class) @@ -41,4 +48,25 @@ public class OpenAPIDocumentationConfig { .apiInfo(apiInfo()); } + class BasePathAwareRelativePathProvider extends RelativePathProvider { + private String basePath; + + public BasePathAwareRelativePathProvider(ServletContext servletContext, String basePath) { + super(servletContext); + this.basePath = basePath; + } + + @Override + protected String applicationPath() { + return Paths.removeAdjacentForwardSlashes(UriComponentsBuilder.fromPath(super.applicationPath()).path(basePath).build().toString()); + } + + @Override + public String getOperationPath(String operationPath) { + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("/"); + return Paths.removeAdjacentForwardSlashes( + uriComponentsBuilder.path(operationPath.replaceFirst("^" + basePath, "")).build().toString()); + } + } + } diff --git a/samples/server/petstore/springboot-delegate/src/main/resources/application.properties b/samples/server/petstore/springboot-delegate/src/main/resources/application.properties index f2f5ff7328b..13b0dc6ab96 100644 --- a/samples/server/petstore/springboot-delegate/src/main/resources/application.properties +++ b/samples/server/petstore/springboot-delegate/src/main/resources/application.properties @@ -1,5 +1,4 @@ springfox.documentation.swagger.v2.path=/api-docs -server.servlet.context-path=/v2 server.port=80 spring.jackson.date-format=org.openapitools.RFC3339DateFormat spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false \ No newline at end of file diff --git a/samples/server/petstore/springboot-implicitHeaders/README.md b/samples/server/petstore/springboot-implicitHeaders/README.md index a12a59c79ed..f7a85c93303 100644 --- a/samples/server/petstore/springboot-implicitHeaders/README.md +++ b/samples/server/petstore/springboot-implicitHeaders/README.md @@ -12,4 +12,7 @@ The underlying library integrating OpenAPI to SpringBoot is [springfox](https:// Start your server as an simple java application +You can view the api documentation in swagger-ui by pointing to +http://localhost:8080/ + Change default port value in application.properties \ No newline at end of file diff --git a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/AnotherFakeApiController.java b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/AnotherFakeApiController.java index a00284b15e7..fff17a03c07 100644 --- a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/AnotherFakeApiController.java +++ b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/AnotherFakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class AnotherFakeApiController implements AnotherFakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApiController.java b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApiController.java index b9cfa40cde3..36a7304885e 100644 --- a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApiController.java +++ b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeApiController implements FakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java index f3b7fa0a14a..f4cccda6d62 100644 --- a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java +++ b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeClassnameTestApiController implements FakeClassnameTestApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/PetApiController.java index 2afbaa68af5..1138014eedf 100644 --- a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/PetApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class PetApiController implements PetApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/StoreApiController.java index a56c2f1d774..7b2593af1b1 100644 --- a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/StoreApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class StoreApiController implements StoreApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/UserApiController.java index 0577fc8f345..5eca262e432 100644 --- a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/api/UserApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class UserApiController implements UserApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java index e5dbf694c6a..77dca61d0e5 100644 --- a/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java +++ b/samples/server/petstore/springboot-implicitHeaders/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java @@ -1,16 +1,22 @@ package org.openapitools.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.Paths; +import springfox.documentation.spring.web.paths.RelativePathProvider; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +import javax.servlet.ServletContext; + @Configuration @EnableSwagger2 @@ -29,14 +35,36 @@ public class OpenAPIDocumentationConfig { } @Bean - public Docket customImplementation(){ + public Docket customImplementation(ServletContext servletContext, @Value("${openapi.openAPIPetstore.base-path:/v2}") String basePath) { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("org.openapitools.api")) .build() + .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) .apiInfo(apiInfo()); } + class BasePathAwareRelativePathProvider extends RelativePathProvider { + private String basePath; + + public BasePathAwareRelativePathProvider(ServletContext servletContext, String basePath) { + super(servletContext); + this.basePath = basePath; + } + + @Override + protected String applicationPath() { + return Paths.removeAdjacentForwardSlashes(UriComponentsBuilder.fromPath(super.applicationPath()).path(basePath).build().toString()); + } + + @Override + public String getOperationPath(String operationPath) { + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("/"); + return Paths.removeAdjacentForwardSlashes( + uriComponentsBuilder.path(operationPath.replaceFirst("^" + basePath, "")).build().toString()); + } + } + } diff --git a/samples/server/petstore/springboot-implicitHeaders/src/main/resources/application.properties b/samples/server/petstore/springboot-implicitHeaders/src/main/resources/application.properties index f2f5ff7328b..13b0dc6ab96 100644 --- a/samples/server/petstore/springboot-implicitHeaders/src/main/resources/application.properties +++ b/samples/server/petstore/springboot-implicitHeaders/src/main/resources/application.properties @@ -1,5 +1,4 @@ springfox.documentation.swagger.v2.path=/api-docs -server.servlet.context-path=/v2 server.port=80 spring.jackson.date-format=org.openapitools.RFC3339DateFormat spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false \ No newline at end of file diff --git a/samples/server/petstore/springboot-reactive/README.md b/samples/server/petstore/springboot-reactive/README.md index f7a85c93303..a12a59c79ed 100644 --- a/samples/server/petstore/springboot-reactive/README.md +++ b/samples/server/petstore/springboot-reactive/README.md @@ -12,7 +12,4 @@ The underlying library integrating OpenAPI to SpringBoot is [springfox](https:// Start your server as an simple java application -You can view the api documentation in swagger-ui by pointing to -http://localhost:8080/ - Change default port value in application.properties \ No newline at end of file diff --git a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/AnotherFakeApiController.java b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/AnotherFakeApiController.java index 531d3f668df..997ef4798bb 100644 --- a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/AnotherFakeApiController.java +++ b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/AnotherFakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class AnotherFakeApiController implements AnotherFakeApi { } diff --git a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApiController.java b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApiController.java index 6218dc43017..9d4b5917508 100644 --- a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApiController.java +++ b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeApiController implements FakeApi { } diff --git a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java index 816d59d44c5..905d8b60bd7 100644 --- a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java +++ b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeClassnameTestApiController implements FakeClassnameTestApi { } diff --git a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/PetApiController.java index 1596645761f..dba362fde18 100644 --- a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/PetApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class PetApiController implements PetApi { } diff --git a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/StoreApiController.java index c2eb7de8a1a..f6d80aa6cce 100644 --- a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/StoreApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class StoreApiController implements StoreApi { } diff --git a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/UserApiController.java index 0463a6b148e..570a05d8d37 100644 --- a/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/springboot-reactive/src/main/java/org/openapitools/api/UserApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class UserApiController implements UserApi { } diff --git a/samples/server/petstore/springboot-reactive/src/main/resources/application.properties b/samples/server/petstore/springboot-reactive/src/main/resources/application.properties index f2f5ff7328b..13b0dc6ab96 100644 --- a/samples/server/petstore/springboot-reactive/src/main/resources/application.properties +++ b/samples/server/petstore/springboot-reactive/src/main/resources/application.properties @@ -1,5 +1,4 @@ springfox.documentation.swagger.v2.path=/api-docs -server.servlet.context-path=/v2 server.port=80 spring.jackson.date-format=org.openapitools.RFC3339DateFormat spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false \ No newline at end of file diff --git a/samples/server/petstore/springboot-useoptional/README.md b/samples/server/petstore/springboot-useoptional/README.md index a12a59c79ed..f7a85c93303 100644 --- a/samples/server/petstore/springboot-useoptional/README.md +++ b/samples/server/petstore/springboot-useoptional/README.md @@ -12,4 +12,7 @@ The underlying library integrating OpenAPI to SpringBoot is [springfox](https:// Start your server as an simple java application +You can view the api documentation in swagger-ui by pointing to +http://localhost:8080/ + Change default port value in application.properties \ No newline at end of file diff --git a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/AnotherFakeApiController.java b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/AnotherFakeApiController.java index a00284b15e7..fff17a03c07 100644 --- a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/AnotherFakeApiController.java +++ b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/AnotherFakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class AnotherFakeApiController implements AnotherFakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeApiController.java b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeApiController.java index b9cfa40cde3..36a7304885e 100644 --- a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeApiController.java +++ b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeApiController implements FakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java index f3b7fa0a14a..f4cccda6d62 100644 --- a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java +++ b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeClassnameTestApiController implements FakeClassnameTestApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/PetApiController.java index 2afbaa68af5..1138014eedf 100644 --- a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/PetApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class PetApiController implements PetApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/StoreApiController.java index a56c2f1d774..7b2593af1b1 100644 --- a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/StoreApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class StoreApiController implements StoreApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/UserApiController.java index 0577fc8f345..5eca262e432 100644 --- a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/api/UserApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class UserApiController implements UserApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java index 13e16885a87..0a9d8095dd5 100644 --- a/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java +++ b/samples/server/petstore/springboot-useoptional/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java @@ -1,17 +1,22 @@ package org.openapitools.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.Paths; +import springfox.documentation.spring.web.paths.RelativePathProvider; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; import java.util.Optional; +import javax.servlet.ServletContext; @Configuration @@ -31,15 +36,37 @@ public class OpenAPIDocumentationConfig { } @Bean - public Docket customImplementation(){ + public Docket customImplementation(ServletContext servletContext, @Value("${openapi.openAPIPetstore.base-path:/v2}") String basePath) { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("org.openapitools.api")) .build() + .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) .genericModelSubstitutes(Optional.class) .apiInfo(apiInfo()); } + class BasePathAwareRelativePathProvider extends RelativePathProvider { + private String basePath; + + public BasePathAwareRelativePathProvider(ServletContext servletContext, String basePath) { + super(servletContext); + this.basePath = basePath; + } + + @Override + protected String applicationPath() { + return Paths.removeAdjacentForwardSlashes(UriComponentsBuilder.fromPath(super.applicationPath()).path(basePath).build().toString()); + } + + @Override + public String getOperationPath(String operationPath) { + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("/"); + return Paths.removeAdjacentForwardSlashes( + uriComponentsBuilder.path(operationPath.replaceFirst("^" + basePath, "")).build().toString()); + } + } + } diff --git a/samples/server/petstore/springboot-useoptional/src/main/resources/application.properties b/samples/server/petstore/springboot-useoptional/src/main/resources/application.properties index f2f5ff7328b..13b0dc6ab96 100644 --- a/samples/server/petstore/springboot-useoptional/src/main/resources/application.properties +++ b/samples/server/petstore/springboot-useoptional/src/main/resources/application.properties @@ -1,5 +1,4 @@ springfox.documentation.swagger.v2.path=/api-docs -server.servlet.context-path=/v2 server.port=80 spring.jackson.date-format=org.openapitools.RFC3339DateFormat spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false \ No newline at end of file diff --git a/samples/server/petstore/springboot/README.md b/samples/server/petstore/springboot/README.md index a12a59c79ed..f7a85c93303 100644 --- a/samples/server/petstore/springboot/README.md +++ b/samples/server/petstore/springboot/README.md @@ -12,4 +12,7 @@ The underlying library integrating OpenAPI to SpringBoot is [springfox](https:// Start your server as an simple java application +You can view the api documentation in swagger-ui by pointing to +http://localhost:8080/ + Change default port value in application.properties \ No newline at end of file diff --git a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/AnotherFakeApiController.java b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/AnotherFakeApiController.java index a00284b15e7..fff17a03c07 100644 --- a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/AnotherFakeApiController.java +++ b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/AnotherFakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class AnotherFakeApiController implements AnotherFakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeApiController.java b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeApiController.java index b9cfa40cde3..36a7304885e 100644 --- a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeApiController.java +++ b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeApiController implements FakeApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java index f3b7fa0a14a..f4cccda6d62 100644 --- a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java +++ b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/FakeClassnameTestApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class FakeClassnameTestApiController implements FakeClassnameTestApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/PetApiController.java b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/PetApiController.java index 2afbaa68af5..1138014eedf 100644 --- a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/PetApiController.java +++ b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/PetApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class PetApiController implements PetApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/StoreApiController.java b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/StoreApiController.java index a56c2f1d774..7b2593af1b1 100644 --- a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/StoreApiController.java +++ b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/StoreApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class StoreApiController implements StoreApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/UserApiController.java b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/UserApiController.java index 0577fc8f345..5eca262e432 100644 --- a/samples/server/petstore/springboot/src/main/java/org/openapitools/api/UserApiController.java +++ b/samples/server/petstore/springboot/src/main/java/org/openapitools/api/UserApiController.java @@ -1,10 +1,12 @@ package org.openapitools.api; import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.NativeWebRequest; import java.util.Optional; @Controller +@RequestMapping("${openapi.openAPIPetstore.base-path:/v2}") public class UserApiController implements UserApi { private final NativeWebRequest request; diff --git a/samples/server/petstore/springboot/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java b/samples/server/petstore/springboot/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java index e5dbf694c6a..77dca61d0e5 100644 --- a/samples/server/petstore/springboot/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java +++ b/samples/server/petstore/springboot/src/main/java/org/openapitools/configuration/OpenAPIDocumentationConfig.java @@ -1,16 +1,22 @@ package org.openapitools.configuration; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.util.UriComponentsBuilder; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.paths.Paths; +import springfox.documentation.spring.web.paths.RelativePathProvider; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; +import javax.servlet.ServletContext; + @Configuration @EnableSwagger2 @@ -29,14 +35,36 @@ public class OpenAPIDocumentationConfig { } @Bean - public Docket customImplementation(){ + public Docket customImplementation(ServletContext servletContext, @Value("${openapi.openAPIPetstore.base-path:/v2}") String basePath) { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage("org.openapitools.api")) .build() + .pathProvider(new BasePathAwareRelativePathProvider(servletContext, basePath)) .directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class) .directModelSubstitute(java.time.OffsetDateTime.class, java.util.Date.class) .apiInfo(apiInfo()); } + class BasePathAwareRelativePathProvider extends RelativePathProvider { + private String basePath; + + public BasePathAwareRelativePathProvider(ServletContext servletContext, String basePath) { + super(servletContext); + this.basePath = basePath; + } + + @Override + protected String applicationPath() { + return Paths.removeAdjacentForwardSlashes(UriComponentsBuilder.fromPath(super.applicationPath()).path(basePath).build().toString()); + } + + @Override + public String getOperationPath(String operationPath) { + UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.fromPath("/"); + return Paths.removeAdjacentForwardSlashes( + uriComponentsBuilder.path(operationPath.replaceFirst("^" + basePath, "")).build().toString()); + } + } + } diff --git a/samples/server/petstore/springboot/src/main/resources/application.properties b/samples/server/petstore/springboot/src/main/resources/application.properties index f2f5ff7328b..13b0dc6ab96 100644 --- a/samples/server/petstore/springboot/src/main/resources/application.properties +++ b/samples/server/petstore/springboot/src/main/resources/application.properties @@ -1,5 +1,4 @@ springfox.documentation.swagger.v2.path=/api-docs -server.servlet.context-path=/v2 server.port=80 spring.jackson.date-format=org.openapitools.RFC3339DateFormat spring.jackson.serialization.WRITE_DATES_AS_TIMESTAMPS=false \ No newline at end of file