From 4de7d54464cae8a0b1157d31958d52e4bd9edd14 Mon Sep 17 00:00:00 2001 From: altro3 Date: Fri, 18 Oct 2024 14:13:53 +0700 Subject: [PATCH] Micronaut Spring 5.8.1 --- gradle/libs.versions.toml | 2 +- .../AbstractOpenApiEndpointVisitor.java | 3 ++ .../openapi/visitor/ConfigUtils.java | 17 ++++--- .../visitor/OpenApiApplicationVisitor.java | 4 ++ .../visitor/OpenApiConfigProperty.java | 9 +++- .../OpenApiApplicationVisitorSpec.groovy | 38 +++++++++++++++ test-suite-java-spring/build.gradle | 1 + .../micronaut/openapi/spring/Application.java | 3 +- .../openapi/spring/OpenApiExposedTest.java | 6 ++- .../micronaut/openapi/spring/TestConfig.java | 3 ++ .../openapi/spring/TestControllerTest.java | 47 ++++++++++++++----- 11 files changed, 106 insertions(+), 27 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f5310816a9..9315be861e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -40,7 +40,7 @@ micronaut-kotlin = "4.4.0" micronaut-logging = "1.5.0" micronaut-session = "4.4.0" micronaut-grpc = "4.7.1" -micronaut-spring = "5.8.0" +micronaut-spring = "5.8.1" micronaut-docs = "2.0.0" [libraries] diff --git a/openapi/src/main/java/io/micronaut/openapi/visitor/AbstractOpenApiEndpointVisitor.java b/openapi/src/main/java/io/micronaut/openapi/visitor/AbstractOpenApiEndpointVisitor.java index 5829a2234c..02f0f9f47a 100644 --- a/openapi/src/main/java/io/micronaut/openapi/visitor/AbstractOpenApiEndpointVisitor.java +++ b/openapi/src/main/java/io/micronaut/openapi/visitor/AbstractOpenApiEndpointVisitor.java @@ -986,6 +986,9 @@ private Parameter processMethodParameterAnnotation(VisitorContext context, Opera } } else if (parameter.isAnnotationPresent(PathVariable.class)) { String paramName = parameter.getValue(PathVariable.class, String.class).orElse(parameterName); + if (paramName.isEmpty()) { + paramName = parameterName; + } UriMatchVariable variable = pathVariables.get(paramName); if (variable == null) { warn("Path variable name: '" + paramName + "' not found in path, operation: " + swaggerOperation.getOperationId(), context, parameter); diff --git a/openapi/src/main/java/io/micronaut/openapi/visitor/ConfigUtils.java b/openapi/src/main/java/io/micronaut/openapi/visitor/ConfigUtils.java index 8d573f79d2..8540d199e1 100644 --- a/openapi/src/main/java/io/micronaut/openapi/visitor/ConfigUtils.java +++ b/openapi/src/main/java/io/micronaut/openapi/visitor/ConfigUtils.java @@ -324,13 +324,14 @@ public static List> getExpandableProperties(VisitorContext } var expandableProperties = new ArrayList>(); + var expandPrefix = MICRONAUT_OPENAPI_EXPAND_PREFIX + DOT; // first, check system properties and environments config files var env = (AnnProcessorEnvironment) getEnv(context); Map propertiesFromEnv = null; if (env != null) { try { - propertiesFromEnv = env.getProperties(MICRONAUT_OPENAPI_EXPAND_PREFIX.substring(0, MICRONAUT_OPENAPI_EXPAND_PREFIX.length() - 1), null); + propertiesFromEnv = env.getProperties(expandPrefix.substring(0, expandPrefix.length() - 1), null); } catch (Exception e) { warn("Error:\n" + Utils.printStackTrace(e), context); } @@ -347,7 +348,7 @@ public static List> getExpandableProperties(VisitorContext Properties openapiProps = readOpenApiConfigFile(context); for (Map.Entry entry : openapiProps.entrySet()) { String key = entry.getKey().toString(); - if (!key.startsWith(MICRONAUT_OPENAPI_EXPAND_PREFIX)) { + if (!key.startsWith(expandPrefix)) { continue; } expandedPropsMap.put(key, entry.getValue().toString()); @@ -357,7 +358,7 @@ public static List> getExpandableProperties(VisitorContext if (CollectionUtils.isNotEmpty(System.getProperties())) { for (Map.Entry entry : System.getProperties().entrySet()) { String key = entry.getKey().toString(); - if (!key.startsWith(MICRONAUT_OPENAPI_EXPAND_PREFIX)) { + if (!key.startsWith(expandPrefix)) { continue; } expandedPropsMap.put(key, entry.getValue().toString()); @@ -366,8 +367,8 @@ public static List> getExpandableProperties(VisitorContext for (Map.Entry entry : expandedPropsMap.entrySet()) { String key = entry.getKey(); - if (key.startsWith(MICRONAUT_OPENAPI_EXPAND_PREFIX)) { - key = key.substring(MICRONAUT_OPENAPI_EXPAND_PREFIX.length()); + if (key.startsWith(expandPrefix)) { + key = key.substring(expandPrefix.length()); } var prop = Pair.of("\\$\\{" + key + '}', entry.getValue()); if (!expandableProperties.contains(prop)) { @@ -390,6 +391,8 @@ public static Map getAdocProperties(OpenApiInfo openApiInfo, boo adocProperties.put(MICRONAUT_OPENAPI_ADOC_OUTPUT_FILENAME, getConfigProperty(MICRONAUT_OPENAPI_ADOC_OUTPUT_FILENAME, context)); adocProperties.put(MICRONAUT_OPENAPI_ADOC_OPENAPI_PATH, getConfigProperty(MICRONAUT_OPENAPI_ADOC_OPENAPI_PATH, context)); + var expandPrefix = MICRONAUT_OPENAPI_EXPAND_PREFIX + DOT; + // first, check system properties and environments config files var env = (AnnProcessorEnvironment) getEnv(context); Map propertiesFromEnv = null; @@ -411,7 +414,7 @@ public static Map getAdocProperties(OpenApiInfo openApiInfo, boo Properties openapiProps = readOpenApiConfigFile(context); for (Map.Entry entry : openapiProps.entrySet()) { String key = entry.getKey().toString(); - if (!key.startsWith(MICRONAUT_OPENAPI_EXPAND_PREFIX)) { + if (!key.startsWith(expandPrefix)) { continue; } adocProperties.put(key, entry.getValue().toString()); @@ -421,7 +424,7 @@ public static Map getAdocProperties(OpenApiInfo openApiInfo, boo if (CollectionUtils.isNotEmpty(System.getProperties())) { for (Map.Entry entry : System.getProperties().entrySet()) { String key = entry.getKey().toString(); - if (!key.startsWith(MICRONAUT_OPENAPI_EXPAND_PREFIX)) { + if (!key.startsWith(expandPrefix)) { continue; } adocProperties.put(key, entry.getValue().toString()); diff --git a/openapi/src/main/java/io/micronaut/openapi/visitor/OpenApiApplicationVisitor.java b/openapi/src/main/java/io/micronaut/openapi/visitor/OpenApiApplicationVisitor.java index 78c771c59f..ab1ca3f65b 100644 --- a/openapi/src/main/java/io/micronaut/openapi/visitor/OpenApiApplicationVisitor.java +++ b/openapi/src/main/java/io/micronaut/openapi/visitor/OpenApiApplicationVisitor.java @@ -101,6 +101,7 @@ import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_JSON_FORMAT; import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_PROPERTY_NAMING_STRATEGY; import static io.micronaut.openapi.visitor.OpenApiConfigProperty.MICRONAUT_OPENAPI_VIEWS_SPEC; +import static io.micronaut.openapi.visitor.OpenApiConfigProperty.SPRING_APPLICATION_NAME; import static io.micronaut.openapi.visitor.OpenApiModelProp.PROP_SECURITY; import static io.micronaut.openapi.visitor.OpenApiNormalizeUtils.findAndRemoveDuplicates; import static io.micronaut.openapi.visitor.OpenApiNormalizeUtils.normalizeOpenApi; @@ -741,6 +742,9 @@ private void fixInfoBlockIfNeeded(OpenAPI openApi, VisitorContext context) { var info = openApi.getInfo(); if (info.getTitle() == null) { String applicationName = ConfigUtils.getConfigProperty(MICRONAUT_APPLICATION_NAME, context); + if (applicationName == null) { + applicationName = ConfigUtils.getConfigProperty(SPRING_APPLICATION_NAME, context); + } info.setTitle(applicationName != null ? applicationName : DEFAULT_OPENAPI_TITLE); } if (info.getVersion() == null) { diff --git a/openapi/src/main/java/io/micronaut/openapi/visitor/OpenApiConfigProperty.java b/openapi/src/main/java/io/micronaut/openapi/visitor/OpenApiConfigProperty.java index 4e45c192f6..862c99a98c 100644 --- a/openapi/src/main/java/io/micronaut/openapi/visitor/OpenApiConfigProperty.java +++ b/openapi/src/main/java/io/micronaut/openapi/visitor/OpenApiConfigProperty.java @@ -104,7 +104,7 @@ public interface OpenApiConfigProperty { /** * Prefix for expandable properties. */ - String MICRONAUT_OPENAPI_EXPAND_PREFIX = "micronaut.openapi.expand."; + String MICRONAUT_OPENAPI_EXPAND_PREFIX = "micronaut.openapi.expand"; /** * System property for server context path. */ @@ -204,6 +204,10 @@ public interface OpenApiConfigProperty { * micronaut-context application name property. */ String MICRONAUT_APPLICATION_NAME = "micronaut.application.name"; + /** + * spring-context application name property. + */ + String SPRING_APPLICATION_NAME = "spring.application.name"; /** * If this property is 'true', then generated OpenAPI specification will be with extensions for OpenAPI Generator * and the generated client according to this specification will be much more accurate than without it. @@ -381,6 +385,7 @@ public interface OpenApiConfigProperty { MICRONAUT_OPENAPI_SWAGGER_FILE_GENERATION_ENABLED, MICRONAUT_OPENAPI_SCHEMA_EXTRA_ENABLED, MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_EMPTY, - MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_GENERIC + MICRONAUT_OPENAPI_SCHEMA_NAME_SEPARATOR_GENERIC, + MICRONAUT_OPENAPI_EXPAND_PREFIX ); } diff --git a/openapi/src/test/groovy/io/micronaut/openapi/visitor/OpenApiApplicationVisitorSpec.groovy b/openapi/src/test/groovy/io/micronaut/openapi/visitor/OpenApiApplicationVisitorSpec.groovy index 5263018065..d4525dac34 100644 --- a/openapi/src/test/groovy/io/micronaut/openapi/visitor/OpenApiApplicationVisitorSpec.groovy +++ b/openapi/src/test/groovy/io/micronaut/openapi/visitor/OpenApiApplicationVisitorSpec.groovy @@ -1050,6 +1050,44 @@ class MyController { } } +@jakarta.inject.Singleton +class MyBean {} +''') + then: + Utils.testReference != null + + when: + OpenAPI openAPI = Utils.testReference + + then: + openAPI.info + openAPI.info.title == serviceName + openAPI.info.version == OpenApiApplicationVisitor.DEFAULT_OPENAPI_VERSION + } + + @RestoreSystemProperties + void "test auto generated info block with spring application name"() { + + given: + def serviceName = "This is my service" + System.setProperty(OpenApiConfigProperty.SPRING_APPLICATION_NAME, serviceName) + + when: + buildBeanDefinition('test.MyBean', ''' +package test; + +import io.micronaut.http.annotation.Controller; +import io.micronaut.http.annotation.Get; + +@Controller +class MyController { + + @Get("/get") + public String get() { + return null; + } +} + @jakarta.inject.Singleton class MyBean {} ''') diff --git a/test-suite-java-spring/build.gradle b/test-suite-java-spring/build.gradle index f89fa60fa3..f0976dfede 100644 --- a/test-suite-java-spring/build.gradle +++ b/test-suite-java-spring/build.gradle @@ -51,4 +51,5 @@ tasks.withType(JavaCompile).configureEach { '-Xlint:unchecked', '-Xlint:deprecation' ] + options.forkOptions.jvmArgs += "-Dapp.version=myVersion" } diff --git a/test-suite-java-spring/src/main/java/io/micronaut/openapi/spring/Application.java b/test-suite-java-spring/src/main/java/io/micronaut/openapi/spring/Application.java index 335485fc29..c6d71e024f 100644 --- a/test-suite-java-spring/src/main/java/io/micronaut/openapi/spring/Application.java +++ b/test-suite-java-spring/src/main/java/io/micronaut/openapi/spring/Application.java @@ -9,8 +9,7 @@ @SpringBootApplication @OpenAPIDefinition( info = @Info( - title = "demo", - version = "0.0" + version = "${app.version}" ) ) public class Application { diff --git a/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/OpenApiExposedTest.java b/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/OpenApiExposedTest.java index 19437341fa..dadf5fe524 100644 --- a/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/OpenApiExposedTest.java +++ b/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/OpenApiExposedTest.java @@ -10,6 +10,8 @@ import java.io.IOException; import java.util.concurrent.atomic.AtomicReference; +import static io.micronaut.openapi.spring.TestConfig.APP_NAME; +import static io.micronaut.openapi.spring.TestConfig.APP_VERSION; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -29,7 +31,7 @@ class OpenApiExposedTest { void testOpenApiSpecEndpoint() throws IOException { String openApiSpec; - try (var is = getClass().getResourceAsStream("/META-INF/swagger/demo-0.0.yml")) { + try (var is = getClass().getResourceAsStream("/META-INF/swagger/" + APP_NAME + '-' + APP_VERSION + ".yml")) { assertNotNull(is); openApiSpec = new String(is.readAllBytes()); } @@ -37,7 +39,7 @@ void testOpenApiSpecEndpoint() throws IOException { assertDoesNotThrow(() -> { var result = restClient.get() - .uri("/swagger/demo-0.0.yml") + .uri("/swagger/" + APP_NAME + '-' + APP_VERSION + ".yml") .retrieve(); recievedOpenApiSpec.set(result.body(String.class)); diff --git a/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/TestConfig.java b/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/TestConfig.java index fc0a12a23d..0720094603 100644 --- a/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/TestConfig.java +++ b/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/TestConfig.java @@ -8,6 +8,9 @@ @Configuration public class TestConfig { + public static final String APP_NAME = "test-suite-java-spring"; + public static final String APP_VERSION = "myVersion"; + @Bean RestClient restClient(@Value("${server.port:8080}") int port) { return RestClient.builder() diff --git a/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/TestControllerTest.java b/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/TestControllerTest.java index 4eb314d3c2..bd3376dc24 100644 --- a/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/TestControllerTest.java +++ b/test-suite-java-spring/src/test/java/io/micronaut/openapi/spring/TestControllerTest.java @@ -3,14 +3,20 @@ import com.fasterxml.jackson.core.JsonProcessingException; import io.micronaut.openapi.OpenApiUtils; import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.parameters.Parameter; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.web.client.RestClient; +import java.util.List; + +import static io.micronaut.openapi.spring.TestConfig.APP_NAME; +import static io.micronaut.openapi.spring.TestConfig.APP_VERSION; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @ActiveProfiles("test") @@ -27,11 +33,13 @@ class TestControllerTest { @Test void springOpenApiPathTest() throws JsonProcessingException { var result = restClient.get() - .uri("/swagger/demo-0.0.yml") + .uri("/swagger/" + APP_NAME + '-' + APP_VERSION + ".yml") .retrieve() .body(String.class); var openApi = OpenApiUtils.getYamlMapper().readValue(result, OpenAPI.class); + assertNotNull(openApi.getInfo()); + assertEquals(APP_VERSION, openApi.getInfo().getVersion()); assertNotNull(openApi.getPaths()); var userSchema = openApi.getComponents().getSchemas().get("User"); @@ -72,17 +80,30 @@ void springOpenApiPathTest() throws JsonProcessingException { assertNotNull(params); assertEquals(2, params.size()); - assertEquals("userId", params.get(0).getName()); - assertEquals("path", params.get(0).getIn()); - assertTrue(params.get(0).getRequired()); - assertNotNull(params.get(0).getSchema()); - assertEquals("string", params.get(0).getSchema().getType()); - - assertEquals("age", params.get(1).getName()); - assertEquals("query", params.get(1).getIn()); - assertNotNull(params.get(1).getSchema()); - assertEquals("integer", params.get(1).getSchema().getType()); - assertEquals("int32", params.get(1).getSchema().getFormat()); - assertTrue(params.get(1).getSchema().getNullable()); + var userIdParam = getParamByName("userId", params); + assertNotNull(userIdParam); + assertEquals("userId", userIdParam.getName()); + assertEquals("path", userIdParam.getIn()); + assertTrue(userIdParam.getRequired()); + assertNotNull(userIdParam.getSchema()); + assertEquals("string", userIdParam.getSchema().getType()); + + var ageParam = getParamByName("age", params); + assertNotNull(ageParam); + assertEquals("age", ageParam.getName()); + assertEquals("query", ageParam.getIn()); + assertNotNull(ageParam.getSchema()); + assertNull(ageParam.getRequired()); + assertEquals("integer", ageParam.getSchema().getType()); + assertEquals("int32", ageParam.getSchema().getFormat()); + assertEquals(123, ageParam.getSchema().getDefault()); + assertTrue(ageParam.getSchema().getNullable()); + } + + private Parameter getParamByName(String name, List params) { + return params.stream() + .filter(p -> name.equals(p.getName())) + .findFirst() + .orElse(null); } }