From 2e35d4896a8265a055be040256049032c811df8c Mon Sep 17 00:00:00 2001 From: matyasberry Date: Fri, 27 Aug 2021 08:20:39 +0200 Subject: [PATCH] Allow subclasses to be considered as services. --- .../java/io/scalecube/services/Reflect.java | 18 ++++++++---- .../io/scalecube/services/ServiceScanner.java | 4 +-- .../services/methods/ReflectTest.java | 29 +++++++++++++++++++ 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/services-api/src/main/java/io/scalecube/services/Reflect.java b/services-api/src/main/java/io/scalecube/services/Reflect.java index 7b5604488..0217e9914 100644 --- a/services-api/src/main/java/io/scalecube/services/Reflect.java +++ b/services-api/src/main/java/io/scalecube/services/Reflect.java @@ -18,11 +18,13 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.reactivestreams.Publisher; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -255,11 +257,15 @@ public static Map serviceMethods(Class serviceInterface) { * @param serviceObject with extends service interface with @Service annotation. * @return service interface class. */ - public static Collection> serviceInterfaces(Object serviceObject) { - Class[] interfaces = serviceObject.getClass().getInterfaces(); - return Arrays.stream(interfaces) - .filter(interfaceClass -> interfaceClass.isAnnotationPresent(Service.class)) - .collect(Collectors.toList()); + public static Stream> serviceInterfaces(Object serviceObject) { + Class current = serviceObject.getClass(); + Set> interfaces = new HashSet<>(); + while (current != Object.class) { + interfaces.addAll(Arrays.asList(current.getInterfaces())); + current = current.getSuperclass(); + } + return interfaces.stream() + .filter(interfaceClass -> interfaceClass.isAnnotationPresent(Service.class)); } public static String methodName(Method method) { diff --git a/services-api/src/main/java/io/scalecube/services/ServiceScanner.java b/services-api/src/main/java/io/scalecube/services/ServiceScanner.java index 45e564528..38c3124a5 100644 --- a/services-api/src/main/java/io/scalecube/services/ServiceScanner.java +++ b/services-api/src/main/java/io/scalecube/services/ServiceScanner.java @@ -1,6 +1,5 @@ package io.scalecube.services; -import io.scalecube.services.annotations.Service; import io.scalecube.services.annotations.ServiceMethod; import java.util.Arrays; import java.util.Collections; @@ -22,8 +21,7 @@ private ServiceScanner() { * @return list of {@code ServiceRegistration}-s */ public static List scanServiceInfo(ServiceInfo serviceInfo) { - return Arrays.stream(serviceInfo.serviceInstance().getClass().getInterfaces()) - .filter(serviceInterface -> serviceInterface.isAnnotationPresent(Service.class)) + return Reflect.serviceInterfaces(serviceInfo.serviceInstance()) .map( serviceInterface -> { Map serviceInfoTags = serviceInfo.tags(); diff --git a/services-api/src/test/java/io/scalecube/services/methods/ReflectTest.java b/services-api/src/test/java/io/scalecube/services/methods/ReflectTest.java index 4eb4cc1b1..e042425d0 100644 --- a/services-api/src/test/java/io/scalecube/services/methods/ReflectTest.java +++ b/services-api/src/test/java/io/scalecube/services/methods/ReflectTest.java @@ -7,11 +7,13 @@ import io.scalecube.services.CommunicationMode; import io.scalecube.services.Reflect; +import io.scalecube.services.annotations.Service; import io.scalecube.services.api.ServiceMessage; import java.lang.reflect.Method; import java.util.Arrays; import java.util.stream.Stream; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -108,4 +110,31 @@ private interface TestService { Flux requestChannelMessage(Flux sm); } + + @Service + private interface SimpleService { + public String name(); + } + + private class ServiceImpl implements SimpleService { + @Override + public String name() { + return "duke"; + } + } + + private class SubServiceImpl extends ServiceImpl { + + } + + @Test + public void testSubServiceInterfaces() { + + // When: + Stream> interfaces = Reflect.serviceInterfaces(new SubServiceImpl()); + // Then: + Assertions.assertEquals( + 1, + interfaces.count(), "serviceInterfaces(..) should detect interfaces in SubServiceImpl"); + } }