1010import static java .util .function .Predicate .not ;
1111
1212import java .util .ArrayList ;
13+ import java .util .HashSet ;
14+ import java .util .Iterator ;
1315import java .util .List ;
1416import java .util .Optional ;
1517import java .util .Set ;
@@ -35,6 +37,7 @@ public final class ControllerReader {
3537 private final List <ExecutableElement > interfaceMethods ;
3638 private final List <String > roles ;
3739 private final List <MethodReader > methods = new ArrayList <>();
40+ private final Set <String > seenMethods = new HashSet <>();
3841 private final Set <String > staticImportTypes = new TreeSet <>();
3942 private final Set <String > importTypes = new TreeSet <>();
4043 private final List <OpenAPIResponsePrism > apiResponses ;
@@ -54,7 +57,7 @@ public final class ControllerReader {
5457
5558 public ControllerReader (TypeElement beanType ) {
5659 this .beanType = beanType ;
57- this .interfaces = initInterfaces ();
60+ this .interfaces = initInterfaces (beanType );
5861 this .interfaceMethods = initInterfaceMethods ();
5962 this .roles = buildRoles ();
6063 if (isOpenApiAvailable ()) {
@@ -115,9 +118,9 @@ void addImports(boolean withSingleton) {
115118 }
116119 }
117120
118- private List <TypeElement > initInterfaces () {
121+ private List <TypeElement > initInterfaces (TypeElement element ) {
119122 final List <TypeElement > superInterfaces = new ArrayList <>();
120- for (final TypeMirror anInterface : beanType .getInterfaces ()) {
123+ for (final TypeMirror anInterface : element .getInterfaces ()) {
121124 final var ifaceElement = asElement (anInterface );
122125 final var controller = ControllerPrism .getInstanceOn (ifaceElement );
123126 if (controller != null && !controller .value ().isBlank ()
@@ -224,7 +227,9 @@ public void read(boolean withSingleton) {
224227 readSuper (beanType );
225228
226229 if (platform ().getClass ().getSimpleName ().contains ("Client" )) {
227- readInterfaces ();
230+ for (final var superInterface : interfaces ) {
231+ readInterfaces (superInterface );
232+ }
228233 }
229234 deriveIncludeValidation ();
230235 addImports (withSingleton );
@@ -273,12 +278,17 @@ private void readSuper(TypeElement beanType) {
273278 }
274279 }
275280
276- /** Read methods from interfaces taking into account generics. */
277- private void readInterfaces () {
278- for (final var superInterfaces : interfaces ) {
279- for (final var element : ElementFilter .methodsIn (superInterfaces .getEnclosedElements ())) {
280- readMethod (element , (DeclaredType ) superInterfaces .asType ());
281- }
281+ /**
282+ * Read methods from interfaces taking into account generics.
283+ *
284+ * @param interfaceElement
285+ */
286+ private void readInterfaces (TypeElement interfaceElement ) {
287+ for (final var element : ElementFilter .methodsIn (interfaceElement .getEnclosedElements ())) {
288+ readMethod (element , (DeclaredType ) interfaceElement .asType ());
289+ }
290+ for (final var element : initInterfaces (interfaceElement )) {
291+ readInterfaces (element );
282292 }
283293 }
284294
@@ -293,7 +303,7 @@ private void readMethod(ExecutableElement method, DeclaredType declaredType) {
293303 actualExecutable = (ExecutableType ) asMemberOf (declaredType , method );
294304 }
295305 final MethodReader methodReader = new MethodReader (this , method , actualExecutable );
296- if (methodReader .isWebMethod ()) {
306+ if (methodReader .isWebMethod () && seenMethods . add ( method . toString ()) ) {
297307 methodReader .read ();
298308 methods .add (methodReader );
299309 }
0 commit comments