Skip to content

Commit eae78b2

Browse files
author
bnasslahsen
committed
Being able to see the class within an EntityModel as a Schema. Fixes #453
1 parent f144af0 commit eae78b2

File tree

9 files changed

+384
-6
lines changed

9 files changed

+384
-6
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/api/AbstractOpenApiResource.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,9 @@ public abstract class AbstractOpenApiResource extends SpecFilter {
8484
protected final SpringDocConfigProperties springDocConfigProperties;
8585

8686
private static final List<Class<?>> ADDITIONAL_REST_CONTROLLERS = new ArrayList<>();
87+
8788
private static final List<Class<?>> HIDDEN_REST_CONTROLLERS = new ArrayList<>();
89+
8890
private static final List<Class> DEPRECATED_TYPES = new ArrayList<>();
8991

9092
private boolean computeDone;
@@ -129,7 +131,8 @@ protected synchronized OpenAPI getOpenApi() {
129131
// run the optional customisers
130132
openApiCustomisers.ifPresent(apiCustomisers -> apiCustomisers.forEach(openApiCustomiser -> openApiCustomiser.customise(openApi)));
131133
computeDone = true;
132-
this.removeBrokenReferenceDefinitions(openApi);
134+
if (springDocConfigProperties.isRemoveBrokenReferenceDefinitions())
135+
this.removeBrokenReferenceDefinitions(openApi);
133136
openAPIBuilder.setCachedOpenAPI(openApi);
134137
openAPIBuilder.resetCalculatedOpenAPI();
135138
LOGGER.info("Init duration for springdoc-openapi is: {} ms",
@@ -166,7 +169,7 @@ protected void calculatePath(HandlerMethod handlerMethod, String operationPath,
166169
continue;
167170
}
168171

169-
RequestMapping reqMappingClass = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(),
172+
RequestMapping reqMappingClass = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(),
170173
RequestMapping.class);
171174

172175
MethodAttributes methodAttributes = new MethodAttributes(springDocConfigProperties.getDefaultConsumesMediaType(), springDocConfigProperties.getDefaultProducesMediaType());
@@ -186,7 +189,7 @@ protected void calculatePath(HandlerMethod handlerMethod, String operationPath,
186189
}
187190

188191
// Add documentation from operation annotation
189-
io.swagger.v3.oas.annotations.Operation apiOperation = AnnotatedElementUtils.findMergedAnnotation(method,
192+
io.swagger.v3.oas.annotations.Operation apiOperation = AnnotatedElementUtils.findMergedAnnotation(method,
190193
io.swagger.v3.oas.annotations.Operation.class);
191194

192195
calculateJsonView(apiOperation, methodAttributes, method);
@@ -198,7 +201,7 @@ protected void calculatePath(HandlerMethod handlerMethod, String operationPath,
198201
// compute tags
199202
operation = openAPIBuilder.buildTags(handlerMethod, operation, openAPI);
200203

201-
io.swagger.v3.oas.annotations.parameters.RequestBody requestBodyDoc = AnnotatedElementUtils.findMergedAnnotation(method,
204+
io.swagger.v3.oas.annotations.parameters.RequestBody requestBodyDoc = AnnotatedElementUtils.findMergedAnnotation(method,
202205
io.swagger.v3.oas.annotations.parameters.RequestBody.class);
203206

204207
// RequestBody in Operation
@@ -214,7 +217,7 @@ protected void calculatePath(HandlerMethod handlerMethod, String operationPath,
214217
ApiResponses apiResponses = responseBuilder.build(components, handlerMethod, operation, methodAttributes);
215218
operation.setResponses(apiResponses);
216219

217-
Set<io.swagger.v3.oas.annotations.callbacks.Callback> apiCallbacks = AnnotatedElementUtils.findMergedRepeatableAnnotations(method, io.swagger.v3.oas.annotations.callbacks.Callback.class);
220+
Set<io.swagger.v3.oas.annotations.callbacks.Callback> apiCallbacks = AnnotatedElementUtils.findMergedRepeatableAnnotations(method, io.swagger.v3.oas.annotations.callbacks.Callback.class);
218221

219222
// callbacks
220223
if (!CollectionUtils.isEmpty(apiCallbacks)) {
@@ -236,7 +239,7 @@ private void calculateJsonView(io.swagger.v3.oas.annotations.Operation apiOperat
236239
jsonViewAnnotationForRequestBody = null;
237240
}
238241
else {
239-
jsonViewAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, JsonView.class);
242+
jsonViewAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, JsonView.class);
240243
/*
241244
* If one and only one exists, use the @JsonView annotation from the method
242245
* parameter annotated with @RequestBody. Otherwise fall back to the @JsonView
@@ -389,6 +392,7 @@ public static void addRestControllers(Class<?>... classes) {
389392
public static void addHiddenRestControllers(Class<?>... classes) {
390393
HIDDEN_REST_CONTROLLERS.addAll(Arrays.asList(classes));
391394
}
395+
392396
protected boolean isHiddenRestControllers(Class<?> rawClass) {
393397
return HIDDEN_REST_CONTROLLERS.stream().anyMatch(clazz -> clazz.isAssignableFrom(rawClass));
394398
}

springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocConfigProperties.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ public class SpringDocConfigProperties {
5757

5858
private boolean overrideWithGenericResponse = true;
5959

60+
private boolean removeBrokenReferenceDefinitions = true;
61+
6062
private String defaultConsumesMediaType = MediaType.APPLICATION_JSON_VALUE;
6163

6264
private String defaultProducesMediaType = MediaType.ALL_VALUE;
@@ -313,4 +315,12 @@ public boolean isOverrideWithGenericResponse() {
313315
public void setOverrideWithGenericResponse(boolean overrideWithGenericResponse) {
314316
this.overrideWithGenericResponse = overrideWithGenericResponse;
315317
}
318+
319+
public boolean isRemoveBrokenReferenceDefinitions() {
320+
return removeBrokenReferenceDefinitions;
321+
}
322+
323+
public void setRemoveBrokenReferenceDefinitions(boolean removeBrokenReferenceDefinitions) {
324+
this.removeBrokenReferenceDefinitions = removeBrokenReferenceDefinitions;
325+
}
316326
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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+
package test.org.springdoc.api.app6;
19+
20+
import org.springframework.boot.CommandLineRunner;
21+
import org.springframework.context.annotation.Bean;
22+
import org.springframework.stereotype.Component;
23+
24+
/**
25+
* Pre-load some data using a Spring Boot {@link CommandLineRunner}.
26+
*
27+
* @author Greg Turnquist
28+
*/
29+
@Component
30+
class DatabaseLoader {
31+
32+
/**
33+
* Use Spring to inject a {@link EmployeeRepository} that can then load data. Since this will run only after the app
34+
* is operational, the database will be up.
35+
*
36+
* @param repository
37+
*/
38+
@Bean
39+
CommandLineRunner init(EmployeeRepository repository) {
40+
41+
return args -> {
42+
repository.save(new Employee("Frodo", "Baggins", "ring bearer"));
43+
repository.save(new Employee("Bilbo", "Baggins", "burglar"));
44+
};
45+
}
46+
47+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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+
package test.org.springdoc.api.app6;
19+
20+
import javax.persistence.Entity;
21+
import javax.persistence.GeneratedValue;
22+
import javax.persistence.Id;
23+
24+
import lombok.AccessLevel;
25+
import lombok.AllArgsConstructor;
26+
import lombok.Data;
27+
import lombok.NoArgsConstructor;
28+
29+
/**
30+
* Domain object representing a company employee. Project Lombok keeps actual code at a minimum. {@code @Data} -
31+
* Generates getters, setters, toString, hash, and equals functions {@code @Entity} - JPA annotation to flag this class
32+
* for DB persistence {@code @NoArgsConstructor} - Create a constructor with no args to support JPA
33+
* {@code @AllArgsConstructor} - Create a constructor with all args to support testing
34+
* {@code @JsonIgnoreProperties(ignoreUnknow=true)} When converting JSON to Java, ignore any unrecognized attributes.
35+
* This is critical for REST because it encourages adding new fields in later versions that won't break. It also allows
36+
* things like _links to be ignore as well, meaning HAL documents can be fetched and later posted to the server without
37+
* adjustment.
38+
*
39+
* @author Greg Turnquist
40+
*/
41+
@Data
42+
@Entity
43+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
44+
@AllArgsConstructor
45+
class Employee {
46+
47+
@Id
48+
@GeneratedValue
49+
private Long id;
50+
51+
private String firstName;
52+
53+
private String lastName;
54+
55+
private String role;
56+
57+
/**
58+
* Useful constructor when id is not yet known.
59+
*
60+
* @param firstName
61+
* @param lastName
62+
* @param role
63+
*/
64+
Employee(String firstName, String lastName, String role) {
65+
66+
this.firstName = firstName;
67+
this.lastName = lastName;
68+
this.role = role;
69+
}
70+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
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+
package test.org.springdoc.api.app6;
19+
20+
import org.springframework.hateoas.EntityModel;
21+
import org.springframework.http.ResponseEntity;
22+
import org.springframework.web.bind.annotation.GetMapping;
23+
import org.springframework.web.bind.annotation.PathVariable;
24+
import org.springframework.web.bind.annotation.RestController;
25+
26+
/**
27+
* Spring Web {@link RestController} used to generate a REST API.
28+
*
29+
* @author Greg Turnquist
30+
*/
31+
@RestController
32+
class EmployeeController {
33+
34+
private final EmployeeRepository repository;
35+
36+
EmployeeController(EmployeeRepository repository) {
37+
this.repository = repository;
38+
}
39+
40+
/**
41+
* Look up a single {@link Employee} and transform it into a REST resource. Then return it through Spring Web's
42+
* {@link ResponseEntity} fluent API.
43+
*
44+
* @param id
45+
*/
46+
@GetMapping("/employees/{id}")
47+
EntityModel<Employee> findOne(@PathVariable long id) {
48+
49+
return null;
50+
}
51+
52+
53+
54+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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+
package test.org.springdoc.api.app6;
19+
20+
import org.springframework.data.repository.CrudRepository;
21+
22+
/**
23+
* A simple Spring Data {@link CrudRepository} for storing {@link Employee}s.
24+
*
25+
* @author Greg Turnquist
26+
*/
27+
interface EmployeeRepository extends CrudRepository<Employee, Long> {
28+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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.app6;
20+
21+
import test.org.springdoc.api.AbstractSpringDocTest;
22+
23+
import org.springframework.test.context.TestPropertySource;
24+
25+
@TestPropertySource(properties = "springdoc.remove-broken-reference-definitions=false")
26+
public class SpringDocApp6Test extends AbstractSpringDocTest {
27+
28+
29+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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.app6;
20+
21+
import org.springframework.boot.SpringApplication;
22+
import org.springframework.boot.autoconfigure.SpringBootApplication;
23+
import org.springframework.context.annotation.Bean;
24+
import org.springframework.hateoas.server.core.EvoInflectorLinkRelationProvider;
25+
26+
@SpringBootApplication
27+
public class SpringDocTestApp {
28+
29+
public static void main(String[] args) {
30+
SpringApplication.run(SpringDocTestApp.class, args);
31+
}
32+
33+
@Bean
34+
EvoInflectorLinkRelationProvider relProvider() {
35+
return new EvoInflectorLinkRelationProvider();
36+
}
37+
38+
}

0 commit comments

Comments
 (0)