Skip to content

Commit aad686c

Browse files
committed
WIP on enhanced service registration for RESTful services
1 parent 5b49fd9 commit aad686c

File tree

5 files changed

+118
-8
lines changed

5 files changed

+118
-8
lines changed

services-api/src/main/java/io/scalecube/services/Reflect.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,29 @@ private static Map<String, String> transformArrayToMap(Tag[] array) {
220220
* @param serviceInterface with {@link Service} annotation
221221
* @return service name
222222
*/
223-
public static Map<String, Method> serviceMethods(Class<?> serviceInterface) {
224-
return Arrays.stream(serviceInterface.getMethods())
225-
.filter(method -> method.isAnnotationPresent(ServiceMethod.class))
226-
.collect(Collectors.toMap(Reflect::methodName, Function.identity()));
223+
public static Collection<Method> serviceMethods(Class<?> serviceInterface) {
224+
final var methodList =
225+
Arrays.stream(serviceInterface.getMethods())
226+
.filter(method -> method.isAnnotationPresent(ServiceMethod.class))
227+
.toList();
228+
229+
//noinspection unused
230+
final var collect =
231+
methodList.stream()
232+
.collect(
233+
Collectors.toMap(
234+
method ->
235+
String.join(":", Reflect.methodName(method), Reflect.restMethod(method)),
236+
Function.identity(),
237+
(method, duplicate) -> {
238+
throw new IllegalArgumentException(
239+
"Duplicate method found for method: "
240+
+ method
241+
+ ", duplicate: "
242+
+ duplicate);
243+
}));
244+
245+
return methodList;
227246
}
228247

229248
/**

services-api/src/test/java/io/scalecube/services/methods/ServiceMethodInvokerTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,11 @@ private static Consumer<ServiceMessage> assertError(int errorCode, String errorM
368368
private static MethodInfo getMethodInfo(Object serviceInstance, String methodName) {
369369
final var serviceInstanceClass = serviceInstance.getClass();
370370
final Class<?> serviceInterface = Reflect.serviceInterfaces(serviceInstance).toList().get(0);
371-
final var method = Reflect.serviceMethods(serviceInterface).get(methodName);
371+
final var method =
372+
Reflect.serviceMethods(serviceInterface).stream()
373+
.filter(m -> m.getName().equals(methodName))
374+
.findFirst()
375+
.get();
372376

373377
// get service instance method
374378
Method serviceMethod;
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package io.scalecube.services.gateway.rest;
2+
3+
import static io.scalecube.services.api.ServiceMessage.HEADER_REQUEST_METHOD;
4+
import static org.hamcrest.MatcherAssert.assertThat;
5+
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
6+
import static org.junit.jupiter.api.Assertions.assertNotNull;
7+
import static org.junit.jupiter.api.Assertions.assertNull;
8+
import static org.junit.jupiter.api.Assertions.fail;
9+
import static org.mockito.Mockito.mock;
10+
11+
import io.scalecube.services.Microservices;
12+
import io.scalecube.services.Microservices.Context;
13+
import io.scalecube.services.annotations.RestMethod;
14+
import io.scalecube.services.annotations.Service;
15+
import io.scalecube.services.annotations.ServiceMethod;
16+
import io.scalecube.services.api.ServiceMessage;
17+
import org.hamcrest.Matchers;
18+
import org.junit.jupiter.api.Test;
19+
import reactor.core.publisher.Mono;
20+
21+
public class RestServiceDefinitionTest {
22+
23+
@Test
24+
void registerInvalidService() {
25+
try {
26+
Microservices.start(new Context().services(mock(BadService.class)));
27+
fail("Expected exception");
28+
} catch (Exception e) {
29+
assertInstanceOf(IllegalArgumentException.class, e, e::getMessage);
30+
assertThat(e.getMessage(), Matchers.startsWith("Duplicate method found for method"));
31+
}
32+
}
33+
34+
@Test
35+
void registerValidService() {
36+
try (final var microservices =
37+
Microservices.start(new Context().services(mock(GoodService.class)))) {
38+
final var serviceRegistry = microservices.serviceRegistry();
39+
40+
final var foo = System.nanoTime();
41+
final var methodInvokerWithoutRestMethod =
42+
serviceRegistry.lookupInvoker(
43+
ServiceMessage.builder().qualifier("v1/service/echo/" + foo).build());
44+
assertNull(methodInvokerWithoutRestMethod);
45+
46+
final var methodInvokerByGet =
47+
serviceRegistry.lookupInvoker(
48+
ServiceMessage.builder()
49+
.header(HEADER_REQUEST_METHOD, "GET")
50+
.qualifier("v1/service/echo/" + foo)
51+
.build());
52+
assertNotNull(methodInvokerByGet);
53+
54+
final var methodInvokerByPost =
55+
serviceRegistry.lookupInvoker(
56+
ServiceMessage.builder()
57+
.header(HEADER_REQUEST_METHOD, "POST")
58+
.qualifier("v1/service/echo/" + foo)
59+
.build());
60+
assertNotNull(methodInvokerByPost);
61+
}
62+
}
63+
64+
@Service("v1/service")
65+
interface BadService {
66+
67+
@RestMethod("GET")
68+
@ServiceMethod("get/:foo")
69+
Mono<SomeResponse> echo();
70+
71+
@RestMethod("GET")
72+
@ServiceMethod("get/:foo")
73+
Mono<SomeResponse> ping();
74+
}
75+
76+
@Service("v1/service")
77+
interface GoodService {
78+
79+
@RestMethod("GET")
80+
@ServiceMethod("echo/:foo")
81+
Mono<SomeResponse> echo();
82+
83+
@RestMethod("POST")
84+
@ServiceMethod("echo/:foo")
85+
Mono<SomeResponse> ping();
86+
}
87+
}

services/src/main/java/io/scalecube/services/ServiceScanner.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public static List<ServiceRegistration> toServiceRegistrations(ServiceInfo servi
3232
final var namespace = Reflect.serviceName(serviceInterface);
3333

3434
final var methodDefinitions =
35-
Reflect.serviceMethods(serviceInterface).values().stream()
35+
Reflect.serviceMethods(serviceInterface).stream()
3636
.map(
3737
method -> {
3838
// validate method
@@ -113,7 +113,7 @@ public static Collection<ServiceRoleDefinition> collectServiceRoles(
113113
serviceInterface ->
114114
Reflect.serviceMethods(serviceInterface)
115115
.forEach(
116-
(key, method) -> {
116+
method -> {
117117
// validate method
118118
Reflect.validateMethodOrThrow(method);
119119

services/src/main/java/io/scalecube/services/registry/ServiceRegistryImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ public void registerService(
152152
serviceInterface ->
153153
Reflect.serviceMethods(serviceInterface)
154154
.forEach(
155-
(key, method) -> {
155+
method -> {
156156
// validate method
157157
Reflect.validateMethodOrThrow(method);
158158

0 commit comments

Comments
 (0)