Repository: quarkusio/quarkus
Issue: 404 error from resources declared in javax.ws.rs.core.Application#getClasses

I'm trying to upgrade to **1.13.2.Final** and use the ability to limit the JAX-RS resources introduced by [this](https://github.com/quarkusio/quarkus/pull/14207) feature, but the declared resources in the overriden ``javax.ws.rs.core.Application#getClasses`` method return 404 error. If i do not override ``getClasses`` (or return an empty set, which as far as i understand is equivalent), the endpoints work as expected.

#### To Reproduce
You can use [this](https://github.com/blxbrgld/jaxrs-application) sample. ``/api/test`` is the endpoint that returns the 404 error.

Changed files:
extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java
extensions/resteasy-classic/resteasy/deployment/src/test/java/io/quarkus/resteasy/test/root/ApplicationTest.java

diff --git a/extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java b/extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java
index cf5e28f75f0..c149679b7ab 100755
--- a/extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java
+++ b/extensions/resteasy-classic/resteasy-server-common/deployment/src/main/java/io/quarkus/resteasy/server/common/deployment/ResteasyServerCommonProcessor.java
@@ -13,6 +13,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.BiFunction;
@@ -236,7 +237,8 @@ public void build(
         final Collection<AnnotationInstance> allPaths;
         if (filterClasses) {
             allPaths = paths.stream().filter(
-                    annotationInstance -> keepEnclosingClass(allowedClasses, excludedClasses, annotationInstance))
+                    annotationInstance -> keepAnnotation(beanArchiveIndexBuildItem.getIndex(), allowedClasses, excludedClasses,
+                            annotationInstance))
                     .collect(Collectors.toList());
         } else {
             allPaths = new ArrayList<>(paths);
@@ -889,21 +891,32 @@ private static Set<String> getExcludedClasses(List<BuildTimeConditionBuildItem>
     }
 
     /**
-     * @param allowedClasses the classes returned by the methods {@link Application#getClasses()} and
-     *        {@link Application#getSingletons()} to keep.
-     * @param excludedClasses the classes that have been annotated wih unsuccessful build time conditions and that
+     * @param index the Jandex index view from which the class information is extracted.
+     * @param allowedClasses the classes to keep provided by the methods {@link Application#getClasses()} and
+     *        {@link Application#getSingletons()}.
+     * @param excludedClasses the classes that have been annotated with unsuccessful build time conditions and that
      *        need to be excluded from the list of paths.
-     * @param annotationInstance the annotation instance from which the enclosing class will be extracted.
-     * @return {@code true} if the enclosing class of the annotation is part of the allowed classes if not empty
-     *         or if is not part of the excluded classes, {@code false} otherwise.
+     * @param annotationInstance the annotation instance to test.
+     * @return {@code true} if the enclosing class of the annotation is a concrete class and is part of the allowed
+     *         classes, or is an interface and at least one concrete implementation is included, or is an abstract class
+     *         and at least one concrete sub class is included, or is not part of the excluded classes, {@code false} otherwise.
      */
-    private static boolean keepEnclosingClass(Set<String> allowedClasses, Set<String> excludedClasses,
+    private static boolean keepAnnotation(IndexView index, Set<String> allowedClasses, Set<String> excludedClasses,
             AnnotationInstance annotationInstance) {
-        final String className = JandexUtil.getEnclosingClass(annotationInstance).toString();
+        final ClassInfo classInfo = JandexUtil.getEnclosingClass(annotationInstance);
+        final String className = classInfo.toString();
         if (allowedClasses.isEmpty()) {
             // No allowed classes have been set, meaning that only excluded classes have been provided.
             // Keep the enclosing class only if not excluded
             return !excludedClasses.contains(className);
+        } else if (Modifier.isAbstract(classInfo.flags())) {
+            // Only keep the annotation if a concrete implementation or a sub class has been included
+            return (Modifier.isInterface(classInfo.flags()) ? index.getAllKnownImplementors(classInfo.name())
+                    : index.getAllKnownSubclasses(classInfo.name()))
+                            .stream()
+                            .filter(clazz -> !Modifier.isAbstract(clazz.flags()))
+                            .map(Objects::toString)
+                            .anyMatch(allowedClasses::contains);
         }
         return allowedClasses.contains(className);
     }
diff --git a/extensions/resteasy-classic/resteasy/deployment/src/test/java/io/quarkus/resteasy/test/root/ApplicationTest.java b/extensions/resteasy-classic/resteasy/deployment/src/test/java/io/quarkus/resteasy/test/root/ApplicationTest.java
index a8613bd142b..e00eb8b9058 100644
--- a/extensions/resteasy-classic/resteasy/deployment/src/test/java/io/quarkus/resteasy/test/root/ApplicationTest.java
+++ b/extensions/resteasy-classic/resteasy/deployment/src/test/java/io/quarkus/resteasy/test/root/ApplicationTest.java
@@ -38,7 +38,10 @@ class ApplicationTest {
     static QuarkusUnitTest runner = new QuarkusUnitTest()
             .setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
                     .addClasses(
-                            ResourceTest1.class, ResourceTest2.class, ResponseFilter1.class, ResponseFilter2.class,
+                            IResourceTest.class, ResourceInheritedInterfaceTest.class,
+                            AResourceTest.class, ResourceInheritedClassTest.class,
+                            ResourceTest1.class, ResourceTest2.class,
+                            ResponseFilter1.class, ResponseFilter2.class,
                             ResponseFilter3.class, ResponseFilter4.class, ResponseFilter5.class, ResponseFilter6.class,
                             Feature1.class, Feature2.class, DynamicFeature1.class, DynamicFeature2.class,
                             ExceptionMapper1.class, ExceptionMapper2.class, AppTest.class));
@@ -76,6 +79,79 @@ void should_not_call_ok_of_resource_2() {
                 .statusCode(Response.Status.SERVICE_UNAVAILABLE.getStatusCode());
     }
 
+    @DisplayName("Should access to path inherited from an interface")
+    @Test
+    void should_call_inherited_from_interface() {
+        when()
+                .get("/rt-i/ok")
+                .then()
+                .statusCode(Response.Status.OK.getStatusCode())
+                .body(Matchers.is("ok-i"));
+    }
+
+    @DisplayName("Should access to path inherited from a class where method is implemented")
+    @Test
+    void should_call_inherited_from_class_implemented() {
+        when()
+                .get("/rt-a/ok-1")
+                .then()
+                .statusCode(Response.Status.OK.getStatusCode())
+                .body(Matchers.is("ok-a-1"));
+    }
+
+    @DisplayName("Should access to path inherited from a class where method is overridden")
+    @Test
+    void should_call_inherited_from_class_overridden() {
+        when()
+                .get("/rt-a/ok-2")
+                .then()
+                .statusCode(Response.Status.OK.getStatusCode())
+                .body(Matchers.is("ok-a-2"));
+    }
+
+    @Path("rt-i")
+    public interface IResourceTest {
+
+        @GET
+        @Path("ok")
+        String ok();
+    }
+
+    public static class ResourceInheritedInterfaceTest implements IResourceTest {
+
+        @Override
+        public String ok() {
+            return "ok-i";
+        }
+    }
+
+    @Path("rt-a")
+    public abstract static class AResourceTest {
+
+        @GET
+        @Path("ok-1")
+        public abstract String ok1();
+
+        @GET
+        @Path("ok-2")
+        public String ok2() {
+            return "ok-a";
+        }
+    }
+
+    public static class ResourceInheritedClassTest extends AResourceTest {
+
+        @Override
+        public String ok1() {
+            return "ok-a-1";
+        }
+
+        @Override
+        public String ok2() {
+            return "ok-a-2";
+        }
+    }
+
     @Path("rt-1")
     public static class ResourceTest1 {
 
@@ -224,6 +300,7 @@ public static class AppTest extends Application {
         public Set<Class<?>> getClasses() {
             return new HashSet<>(
                     Arrays.asList(
+                            ResourceInheritedInterfaceTest.class, ResourceInheritedClassTest.class,
                             ResourceTest1.class, Feature1.class, ExceptionMapper1.class));
         }