From 192409965a1964d06c4bfcdc84d16e26aee45cd1 Mon Sep 17 00:00:00 2001 From: Hugo Mercado Date: Fri, 30 Jun 2023 18:18:17 -0500 Subject: [PATCH] added support for spring-boot v3 --- .../v3/generators/java/SpringCodegen.java | 26 ++++- .../spring-boot3/LocalDateConverter.mustache | 21 ++++ .../LocalDateTimeConverter.mustache | 21 ++++ .../libraries/spring-boot3/README.mustache | 37 +++++++ .../spring-boot3/application.mustache | 3 + .../spring-boot3/homeController.mustache | 16 ++++ .../spring-boot3/openAPISpringBoot.mustache | 48 ++++++++++ .../libraries/spring-boot3/pom.mustache | 96 +++++++++++++++++++ .../swaggerUiConfiguration.mustache | 23 +++++ 9 files changed, 288 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/LocalDateConverter.mustache create mode 100644 src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/LocalDateTimeConverter.mustache create mode 100644 src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/README.mustache create mode 100644 src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/application.mustache create mode 100644 src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/homeController.mustache create mode 100644 src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/openAPISpringBoot.mustache create mode 100644 src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/pom.mustache create mode 100644 src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/swaggerUiConfiguration.mustache diff --git a/src/main/java/io/swagger/codegen/v3/generators/java/SpringCodegen.java b/src/main/java/io/swagger/codegen/v3/generators/java/SpringCodegen.java index 822c1f4444..29b7276a4f 100644 --- a/src/main/java/io/swagger/codegen/v3/generators/java/SpringCodegen.java +++ b/src/main/java/io/swagger/codegen/v3/generators/java/SpringCodegen.java @@ -59,6 +59,7 @@ public class SpringCodegen extends AbstractJavaCodegen implements BeanValidation public static final String USE_TAGS = "useTags"; public static final String SPRING_MVC_LIBRARY = "spring-mvc"; public static final String SPRING_CLOUD_LIBRARY = "spring-cloud"; + public static final String SPRING_BOOT_3_LIBRARY = "spring-boot3"; public static final String IMPLICIT_HEADERS = "implicitHeaders"; public static final String SWAGGER_DOCKET_CONFIG = "swaggerDocketConfig"; public static final String TARGET_OPENFEIGN = "generateForOpenFeign"; @@ -127,6 +128,7 @@ public SpringCodegen() { cliOptions.add(CliOption.newBoolean(DATE_TIME_PATTERN, "use pattern for date time parameters").defaultValue("true")); supportedLibraries.put(DEFAULT_LIBRARY, "Spring-boot Server application using the SpringFox integration."); + supportedLibraries.put(SPRING_BOOT_3_LIBRARY, "Spring-boot v3 Server application."); supportedLibraries.put(SPRING_MVC_LIBRARY, "Spring-MVC Server application using the SpringFox integration."); supportedLibraries.put(SPRING_CLOUD_LIBRARY, "Spring-Cloud-Feign client with Spring-Boot auto-configured settings."); setLibrary(DEFAULT_LIBRARY); @@ -214,6 +216,10 @@ public void processOpts() { LOGGER.info("Set base package to invoker package (" + basePackage + ")"); } + if (isSpringBoot3Library()) { + setDateLibrary("java8"); + } + super.processOpts(); // clear model and api doc template as this codegen @@ -324,7 +330,16 @@ public void processOpts() { supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); if (!this.interfaceOnly) { - + if (isSpringBoot3Library()) { + useOas2 = false; + additionalProperties.remove("threetenbp"); + additionalProperties.put(JAKARTA, jakarta = true); + apiTestTemplateFiles.clear(); + supportingFiles.add(new SupportingFile("homeController.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "HomeController.java")); + supportingFiles.add(new SupportingFile("openAPISpringBoot.mustache", (sourceFolder + File.separator + basePackage).replace(".", java.io.File.separator), "OpenAPISpringBoot.java")); + supportingFiles.add(new SupportingFile("swaggerUiConfiguration.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "SwaggerUiConfiguration.java")); + supportingFiles.add(new SupportingFile("application.mustache", ("src.main.resources").replace(".", java.io.File.separator), "application.properties")); + } if (isDefaultLibrary()) { apiTestTemplateFiles.clear(); supportingFiles.add(new SupportingFile("homeController.mustache", @@ -385,14 +400,16 @@ public void processOpts() { (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "NotFoundException.java")); supportingFiles.add(new SupportingFile("apiOriginFilter.mustache", (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiOriginFilter.java")); - supportingFiles.add(new SupportingFile("swaggerDocumentationConfig.mustache", + if (!isSpringBoot3Library()) { + supportingFiles.add(new SupportingFile("swaggerDocumentationConfig.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "SwaggerDocumentationConfig.java")); + } supportingFiles.add(new SupportingFile("LocalDateConverter.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "LocalDateConverter.java")); supportingFiles.add(new SupportingFile("LocalDateTimeConverter.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "LocalDateTimeConverter.java")); } - } else if ( this.swaggerDocketConfig && !isSpringCloudLibrary()) { + } else if ( this.swaggerDocketConfig && !isSpringCloudLibrary() && !isSpringBoot3Library()) { supportingFiles.add(new SupportingFile("swaggerDocumentationConfig.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "SwaggerDocumentationConfig.java")); } @@ -757,6 +774,9 @@ private boolean isSpringMvcLibrary() { private boolean isDefaultLibrary() { return library.equals(DEFAULT_LIBRARY); } + private boolean isSpringBoot3Library() { + return library.equals(SPRING_BOOT_3_LIBRARY); + } @Override public Map postProcessSupportingFileData(Map objs) { diff --git a/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/LocalDateConverter.mustache b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/LocalDateConverter.mustache new file mode 100644 index 0000000000..75481b41de --- /dev/null +++ b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/LocalDateConverter.mustache @@ -0,0 +1,21 @@ +package {{configPackage}}; + +import org.springframework.core.convert.converter.Converter; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; + +public class LocalDateConverter implements Converter { + private final DateTimeFormatter formatter; + + public LocalDateConverter(String dateFormat) { + this.formatter = DateTimeFormatter.ofPattern(dateFormat); + } + + @Override + public LocalDate convert(String source) { + if(source == null || source.isEmpty()) { + return null; + } + return LocalDate.parse(source, this.formatter); + } +} diff --git a/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/LocalDateTimeConverter.mustache b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/LocalDateTimeConverter.mustache new file mode 100644 index 0000000000..4854688eb6 --- /dev/null +++ b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/LocalDateTimeConverter.mustache @@ -0,0 +1,21 @@ +package {{configPackage}}; + +import org.springframework.core.convert.converter.Converter; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class LocalDateTimeConverter implements Converter { + private final DateTimeFormatter formatter; + + public LocalDateTimeConverter(String dateFormat) { + this.formatter = DateTimeFormatter.ofPattern(dateFormat); + } + + @Override + public LocalDateTime convert(String source) { + if(source == null || source.isEmpty()) { + return null; + } + return LocalDateTime.parse(source, this.formatter); + } +} diff --git a/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/README.mustache b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/README.mustache new file mode 100644 index 0000000000..8e5dd7bb11 --- /dev/null +++ b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/README.mustache @@ -0,0 +1,37 @@ +{{^interfaceOnly}}# Swagger generated server + +Spring Boot Server + + +## Overview +This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. +By using the [OpenAPI-Spec](https://github.com/swagger-api/swagger-core), you can easily generate a server stub. +This is an example of building a swagger-enabled server in Java using the SpringBoot framework. + +The underlying library integrating swagger to SpringBoot is [springdoc-openapi](https://github.com/springdoc/springdoc-openapi) + +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{{/interfaceOnly}}{{#interfaceOnly}} +# Swagger generated API stub + +Spring Framework stub + + +## Overview +This code was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. +By using the [OpenAPI-Spec](https://github.com/swagger-api/swagger-core), you can easily generate an API stub. +This is an example of building API stub interfaces in Java using the Spring framework. + +The stubs generated can be used in your existing Spring-MVC or Spring-Boot application to create controller endpoints +by adding ```@Controller``` classes that implement the interface. Eg: +```java +@Controller +public class PetController implements PetApi { +// implement all PetApi methods +} +``` +{{/interfaceOnly}} diff --git a/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/application.mustache b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/application.mustache new file mode 100644 index 0000000000..5d1635f0a1 --- /dev/null +++ b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/application.mustache @@ -0,0 +1,3 @@ +springfox.documentation.open-api.v3.path=/api-docs +server.servlet.contextPath={{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}} +server.port={{serverPort}} diff --git a/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/homeController.mustache b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/homeController.mustache new file mode 100644 index 0000000000..89f4069854 --- /dev/null +++ b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/homeController.mustache @@ -0,0 +1,16 @@ +package {{configPackage}}; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Home redirection to swagger api documentation + */ +@Controller +public class HomeController { + @RequestMapping(value = "/") + public String index() { + System.out.println("/swagger-ui/index.html"); + return "redirect:/swagger-ui/"; + } +} diff --git a/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/openAPISpringBoot.mustache b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/openAPISpringBoot.mustache new file mode 100644 index 0000000000..876248c766 --- /dev/null +++ b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/openAPISpringBoot.mustache @@ -0,0 +1,48 @@ +package {{basePackage}}; + +import {{configPackage}}.LocalDateConverter; +import {{configPackage}}.LocalDateTimeConverter; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.ExitCodeGenerator; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.format.FormatterRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; + +@SpringBootApplication +@ComponentScan(basePackages = { "{{basePackage}}", "{{apiPackage}}" , "{{configPackage}}"}) +public class OpenAPISpringBoot implements CommandLineRunner { + + @Override + public void run(String... arg0) throws Exception { + if (arg0.length > 0 && arg0[0].equals("exitcode")) { + throw new ExitException(); + } + } + + public static void main(String[] args) throws Exception { + new SpringApplication(OpenAPISpringBoot.class).run(args); + } + + @Configuration + static class CustomDateConfig extends WebMvcConfigurationSupport { + @Override + public void addFormatters(FormatterRegistry registry) { + registry.addConverter(new LocalDateConverter("{{#datePattern}}{{datePattern}}{{/datePattern}}{{^datePattern}}yyyy-MM-dd{{/datePattern}}")); + registry.addConverter(new LocalDateTimeConverter("{{#dateTimePattern}}{{dateTimePattern}}{{/dateTimePattern}}{{^dateTimePattern}}yyyy-MM-dd'T'HH:mm:ss.SSS{{/dateTimePattern}}")); + } + } + + class ExitException extends RuntimeException implements ExitCodeGenerator { + private static final long serialVersionUID = 1L; + + @Override + public int getExitCode() { + return 10; + } + + } +} diff --git a/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/pom.mustache b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/pom.mustache new file mode 100644 index 0000000000..12228a360c --- /dev/null +++ b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/pom.mustache @@ -0,0 +1,96 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + UTF-8 + 17 + 3.1.1 + 2.2.14 + + + org.springframework.boot + spring-boot-starter-parent + 3.1.1 + + + src/main/java + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + + + org.springframework.boot + spring-boot-starter-web + ${springboot-version} + + + org.springframework.boot + spring-boot-starter-tomcat + ${springboot-version} + + {{#withXml}} + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + {{/withXml}} + {{#useBeanValidation}} + + + jakarta.validation + jakarta.validation-api + 3.0.2 + + + jakarta.xml.bind + jakarta.xml.bind-api + 4.0.0 + + + com.sun.xml.bind + jaxb-impl + 4.0.3 + + {{/useBeanValidation}} + {{#notNullJacksonAnnotation}} + + com.fasterxml.jackson.core + jackson-annotations + 2.10.1 + + {{/notNullJacksonAnnotation}} + + + io.swagger.core.v3 + swagger-annotations + ${swagger-annotations-version} + + + org.springframework.plugin + spring-plugin-core + 3.0.0 + + + + org.springframework.boot + spring-boot-starter-test + ${springboot-version} + test + + + diff --git a/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/swaggerUiConfiguration.mustache b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/swaggerUiConfiguration.mustache new file mode 100644 index 0000000000..6c283f4d50 --- /dev/null +++ b/src/main/resources/handlebars/JavaSpring/libraries/spring-boot3/swaggerUiConfiguration.mustache @@ -0,0 +1,23 @@ +package {{configPackage}}; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +{{>generatedAnnotation}} +@Configuration +public class SwaggerUiConfiguration implements WebMvcConfigurer { + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry. + addResourceHandler("/swagger-ui/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/") + .resourceChain(false); + } + + @Override + public void addViewControllers(ViewControllerRegistry registry) { + registry.addViewController("/swagger-ui/").setViewName("forward:/swagger-ui/index.html"); + } +}