diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/properties/SpringDocConfigProperties.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/properties/SpringDocConfigProperties.java index 1ea92f1ff..2a32e6d06 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/properties/SpringDocConfigProperties.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/properties/SpringDocConfigProperties.java @@ -28,11 +28,14 @@ import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.SpecVersion; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.License; import org.springdoc.core.configuration.SpringDocConfiguration; import org.springdoc.core.properties.SpringDocConfigProperties.ApiDocs.OpenApiVersion; import org.springdoc.core.utils.Constants; @@ -44,6 +47,8 @@ import org.springframework.context.annotation.Lazy; import org.springframework.http.MediaType; +import static org.springdoc.core.utils.Constants.DEFAULT_TITLE; +import static org.springdoc.core.utils.Constants.DEFAULT_VERSION; import static org.springdoc.core.utils.Constants.DEFAULT_WEB_JARS_PREFIX_URL; import static org.springdoc.core.utils.Constants.SPRINGDOC_ENABLED; @@ -1451,6 +1456,11 @@ public static class ApiDocs { */ private Groups groups = new Groups(); + /** + * The Info. + */ + private Info info = new Info(); + /** * The OpenAPI version. */ @@ -1510,6 +1520,24 @@ public void setGroups(Groups groups) { this.groups = groups; } + /** + * Gets info. + * + * @return the info + */ + public Info getInfo() { + return info; + } + + /** + * Sets info. + * + * @param info the info + */ + public void setInfo(Info info) { + this.info = info; + } + /** * Is resolve schema properties boolean. * @@ -1947,4 +1975,194 @@ public int hashCode() { return Objects.hash(group); } } + + /** + * The type Info. + */ + public static class Info { + + /** + * The Title. + */ + private String title = DEFAULT_TITLE; + + /** + * The Description. + */ + private String description; + + /** + * The Terms of service. + */ + private String termsOfService; + + /** + * The Contact. + */ + private Contact contact; + + /** + * The License. + */ + private License license; + + /** + * The Version. + */ + private String version = DEFAULT_VERSION; + + /** + * The Extensions. + */ + private Map extensions; + + /** + * The Summary. + */ + private String summary; + + /** + * Gets title. + * + * @return the title + */ + public String getTitle() { + return title; + } + + /** + * Sets title. + * + * @param title the title + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * Gets description. + * + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * Sets description. + * + * @param description the description + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * Gets terms of service. + * + * @return the terms of service + */ + public String getTermsOfService() { + return termsOfService; + } + + /** + * Sets terms of service. + * + * @param termsOfService the terms of service + */ + public void setTermsOfService(String termsOfService) { + this.termsOfService = termsOfService; + } + + /** + * Gets contact. + * + * @return the contact + */ + public Contact getContact() { + return contact; + } + + /** + * Sets contact. + * + * @param contact the contact + */ + public void setContact(Contact contact) { + this.contact = contact; + } + + /** + * Gets license. + * + * @return the license + */ + public License getLicense() { + return license; + } + + /** + * Sets license. + * + * @param license the license + */ + public void setLicense(License license) { + this.license = license; + } + + /** + * Gets version. + * + * @return the version + */ + public String getVersion() { + return version; + } + + /** + * Sets version. + * + * @param version the version + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * Gets extensions. + * + * @return the extensions + */ + public Map getExtensions() { + return extensions; + } + + /** + * Sets extensions. + * + * @param extensions the extensions + */ + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + /** + * Gets summary. + * + * @return the summary + */ + public String getSummary() { + return summary; + } + + /** + * Sets summary. + * + * @param summary the summary + */ + public void setSummary(String summary) { + this.summary = summary; + } + } } diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/OpenAPIService.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/OpenAPIService.java index 2b7504e69..741c98997 100644 --- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/OpenAPIService.java +++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/OpenAPIService.java @@ -254,7 +254,15 @@ public OpenAPI build(Locale locale) { } // Set default info else if (calculatedOpenAPI != null && calculatedOpenAPI.getInfo() == null) { - Info infos = new Info().title(DEFAULT_TITLE).version(DEFAULT_VERSION); + Info infos = new Info() + .title(springDocConfigProperties.getApiDocs().getInfo().getTitle()) + .description(springDocConfigProperties.getApiDocs().getInfo().getDescription()) + .termsOfService(springDocConfigProperties.getApiDocs().getInfo().getTermsOfService()) + .contact(springDocConfigProperties.getApiDocs().getInfo().getContact()) + .license(springDocConfigProperties.getApiDocs().getInfo().getLicense()) + .version(springDocConfigProperties.getApiDocs().getInfo().getVersion()) + .extensions(springDocConfigProperties.getApiDocs().getInfo().getExtensions()) + .summary(springDocConfigProperties.getApiDocs().getInfo().getSummary()); calculatedOpenAPI.setInfo(infos); } // Set default mappings diff --git a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/java/test/org/springdoc/api/v31/app250/OpenApiInfoFromYamlPropertiesTest.java b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/java/test/org/springdoc/api/v31/app250/OpenApiInfoFromYamlPropertiesTest.java new file mode 100644 index 000000000..2cd16f3ac --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/java/test/org/springdoc/api/v31/app250/OpenApiInfoFromYamlPropertiesTest.java @@ -0,0 +1,91 @@ +/* + * + * * + * * * + * * * * + * * * * * + * * * * * * Copyright 2019-2025 the original author or authors. + * * * * * * + * * * * * * Licensed under the Apache License, Version 2.0 (the "License"); + * * * * * * you may not use this file except in compliance with the License. + * * * * * * You may obtain a copy of the License at + * * * * * * + * * * * * * https://www.apache.org/licenses/LICENSE-2.0 + * * * * * * + * * * * * * Unless required by applicable law or agreed to in writing, software + * * * * * * distributed under the License is distributed on an "AS IS" BASIS, + * * * * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * * * * * See the License for the specific language governing permissions and + * * * * * * limitations under the License. + * * * * * + * * * * + * * * + * * + * + */ + +package test.org.springdoc.api.v31.app250; + +import org.junit.jupiter.api.Test; +import org.springdoc.core.utils.Constants; +import test.org.springdoc.api.v31.AbstractSpringDocTest; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.test.context.TestPropertySource; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +/** + * Tests loading OpenAPI info metadata from YAML configuration. + */ +@TestPropertySource(properties = "spring.config.additional-location=classpath:/application-openapi-info.yml") +class OpenApiInfoFromYamlPropertiesTest extends AbstractSpringDocTest { + + /** + * Verifies the configured info block is propagated to the generated OpenAPI document. + * + * @throws Exception the exception + */ + @Test + @Override + protected void testApp() throws Exception { + mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.info.title", is("Configured API"))) + .andExpect(jsonPath("$.info.description", is("Configured via YAML"))) + .andExpect(jsonPath("$.info.termsOfService", is("https://example.org/terms"))) + .andExpect(jsonPath("$.info.summary", is("High level summary"))) + .andExpect(jsonPath("$.info.version", is("9.9.9"))) + .andExpect(jsonPath("$.info.contact.name", is("Example Support"))) + .andExpect(jsonPath("$.info.contact.email", is("support@example.org"))) + .andExpect(jsonPath("$.info.contact.url", is("https://example.org/support"))) + .andExpect(jsonPath("$.info.license.name", is("Example License"))) + .andExpect(jsonPath("$.info.license.url", is("https://example.org/license"))) + .andExpect(jsonPath("$.info['x-company']", is("Example Corp"))) + .andExpect(jsonPath("$.info['x-service-tier']", is("gold"))); + } + + /** + * Minimal application with one endpoint to ensure the OpenAPI doc is generated. + */ + @SpringBootApplication + @RestController + static class SpringDocTestApp { + + /** + * Sample endpoint to register at least one route. + * + * @return the greeting + */ + @GetMapping("/greetings") + public String greetings() { + return "hello"; + } + } +} + diff --git a/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/application-openapi-info.yml b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/application-openapi-info.yml new file mode 100644 index 000000000..e03d9792e --- /dev/null +++ b/springdoc-openapi-tests/springdoc-openapi-javadoc-tests/src/test/resources/application-openapi-info.yml @@ -0,0 +1,19 @@ +springdoc: + api-docs: + info: + title: Configured API + description: Configured via YAML + terms-of-service: https://example.org/terms + summary: High level summary + version: 9.9.9 + contact: + name: Example Support + url: https://example.org/support + email: support@example.org + license: + name: Example License + url: https://example.org/license + extensions: + x-company: Example Corp + x-service-tier: gold +