Skip to content

Commit 56ba24f

Browse files
ioanbsuioanbsu
authored andcommitted
#9870: updating author to ioanbsu <[email protected]>
1 parent b7164f0 commit 56ba24f

File tree

2 files changed

+114
-2
lines changed

2 files changed

+114
-2
lines changed

api/src/main/java/io/grpc/ServerInterceptors.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,41 @@ private static final class KnownLengthBufferedInputStream extends BufferedInputS
184184
public static <T> ServerServiceDefinition useMarshalledMessages(
185185
final ServerServiceDefinition serviceDef,
186186
final MethodDescriptor.Marshaller<T> marshaller) {
187+
return useMarshalledMessages(serviceDef, marshaller, marshaller);
188+
}
189+
190+
/**
191+
* Create a new {@code ServerServiceDefinition} with {@link MethodDescriptor} for deserializing requests and
192+
* separate {@link MethodDescriptor} for serializing responses. The {@code ServerCallHandler} created will
193+
* automatically convert back to the original types for request and response before calling the existing {@code
194+
* ServerCallHandler}. Calling this method combined with the intercept methods will allow the developer to choose
195+
* whether to intercept messages of ReqT/RespT, or the modeled types of their application. This can also be
196+
* chained to
197+
* allow for interceptors to handle messages as multiple different ReqT/RespT types within the chain if the added
198+
* cost of
199+
* serialization is not a concern.
200+
*
201+
* @param serviceDef the sevice definition to add request and response marshallers to.
202+
* @param requestMarshaller request marshaller
203+
* @param responseMarshaller response marshaller
204+
* @param <ReqT> the request payload type
205+
* @param <RespT> the response payload type.
206+
* @return a wrapped version of {@code serviceDef} with the ReqT and RespT conversion applied.
207+
*/
208+
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/9870")
209+
public static <ReqT, RespT> ServerServiceDefinition useMarshalledMessages(
210+
final ServerServiceDefinition serviceDef,
211+
final MethodDescriptor.Marshaller<ReqT> requestMarshaller,
212+
final MethodDescriptor.Marshaller<RespT> responseMarshaller) {
187213
List<ServerMethodDefinition<?, ?>> wrappedMethods =
188214
new ArrayList<>();
189215
List<MethodDescriptor<?, ?>> wrappedDescriptors =
190216
new ArrayList<>();
191217
// Wrap the descriptors
192218
for (final ServerMethodDefinition<?, ?> definition : serviceDef.getMethods()) {
193219
final MethodDescriptor<?, ?> originalMethodDescriptor = definition.getMethodDescriptor();
194-
final MethodDescriptor<T, T> wrappedMethodDescriptor =
195-
originalMethodDescriptor.toBuilder(marshaller, marshaller).build();
220+
final MethodDescriptor<ReqT, RespT> wrappedMethodDescriptor =
221+
originalMethodDescriptor.toBuilder(requestMarshaller, responseMarshaller).build();
196222
wrappedDescriptors.add(wrappedMethodDescriptor);
197223
wrappedMethods.add(wrapMethod(definition, wrappedMethodDescriptor));
198224
}

api/src/test/java/io/grpc/ServerInterceptorsTest.java

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import io.grpc.ServerCall.Listener;
3434
import io.grpc.internal.NoopServerCall;
3535
import java.io.ByteArrayInputStream;
36+
import java.io.IOException;
3637
import java.io.InputStream;
3738
import java.util.ArrayList;
3839
import java.util.Arrays;
@@ -425,6 +426,91 @@ public void onMessage(ReqT message) {
425426
order);
426427
}
427428

429+
/**
430+
* Tests the {@link ServerInterceptors#useMarshalledMessages(ServerServiceDefinition, Marshaller, Marshaller)}.
431+
* Makes sure that on incoming request the request marshaller's stream method is called and on response the
432+
* response marshaller's parse method is called
433+
*/
434+
@Test
435+
public void distinctMarshallerForRequestAndResponse() {
436+
final List<String> requestFlowOrder = new ArrayList<>();
437+
438+
final Marshaller<String> requestMarshaller = new Marshaller<String>() {
439+
@Override
440+
public InputStream stream(String value) {
441+
requestFlowOrder.add("RequestStream");
442+
return new ByteArrayInputStream(value.getBytes());
443+
}
444+
445+
@Override
446+
public String parse(InputStream stream) {
447+
requestFlowOrder.add("RequestParse");
448+
try {
449+
byte[] bytes = new byte[stream.available()];
450+
stream.read(bytes);
451+
return new String(bytes);
452+
} catch (IOException e) {
453+
throw new RuntimeException(e);
454+
}
455+
}
456+
};
457+
final Marshaller<String> responseMarshaller = new Marshaller<String>() {
458+
@Override
459+
public InputStream stream(String value) {
460+
requestFlowOrder.add("ResponseStream");
461+
return new ByteArrayInputStream(value.getBytes());
462+
}
463+
464+
@Override
465+
public String parse(InputStream stream) {
466+
requestFlowOrder.add("ResponseParse");
467+
try {
468+
byte[] bytes = new byte[stream.available()];
469+
stream.read(bytes);
470+
return new String(bytes);
471+
} catch (IOException e) {
472+
throw new RuntimeException(e);
473+
}
474+
}
475+
};
476+
final Marshaller<Holder> dummyMarshaller = new Marshaller<Holder>() {
477+
@Override
478+
public InputStream stream(Holder value) {
479+
return value.get();
480+
}
481+
482+
@Override
483+
public Holder parse(InputStream stream) {
484+
return new Holder(stream);
485+
}
486+
};
487+
ServerCallHandler<Holder, Holder> handler = (call, headers) -> new Listener<Holder>() {
488+
@Override
489+
public void onMessage(Holder message) {
490+
requestFlowOrder.add("handler");
491+
call.sendMessage(message);
492+
}
493+
};
494+
495+
MethodDescriptor<Holder, Holder> wrappedMethod = MethodDescriptor.<Holder, Holder>newBuilder()
496+
.setType(MethodType.UNKNOWN)
497+
.setFullMethodName("basic/wrapped")
498+
.setRequestMarshaller(dummyMarshaller)
499+
.setResponseMarshaller(dummyMarshaller)
500+
.build();
501+
ServerServiceDefinition serviceDef = ServerServiceDefinition.builder(
502+
new ServiceDescriptor("basic", wrappedMethod))
503+
.addMethod(wrappedMethod, handler).build();
504+
ServerServiceDefinition intercepted = ServerInterceptors.useMarshalledMessages(serviceDef, requestMarshaller,
505+
responseMarshaller);
506+
ServerMethodDefinition<String, String> serverMethod =
507+
(ServerMethodDefinition<String, String>) intercepted.getMethod("basic/wrapped");
508+
ServerCall<String, String> serverCall = new NoopServerCall<>();
509+
serverMethod.getServerCallHandler().startCall(serverCall, headers).onMessage("TestMessage");
510+
511+
assertEquals(Arrays.asList("RequestStream", "handler", "ResponseParse"), requestFlowOrder);
512+
}
513+
428514
@SuppressWarnings("unchecked")
429515
private static ServerMethodDefinition<String, Integer> getSoleMethod(
430516
ServerServiceDefinition serviceDef) {

0 commit comments

Comments
 (0)