Skip to content

Commit 5ae2721

Browse files
author
springdoc
committed
Added ability to filter by packages, for multiple OpenAPI definitions in one Spring Boot project. fixes #213.
1 parent 5e79ee3 commit 5ae2721

21 files changed

+917
-640
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,15 @@ protected AbstractOpenApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequest
5555

5656
protected AbstractOpenApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequestBuilder requestBuilder,
5757
AbstractResponseBuilder responseBuilder, OperationBuilder operationParser,
58-
Optional<List<OpenApiCustomiser>> openApiCustomisers, List<String> pathsToMatch) {
58+
Optional<List<OpenApiCustomiser>> openApiCustomisers, List<String> pathsToMatch, List<String> packagesToScan) {
5959
super();
6060
this.openAPIBuilder = openAPIBuilder;
6161
this.requestBuilder = requestBuilder;
6262
this.responseBuilder = responseBuilder;
6363
this.operationParser = operationParser;
6464
this.openApiCustomisers = openApiCustomisers;
6565
this.pathsToMatch = pathsToMatch;
66+
this.packagesToScan = packagesToScan;
6667
}
6768

6869
protected synchronized OpenAPI getOpenApi() {

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

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.springdoc.core;
22

33
import org.springdoc.api.OpenApiCustomiser;
4+
import org.springframework.util.CollectionUtils;
45

56
import java.util.ArrayList;
67
import java.util.Arrays;
@@ -12,12 +13,15 @@ public class GroupedOpenApi {
1213
private final String group;
1314
private final List<OpenApiCustomiser> openApiCustomisers;
1415
private final List<String> pathsToMatch;
15-
16+
private final List<String> packagesToScan;
1617

1718
private GroupedOpenApi(Builder builder) {
1819
this.group = Objects.requireNonNull(builder.group, "group");
20+
this.pathsToMatch = builder.pathsToMatch;
21+
this.packagesToScan = builder.packagesToScan;
1922
this.openApiCustomisers = Objects.requireNonNull(builder.openApiCustomisers);
20-
this.pathsToMatch = Objects.requireNonNull(builder.pathsToMatch);
23+
if (CollectionUtils.isEmpty(this.pathsToMatch) && CollectionUtils.isEmpty(this.packagesToScan))
24+
throw new IllegalStateException("Packages to scan or paths to filter can not be both null for the group:"+ this.group);
2125
}
2226

2327
public static Builder builder() {
@@ -32,13 +36,18 @@ public List<String> getPathsToMatch() {
3236
return pathsToMatch;
3337
}
3438

39+
public List<String> getPackagesToScan() {
40+
return packagesToScan;
41+
}
42+
3543
public List<OpenApiCustomiser> getOpenApiCustomisers() {
3644
return openApiCustomisers;
3745
}
3846

3947
public static class Builder {
4048
private String group;
4149
private List<String> pathsToMatch;
50+
private List<String> packagesToScan;
4251
private List<OpenApiCustomiser> openApiCustomisers = new ArrayList<>();
4352

4453
private Builder() {
@@ -50,11 +59,16 @@ public Builder setGroup(String group) {
5059
return this;
5160
}
5261

53-
public Builder setPathsToMatch(String[] pathsToMatch) {
62+
public Builder pathsToMatch(String[] pathsToMatch) {
5463
this.pathsToMatch = Arrays.asList(pathsToMatch);
5564
return this;
5665
}
5766

67+
public Builder packagesToScan(String[] packagesToScan) {
68+
this.packagesToScan = Arrays.asList(packagesToScan);
69+
return this;
70+
}
71+
5872
public Builder addOpenApiCustomiser(OpenApiCustomiser openApiCustomiser) {
5973
this.openApiCustomisers.add(openApiCustomiser);
6074
return this;

springdoc-openapi-webmvc-core/src/main/java/org/springdoc/api/MultipleOpenApiResource.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public MultipleOpenApiResource(List<GroupedOpenApi> groupedOpenApis,
4646
operationParser,
4747
requestMappingHandlerMapping,
4848
servletContextProvider,
49-
Optional.of(item.getOpenApiCustomisers()), item.getPathsToMatch()
49+
Optional.of(item.getOpenApiCustomisers()), item.getPathsToMatch(), item.getPackagesToScan()
5050
)
5151
));
5252
}

springdoc-openapi-webmvc-core/src/main/java/org/springdoc/api/OpenApiResource.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ public OpenApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequestBuilder req
5454
public OpenApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequestBuilder requestBuilder,
5555
AbstractResponseBuilder responseBuilder, OperationBuilder operationParser,
5656
RequestMappingInfoHandlerMapping requestMappingHandlerMapping, Optional<ActuatorProvider> servletContextProvider,
57-
Optional<List<OpenApiCustomiser>> openApiCustomisers, List<String> pathsToMatch) {
58-
super(openAPIBuilder, requestBuilder, responseBuilder, operationParser, openApiCustomisers, pathsToMatch);
57+
Optional<List<OpenApiCustomiser>> openApiCustomisers, List<String> pathsToMatch, List<String> packagesToScan) {
58+
super(openAPIBuilder, requestBuilder, responseBuilder, operationParser, openApiCustomisers, pathsToMatch,packagesToScan);
5959
this.requestMappingHandlerMapping = requestMappingHandlerMapping;
6060
this.servletContextProvider = servletContextProvider;
6161
}

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/SpringDocApp68Test.java

+26-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class SpringDocApp68Test {
4242
@Test
4343
public void testApp1() throws Exception {
4444
className = getClass().getSimpleName();
45-
MvcResult mockMvcResult = mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/store")).andExpect(status().isOk())
45+
MvcResult mockMvcResult = mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/stores")).andExpect(status().isOk())
4646
.andExpect(jsonPath("$.openapi", is("3.0.1"))).andReturn();
4747
String result = mockMvcResult.getResponse().getContentAsString();
4848
Path path = Paths.get(getClass().getClassLoader().getResource("results/app681.json").toURI());
@@ -54,12 +54,36 @@ public void testApp1() throws Exception {
5454
@Test
5555
public void testApp2() throws Exception {
5656
className = getClass().getSimpleName();
57-
MvcResult mockMvcResult = mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/others")).andExpect(status().isOk())
57+
MvcResult mockMvcResult = mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/users")).andExpect(status().isOk())
5858
.andExpect(jsonPath("$.openapi", is("3.0.1"))).andReturn();
5959
String result = mockMvcResult.getResponse().getContentAsString();
6060
Path path = Paths.get(getClass().getClassLoader().getResource("results/app682.json").toURI());
6161
byte[] fileBytes = Files.readAllBytes(path);
6262
String expected = new String(fileBytes);
6363
assertEquals(expected, result, true);
6464
}
65+
66+
@Test
67+
public void testApp3() throws Exception {
68+
className = getClass().getSimpleName();
69+
MvcResult mockMvcResult = mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/pets")).andExpect(status().isOk())
70+
.andExpect(jsonPath("$.openapi", is("3.0.1"))).andReturn();
71+
String result = mockMvcResult.getResponse().getContentAsString();
72+
Path path = Paths.get(getClass().getClassLoader().getResource("results/app683.json").toURI());
73+
byte[] fileBytes = Files.readAllBytes(path);
74+
String expected = new String(fileBytes);
75+
assertEquals(expected, result, true);
76+
}
77+
78+
@Test
79+
public void testApp4() throws Exception {
80+
className = getClass().getSimpleName();
81+
MvcResult mockMvcResult = mockMvc.perform(get(Constants.DEFAULT_API_DOCS_URL + "/groups")).andExpect(status().isOk())
82+
.andExpect(jsonPath("$.openapi", is("3.0.1"))).andReturn();
83+
String result = mockMvcResult.getResponse().getContentAsString();
84+
Path path = Paths.get(getClass().getClassLoader().getResource("results/app684.json").toURI());
85+
byte[] fileBytes = Files.readAllBytes(path);
86+
String expected = new String(fileBytes);
87+
assertEquals(expected, result, true);
88+
}
6589
}

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/SpringDocTestApp.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,29 @@ public static void main(String[] args) {
1919
@Bean
2020
public GroupedOpenApi storeOpenApi() {
2121
String paths[] = {"/store/**"};
22-
return GroupedOpenApi.builder().setGroup("store").setPathsToMatch(paths)
22+
return GroupedOpenApi.builder().setGroup("stores").pathsToMatch(paths)
2323
.build();
2424
}
2525

2626
@Bean
2727
public GroupedOpenApi userOpenApi() {
28-
String paths[] = {"/user/**", "/pet/**"};
29-
return GroupedOpenApi.builder().setGroup("others").setPathsToMatch(paths)
28+
String packagesToscan[] = {"test.org.springdoc.api.app68.api.user"};
29+
return GroupedOpenApi.builder().setGroup("users").packagesToScan(packagesToscan)
30+
.build();
31+
}
32+
33+
@Bean
34+
public GroupedOpenApi petOpenApi() {
35+
String paths[] = {"/pet/**"};
36+
return GroupedOpenApi.builder().setGroup("pets").pathsToMatch(paths)
37+
.build();
38+
}
39+
40+
@Bean
41+
public GroupedOpenApi groupOpenApi() {
42+
String paths[] = {"/v1/**"};
43+
String packagesToscan[] = {"test.org.springdoc.api.app68.api.user", "test.org.springdoc.api.app68.api.store"};
44+
return GroupedOpenApi.builder().setGroup("groups").pathsToMatch(paths).packagesToScan(packagesToscan)
3045
.build();
3146
}
3247

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/PetApi.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/pet/PetApi.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* https://openapi-generator.tech
44
* Do not edit the class manually.
55
*/
6-
package test.org.springdoc.api.app68.api;
6+
package test.org.springdoc.api.app68.api.pet;
77

88
import io.swagger.v3.oas.annotations.Operation;
99
import io.swagger.v3.oas.annotations.Parameter;
@@ -22,6 +22,7 @@
2222
import test.org.springdoc.api.app68.model.Pet;
2323

2424
import javax.validation.Valid;
25+
import javax.validation.constraints.NotBlank;
2526
import javax.validation.constraints.NotNull;
2627
import java.util.List;
2728

@@ -125,4 +126,9 @@ default ResponseEntity<ModelApiResponse> uploadFile(
125126
return getDelegate().uploadFile(petId, additionalMetadata, file);
126127
}
127128

129+
130+
@GetMapping(value = "/v1/pets")
131+
default void pets(@Valid @NotBlank String name) {
132+
133+
}
128134
}

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/PetApiController.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/pet/PetApiController.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package test.org.springdoc.api.app68.api;
1+
package test.org.springdoc.api.app68.api.pet;
22

33
import org.springframework.stereotype.Controller;
44
import org.springframework.web.bind.annotation.RequestMapping;

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/PetApiDelegate.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/pet/PetApiDelegate.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
package test.org.springdoc.api.app68.api;
1+
package test.org.springdoc.api.app68.api.pet;
22

33
import org.springframework.http.HttpStatus;
44
import org.springframework.http.MediaType;
55
import org.springframework.http.ResponseEntity;
66
import org.springframework.web.context.request.NativeWebRequest;
77
import org.springframework.web.multipart.MultipartFile;
8+
import test.org.springdoc.api.app68.api.ApiUtil;
89
import test.org.springdoc.api.app68.model.ModelApiResponse;
910
import test.org.springdoc.api.app68.model.Pet;
1011

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/PetApiDelegateImpl.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/pet/PetApiDelegateImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package test.org.springdoc.api.app68.api;
1+
package test.org.springdoc.api.app68.api.pet;
22

33
import org.springframework.stereotype.Service;
44

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/StoreApi.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/store/StoreApi.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* https://openapi-generator.tech
44
* Do not edit the class manually.
55
*/
6-
package test.org.springdoc.api.app68.api;
6+
package test.org.springdoc.api.app68.api.store;
77

88
import io.swagger.v3.oas.annotations.Operation;
99
import io.swagger.v3.oas.annotations.Parameter;
@@ -21,6 +21,7 @@
2121
import javax.validation.Valid;
2222
import javax.validation.constraints.Max;
2323
import javax.validation.constraints.Min;
24+
import javax.validation.constraints.NotBlank;
2425
import java.util.Map;
2526

2627
@javax.annotation.Generated(value = "org.springdoc.demo.app2.codegen.languages.SpringCodegen", date = "2019-07-11T00:09:29.839+02:00[Europe/Paris]")
@@ -73,4 +74,8 @@ default ResponseEntity<Order> placeOrder(
7374
return getDelegate().placeOrder(order);
7475
}
7576

77+
@GetMapping(value = "/v1/stores")
78+
default void stores(@Valid @NotBlank String name) {
79+
80+
}
7681
}

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/StoreApiController.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/store/StoreApiController.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package test.org.springdoc.api.app68.api;
1+
package test.org.springdoc.api.app68.api.store;
22

33
import org.springframework.stereotype.Controller;
44
import org.springframework.web.bind.annotation.RequestMapping;

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/StoreApiDelegate.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/store/StoreApiDelegate.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
package test.org.springdoc.api.app68.api;
1+
package test.org.springdoc.api.app68.api.store;
22

33
import org.springframework.http.HttpStatus;
44
import org.springframework.http.MediaType;
55
import org.springframework.http.ResponseEntity;
66
import org.springframework.web.context.request.NativeWebRequest;
7+
import test.org.springdoc.api.app68.api.ApiUtil;
78
import test.org.springdoc.api.app68.model.Order;
89

910
import java.util.Map;

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/StoreApiDelegateImpl.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/store/StoreApiDelegateImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package test.org.springdoc.api.app68.api;
1+
package test.org.springdoc.api.app68.api.store;
22

33
import org.springframework.stereotype.Service;
44

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/UserApi.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/user/UserApi.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* https://openapi-generator.tech
44
* Do not edit the class manually.
55
*/
6-
package test.org.springdoc.api.app68.api;
6+
package test.org.springdoc.api.app68.api.user;
77

88
import io.swagger.v3.oas.annotations.Operation;
99
import io.swagger.v3.oas.annotations.Parameter;
@@ -17,6 +17,7 @@
1717
import test.org.springdoc.api.app68.model.User;
1818

1919
import javax.validation.Valid;
20+
import javax.validation.constraints.NotBlank;
2021
import javax.validation.constraints.NotNull;
2122
import java.util.List;
2223

@@ -104,4 +105,8 @@ default ResponseEntity<Void> updateUser(
104105
return getDelegate().updateUser(username, user);
105106
}
106107

108+
@GetMapping(value = "/v1/users")
109+
default void users(@Valid @NotBlank String name) {
110+
111+
}
107112
}

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/UserApiController.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/user/UserApiController.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package test.org.springdoc.api.app68.api;
1+
package test.org.springdoc.api.app68.api.user;
22

33
import org.springframework.stereotype.Controller;
44
import org.springframework.web.bind.annotation.RequestMapping;

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/UserApiDelegate.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/user/UserApiDelegate.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
package test.org.springdoc.api.app68.api;
1+
package test.org.springdoc.api.app68.api.user;
22

33
import org.springframework.http.HttpStatus;
44
import org.springframework.http.MediaType;
55
import org.springframework.http.ResponseEntity;
66
import org.springframework.web.context.request.NativeWebRequest;
7+
import test.org.springdoc.api.app68.api.ApiUtil;
78
import test.org.springdoc.api.app68.model.User;
89

910
import java.util.List;

springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/UserApiDelegateImpl.java renamed to springdoc-openapi-webmvc-core/src/test/java/test/org/springdoc/api/app68/api/user/UserApiDelegateImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package test.org.springdoc.api.app68.api;
1+
package test.org.springdoc.api.app68.api.user;
22

33
import org.springframework.stereotype.Service;
44

0 commit comments

Comments
 (0)