Skip to content

Commit 04150e1

Browse files
committed
showcase issue
1 parent 2db978a commit 04150e1

File tree

8 files changed

+444
-1
lines changed

8 files changed

+444
-1
lines changed

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/OpenAPIService.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.util.stream.Collectors;
4343
import java.util.stream.Stream;
4444

45+
import com.fasterxml.jackson.annotation.JsonInclude;
4546
import com.fasterxml.jackson.core.JsonProcessingException;
4647
import com.fasterxml.jackson.databind.ObjectMapper;
4748
import io.swagger.v3.core.jackson.TypeNameResolver;
@@ -70,6 +71,7 @@
7071
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
7172
import org.springdoc.core.properties.SpringDocConfigProperties;
7273
import org.springdoc.core.providers.JavadocProvider;
74+
import org.springdoc.core.providers.ObjectMapperProvider;
7375
import org.springdoc.core.utils.PropertyResolverUtils;
7476

7577
import org.springframework.beans.BeansException;
@@ -244,8 +246,11 @@ public OpenAPI build(Locale locale) {
244246
}
245247
else {
246248
try {
247-
ObjectMapper objectMapper = new ObjectMapper();
249+
ObjectMapper objectMapper = ObjectMapperProvider.createJson(springDocConfigProperties);
248250
calculatedOpenAPI = objectMapper.readValue(objectMapper.writeValueAsString(openAPI), OpenAPI.class);
251+
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
252+
Map extensionsClone = objectMapper.readValue(objectMapper.writeValueAsString(openAPI.getExtensions()), Map.class);
253+
calculatedOpenAPI.extensions(extensionsClone);
249254
}
250255
catch (JsonProcessingException e) {
251256
LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package test.org.springdoc.api.app9;
2+
3+
import io.swagger.v3.oas.models.Components;
4+
import io.swagger.v3.oas.models.OpenAPI;
5+
import io.swagger.v3.oas.models.info.Contact;
6+
import io.swagger.v3.oas.models.info.Info;
7+
import io.swagger.v3.oas.models.media.ArraySchema;
8+
import io.swagger.v3.oas.models.media.Schema;
9+
import io.swagger.v3.oas.models.security.SecurityScheme;
10+
import io.swagger.v3.oas.models.tags.Tag;
11+
import org.springdoc.core.models.GroupedOpenApi;
12+
import org.springframework.context.annotation.Bean;
13+
import org.springframework.context.annotation.Configuration;
14+
15+
import java.util.List;
16+
17+
@Configuration
18+
public class FooConfiguration {
19+
@Bean
20+
OpenAPI customOpenApi() {
21+
return new OpenAPI()
22+
.components(new Components().addSecuritySchemes("bearerScheme",
23+
new SecurityScheme()
24+
.type(SecurityScheme.Type.HTTP)
25+
.scheme("bearer")
26+
.bearerFormat("JWT"))
27+
.addSchemas("FeedResponse", feedResponseSchema()))
28+
.info(new Info()
29+
.title("Response API")
30+
.description("API for some response")
31+
.version("0.0.1")
32+
.contact(new Contact()
33+
.name("EAlf91")))
34+
.tags(List.of(new Tag()
35+
.name("ResponseTag")
36+
.description("ResponseTag for API"),
37+
new Tag()
38+
.name("ResponseData")
39+
.description("Version 2 ResponseApi")));
40+
41+
}
42+
43+
private Schema<?> feedResponseSchema() {
44+
Schema<?> schema = new Schema<>();
45+
schema.addProperty("_links", linkSchema());
46+
schema.addProperty("data", new ArraySchema().items(new Schema<>().$ref("#/components/schemas/ResponseData")));
47+
return schema;
48+
}
49+
50+
private Schema<?> linkSchema() {
51+
Schema<?> linkSchema = new Schema<>();
52+
linkSchema.addProperty("next", new Schema<>().$ref("#/components/schemas/Link").example("http://localhost:8080/some-link"));
53+
linkSchema.addProperty("self", new Schema<>().$ref("#/components/schemas/Link").example("http://localhost:8080/some-other-link"));
54+
return linkSchema;
55+
}
56+
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
*
3+
* * Copyright 2019-2020 the original author or authors.
4+
* *
5+
* * Licensed under the Apache License, Version 2.0 (the "License");
6+
* * you may not use this file except in compliance with the License.
7+
* * You may obtain a copy of the License at
8+
* *
9+
* * https://www.apache.org/licenses/LICENSE-2.0
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the License is distributed on an "AS IS" BASIS,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the License for the specific language governing permissions and
15+
* * limitations under the License.
16+
*
17+
*/
18+
19+
package test.org.springdoc.api.app9;
20+
21+
import org.springframework.boot.autoconfigure.SpringBootApplication;
22+
import test.org.springdoc.api.AbstractSpringDocTest;
23+
24+
public class SpringDocApp9Test extends AbstractSpringDocTest {
25+
26+
@SpringBootApplication
27+
static class SpringDocTestApp {
28+
}
29+
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package test.org.springdoc.api.app9.application;
2+
3+
import io.swagger.v3.oas.annotations.Operation;
4+
import io.swagger.v3.oas.annotations.tags.Tag;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.extern.slf4j.Slf4j;
7+
import org.springframework.http.HttpStatus;
8+
import org.springframework.http.MediaType;
9+
import org.springframework.web.bind.annotation.*;
10+
import test.org.springdoc.api.app9.application.dto.ResponseData;
11+
import test.org.springdoc.api.app9.application.dto.FeedResponse;
12+
13+
import java.util.List;
14+
import java.util.UUID;
15+
@Tag(name = "ResponseDataController")
16+
@RestController
17+
@RequestMapping(value = "/some-route", produces = MediaType.APPLICATION_JSON_VALUE)
18+
@RequiredArgsConstructor
19+
@Slf4j
20+
public class FooController {
21+
22+
23+
24+
25+
@Operation(summary = "Get all data", description = "Get all data")
26+
@GetMapping(value = "foo/{id}")
27+
@ResponseStatus(HttpStatus.OK)
28+
public FeedResponse getFoo(@PathVariable("id") UUID id) {
29+
var dataList = List.of(ResponseData.builder().dataId(id).build());
30+
return FeedResponse.createForResponseData(dataList, UUID.randomUUID());
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package test.org.springdoc.api.app9.application.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import jakarta.validation.constraints.NotNull;
5+
import lombok.*;
6+
import lombok.experimental.Accessors;
7+
import org.springframework.hateoas.IanaLinkRelations;
8+
import org.springframework.hateoas.RepresentationModel;
9+
import test.org.springdoc.api.app9.application.FooController;
10+
11+
import java.util.List;
12+
import java.util.UUID;
13+
14+
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
15+
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
16+
17+
@Getter
18+
@Accessors(fluent = true)
19+
@Builder(access = AccessLevel.PACKAGE)
20+
@EqualsAndHashCode(callSuper = true)
21+
public class FeedResponse extends RepresentationModel<FeedResponse> {
22+
@NotNull
23+
@JsonProperty("data")
24+
private final List<ResponseData> data;
25+
26+
public static FeedResponse createForResponseData(@NotNull List<ResponseData> responseData, UUID uuid) {
27+
var feedResponse = new FeedResponse(responseData);
28+
feedResponse.add(linkTo(methodOn(FooController.class).getFoo(uuid)).withSelfRel());
29+
30+
31+
feedResponse.add(linkTo(methodOn(FooController.class).getFoo(uuid)).withRel(IanaLinkRelations.NEXT));
32+
33+
return feedResponse;
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package test.org.springdoc.api.app9.application.dto;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import io.swagger.v3.oas.annotations.media.Schema;
5+
import jakarta.validation.constraints.NotNull;
6+
import lombok.Builder;
7+
8+
import java.time.LocalDate;
9+
import java.util.UUID;
10+
11+
@Builder
12+
public record ResponseData(
13+
@JsonProperty(value = "DATA_ID", required = true)
14+
@NotNull
15+
UUID dataId,
16+
@JsonProperty(value = "DATE", required = true)
17+
@NotNull
18+
@Schema(example = "2024-03-27", format = "date")
19+
LocalDate date
20+
) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
{
2+
"openapi": "3.0.1",
3+
"info": {
4+
"title": "Response API",
5+
"description": "API for some response",
6+
"contact": {
7+
"name": "EAlf91"
8+
},
9+
"version": "0.0.1"
10+
},
11+
"servers": [
12+
{
13+
"url": "http://localhost",
14+
"description": "Generated server url"
15+
}
16+
],
17+
"tags": [
18+
{
19+
"name": "ResponseTag",
20+
"description": "ResponseTag for API"
21+
},
22+
{
23+
"name": "ResponseData",
24+
"description": "Version 2 ResponseApi"
25+
}
26+
],
27+
"paths": {
28+
"/some-route/foo/{id}": {
29+
"get": {
30+
"tags": [
31+
"ResponseDataController"
32+
],
33+
"summary": "Get all data",
34+
"description": "Get all data",
35+
"operationId": "getFoo",
36+
"parameters": [
37+
{
38+
"name": "id",
39+
"in": "path",
40+
"required": true,
41+
"schema": {
42+
"type": "string",
43+
"format": "uuid"
44+
}
45+
}
46+
],
47+
"responses": {
48+
"200": {
49+
"description": "OK",
50+
"content": {
51+
"application/json": {
52+
"schema": {
53+
"$ref": "#/components/schemas/FeedResponse"
54+
}
55+
}
56+
}
57+
}
58+
}
59+
}
60+
}
61+
},
62+
"components": {
63+
"schemas": {
64+
"FeedResponse": {
65+
"type": "object",
66+
"properties": {
67+
"_links": {
68+
"type": "object",
69+
"properties": {
70+
"next": {
71+
"$ref": "#/components/schemas/Link"
72+
},
73+
"self": {
74+
"$ref": "#/components/schemas/Link"
75+
}
76+
}
77+
},
78+
"data": {
79+
"type": "array",
80+
"items": {
81+
"$ref": "#/components/schemas/ResponseData"
82+
}
83+
}
84+
}
85+
},
86+
"ResponseData": {
87+
"required": [
88+
"DATA_ID",
89+
"DATE"
90+
],
91+
"type": "object",
92+
"properties": {
93+
"DATA_ID": {
94+
"type": "string",
95+
"format": "uuid"
96+
},
97+
"DATE": {
98+
"type": "string",
99+
"format": "date",
100+
"example": "2024-03-27"
101+
}
102+
}
103+
},
104+
"Link": {
105+
"type": "object",
106+
"properties": {
107+
"href": {
108+
"type": "string"
109+
},
110+
"hreflang": {
111+
"type": "string"
112+
},
113+
"title": {
114+
"type": "string"
115+
},
116+
"type": {
117+
"type": "string"
118+
},
119+
"deprecation": {
120+
"type": "string"
121+
},
122+
"profile": {
123+
"type": "string"
124+
},
125+
"name": {
126+
"type": "string"
127+
},
128+
"templated": {
129+
"type": "boolean"
130+
}
131+
}
132+
}
133+
},
134+
"securitySchemes": {
135+
"bearerScheme": {
136+
"type": "http",
137+
"scheme": "bearer",
138+
"bearerFormat": "JWT"
139+
}
140+
}
141+
}
142+
}

0 commit comments

Comments
 (0)