Skip to content

Commit f97730f

Browse files
authored
fix: ignore duplicate operationId when source is overridden method (#2072)
Signed-off-by: Michael Edgar <[email protected]>
1 parent f35f7c0 commit f97730f

File tree

6 files changed

+53
-5
lines changed

6 files changed

+53
-5
lines changed

core/src/main/java/io/smallrye/openapi/runtime/scanner/spi/AnnotationScanner.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,23 @@ default Optional<Operation> processOperation(final AnnotationScannerContext cont
305305

306306
// validate operationId
307307
String operationId = operation.getOperationId();
308+
308309
if (operationId != null) {
309-
final MethodInfo conflictingMethod = context.getOperationIdMap().putIfAbsent(operationId, method);
310-
if (conflictingMethod != null) {
310+
saveOperationId(context, resourceClass, method, operationId);
311+
}
312+
313+
return Optional.of(operation);
314+
}
315+
316+
private void saveOperationId(AnnotationScannerContext context, ClassInfo resourceClass, MethodInfo method,
317+
String operationId) {
318+
final MethodInfo conflictingMethod = context.getOperationIdMap().putIfAbsent(operationId, method);
319+
320+
if (conflictingMethod != null) {
321+
if (context.getAugmentedIndex().ancestry(method).values().contains(conflictingMethod)) {
322+
// The conflict was a method from a parent class, replace it
323+
context.getOperationIdMap().put(operationId, method);
324+
} else {
311325
final ClassInfo conflictingClass = conflictingMethod.declaringClass();
312326
final String className = resourceClass.name().toString();
313327
final String methodName = method.toString();
@@ -322,8 +336,6 @@ default Optional<Operation> processOperation(final AnnotationScannerContext cont
322336
}
323337
}
324338
}
325-
326-
return Optional.of(operation);
327339
}
328340

329341
default void setJsonViewContext(AnnotationScannerContext context, Type[] views) {

core/src/test/java/io/smallrye/openapi/runtime/scanner/LogCapture.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,25 @@ public LogRecord assertLogContaining(String substring) {
9090
}
9191
}
9292

93+
public void assertNoLogContaining(String substring) {
94+
synchronized (handler.records) {
95+
for (LogRecord rec : handler.records) {
96+
if (rec.getMessage().contains(substring)) {
97+
StringBuilder sb = new StringBuilder();
98+
sb.append("Log containing \"").append(substring).append("\" was found.");
99+
sb.append("\n");
100+
sb.append("Log records recorded:\n");
101+
for (LogRecord r : handler.records) {
102+
sb.append("[").append(r.getLevel()).append("] ");
103+
sb.append(r.getMessage()).append("\n");
104+
}
105+
106+
throw new AssertionError(sb.toString());
107+
}
108+
}
109+
}
110+
}
111+
93112
private static class TestHandler extends Handler {
94113

95114
private List<LogRecord> records = Collections.synchronizedList(new ArrayList<>());

extension-jaxrs/src/test/java/io/smallrye/openapi/runtime/scanner/OperationIdTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import org.eclipse.microprofile.openapi.models.OpenAPI;
66
import org.jboss.jandex.Index;
77
import org.junit.jupiter.api.Test;
8+
import org.junit.jupiter.api.extension.RegisterExtension;
89
import org.junit.jupiter.params.ParameterizedTest;
910
import org.junit.jupiter.params.provider.CsvSource;
1011

@@ -23,6 +24,9 @@
2324
*/
2425
class OperationIdTest extends JaxRsDataObjectScannerTestBase {
2526

27+
@RegisterExtension
28+
public LogCapture logs = new LogCapture(ScannerLogging.class.getPackage().getName());
29+
2630
@ParameterizedTest
2731
@CsvSource({
2832
"METHOD, test.io.smallrye.openapi.runtime.scanner.resources.javax.GreetingGetResource, resource.testOperationIdMethod.json",
@@ -56,6 +60,7 @@ void testInheritedOperationIdsUtilizeConcreteClassName() throws Exception {
5660
OpenAPI result = OpenApiProcessor.bootstrap(config, index);
5761
printToConsole(result);
5862
assertJsonEquals("resource.testOperationIdWithInheritance.json", result);
63+
logs.assertNoLogContaining("Duplicate operationId");
5964
} finally {
6065
System.clearProperty(SmallRyeOASConfig.OPERATION_ID_STRAGEGY);
6166
}

extension-jaxrs/src/test/java/test/io/smallrye/openapi/runtime/scanner/resources/jakarta/Salutation.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ public interface Salutation {
88

99
@GET
1010
@Produces(MediaType.TEXT_PLAIN)
11-
public String get();
11+
default String get() {
12+
return "hi";
13+
}
1214

1315
}

extension-jaxrs/src/test/java/test/io/smallrye/openapi/runtime/scanner/resources/jakarta/SalutationEnglish.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package test.io.smallrye.openapi.runtime.scanner.resources.jakarta;
22

3+
import jakarta.ws.rs.GET;
34
import jakarta.ws.rs.Path;
5+
import jakarta.ws.rs.Produces;
6+
import jakarta.ws.rs.core.MediaType;
47

58
@Path("/english")
69
public class SalutationEnglish implements Salutation {
710

811
@Override
12+
@GET
13+
@Produces(MediaType.TEXT_PLAIN)
914
public String get() {
1015
return "hello";
1116
}

extension-jaxrs/src/test/java/test/io/smallrye/openapi/runtime/scanner/resources/jakarta/SalutationSpanish.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package test.io.smallrye.openapi.runtime.scanner.resources.jakarta;
22

3+
import jakarta.ws.rs.GET;
34
import jakarta.ws.rs.Path;
5+
import jakarta.ws.rs.Produces;
6+
import jakarta.ws.rs.core.MediaType;
47

58
@Path("/spanish")
69
public class SalutationSpanish implements Salutation {
710

811
@Override
12+
@GET
13+
@Produces(MediaType.TEXT_PLAIN)
914
public String get() {
1015
return "hola";
1116
}

0 commit comments

Comments
 (0)