Skip to content

Commit

Permalink
Allow subclasses to be considered as services.
Browse files Browse the repository at this point in the history
  • Loading branch information
matyasberry committed Aug 27, 2021
1 parent 49f0c27 commit 2e35d48
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 9 deletions.
18 changes: 12 additions & 6 deletions services-api/src/main/java/io/scalecube/services/Reflect.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -255,11 +257,15 @@ public static Map<String, Method> serviceMethods(Class<?> serviceInterface) {
* @param serviceObject with extends service interface with @Service annotation.
* @return service interface class.
*/
public static Collection<Class<?>> serviceInterfaces(Object serviceObject) {
Class<?>[] interfaces = serviceObject.getClass().getInterfaces();
return Arrays.stream(interfaces)
.filter(interfaceClass -> interfaceClass.isAnnotationPresent(Service.class))
.collect(Collectors.toList());
public static Stream<Class<?>> serviceInterfaces(Object serviceObject) {
Class<?> current = serviceObject.getClass();
Set<Class<?>> 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) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -22,8 +21,7 @@ private ServiceScanner() {
* @return list of {@code ServiceRegistration}-s
*/
public static List<ServiceRegistration> scanServiceInfo(ServiceInfo serviceInfo) {
return Arrays.stream(serviceInfo.serviceInstance().getClass().getInterfaces())
.filter(serviceInterface -> serviceInterface.isAnnotationPresent(Service.class))
return Reflect.serviceInterfaces(serviceInfo.serviceInstance())
.map(
serviceInterface -> {
Map<String, String> serviceInfoTags = serviceInfo.tags();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -108,4 +110,31 @@ private interface TestService {

Flux<ServiceMessage> requestChannelMessage(Flux<ServiceMessage> 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<Class<?>> interfaces = Reflect.serviceInterfaces(new SubServiceImpl());
// Then:
Assertions.assertEquals(
1,
interfaces.count(), "serviceInterfaces(..) should detect interfaces in SubServiceImpl");
}
}

0 comments on commit 2e35d48

Please sign in to comment.