From 13e3bfe2b7a988af731796ea185d23bc411e8387 Mon Sep 17 00:00:00 2001 From: bnasslahsen Date: Thu, 27 Aug 2020 01:32:31 +0200 Subject: [PATCH] issues with spring data rest and @ManyToOne relationships. Fixes #792. --- .../rest/SpringDocDataRestConfiguration.java | 11 +- .../SpringRepositoryRestResourceProvider.java | 48 +- .../data/rest/core/ControllerType.java | 12 +- .../rest/core/DataRestOperationBuilder.java | 4 +- .../data/rest/core/DataRestRepository.java | 46 + .../rest/core/DataRestRequestBuilder.java | 4 +- .../core/DataRestRouterOperationBuilder.java | 23 +- .../springdoc/api/app17/ChildProperty.java | 35 + .../api/app17/ChildPropertyRepository.java | 6 + .../org/springdoc/api/app17/Property.java | 49 + .../api/app17/PropertyRepository.java | 6 + .../api/app17/SpringDocApp17Test.java | 33 + .../src/test/resources/results/app10.json | 529 ++------ .../src/test/resources/results/app11.json | 400 +----- .../src/test/resources/results/app16.json | 450 +------ .../src/test/resources/results/app17.json | 1084 +++++++++++++++++ 16 files changed, 1456 insertions(+), 1284 deletions(-) create mode 100644 springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/ChildProperty.java create mode 100644 springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/ChildPropertyRepository.java create mode 100644 springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/Property.java create mode 100644 springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/PropertyRepository.java create mode 100644 springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/SpringDocApp17Test.java create mode 100644 springdoc-openapi-data-rest/src/test/resources/results/app17.json diff --git a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/SpringDocDataRestConfiguration.java b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/SpringDocDataRestConfiguration.java index 46cb102c4..0d9f9fb9a 100644 --- a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/SpringDocDataRestConfiguration.java +++ b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/SpringDocDataRestConfiguration.java @@ -25,6 +25,7 @@ import java.util.Optional; +import com.fasterxml.jackson.databind.ObjectMapper; import com.querydsl.core.types.Predicate; import org.springdoc.core.AbstractRequestBuilder; import org.springdoc.core.GenericParameterBuilder; @@ -53,6 +54,7 @@ import org.springframework.context.annotation.Primary; import org.springframework.core.LocalVariableTableParameterNameDiscoverer; import org.springframework.data.domain.Sort; +import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.querydsl.binding.QuerydslBindingsFactory; import org.springframework.data.repository.support.Repositories; import org.springframework.data.rest.core.config.RepositoryRestConfiguration; @@ -157,15 +159,18 @@ static class SpringRepositoryRestResourceProviderConfiguration { * @param associations the associations * @param delegatingHandlerMapping the delegating handler mapping * @param dataRestRouterOperationBuilder the data rest router operation builder + * @param persistentEntities the persistent entities + * @param mapper the mapper * @return the spring repository rest resource provider */ @Bean @ConditionalOnMissingBean SpringRepositoryRestResourceProvider springRepositoryRestResourceProvider(ResourceMappings mappings, Repositories repositories, Associations associations, DelegatingHandlerMapping delegatingHandlerMapping, - DataRestRouterOperationBuilder dataRestRouterOperationBuilder) { - return new SpringRepositoryRestResourceProvider(mappings, repositories, associations, - delegatingHandlerMapping, dataRestRouterOperationBuilder); + DataRestRouterOperationBuilder dataRestRouterOperationBuilder, PersistentEntities persistentEntities, + ObjectMapper mapper) { + return new SpringRepositoryRestResourceProvider(mappings,repositories, associations, delegatingHandlerMapping, + dataRestRouterOperationBuilder, persistentEntities, mapper); } /** diff --git a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/SpringRepositoryRestResourceProvider.java b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/SpringRepositoryRestResourceProvider.java index 813a2d773..d041f5c4b 100644 --- a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/SpringRepositoryRestResourceProvider.java +++ b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/SpringRepositoryRestResourceProvider.java @@ -29,13 +29,19 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.models.OpenAPI; import org.springdoc.api.AbstractOpenApiResource; import org.springdoc.core.RepositoryRestResourceProvider; import org.springdoc.core.fn.RouterOperation; +import org.springdoc.data.rest.core.ControllerType; import org.springdoc.data.rest.core.DataRestRepository; import org.springdoc.data.rest.core.DataRestRouterOperationBuilder; +import org.springframework.data.mapping.PersistentEntity; +import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.mapping.SimpleAssociationHandler; +import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.repository.support.Repositories; import org.springframework.data.rest.core.mapping.MethodResourceMapping; import org.springframework.data.rest.core.mapping.ResourceMappings; @@ -45,6 +51,7 @@ import org.springframework.data.rest.webmvc.ProfileController; import org.springframework.data.rest.webmvc.RepositoryRestHandlerMapping; import org.springframework.data.rest.webmvc.alps.AlpsController; +import org.springframework.data.rest.webmvc.json.JacksonMetadata; import org.springframework.data.rest.webmvc.mapping.Associations; import org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping; import org.springframework.web.method.HandlerMethod; @@ -102,6 +109,16 @@ public class SpringRepositoryRestResourceProvider implements RepositoryRestResou */ private DataRestRouterOperationBuilder dataRestRouterOperationBuilder; + /** + * The Persistent entities. + */ + private PersistentEntities persistentEntities; + + /** + * The Mapper. + */ + private ObjectMapper mapper; + /** * Instantiates a new Spring repository rest resource provider. * @@ -110,14 +127,17 @@ public class SpringRepositoryRestResourceProvider implements RepositoryRestResou * @param associations the associations * @param delegatingHandlerMapping the delegating handler mapping * @param dataRestRouterOperationBuilder the data rest router operation builder + * @param persistentEntities the persistent entities + * @param mapper the mapper */ - public SpringRepositoryRestResourceProvider(ResourceMappings mappings, Repositories repositories, Associations associations, - DelegatingHandlerMapping delegatingHandlerMapping, DataRestRouterOperationBuilder dataRestRouterOperationBuilder) { + public SpringRepositoryRestResourceProvider(ResourceMappings mappings, Repositories repositories, Associations associations, DelegatingHandlerMapping delegatingHandlerMapping, DataRestRouterOperationBuilder dataRestRouterOperationBuilder, PersistentEntities persistentEntities, ObjectMapper mapper) { this.mappings = mappings; this.repositories = repositories; this.associations = associations; this.delegatingHandlerMapping = delegatingHandlerMapping; this.dataRestRouterOperationBuilder = dataRestRouterOperationBuilder; + this.persistentEntities = persistentEntities; + this.mapper = mapper; } public List getRouterOperations(OpenAPI openAPI) { @@ -127,18 +147,38 @@ public List getRouterOperations(OpenAPI openAPI) { Class repository = repositories.getRequiredRepositoryInformation(domainType).getRepositoryInterface(); DataRestRepository dataRestRepository = new DataRestRepository(domainType, repository); ResourceMetadata resourceMetadata = mappings.getMetadataFor(domainType); + final PersistentEntity entity = persistentEntities.getRequiredPersistentEntity(domainType); + final JacksonMetadata jackson = new JacksonMetadata(mapper, domainType); + if (resourceMetadata.isExported()) { for (HandlerMapping handlerMapping : handlerMappingList) { if (handlerMapping instanceof RepositoryRestHandlerMapping) { RepositoryRestHandlerMapping repositoryRestHandlerMapping = (RepositoryRestHandlerMapping) handlerMapping; Map handlerMethodMap = repositoryRestHandlerMapping.getHandlerMethods(); + // Entity controllers lookup first Map handlerMethodMapFiltered = handlerMethodMap.entrySet().stream() .filter(requestMappingInfoHandlerMethodEntry -> REPOSITORY_ENTITY_CONTROLLER.equals(requestMappingInfoHandlerMethodEntry - .getValue().getBeanType().getName()) || REPOSITORY_PROPERTY_CONTROLLER.equals(requestMappingInfoHandlerMethodEntry .getValue().getBeanType().getName())) .filter(controller -> !AbstractOpenApiResource.isHiddenRestControllers(controller.getValue().getBeanType())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a1, a2) -> a1)); + dataRestRepository.setControllerType(ControllerType.ENTITY); findControllers(routerOperationList, handlerMethodMapFiltered, resourceMetadata, dataRestRepository, openAPI); + + Map handlerMethodMapFilteredMethodMap = handlerMethodMap.entrySet().stream() + .filter(requestMappingInfoHandlerMethodEntry -> REPOSITORY_PROPERTY_CONTROLLER.equals(requestMappingInfoHandlerMethodEntry + .getValue().getBeanType().getName())) + .filter(controller -> !AbstractOpenApiResource.isHiddenRestControllers(controller.getValue().getBeanType())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a1, a2) -> a1)); + + entity.doWithAssociations((SimpleAssociationHandler) association -> { + PersistentProperty property = association.getInverse(); + if (jackson.isExported(property) && associations.isLinkableAssociation(property)) { + ResourceMetadata targetTypeMetadata = associations.getMetadataFor(property.getActualType()); + dataRestRepository.setRelationName(targetTypeMetadata.getItemResourceRel().toString()); + dataRestRepository.setControllerType(ControllerType.PROPERTY); + findControllers(routerOperationList, handlerMethodMapFilteredMethodMap, resourceMetadata, dataRestRepository, openAPI); + } + }); } else if (handlerMapping instanceof BasePathAwareHandlerMapping) { BasePathAwareHandlerMapping beanBasePathAwareHandlerMapping = (BasePathAwareHandlerMapping) handlerMapping; @@ -148,7 +188,7 @@ else if (handlerMapping instanceof BasePathAwareHandlerMapping) { .getValue().getBeanType().getName())) .filter(controller -> !AbstractOpenApiResource.isHiddenRestControllers(controller.getValue().getBeanType())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a1, a2) -> a1)); - + dataRestRepository.setControllerType(ControllerType.SCHEMA); findControllers(routerOperationList, handlerMethodMapFiltered, resourceMetadata, dataRestRepository, openAPI); handlerMethodMapFiltered = handlerMethodMap.entrySet().stream() .filter(requestMappingInfoHandlerMethodEntry -> ProfileController.class.equals(requestMappingInfoHandlerMethodEntry diff --git a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/ControllerType.java b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/ControllerType.java index b21a1a953..04d3c8493 100644 --- a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/ControllerType.java +++ b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/ControllerType.java @@ -27,7 +27,7 @@ * The enum Controller type. * @author bnasslahsen */ -enum ControllerType { +public enum ControllerType { /** *Entity controller type. */ @@ -35,5 +35,13 @@ enum ControllerType { /** *Search controller type. */ - SEARCH + SEARCH, + /** + *Schema controller type. + */ + SCHEMA, + /** + *PROPERTY controller type. + */ + PROPERTY } diff --git a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestOperationBuilder.java b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestOperationBuilder.java index d5d347763..12252555c 100644 --- a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestOperationBuilder.java +++ b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestOperationBuilder.java @@ -111,7 +111,9 @@ public Operation buildOperation(HandlerMethod handlerMethod, DataRestRepository OpenAPI openAPI, RequestMethod requestMethod, String operationPath, MethodAttributes methodAttributes, ResourceMetadata resourceMetadata, MethodResourceMapping methodResourceMapping, ControllerType controllerType) { Operation operation = null; - if (ControllerType.ENTITY.equals(controllerType)) { + if (ControllerType.ENTITY.equals(controllerType) + || ControllerType.PROPERTY.equals(controllerType) + || ControllerType.SCHEMA.equals(controllerType)) { operation = buildEntityOperation(handlerMethod, dataRestRepository, openAPI, requestMethod, operationPath, methodAttributes, resourceMetadata); } diff --git a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRepository.java b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRepository.java index dea41f146..1b4b8f089 100644 --- a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRepository.java +++ b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRepository.java @@ -39,6 +39,16 @@ public class DataRestRepository { */ private Class repositoryType; + /** + * The Relation name. + */ + private String relationName; + + /** + * The Controller type. + */ + private ControllerType controllerType; + /** * Instantiates a new Data rest repository. * @@ -85,4 +95,40 @@ public Class getRepositoryType() { public void setRepositoryType(Class repositoryType) { this.repositoryType = repositoryType; } + + /** + * Gets relation name. + * + * @return the relation name + */ + public String getRelationName() { + return relationName; + } + + /** + * Sets relation name. + * + * @param relationName the relation name + */ + public void setRelationName(String relationName) { + this.relationName = relationName; + } + + /** + * Gets controller type. + * + * @return the controller type + */ + public ControllerType getControllerType() { + return controllerType; + } + + /** + * Sets controller type. + * + * @param controllerType the controller type + */ + public void setControllerType(ControllerType controllerType) { + this.controllerType = controllerType; + } } diff --git a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRequestBuilder.java b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRequestBuilder.java index 81c37b250..2697c5abd 100644 --- a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRequestBuilder.java +++ b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRequestBuilder.java @@ -172,7 +172,9 @@ else if (methodParameter.getParameterAnnotation(BackendId.class) != null) { * @return the boolean */ private boolean isParamToIgnore(MethodParameter methodParameter) { - return !requestBuilder.isParamToIgnore(methodParameter) && !isHeaderToIgnore(methodParameter); + return !requestBuilder.isParamToIgnore(methodParameter) + && !isHeaderToIgnore(methodParameter) + && !"property".equals(methodParameter.getParameterName()); } /** diff --git a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRouterOperationBuilder.java b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRouterOperationBuilder.java index 277ef5042..656a59b85 100644 --- a/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRouterOperationBuilder.java +++ b/springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/core/DataRestRouterOperationBuilder.java @@ -113,8 +113,9 @@ public void buildEntityRouterOperationList(List routerOperation Map handlerMethodMap, ResourceMetadata resourceMetadata, DataRestRepository dataRestRepository, OpenAPI openAPI) { String path = resourceMetadata.getPath().toString(); + ControllerType controllerType = (dataRestRepository == null) ? ControllerType.SCHEMA : dataRestRepository.getControllerType(); for (Entry entry : handlerMethodMap.entrySet()) { - buildRouterOperationList(routerOperationList, resourceMetadata, dataRestRepository, openAPI, path, entry, null, ControllerType.ENTITY, null); + buildRouterOperationList(routerOperationList, resourceMetadata, dataRestRepository, openAPI, path, entry, null, controllerType, null); } } @@ -150,12 +151,12 @@ public void buildSearchRouterOperationList(List routerOperation * @param path the path * @param entry the entry * @param subPath the sub path - * @param entity the entity + * @param controllerType the controllerType * @param methodResourceMapping the method resource mapping */ private void buildRouterOperationList(List routerOperationList, ResourceMetadata resourceMetadata, DataRestRepository dataRestRepository, OpenAPI openAPI, String path, Entry entry, - String subPath, ControllerType entity, MethodResourceMapping methodResourceMapping) { + String subPath, ControllerType controllerType, MethodResourceMapping methodResourceMapping) { RequestMappingInfo requestMappingInfo = entry.getKey(); HandlerMethod handlerMethod = entry.getValue(); Set requestMethods = requestMappingInfo.getMethodsCondition().getMethods(); @@ -163,10 +164,12 @@ private void buildRouterOperationList(List routerOperationList, HttpMethods httpMethodsItem = resourceMetadata.getSupportedHttpMethods().getMethodsFor(ResourceType.ITEM); Set requestMethodsItem = requestMethods.stream().filter(requestMethod -> httpMethodsItem.contains(HttpMethod.valueOf(requestMethod.toString()))) .collect(Collectors.toSet()); - HttpMethods httpMethodsCollection = resourceMetadata.getSupportedHttpMethods().getMethodsFor(ResourceType.COLLECTION); - Set requestMethodsCollection = requestMethods.stream().filter(requestMethod -> httpMethodsCollection.contains(HttpMethod.valueOf(requestMethod.toString()))) - .collect(Collectors.toSet()); - requestMethodsItem.addAll(requestMethodsCollection); + if (!ControllerType.PROPERTY.equals(controllerType)) { + HttpMethods httpMethodsCollection = resourceMetadata.getSupportedHttpMethods().getMethodsFor(ResourceType.COLLECTION); + Set requestMethodsCollection = requestMethods.stream().filter(requestMethod -> httpMethodsCollection.contains(HttpMethod.valueOf(requestMethod.toString()))) + .collect(Collectors.toSet()); + requestMethodsItem.addAll(requestMethodsCollection); + } requestMethods = requestMethodsItem; } @@ -176,9 +179,11 @@ private void buildRouterOperationList(List routerOperationList, PatternsRequestCondition patternsRequestCondition = requestMappingInfo.getPatternsCondition(); Set patterns = patternsRequestCondition.getPatterns(); Map regexMap = new LinkedHashMap<>(); - String operationPath = calculateOperationPath(path, subPath, patterns, regexMap, entity); + String operationPath = calculateOperationPath(path, subPath, patterns, regexMap, controllerType); + if (ControllerType.PROPERTY.equals(controllerType)) + operationPath = operationPath.replace("{property}", dataRestRepository.getRelationName()); buildRouterOperation(routerOperationList, dataRestRepository, openAPI, methodResourceMapping, - handlerMethod, requestMethod, resourceMetadata, operationPath, entity); + handlerMethod, requestMethod, resourceMetadata, operationPath, controllerType); } } } diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/ChildProperty.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/ChildProperty.java new file mode 100644 index 000000000..c2256acce --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/ChildProperty.java @@ -0,0 +1,35 @@ +package test.org.springdoc.api.app17; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import lombok.Data; + +@Entity +public @Data +class ChildProperty { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/ChildPropertyRepository.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/ChildPropertyRepository.java new file mode 100644 index 000000000..f9572893c --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/ChildPropertyRepository.java @@ -0,0 +1,6 @@ +package test.org.springdoc.api.app17; + +import org.springframework.data.repository.PagingAndSortingRepository; + +public interface ChildPropertyRepository extends PagingAndSortingRepository { +} \ No newline at end of file diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/Property.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/Property.java new file mode 100644 index 000000000..32fdc73ef --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/Property.java @@ -0,0 +1,49 @@ +package test.org.springdoc.api.app17; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; + +import lombok.Data; + +@Entity +public @Data +class Property { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + + @ManyToOne + @JoinColumn(name = "child_property_id") + private ChildProperty childProperty; + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public ChildProperty getChildProperty() { + return childProperty; + } + + public void setChildProperty(ChildProperty childProperty) { + this.childProperty = childProperty; + } +} \ No newline at end of file diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/PropertyRepository.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/PropertyRepository.java new file mode 100644 index 000000000..51da75c24 --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/PropertyRepository.java @@ -0,0 +1,6 @@ +package test.org.springdoc.api.app17; + +import org.springframework.data.repository.PagingAndSortingRepository; + +public interface PropertyRepository extends PagingAndSortingRepository { +} \ No newline at end of file diff --git a/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/SpringDocApp17Test.java b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/SpringDocApp17Test.java new file mode 100644 index 000000000..91f369ed2 --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/java/test/org/springdoc/api/app17/SpringDocApp17Test.java @@ -0,0 +1,33 @@ +/* + * + * * + * * * + * * * * Copyright 2019-2020 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.app17; + +import test.org.springdoc.api.AbstractSpringDocTest; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +public class SpringDocApp17Test extends AbstractSpringDocTest { + + @SpringBootApplication + static class SpringDocTestApp {} +} \ No newline at end of file diff --git a/springdoc-openapi-data-rest/src/test/resources/results/app10.json b/springdoc-openapi-data-rest/src/test/resources/results/app10.json index 2000fc1fe..862e0394b 100644 --- a/springdoc-openapi-data-rest/src/test/resources/results/app10.json +++ b/springdoc-openapi-data-rest/src/test/resources/results/app10.json @@ -253,7 +253,7 @@ } } }, - "/accounts/{id}/{property}": { + "/accounts/{id}/customer": { "get": { "tags": [ "account-property-reference-controller" @@ -268,14 +268,6 @@ "schema": { "type": "string" } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } } ], "responses": { @@ -313,14 +305,6 @@ "schema": { "type": "string" } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } } ], "requestBody": { @@ -368,62 +352,6 @@ } } }, - "post": { - "tags": [ - "account-property-reference-controller" - ], - "description": "create-account", - "operationId": "createPropertyReference-account-post", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "201": { - "description": "Created", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelAccount" - } - } - } - } - } - }, "delete": { "tags": [ "account-property-reference-controller" @@ -438,14 +366,6 @@ "schema": { "type": "string" } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } } ], "responses": { @@ -471,14 +391,6 @@ "schema": { "type": "string" } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } } ], "requestBody": { @@ -517,7 +429,7 @@ } } }, - "/accounts/{id}/{property}/{propertyId}": { + "/accounts/{id}/customer/{propertyId}": { "get": { "tags": [ "account-property-reference-controller" @@ -533,14 +445,6 @@ "type": "string" } }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, { "name": "propertyId", "in": "path", @@ -581,14 +485,6 @@ "type": "string" } }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, { "name": "propertyId", "in": "path", @@ -859,287 +755,6 @@ } } }, - "/customers/{id}/{property}": { - "get": { - "tags": [ - "customer-property-reference-controller" - ], - "description": "get-customer", - "operationId": "followPropertyReference-customer-get_1", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - }, - "404": { - "description": "Not Found" - } - } - }, - "put": { - "tags": [ - "customer-property-reference-controller" - ], - "description": "update-customer", - "operationId": "createPropertyReference-customer-put", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - }, - "201": { - "description": "Created", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - }, - "204": { - "description": "No Content" - } - } - }, - "post": { - "tags": [ - "customer-property-reference-controller" - ], - "description": "create-customer", - "operationId": "createPropertyReference-customer-post", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "201": { - "description": "Created", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - } - } - }, - "patch": { - "tags": [ - "customer-property-reference-controller" - ], - "description": "patch-customer", - "operationId": "createPropertyReference-customer-patch", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - }, - "204": { - "description": "No Content" - } - } - } - }, - "/customers/{id}/{property}/{propertyId}": { - "get": { - "tags": [ - "customer-property-reference-controller" - ], - "description": "get-customer", - "operationId": "followPropertyReference-customer-get", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "propertyId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - }, - "404": { - "description": "Not Found" - } - } - } - }, "/profile": { "get": { "tags": [ @@ -1303,31 +918,49 @@ } } }, - "RepresentationModelAccount": { + "CollectionModelCustomer": { "type": "object", "properties": { + "_embedded": { + "type": "object", + "properties": { + "customers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Customer" + } + } + } + }, "_links": { "$ref": "#/components/schemas/Links" } } }, - "Account": { + "Customer": { "type": "object", "properties": { "id": { "type": "integer", "format": "int64" }, - "customer": { - "$ref": "#/components/schemas/Customer" + "firstname": { + "type": "string" }, - "expiryDate": { - "type": "string", - "format": "date-time" + "lastname": { + "type": "string" } } }, - "Customer": { + "RepresentationModelCustomer": { + "type": "object", + "properties": { + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, + "EntityModelCustomer": { "type": "object", "properties": { "id": { @@ -1339,84 +972,81 @@ }, "lastname": { "type": "string" - } - } - }, - "CollectionModelAccount": { - "type": "object", - "properties": { - "_embedded": { - "type": "object", - "properties": { - "accounts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Account" - } - } - } }, "_links": { "$ref": "#/components/schemas/Links" } } }, - "EntityModelAccount": { + "PageMetadata": { "type": "object", "properties": { - "id": { + "size": { "type": "integer", "format": "int64" }, - "customer": { - "$ref": "#/components/schemas/Customer" + "totalElements": { + "type": "integer", + "format": "int64" }, - "expiryDate": { - "type": "string", - "format": "date-time" + "totalPages": { + "type": "integer", + "format": "int64" }, - "_links": { - "$ref": "#/components/schemas/Links" + "number": { + "type": "integer", + "format": "int64" } } }, - "CollectionModelObject": { + "PagedModelCustomer": { "type": "object", "properties": { "_embedded": { "type": "object", "properties": { - "objects": { + "customers": { "type": "array", "items": { - "type": "object" + "$ref": "#/components/schemas/Customer" } } } }, "_links": { "$ref": "#/components/schemas/Links" + }, + "page": { + "$ref": "#/components/schemas/PageMetadata" } } }, - "RepresentationModelCustomer": { + "Account": { "type": "object", "properties": { - "_links": { - "$ref": "#/components/schemas/Links" + "id": { + "type": "integer", + "format": "int64" + }, + "customer": { + "$ref": "#/components/schemas/Customer" + }, + "expiryDate": { + "type": "string", + "format": "date-time" } } }, - "CollectionModelCustomer": { + "CollectionModelAccount": { "type": "object", "properties": { "_embedded": { "type": "object", "properties": { - "customers": { + "accounts": { "type": "array", "items": { - "$ref": "#/components/schemas/Customer" + "$ref": "#/components/schemas/Account" } } } @@ -1426,64 +1056,49 @@ } } }, - "EntityModelCustomer": { + "RepresentationModelAccount": { "type": "object", "properties": { - "id": { - "type": "integer", - "format": "int64" - }, - "firstname": { - "type": "string" - }, - "lastname": { - "type": "string" - }, "_links": { "$ref": "#/components/schemas/Links" } } }, - "PageMetadata": { + "EntityModelAccount": { "type": "object", "properties": { - "size": { + "id": { "type": "integer", "format": "int64" }, - "totalElements": { - "type": "integer", - "format": "int64" + "customer": { + "$ref": "#/components/schemas/Customer" }, - "totalPages": { - "type": "integer", - "format": "int64" + "expiryDate": { + "type": "string", + "format": "date-time" }, - "number": { - "type": "integer", - "format": "int64" + "_links": { + "$ref": "#/components/schemas/Links" } } }, - "PagedModelCustomer": { + "CollectionModelObject": { "type": "object", "properties": { "_embedded": { "type": "object", "properties": { - "customers": { + "objects": { "type": "array", "items": { - "$ref": "#/components/schemas/Customer" + "type": "object" } } } }, "_links": { "$ref": "#/components/schemas/Links" - }, - "page": { - "$ref": "#/components/schemas/PageMetadata" } } }, diff --git a/springdoc-openapi-data-rest/src/test/resources/results/app11.json b/springdoc-openapi-data-rest/src/test/resources/results/app11.json index a69750fc1..c4ffdb8c8 100644 --- a/springdoc-openapi-data-rest/src/test/resources/results/app11.json +++ b/springdoc-openapi-data-rest/src/test/resources/results/app11.json @@ -289,361 +289,6 @@ } } }, - "/peopleme/{id}/{property}": { - "get": { - "tags": [ - "person-property-reference-controller" - ], - "description": "get-person", - "operationId": "followPropertyReference-person-get_1", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelPerson" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelPerson" - } - } - } - }, - "404": { - "description": "Not Found" - } - } - }, - "put": { - "tags": [ - "person-property-reference-controller" - ], - "description": "update-person", - "operationId": "createPropertyReference-person-put", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelPerson" - } - } - } - }, - "201": { - "description": "Created", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelPerson" - } - } - } - }, - "204": { - "description": "No Content" - } - } - }, - "post": { - "tags": [ - "person-property-reference-controller" - ], - "description": "create-person", - "operationId": "createPropertyReference-person-post", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "201": { - "description": "Created", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelPerson" - } - } - } - } - } - }, - "delete": { - "tags": [ - "person-property-reference-controller" - ], - "description": "delete-person", - "operationId": "deletePropertyReference-person-delete", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "No Content" - }, - "404": { - "description": "Not Found" - } - } - }, - "patch": { - "tags": [ - "person-property-reference-controller" - ], - "description": "patch-person", - "operationId": "createPropertyReference-person-patch", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelPerson" - } - } - } - }, - "204": { - "description": "No Content" - } - } - } - }, - "/peopleme/{id}/{property}/{propertyId}": { - "get": { - "tags": [ - "person-property-reference-controller" - ], - "description": "get-person", - "operationId": "followPropertyReference-person-get", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "propertyId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelPerson" - } - } - } - }, - "404": { - "description": "Not Found" - } - } - }, - "delete": { - "tags": [ - "person-property-reference-controller" - ], - "description": "delete-person", - "operationId": "deletePropertyReferenceId-person-delete", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "propertyId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "204": { - "description": "No Content" - }, - "404": { - "description": "Not Found" - } - } - } - }, "/profile": { "get": { "tags": [ @@ -777,25 +422,6 @@ } } }, - "RepresentationModelPerson": { - "type": "object", - "properties": { - "_links": { - "$ref": "#/components/schemas/Links" - } - } - }, - "Person": { - "type": "object", - "properties": { - "firstName": { - "type": "string" - }, - "lastName": { - "type": "string" - } - } - }, "CollectionModelPerson": { "type": "object", "properties": { @@ -815,7 +441,7 @@ } } }, - "EntityModelPerson": { + "Person": { "type": "object", "properties": { "firstName": { @@ -823,25 +449,25 @@ }, "lastName": { "type": "string" - }, + } + } + }, + "RepresentationModelPerson": { + "type": "object", + "properties": { "_links": { "$ref": "#/components/schemas/Links" } } }, - "CollectionModelObject": { + "EntityModelPerson": { "type": "object", "properties": { - "_embedded": { - "type": "object", - "properties": { - "objects": { - "type": "array", - "items": { - "type": "object" - } - } - } + "firstName": { + "type": "string" + }, + "lastName": { + "type": "string" }, "_links": { "$ref": "#/components/schemas/Links" diff --git a/springdoc-openapi-data-rest/src/test/resources/results/app16.json b/springdoc-openapi-data-rest/src/test/resources/results/app16.json index 44d44189d..6deeffca5 100644 --- a/springdoc-openapi-data-rest/src/test/resources/results/app16.json +++ b/springdoc-openapi-data-rest/src/test/resources/results/app16.json @@ -293,7 +293,7 @@ ] } }, - "/accounts/{id}/{property}": { + "/accounts/{id}/customer": { "get": { "tags": [ "The account Repository" @@ -308,14 +308,6 @@ "schema": { "type": "string" } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } } ], "responses": { @@ -358,14 +350,6 @@ "schema": { "type": "string" } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } } ], "requestBody": { @@ -418,67 +402,6 @@ } ] }, - "post": { - "tags": [ - "The account Repository" - ], - "description": "create-account", - "operationId": "createPropertyReference-account-post", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "201": { - "description": "Created", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelAccount" - } - } - } - } - }, - "security": [ - { - "bearer": [] - } - ] - }, "delete": { "tags": [ "The account Repository" @@ -493,14 +416,6 @@ "schema": { "type": "string" } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } } ], "responses": { @@ -531,14 +446,6 @@ "schema": { "type": "string" } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } } ], "requestBody": { @@ -582,7 +489,7 @@ ] } }, - "/accounts/{id}/{property}/{propertyId}": { + "/accounts/{id}/customer/{propertyId}": { "get": { "tags": [ "The account Repository" @@ -598,14 +505,6 @@ "type": "string" } }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, { "name": "propertyId", "in": "path", @@ -651,14 +550,6 @@ "type": "string" } }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, { "name": "propertyId", "in": "path", @@ -934,287 +825,6 @@ } } }, - "/customers/{id}/{property}": { - "get": { - "tags": [ - "The customer Repository" - ], - "description": "get-customer", - "operationId": "followPropertyReference-customer-get_1", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - }, - "404": { - "description": "Not Found" - } - } - }, - "put": { - "tags": [ - "The customer Repository" - ], - "description": "update-customer", - "operationId": "createPropertyReference-customer-put", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - }, - "201": { - "description": "Created", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - }, - "204": { - "description": "No Content" - } - } - }, - "post": { - "tags": [ - "The customer Repository" - ], - "description": "create-customer", - "operationId": "createPropertyReference-customer-post", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "201": { - "description": "Created", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - } - } - }, - "patch": { - "tags": [ - "The customer Repository" - ], - "description": "patch-customer", - "operationId": "createPropertyReference-customer-patch", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "application/x-spring-data-compact+json": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - }, - "text/uri-list": { - "schema": { - "$ref": "#/components/schemas/CollectionModelObject" - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - }, - "204": { - "description": "No Content" - } - } - } - }, - "/customers/{id}/{property}/{propertyId}": { - "get": { - "tags": [ - "The customer Repository" - ], - "description": "get-customer", - "operationId": "followPropertyReference-customer-get", - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "property", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "propertyId", - "in": "path", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "OK", - "content": { - "application/hal+json": { - "schema": { - "$ref": "#/components/schemas/RepresentationModelCustomer" - } - } - } - }, - "404": { - "description": "Not Found" - } - } - } - }, "/profile": { "get": { "tags": [ @@ -1378,14 +988,6 @@ } } }, - "RepresentationModelAccount": { - "type": "object", - "properties": { - "_links": { - "$ref": "#/components/schemas/Links" - } - } - }, "Account": { "type": "object", "properties": { @@ -1402,6 +1004,25 @@ } } }, + "CollectionModelAccount": { + "type": "object", + "properties": { + "_embedded": { + "type": "object", + "properties": { + "accounts": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Account" + } + } + } + }, + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, "Customer": { "type": "object", "properties": { @@ -1417,20 +1038,9 @@ } } }, - "CollectionModelAccount": { + "RepresentationModelAccount": { "type": "object", "properties": { - "_embedded": { - "type": "object", - "properties": { - "accounts": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Account" - } - } - } - }, "_links": { "$ref": "#/components/schemas/Links" } @@ -1474,14 +1084,6 @@ } } }, - "RepresentationModelCustomer": { - "type": "object", - "properties": { - "_links": { - "$ref": "#/components/schemas/Links" - } - } - }, "CollectionModelCustomer": { "type": "object", "properties": { @@ -1501,6 +1103,14 @@ } } }, + "RepresentationModelCustomer": { + "type": "object", + "properties": { + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, "EntityModelCustomer": { "type": "object", "properties": { diff --git a/springdoc-openapi-data-rest/src/test/resources/results/app17.json b/springdoc-openapi-data-rest/src/test/resources/results/app17.json new file mode 100644 index 000000000..44a915b18 --- /dev/null +++ b/springdoc-openapi-data-rest/src/test/resources/results/app17.json @@ -0,0 +1,1084 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "OpenAPI definition", + "version": "v0" + }, + "servers": [ + { + "url": "http://localhost", + "description": "Generated server url" + } + ], + "paths": { + "/childProperties": { + "get": { + "tags": [ + "child-property-entity-controller" + ], + "description": "get-childproperty", + "operationId": "getCollectionResource-childproperty-get_1", + "parameters": [ + { + "name": "page", + "in": "query", + "description": "Zero-based page index (0..N)", + "required": false, + "schema": { + "minimum": 0, + "type": "integer", + "default": "0" + } + }, + { + "name": "size", + "in": "query", + "description": "The size of the page to be returned", + "required": false, + "schema": { + "minimum": 1, + "type": "integer", + "default": "20" + } + }, + { + "name": "sort", + "in": "query", + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/CollectionModelChildProperty" + } + }, + "application/x-spring-data-compact+json": { + "schema": { + "$ref": "#/components/schemas/CollectionModelChildProperty" + } + }, + "text/uri-list": { + "schema": { + "$ref": "#/components/schemas/CollectionModelChildProperty" + } + } + } + } + } + }, + "post": { + "tags": [ + "child-property-entity-controller" + ], + "description": "create-childproperty", + "operationId": "postCollectionResource-childproperty-post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChildProperty" + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelChildProperty" + } + } + } + } + } + } + }, + "/childProperties/{id}": { + "get": { + "tags": [ + "child-property-entity-controller" + ], + "description": "get-childproperty", + "operationId": "getItemResource-childproperty-get", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/EntityModelChildProperty" + } + } + } + }, + "404": { + "description": "Not Found" + } + } + }, + "put": { + "tags": [ + "child-property-entity-controller" + ], + "description": "update-childproperty", + "operationId": "putItemResource-childproperty-put", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChildProperty" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelChildProperty" + } + } + } + }, + "201": { + "description": "Created", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelChildProperty" + } + } + } + }, + "204": { + "description": "No Content" + } + } + }, + "delete": { + "tags": [ + "child-property-entity-controller" + ], + "description": "delete-childproperty", + "operationId": "deleteItemResource-childproperty-delete", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found" + } + } + }, + "patch": { + "tags": [ + "child-property-entity-controller" + ], + "description": "patch-childproperty", + "operationId": "patchItemResource-childproperty-patch", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChildProperty" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelChildProperty" + } + } + } + }, + "204": { + "description": "No Content" + } + } + } + }, + "/profile": { + "get": { + "tags": [ + "profile-controller" + ], + "operationId": "listAllFormsOfMetadata_1", + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelObject" + } + } + } + } + } + } + }, + "/profile/childProperties": { + "get": { + "tags": [ + "profile-controller" + ], + "operationId": "descriptor_1", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "string" + } + }, + "application/alps+json": { + "schema": { + "type": "string" + } + }, + "application/schema+json": { + "schema": { + "$ref": "#/components/schemas/JsonSchema" + } + } + } + } + } + } + }, + "/profile/properties": { + "get": { + "tags": [ + "profile-controller" + ], + "operationId": "descriptor_2", + "responses": { + "200": { + "description": "OK", + "content": { + "*/*": { + "schema": { + "type": "string" + } + }, + "application/alps+json": { + "schema": { + "type": "string" + } + }, + "application/schema+json": { + "schema": { + "$ref": "#/components/schemas/JsonSchema" + } + } + } + } + } + } + }, + "/properties": { + "get": { + "tags": [ + "property-entity-controller" + ], + "description": "get-property", + "operationId": "getCollectionResource-property-get_1", + "parameters": [ + { + "name": "page", + "in": "query", + "description": "Zero-based page index (0..N)", + "required": false, + "schema": { + "minimum": 0, + "type": "integer", + "default": "0" + } + }, + { + "name": "size", + "in": "query", + "description": "The size of the page to be returned", + "required": false, + "schema": { + "minimum": 1, + "type": "integer", + "default": "20" + } + }, + { + "name": "sort", + "in": "query", + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/CollectionModelProperty" + } + }, + "application/x-spring-data-compact+json": { + "schema": { + "$ref": "#/components/schemas/CollectionModelProperty" + } + }, + "text/uri-list": { + "schema": { + "$ref": "#/components/schemas/CollectionModelProperty" + } + } + } + } + } + }, + "post": { + "tags": [ + "property-entity-controller" + ], + "description": "create-property", + "operationId": "postCollectionResource-property-post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Property" + } + } + } + }, + "responses": { + "201": { + "description": "Created", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelProperty" + } + } + } + } + } + } + }, + "/properties/{id}": { + "get": { + "tags": [ + "property-entity-controller" + ], + "description": "get-property", + "operationId": "getItemResource-property-get", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/EntityModelProperty" + } + } + } + }, + "404": { + "description": "Not Found" + } + } + }, + "put": { + "tags": [ + "property-entity-controller" + ], + "description": "update-property", + "operationId": "putItemResource-property-put", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Property" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelProperty" + } + } + } + }, + "201": { + "description": "Created", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelProperty" + } + } + } + }, + "204": { + "description": "No Content" + } + } + }, + "delete": { + "tags": [ + "property-entity-controller" + ], + "description": "delete-property", + "operationId": "deleteItemResource-property-delete", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found" + } + } + }, + "patch": { + "tags": [ + "property-entity-controller" + ], + "description": "patch-property", + "operationId": "patchItemResource-property-patch", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Property" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelProperty" + } + } + } + }, + "204": { + "description": "No Content" + } + } + } + }, + "/properties/{id}/childProperty": { + "get": { + "tags": [ + "property-property-reference-controller" + ], + "description": "get-property", + "operationId": "followPropertyReference-property-get_1", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelProperty" + } + }, + "text/uri-list": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelProperty" + } + } + } + }, + "404": { + "description": "Not Found" + } + } + }, + "put": { + "tags": [ + "property-property-reference-controller" + ], + "description": "update-property", + "operationId": "createPropertyReference-property-put", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CollectionModelObject" + } + }, + "application/x-spring-data-compact+json": { + "schema": { + "$ref": "#/components/schemas/CollectionModelObject" + } + }, + "text/uri-list": { + "schema": { + "$ref": "#/components/schemas/CollectionModelObject" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelProperty" + } + } + } + }, + "201": { + "description": "Created", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelProperty" + } + } + } + }, + "204": { + "description": "No Content" + } + } + }, + "delete": { + "tags": [ + "property-property-reference-controller" + ], + "description": "delete-property", + "operationId": "deletePropertyReference-property-delete", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found" + } + } + }, + "patch": { + "tags": [ + "property-property-reference-controller" + ], + "description": "patch-property", + "operationId": "createPropertyReference-property-patch", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CollectionModelObject" + } + }, + "application/x-spring-data-compact+json": { + "schema": { + "$ref": "#/components/schemas/CollectionModelObject" + } + }, + "text/uri-list": { + "schema": { + "$ref": "#/components/schemas/CollectionModelObject" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelProperty" + } + } + } + }, + "204": { + "description": "No Content" + } + } + } + }, + "/properties/{id}/childProperty/{propertyId}": { + "get": { + "tags": [ + "property-property-reference-controller" + ], + "description": "get-property", + "operationId": "followPropertyReference-property-get", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "propertyId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK", + "content": { + "application/hal+json": { + "schema": { + "$ref": "#/components/schemas/RepresentationModelProperty" + } + } + } + }, + "404": { + "description": "Not Found" + } + } + }, + "delete": { + "tags": [ + "property-property-reference-controller" + ], + "description": "delete-property", + "operationId": "deletePropertyReferenceId-property-delete", + "parameters": [ + { + "name": "id", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "propertyId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "404": { + "description": "Not Found" + } + } + } + } + }, + "components": { + "schemas": { + "AbstractJsonSchemaPropertyObject": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "readOnly": { + "type": "boolean" + } + } + }, + "Item": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "properties": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AbstractJsonSchemaPropertyObject" + } + }, + "requiredProperties": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "JsonSchema": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "properties": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/AbstractJsonSchemaPropertyObject" + } + }, + "requiredProperties": { + "type": "array", + "items": { + "type": "string" + } + }, + "definitions": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/Item" + } + }, + "type": { + "type": "string" + }, + "$schema": { + "type": "string" + } + } + }, + "Links": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/Link" + } + }, + "RepresentationModelObject": { + "type": "object", + "properties": { + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, + "ChildProperty": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + } + } + }, + "CollectionModelChildProperty": { + "type": "object", + "properties": { + "_embedded": { + "type": "object", + "properties": { + "childProperties": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChildProperty" + } + } + } + }, + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, + "RepresentationModelChildProperty": { + "type": "object", + "properties": { + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, + "EntityModelChildProperty": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + }, + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, + "CollectionModelProperty": { + "type": "object", + "properties": { + "_embedded": { + "type": "object", + "properties": { + "properties": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Property" + } + } + } + }, + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, + "Property": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + }, + "childProperty": { + "$ref": "#/components/schemas/ChildProperty" + } + } + }, + "RepresentationModelProperty": { + "type": "object", + "properties": { + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, + "EntityModelProperty": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64" + }, + "name": { + "type": "string" + }, + "childProperty": { + "$ref": "#/components/schemas/ChildProperty" + }, + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, + "CollectionModelObject": { + "type": "object", + "properties": { + "_embedded": { + "type": "object", + "properties": { + "objects": { + "type": "array", + "items": { + "type": "object" + } + } + } + }, + "_links": { + "$ref": "#/components/schemas/Links" + } + } + }, + "Link": { + "type": "object", + "properties": { + "href": { + "type": "string" + }, + "hreflang": { + "type": "string" + }, + "title": { + "type": "string" + }, + "type": { + "type": "string" + }, + "deprecation": { + "type": "string" + }, + "profile": { + "type": "string" + }, + "name": { + "type": "string" + }, + "templated": { + "type": "boolean" + } + } + } + } + } +}