Skip to content

Commit 4da8b57

Browse files
authored
refactoring to improve code quality (#67)
1 parent 70f07bd commit 4da8b57

File tree

22 files changed

+251
-226
lines changed

22 files changed

+251
-226
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.getyourguide.openapi.validation.api.log;
2+
3+
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
4+
5+
public interface OpenApiViolationHandler {
6+
void onOpenApiViolation(OpenApiViolation violation);
7+
}

Diff for: openapi-validation-api/src/main/java/com/getyourguide/openapi/validation/api/model/ValidationResult.java

-3
This file was deleted.

Diff for: openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidationConfiguration.java

-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,4 @@
88
public class OpenApiRequestValidationConfiguration {
99
private double sampleRate;
1010
private int validationReportThrottleWaitSeconds;
11-
private boolean shouldFailOnRequestViolation;
1211
}

Diff for: openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidator.java

+34-37
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
import com.atlassian.oai.validator.model.Request;
44
import com.atlassian.oai.validator.model.SimpleRequest;
55
import com.atlassian.oai.validator.model.SimpleResponse;
6-
import com.atlassian.oai.validator.report.ValidationReport;
6+
import com.getyourguide.openapi.validation.api.log.OpenApiViolationHandler;
77
import com.getyourguide.openapi.validation.api.metrics.MetricsReporter;
88
import com.getyourguide.openapi.validation.api.model.Direction;
9+
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
910
import com.getyourguide.openapi.validation.api.model.RequestMetaData;
1011
import com.getyourguide.openapi.validation.api.model.ResponseMetaData;
11-
import com.getyourguide.openapi.validation.api.model.ValidationResult;
12+
import com.getyourguide.openapi.validation.core.mapper.ValidationReportToOpenApiViolationsMapper;
1213
import com.getyourguide.openapi.validation.core.validator.OpenApiInteractionValidatorWrapper;
1314
import java.net.URLDecoder;
1415
import java.nio.charset.StandardCharsets;
16+
import java.util.List;
1517
import java.util.concurrent.RejectedExecutionException;
1618
import java.util.concurrent.ThreadPoolExecutor;
1719
import javax.annotation.Nullable;
@@ -22,20 +24,18 @@
2224
public class OpenApiRequestValidator {
2325
private final ThreadPoolExecutor threadPoolExecutor;
2426
private final OpenApiInteractionValidatorWrapper validator;
25-
private final ValidationReportHandler validationReportHandler;
26-
private final OpenApiRequestValidationConfiguration configuration;
27+
private final ValidationReportToOpenApiViolationsMapper mapper;
2728

2829
public OpenApiRequestValidator(
2930
ThreadPoolExecutor threadPoolExecutor,
30-
ValidationReportHandler validationReportHandler,
3131
MetricsReporter metricsReporter,
3232
OpenApiInteractionValidatorWrapper validator,
33+
ValidationReportToOpenApiViolationsMapper mapper,
3334
OpenApiRequestValidationConfiguration configuration
3435
) {
3536
this.threadPoolExecutor = threadPoolExecutor;
3637
this.validator = validator;
37-
this.validationReportHandler = validationReportHandler;
38-
this.configuration = configuration;
38+
this.mapper = mapper;
3939

4040
metricsReporter.reportStartup(
4141
validator != null,
@@ -48,12 +48,28 @@ public boolean isReady() {
4848
return validator != null;
4949
}
5050

51-
public void validateRequestObjectAsync(final RequestMetaData request, @Nullable ResponseMetaData response, String requestBody) {
52-
executeAsync(() -> validateRequestObject(request, response, requestBody));
51+
public void validateRequestObjectAsync(
52+
final RequestMetaData request,
53+
@Nullable ResponseMetaData response,
54+
String requestBody,
55+
OpenApiViolationHandler listener
56+
) {
57+
executeAsync(() -> {
58+
var violations = validateRequestObject(request, response, requestBody);
59+
violations.forEach(listener::onOpenApiViolation);
60+
});
5361
}
5462

55-
public void validateResponseObjectAsync(final RequestMetaData request, ResponseMetaData response, final String responseBody) {
56-
executeAsync(() -> validateResponseObject(request, response, responseBody));
63+
public void validateResponseObjectAsync(
64+
final RequestMetaData request,
65+
ResponseMetaData response,
66+
final String responseBody,
67+
OpenApiViolationHandler listener
68+
) {
69+
executeAsync(() -> {
70+
var violations = validateResponseObject(request, response, responseBody);
71+
violations.forEach(listener::onOpenApiViolation);
72+
});
5773
}
5874

5975
private void executeAsync(Runnable command) {
@@ -64,28 +80,22 @@ private void executeAsync(Runnable command) {
6480
}
6581
}
6682

67-
public ValidationResult validateRequestObject(final RequestMetaData request, String requestBody) {
83+
public List<OpenApiViolation> validateRequestObject(final RequestMetaData request, String requestBody) {
6884
return validateRequestObject(request, null, requestBody);
6985
}
7086

71-
public ValidationResult validateRequestObject(
87+
public List<OpenApiViolation> validateRequestObject(
7288
final RequestMetaData request,
7389
@Nullable final ResponseMetaData response,
7490
String requestBody
7591
) {
7692
try {
7793
var simpleRequest = buildSimpleRequest(request, requestBody);
7894
var result = validator.validateRequest(simpleRequest);
79-
// TODO this should not be done here, but currently the only way to do it -> Refactor this so that logging
80-
// is actually done in the interceptor/filter where logging can easily be skipped then.
81-
if (!configuration.isShouldFailOnRequestViolation()) {
82-
validationReportHandler
83-
.handleValidationReport(request, response, Direction.REQUEST, requestBody, result);
84-
}
85-
return buildValidationResult(result);
95+
return mapper.map(result, request, response, Direction.REQUEST, requestBody);
8696
} catch (Exception e) {
8797
log.error("Could not validate request", e);
88-
return ValidationResult.NOT_APPLICABLE;
98+
return List.of();
8999
}
90100
}
91101

@@ -108,7 +118,7 @@ private static String nullSafeUrlDecode(String value) {
108118
return URLDecoder.decode(value, StandardCharsets.UTF_8);
109119
}
110120

111-
public ValidationResult validateResponseObject(
121+
public List<OpenApiViolation> validateResponseObject(
112122
final RequestMetaData request,
113123
final ResponseMetaData response,
114124
final String responseBody
@@ -126,23 +136,10 @@ public ValidationResult validateResponseObject(
126136
Request.Method.valueOf(request.getMethod().toUpperCase()),
127137
responseBuilder.build()
128138
);
129-
validationReportHandler.handleValidationReport(request, response, Direction.RESPONSE, responseBody, result);
130-
return buildValidationResult(result);
139+
return mapper.map(result, request, response, Direction.RESPONSE, responseBody);
131140
} catch (Exception e) {
132141
log.error("Could not validate response", e);
133-
return ValidationResult.NOT_APPLICABLE;
142+
return List.of();
134143
}
135144
}
136-
137-
private ValidationResult buildValidationResult(ValidationReport validationReport) {
138-
if (validationReport == null) {
139-
return ValidationResult.NOT_APPLICABLE;
140-
}
141-
142-
if (validationReport.getMessages().isEmpty()) {
143-
return ValidationResult.VALID;
144-
}
145-
146-
return ValidationResult.INVALID;
147-
}
148145
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.getyourguide.openapi.validation.core.log;
2+
3+
import com.getyourguide.openapi.validation.api.log.OpenApiViolationHandler;
4+
import com.getyourguide.openapi.validation.api.log.ViolationLogger;
5+
import com.getyourguide.openapi.validation.api.metrics.MetricsReporter;
6+
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
7+
import lombok.AllArgsConstructor;
8+
9+
@AllArgsConstructor
10+
public class DefaultOpenApiViolationHandler implements OpenApiViolationHandler {
11+
private final ViolationLogger logger;
12+
private final MetricsReporter metrics;
13+
14+
@Override
15+
public void onOpenApiViolation(OpenApiViolation violation) {
16+
logger.log(violation);
17+
metrics.reportViolation(violation);
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.getyourguide.openapi.validation.core.log;
2+
3+
import com.getyourguide.openapi.validation.api.log.OpenApiViolationHandler;
4+
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
5+
import com.getyourguide.openapi.validation.core.exclusions.InternalViolationExclusions;
6+
import lombok.AllArgsConstructor;
7+
8+
@AllArgsConstructor
9+
public class ExclusionsOpenApiViolationHandler implements OpenApiViolationHandler {
10+
private final OpenApiViolationHandler delegate;
11+
private final InternalViolationExclusions violationExclusions;
12+
13+
@Override
14+
public void onOpenApiViolation(OpenApiViolation violation) {
15+
if (violationExclusions.isExcluded(violation)) {
16+
return;
17+
}
18+
19+
delegate.onOpenApiViolation(violation);
20+
}
21+
}
+8-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
package com.getyourguide.openapi.validation.core.throttle;
1+
package com.getyourguide.openapi.validation.core.log;
22

3+
import com.getyourguide.openapi.validation.api.log.OpenApiViolationHandler;
34
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
45
import java.util.Map;
56
import java.util.concurrent.ConcurrentHashMap;
@@ -8,20 +9,19 @@
89
import org.joda.time.DateTime;
910

1011
@AllArgsConstructor
11-
public class RequestBasedValidationReportThrottler implements ValidationReportThrottler {
12-
12+
public class ThrottlingOpenApiViolationHandler implements OpenApiViolationHandler {
13+
private final OpenApiViolationHandler delegate;
1314
private final int waitSeconds;
14-
1515
private final Map<String, DateTime> loggedMessages = new ConcurrentHashMap<>();
1616

1717
@Override
18-
public void throttle(OpenApiViolation openApiViolation, Runnable runnable) {
19-
if (isThrottled(openApiViolation)) {
18+
public void onOpenApiViolation(OpenApiViolation violation) {
19+
if (isThrottled(violation)) {
2020
return;
2121
}
2222

23-
runnable.run();
24-
registerLoggedMessage(openApiViolation);
23+
delegate.onOpenApiViolation(violation);
24+
registerLoggedMessage(violation);
2525
}
2626

2727
private void registerLoggedMessage(OpenApiViolation openApiViolation) {

Diff for: openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/ValidationReportHandler.java renamed to openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/mapper/ValidationReportToOpenApiViolationsMapper.java

+11-29
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,29 @@
1-
package com.getyourguide.openapi.validation.core;
1+
package com.getyourguide.openapi.validation.core.mapper;
22

33
import com.atlassian.oai.validator.report.ValidationReport;
44
import com.getyourguide.openapi.validation.api.log.LogLevel;
5-
import com.getyourguide.openapi.validation.api.log.ViolationLogger;
6-
import com.getyourguide.openapi.validation.api.metrics.MetricsReporter;
75
import com.getyourguide.openapi.validation.api.model.Direction;
86
import com.getyourguide.openapi.validation.api.model.OpenApiViolation;
97
import com.getyourguide.openapi.validation.api.model.RequestMetaData;
108
import com.getyourguide.openapi.validation.api.model.ResponseMetaData;
11-
import com.getyourguide.openapi.validation.core.exclusions.InternalViolationExclusions;
12-
import com.getyourguide.openapi.validation.core.throttle.ValidationReportThrottler;
139
import io.swagger.v3.oas.models.parameters.Parameter;
10+
import java.util.List;
1411
import java.util.Optional;
1512
import javax.annotation.Nullable;
16-
import lombok.AllArgsConstructor;
1713

18-
@AllArgsConstructor
19-
public class ValidationReportHandler {
20-
private final ValidationReportThrottler throttleHelper;
21-
private final ViolationLogger logger;
22-
private final MetricsReporter metrics;
23-
private final InternalViolationExclusions violationExclusions;
24-
25-
public void handleValidationReport(
14+
public class ValidationReportToOpenApiViolationsMapper {
15+
public List<OpenApiViolation> map(
16+
ValidationReport validationReport,
2617
RequestMetaData request,
2718
@Nullable ResponseMetaData response,
2819
Direction direction,
29-
String body,
30-
ValidationReport result
20+
String body
3121
) {
32-
if (!result.getMessages().isEmpty()) {
33-
result
34-
.getMessages()
35-
.stream()
36-
.map(message -> buildOpenApiViolation(message, request, response, body, direction))
37-
.filter(violation -> !violationExclusions.isExcluded(violation))
38-
.forEach(violation -> throttleHelper.throttle(violation, () -> logValidationError(violation)));
39-
}
40-
}
41-
42-
private void logValidationError(OpenApiViolation openApiViolation) {
43-
logger.log(openApiViolation);
44-
metrics.reportViolation(openApiViolation);
22+
return validationReport
23+
.getMessages()
24+
.stream()
25+
.map(message -> buildOpenApiViolation(message, request, response, body, direction))
26+
.toList();
4527
}
4628

4729
private OpenApiViolation buildOpenApiViolation(

Diff for: openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/throttle/ValidationReportThrottler.java

-8
This file was deleted.

Diff for: openapi-validation-core/src/main/java/com/getyourguide/openapi/validation/core/throttle/ValidationReportThrottlerNone.java

-10
This file was deleted.

Diff for: openapi-validation-core/src/test/java/com/getyourguide/openapi/validation/core/OpenApiRequestValidatorTest.java

+7-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
import static org.mockito.ArgumentMatchers.any;
55
import static org.mockito.Mockito.mock;
66
import static org.mockito.Mockito.verify;
7+
import static org.mockito.Mockito.when;
78

89
import com.atlassian.oai.validator.model.SimpleRequest;
910
import com.getyourguide.openapi.validation.api.metrics.MetricsReporter;
1011
import com.getyourguide.openapi.validation.api.model.RequestMetaData;
12+
import com.getyourguide.openapi.validation.core.mapper.ValidationReportToOpenApiViolationsMapper;
1113
import com.getyourguide.openapi.validation.core.validator.OpenApiInteractionValidatorWrapper;
1214
import java.net.URI;
1315
import java.util.HashMap;
16+
import java.util.List;
1417
import java.util.concurrent.RejectedExecutionException;
1518
import java.util.concurrent.ThreadPoolExecutor;
1619
import org.junit.jupiter.api.BeforeEach;
@@ -29,14 +32,15 @@ public class OpenApiRequestValidatorTest {
2932
public void setup() {
3033
threadPoolExecutor = mock();
3134
validator = mock();
32-
ValidationReportHandler validationReportHandler = mock();
3335
MetricsReporter metricsReporter = mock();
36+
var mapper = mock(ValidationReportToOpenApiViolationsMapper.class);
37+
when(mapper.map(any(), any(), any(), any(), any())).thenReturn(List.of());
3438

3539
openApiRequestValidator = new OpenApiRequestValidator(
3640
threadPoolExecutor,
37-
validationReportHandler,
3841
metricsReporter,
3942
validator,
43+
mapper,
4044
mock()
4145
);
4246
}
@@ -45,7 +49,7 @@ public void setup() {
4549
public void testWhenThreadPoolExecutorRejectsExecutionThenItShouldNotThrow() {
4650
Mockito.doThrow(new RejectedExecutionException()).when(threadPoolExecutor).execute(any());
4751

48-
openApiRequestValidator.validateRequestObjectAsync(mock(), null, null);
52+
openApiRequestValidator.validateRequestObjectAsync(mock(), null, null, mock());
4953
}
5054

5155
@Test

0 commit comments

Comments
 (0)