diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle
index 64bb6a8f1f0..c7a1db79f38 100644
--- a/benchmarks/build.gradle
+++ b/benchmarks/build.gradle
@@ -18,6 +18,7 @@ dependencies {
implementation project(':thrift')
implementation 'com.squareup.retrofit2:converter-jackson'
+ implementation 'com.google.protobuf:protobuf-java-util'
implementation 'io.grpc:grpc-okhttp'
implementation 'io.grpc:grpc-netty-shaded'
implementation 'org.awaitility:awaitility'
diff --git a/dependencies.yml b/dependencies.yml
index 81c2a8648e8..2833b299382 100644
--- a/dependencies.yml
+++ b/dependencies.yml
@@ -5,7 +5,7 @@
boms:
- com.fasterxml.jackson:jackson-bom:2.11.0
- io.dropwizard.metrics:metrics-bom:4.1.9
- - io.grpc:grpc-bom:1.29.0
+ - io.grpc:grpc-bom:1.30.0
- io.micrometer:micrometer-bom:1.5.1
# NOTE: When changing this, re-evaluate netty-tcnative-boringssl-static below
- io.netty:netty-bom:4.1.50.Final
@@ -107,7 +107,7 @@ com.google.j2objc:
# See: https://github.com/grpc/grpc-java/blob/master/build.gradle
# (Switch to the right tag and look for 'protobufVersion' and 'protocVersion'.)
com.google.protobuf:
- protobuf-java: { version: &PROTOBUF_VERSION '3.11.4' }
+ protobuf-java: { version: &PROTOBUF_VERSION '3.12.0' }
protobuf-java-util:
version: *PROTOBUF_VERSION
exclusions:
diff --git a/examples/grpc-kotlin/gen-src/main/grpc/example/armeria/grpc/kotlin/HelloServiceGrpc.java b/examples/grpc-kotlin/gen-src/main/grpc/example/armeria/grpc/kotlin/HelloServiceGrpc.java
index 6026b26dee4..0edb4738bb6 100644
--- a/examples/grpc-kotlin/gen-src/main/grpc/example/armeria/grpc/kotlin/HelloServiceGrpc.java
+++ b/examples/grpc-kotlin/gen-src/main/grpc/example/armeria/grpc/kotlin/HelloServiceGrpc.java
@@ -18,7 +18,7 @@
/**
*/
@javax.annotation.Generated(
- value = "by gRPC proto compiler (version 1.29.0)",
+ value = "by gRPC proto compiler (version 1.30.0)",
comments = "Source: hello.proto")
public final class HelloServiceGrpc {
diff --git a/examples/grpc-kotlin/gen-src/main/java/example/armeria/grpc/kotlin/Hello.java b/examples/grpc-kotlin/gen-src/main/java/example/armeria/grpc/kotlin/Hello.java
index b290746a2b7..3531fac6d7c 100644
--- a/examples/grpc-kotlin/gen-src/main/java/example/armeria/grpc/kotlin/Hello.java
+++ b/examples/grpc-kotlin/gen-src/main/java/example/armeria/grpc/kotlin/Hello.java
@@ -33,7 +33,7 @@ public interface HelloRequestOrBuilder extends
/**
* Protobuf type {@code example.grpc.hello.HelloRequest}
*/
- public static final class HelloRequest extends
+ public static final class HelloRequest extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:example.grpc.hello.HelloRequest)
HelloRequestOrBuilder {
@@ -120,6 +120,7 @@ private HelloRequest(
* string name = 1;
* @return The name.
*/
+ @java.lang.Override
public java.lang.String getName() {
java.lang.Object ref = name_;
if (ref instanceof java.lang.String) {
@@ -136,6 +137,7 @@ public java.lang.String getName() {
* string name = 1;
* @return The bytes for name.
*/
+ @java.lang.Override
public com.google.protobuf.ByteString
getNameBytes() {
java.lang.Object ref = name_;
@@ -599,7 +601,7 @@ public interface HelloReplyOrBuilder extends
/**
* Protobuf type {@code example.grpc.hello.HelloReply}
*/
- public static final class HelloReply extends
+ public static final class HelloReply extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:example.grpc.hello.HelloReply)
HelloReplyOrBuilder {
@@ -686,6 +688,7 @@ private HelloReply(
* string message = 1;
* @return The message.
*/
+ @java.lang.Override
public java.lang.String getMessage() {
java.lang.Object ref = message_;
if (ref instanceof java.lang.String) {
@@ -702,6 +705,7 @@ public java.lang.String getMessage() {
* string message = 1;
* @return The bytes for message.
*/
+ @java.lang.Override
public com.google.protobuf.ByteString
getMessageBytes() {
java.lang.Object ref = message_;
diff --git a/grpc/src/main/java/com/linecorp/armeria/server/grpc/FramedGrpcService.java b/grpc/src/main/java/com/linecorp/armeria/server/grpc/FramedGrpcService.java
index 2cfc7768242..b851de3ceff 100644
--- a/grpc/src/main/java/com/linecorp/armeria/server/grpc/FramedGrpcService.java
+++ b/grpc/src/main/java/com/linecorp/armeria/server/grpc/FramedGrpcService.java
@@ -73,7 +73,6 @@
import io.grpc.ServerMethodDefinition;
import io.grpc.ServerServiceDefinition;
import io.grpc.Status;
-import io.grpc.protobuf.services.ProtoReflectionService;
/**
* The framed {@link GrpcService} implementation.
@@ -89,13 +88,13 @@ final class FramedGrpcService extends AbstractHttpService implements GrpcService
private final Set supportedSerializationFormats;
@Nullable
private final MessageMarshaller jsonMarshaller;
+ @Nullable
+ private final ProtoReflectionServiceInterceptor protoReflectionServiceInterceptor;
private final int maxOutboundMessageSizeBytes;
private final boolean useBlockingTaskExecutor;
private final boolean unsafeWrapRequestBuffers;
private final boolean useClientTimeoutHeader;
private final String advertisedEncodingsHeader;
- @Nullable
- private final ProtoReflectionService protoReflectionService;
private final Map defaultHeaders;
@@ -107,11 +106,11 @@ final class FramedGrpcService extends AbstractHttpService implements GrpcService
CompressorRegistry compressorRegistry,
Set supportedSerializationFormats,
Consumer jsonMarshallerCustomizer,
+ @Nullable ProtoReflectionServiceInterceptor protoReflectionServiceInterceptor,
int maxOutboundMessageSizeBytes,
boolean useBlockingTaskExecutor,
boolean unsafeWrapRequestBuffers,
boolean useClientTimeoutHeader,
- @Nullable ProtoReflectionService protoReflectionService,
int maxInboundMessageSizeBytes) {
this.registry = requireNonNull(registry, "registry");
this.routes = requireNonNull(routes, "routes");
@@ -119,8 +118,8 @@ final class FramedGrpcService extends AbstractHttpService implements GrpcService
this.compressorRegistry = requireNonNull(compressorRegistry, "compressorRegistry");
this.supportedSerializationFormats = supportedSerializationFormats;
this.useClientTimeoutHeader = useClientTimeoutHeader;
- this.protoReflectionService = protoReflectionService;
jsonMarshaller = jsonMarshaller(registry, supportedSerializationFormats, jsonMarshallerCustomizer);
+ this.protoReflectionServiceInterceptor = protoReflectionServiceInterceptor;
this.maxOutboundMessageSizeBytes = maxOutboundMessageSizeBytes;
this.useBlockingTaskExecutor = useBlockingTaskExecutor;
this.unsafeWrapRequestBuffers = unsafeWrapRequestBuffers;
@@ -256,7 +255,7 @@ public void serviceAdded(ServiceConfig cfg) {
maxInboundMessageSizeBytes = (int) Math.min(cfg.maxRequestLength(), Integer.MAX_VALUE);
}
- if (protoReflectionService != null) {
+ if (protoReflectionServiceInterceptor != null) {
final Map grpcServices =
cfg.server().config().virtualHosts().stream()
.flatMap(host -> host.serviceConfigs().stream())
@@ -269,62 +268,66 @@ public void serviceAdded(ServiceConfig cfg) {
.collect(toImmutableMap(def -> def.getServiceDescriptor().getName(),
Function.identity(),
(a, b) -> a));
- protoReflectionService.notifyOnBuild(new Server() {
- @Override
- public Server start() {
- throw new UnsupportedOperationException();
- }
+ protoReflectionServiceInterceptor.setServer(newDummyServer(grpcServices));
+ }
+ }
- @Override
- public List getServices() {
- return ImmutableList.copyOf(grpcServices.values());
- }
+ private static Server newDummyServer(Map grpcServices) {
+ return new Server() {
+ @Override
+ public Server start() {
+ throw new UnsupportedOperationException();
+ }
- @Override
- public List getImmutableServices() {
- // NB: This will probably go away in favor of just getServices above, so we
- // implement both the same.
- // https://github.com/grpc/grpc-java/issues/4600
- return getServices();
- }
+ @Override
+ public List getServices() {
+ return ImmutableList.copyOf(grpcServices.values());
+ }
- @Override
- public List getMutableServices() {
- // Armeria does not have the concept of mutable services.
- return ImmutableList.of();
- }
+ @Override
+ public List getImmutableServices() {
+ // NB: This will probably go away in favor of just getServices above, so we
+ // implement both the same.
+ // https://github.com/grpc/grpc-java/issues/4600
+ return getServices();
+ }
- @Override
- public Server shutdown() {
- throw new UnsupportedOperationException();
- }
+ @Override
+ public List getMutableServices() {
+ // Armeria does not have the concept of mutable services.
+ return ImmutableList.of();
+ }
- @Override
- public Server shutdownNow() {
- throw new UnsupportedOperationException();
- }
+ @Override
+ public Server shutdown() {
+ throw new UnsupportedOperationException();
+ }
- @Override
- public boolean isShutdown() {
- throw new UnsupportedOperationException();
- }
+ @Override
+ public Server shutdownNow() {
+ throw new UnsupportedOperationException();
+ }
- @Override
- public boolean isTerminated() {
- throw new UnsupportedOperationException();
- }
+ @Override
+ public boolean isShutdown() {
+ throw new UnsupportedOperationException();
+ }
- @Override
- public boolean awaitTermination(long timeout, TimeUnit unit) {
- throw new UnsupportedOperationException();
- }
+ @Override
+ public boolean isTerminated() {
+ throw new UnsupportedOperationException();
+ }
- @Override
- public void awaitTermination() {
- throw new UnsupportedOperationException();
- }
- });
- }
+ @Override
+ public boolean awaitTermination(long timeout, TimeUnit unit) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void awaitTermination() {
+ throw new UnsupportedOperationException();
+ }
+ };
}
@Override
diff --git a/grpc/src/main/java/com/linecorp/armeria/server/grpc/GrpcServiceBuilder.java b/grpc/src/main/java/com/linecorp/armeria/server/grpc/GrpcServiceBuilder.java
index a88d0a36683..ba2b8eb9283 100644
--- a/grpc/src/main/java/com/linecorp/armeria/server/grpc/GrpcServiceBuilder.java
+++ b/grpc/src/main/java/com/linecorp/armeria/server/grpc/GrpcServiceBuilder.java
@@ -52,6 +52,7 @@
import io.grpc.BindableService;
import io.grpc.CompressorRegistry;
import io.grpc.DecompressorRegistry;
+import io.grpc.ServerInterceptors;
import io.grpc.ServerServiceDefinition;
import io.grpc.protobuf.services.ProtoReflectionService;
@@ -71,6 +72,9 @@ public final class GrpcServiceBuilder {
@Nullable
private CompressorRegistry compressorRegistry;
+ @Nullable
+ private ProtoReflectionServiceInterceptor protoReflectionServiceInterceptor;
+
private Set supportedSerializationFormats = DEFAULT_SUPPORTED_SERIALIZATION_FORMATS;
private int maxInboundMessageSizeBytes = ArmeriaMessageDeframer.NO_MAX_INBOUND_MESSAGE_SIZE;
@@ -87,9 +91,6 @@ public final class GrpcServiceBuilder {
private boolean useClientTimeoutHeader = true;
- @Nullable
- private ProtoReflectionService protoReflectionService;
-
GrpcServiceBuilder() {}
/**
@@ -107,10 +108,11 @@ public GrpcServiceBuilder addService(ServerServiceDefinition service) {
*/
public GrpcServiceBuilder addService(BindableService bindableService) {
if (bindableService instanceof ProtoReflectionService) {
- checkState(protoReflectionService == null,
+ checkState(protoReflectionServiceInterceptor == null,
"Attempting to add a ProtoReflectionService but one is already present. " +
"ProtoReflectionService must only be added once.");
- protoReflectionService = (ProtoReflectionService) bindableService;
+ protoReflectionServiceInterceptor = new ProtoReflectionServiceInterceptor();
+ return addService(ServerInterceptors.intercept(bindableService, protoReflectionServiceInterceptor));
}
return addService(bindableService.bindService());
@@ -308,11 +310,11 @@ public GrpcService build() {
firstNonNull(compressorRegistry, CompressorRegistry.getDefaultInstance()),
supportedSerializationFormats,
jsonMarshallerCustomizer,
+ protoReflectionServiceInterceptor,
maxOutboundMessageSizeBytes,
useBlockingTaskExecutor,
unsafeWrapRequestBuffers,
useClientTimeoutHeader,
- protoReflectionService,
maxInboundMessageSizeBytes);
return enableUnframedRequests ? new UnframedGrpcService(grpcService) : grpcService;
}
diff --git a/grpc/src/main/java/com/linecorp/armeria/server/grpc/ProtoReflectionServiceInterceptor.java b/grpc/src/main/java/com/linecorp/armeria/server/grpc/ProtoReflectionServiceInterceptor.java
new file mode 100644
index 00000000000..b1ecf7e66ec
--- /dev/null
+++ b/grpc/src/main/java/com/linecorp/armeria/server/grpc/ProtoReflectionServiceInterceptor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2020 LINE Corporation
+ *
+ * LINE Corporation licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.linecorp.armeria.server.grpc;
+
+import javax.annotation.Nullable;
+
+import io.grpc.Context;
+import io.grpc.Contexts;
+import io.grpc.InternalServer;
+import io.grpc.Metadata;
+import io.grpc.Server;
+import io.grpc.ServerCall;
+import io.grpc.ServerCall.Listener;
+import io.grpc.ServerCallHandler;
+import io.grpc.ServerInterceptor;
+
+final class ProtoReflectionServiceInterceptor implements ServerInterceptor {
+
+ @Nullable
+ private Server server;
+
+ @Override
+ public Listener interceptCall(ServerCall call, Metadata headers,
+ ServerCallHandler next) {
+ // Should set server before calling this
+ assert server != null;
+
+ final Context context = Context.current().withValue(InternalServer.SERVER_CONTEXT_KEY, server);
+ return Contexts.interceptCall(context, call, headers, next);
+ }
+
+ public void setServer(Server server) {
+ this.server = server;
+ }
+}
diff --git a/it/server/build.gradle b/it/server/build.gradle
index 13cea6beb03..388ed45ddb7 100644
--- a/it/server/build.gradle
+++ b/it/server/build.gradle
@@ -2,5 +2,7 @@ dependencies {
testImplementation project(':grpc')
testImplementation 'io.grpc:grpc-core'
testImplementation 'io.grpc:grpc-interop-testing'
+ testImplementation 'io.grpc:grpc-okhttp'
+ testImplementation 'io.grpc:grpc-testing'
testImplementation 'org.apache.hbase:hbase-shaded-client'
}