diff --git a/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/BenchmarkServiceGrpc.java b/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/BenchmarkServiceGrpc.java index d0ecea4601..12675c763e 100644 --- a/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/BenchmarkServiceGrpc.java +++ b/benchmarks/src/generated/main/grpc/io/grpc/benchmarks/proto/BenchmarkServiceGrpc.java @@ -38,6 +38,7 @@ public final class BenchmarkServiceGrpc { io.grpc.benchmarks.proto.Messages.SimpleRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( io.grpc.benchmarks.proto.Messages.SimpleResponse.getDefaultInstance())) + .setSchemaDescriptor(new BenchmarkServiceMethodDescriptorSupplier("UnaryCall")) .build(); @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901") public static final io.grpc.MethodDescriptorname() + "MethodDescriptorSupplier"; + if (flavor == ProtoFlavor::NORMAL) { + p->Print( + *vars, + " .setSchemaDescriptor(new $proto_method_descriptor_supplier$(\"$method_name$\"))\n"); + } + + p->Print( + *vars, " .build();\n"); } } @@ -893,22 +903,46 @@ static void PrintGetServiceDescriptorMethod(const ServiceDescriptor* service, if (flavor == ProtoFlavor::NORMAL) { - (*vars)["proto_descriptor_supplier"] = service->name() + "DescriptorSupplier"; + (*vars)["proto_base_descriptor_supplier"] = service->name() + "BaseDescriptorSupplier"; + (*vars)["proto_file_descriptor_supplier"] = service->name() + "FileDescriptorSupplier"; + (*vars)["proto_method_descriptor_supplier"] = service->name() + "MethodDescriptorSupplier"; (*vars)["proto_class_name"] = google::protobuf::compiler::java::ClassName(service->file()); p->Print( *vars, - "private static final class $proto_descriptor_supplier$ implements $ProtoFileDescriptorSupplier$ {\n"); - p->Indent(); - p->Print(*vars, "@$Override$\n"); - p->Print( - *vars, - "public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {\n"); - p->Indent(); - p->Print(*vars, "return $proto_class_name$.getDescriptor();\n"); - p->Outdent(); - p->Print(*vars, "}\n"); - p->Outdent(); - p->Print(*vars, "}\n\n"); + "private static abstract class $proto_base_descriptor_supplier$\n" + " implements $ProtoFileDescriptorSupplier$, $ProtoServiceDescriptorSupplier$ {\n" + " $proto_base_descriptor_supplier$() {}\n" + "\n" + " @$Override$\n" + " public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() {\n" + " return $proto_class_name$.getDescriptor();\n" + " }\n" + "\n" + " @$Override$\n" + " public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() {\n" + " return getFileDescriptor().findServiceByName(\"$service_name$\");\n" + " }\n" + "}\n" + "\n" + "private static final class $proto_file_descriptor_supplier$\n" + " extends $proto_base_descriptor_supplier$ {\n" + " $proto_file_descriptor_supplier$() {}\n" + "}\n" + "\n" + "private static final class $proto_method_descriptor_supplier$\n" + " extends $proto_base_descriptor_supplier$\n" + " implements $ProtoMethodDescriptorSupplier$ {\n" + " private final String methodName;\n" + "\n" + " $proto_method_descriptor_supplier$(String methodName) {\n" + " this.methodName = methodName;\n" + " }\n" + "\n" + " @$Override$\n" + " public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() {\n" + " return getServiceDescriptor().findMethodByName(methodName);\n" + " }\n" + "}\n\n"); } p->Print( @@ -940,7 +974,7 @@ static void PrintGetServiceDescriptorMethod(const ServiceDescriptor* service, if (flavor == ProtoFlavor::NORMAL) { p->Print( *vars, - "\n.setSchemaDescriptor(new $proto_descriptor_supplier$())"); + "\n.setSchemaDescriptor(new $proto_file_descriptor_supplier$())"); } for (int i = 0; i < service->method_count(); ++i) { const MethodDescriptor* method = service->method(i); @@ -1190,6 +1224,10 @@ void GenerateService(const ServiceDescriptor* service, "io.grpc.ServiceDescriptor"; vars["ProtoFileDescriptorSupplier"] = "io.grpc.protobuf.ProtoFileDescriptorSupplier"; + vars["ProtoServiceDescriptorSupplier"] = + "io.grpc.protobuf.ProtoServiceDescriptorSupplier"; + vars["ProtoMethodDescriptorSupplier"] = + "io.grpc.protobuf.ProtoMethodDescriptorSupplier"; vars["AbstractStub"] = "io.grpc.stub.AbstractStub"; vars["MethodDescriptor"] = "io.grpc.MethodDescriptor"; vars["NanoUtils"] = "io.grpc.protobuf.nano.NanoUtils"; diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt index dde48d81b9..49b6455515 100644 --- a/compiler/src/test/golden/TestService.java.txt +++ b/compiler/src/test/golden/TestService.java.txt @@ -41,6 +41,7 @@ public final class TestServiceGrpc { io.grpc.testing.integration.Test.SimpleRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( io.grpc.testing.integration.Test.SimpleResponse.getDefaultInstance())) + .setSchemaDescriptor(new TestServiceMethodDescriptorSupplier("UnaryCall")) .build(); @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901") public static final io.grpc.MethodDescriptor { private final String fullMethodName; private final Marshaller requestMarshaller; private final Marshaller responseMarshaller; + private final @Nullable Object schemaDescriptor; private final boolean idempotent; private final boolean safe; @@ -208,7 +209,7 @@ public final class MethodDescriptor { Marshaller requestMarshaller, Marshaller responseMarshaller) { return new MethodDescriptor( - type, fullMethodName, requestMarshaller, responseMarshaller, false, false); + type, fullMethodName, requestMarshaller, responseMarshaller, null, false, false); } private MethodDescriptor( @@ -216,6 +217,7 @@ public final class MethodDescriptor { String fullMethodName, Marshaller requestMarshaller, Marshaller responseMarshaller, + Object schemaDescriptor, boolean idempotent, boolean safe) { @@ -223,6 +225,7 @@ public final class MethodDescriptor { this.fullMethodName = Preconditions.checkNotNull(fullMethodName, "fullMethodName"); this.requestMarshaller = Preconditions.checkNotNull(requestMarshaller, "requestMarshaller"); this.responseMarshaller = Preconditions.checkNotNull(responseMarshaller, "responseMarshaller"); + this.schemaDescriptor = schemaDescriptor; this.idempotent = idempotent; this.safe = safe; Preconditions.checkArgument(!safe || type == MethodType.UNARY, @@ -311,6 +314,20 @@ public final class MethodDescriptor { return responseMarshaller; } + /** + * Returns the schema descriptor for this method. A schema descriptor is an object that is not + * used by gRPC core but includes information related to the service method. The type of the + * object is specific to the consumer, so both the code setting the schema descriptor and the code + * calling {@link #getSchemaDescriptor()} must coordinate. For example, protobuf generated code + * sets this value, in order to be consumed by the server reflection service. See also: + * {@code io.grpc.protobuf.ProtoMethodDescriptorSupplier}. + * + * @since 1.7.0 + */ + public @Nullable Object getSchemaDescriptor() { + return schemaDescriptor; + } + /** * Returns whether this method is idempotent. * @@ -425,6 +442,7 @@ public final class MethodDescriptor { private String fullMethodName; private boolean idempotent; private boolean safe; + private Object schemaDescriptor; private Builder() {} @@ -473,6 +491,20 @@ public final class MethodDescriptor { return this; } + /** + * Sets the schema descriptor for this builder. A schema descriptor is an object that is not + * used by gRPC core but includes information related to the methods. The type of the object + * is specific to the consumer, so both the code calling this and the code calling + * {@link MethodDescriptor#getSchemaDescriptor()} must coordinate. + * + * @param schemaDescriptor an object that describes the service structure. Should be immutable. + * @since 1.7.0 + */ + public Builder setSchemaDescriptor(@Nullable Object schemaDescriptor) { + this.schemaDescriptor = schemaDescriptor; + return this; + } + /** * Sets whether the method is idempotent. If true, calling this method more than once doesn't * have additional side effects. @@ -509,6 +541,7 @@ public final class MethodDescriptor { fullMethodName, requestMarshaller, responseMarshaller, + schemaDescriptor, idempotent, safe); } diff --git a/grpclb/src/generated/main/grpc/io/grpc/grpclb/LoadBalancerGrpc.java b/grpclb/src/generated/main/grpc/io/grpc/grpclb/LoadBalancerGrpc.java index 5f5406728d..76fb80e75e 100644 --- a/grpclb/src/generated/main/grpc/io/grpc/grpclb/LoadBalancerGrpc.java +++ b/grpclb/src/generated/main/grpc/io/grpc/grpclb/LoadBalancerGrpc.java @@ -38,6 +38,7 @@ public final class LoadBalancerGrpc { io.grpc.grpclb.LoadBalanceRequest.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( io.grpc.grpclb.LoadBalanceResponse.getDefaultInstance())) + .setSchemaDescriptor(new LoadBalancerMethodDescriptorSupplier("BalanceLoad")) .build(); /** @@ -196,11 +197,39 @@ public final class LoadBalancerGrpc { } } - private static final class LoadBalancerDescriptorSupplier implements io.grpc.protobuf.ProtoFileDescriptorSupplier { + private static abstract class LoadBalancerBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoFileDescriptorSupplier, io.grpc.protobuf.ProtoServiceDescriptorSupplier { + LoadBalancerBaseDescriptorSupplier() {} + @java.lang.Override public com.google.protobuf.Descriptors.FileDescriptor getFileDescriptor() { return io.grpc.grpclb.LoadBalancerProto.getDescriptor(); } + + @java.lang.Override + public com.google.protobuf.Descriptors.ServiceDescriptor getServiceDescriptor() { + return getFileDescriptor().findServiceByName("LoadBalancer"); + } + } + + private static final class LoadBalancerFileDescriptorSupplier + extends LoadBalancerBaseDescriptorSupplier { + LoadBalancerFileDescriptorSupplier() {} + } + + private static final class LoadBalancerMethodDescriptorSupplier + extends LoadBalancerBaseDescriptorSupplier + implements io.grpc.protobuf.ProtoMethodDescriptorSupplier { + private final String methodName; + + LoadBalancerMethodDescriptorSupplier(String methodName) { + this.methodName = methodName; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.MethodDescriptor getMethodDescriptor() { + return getServiceDescriptor().findMethodByName(methodName); + } } private static volatile io.grpc.ServiceDescriptor serviceDescriptor; @@ -212,7 +241,7 @@ public final class LoadBalancerGrpc { result = serviceDescriptor; if (result == null) { serviceDescriptor = result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) - .setSchemaDescriptor(new LoadBalancerDescriptorSupplier()) + .setSchemaDescriptor(new LoadBalancerFileDescriptorSupplier()) .addMethod(METHOD_BALANCE_LOAD) .build(); } diff --git a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java index f80b096687..1b609bc82b 100644 --- a/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java +++ b/interop-testing/src/generated/main/grpc/io/grpc/testing/integration/MetricsServiceGrpc.java @@ -38,6 +38,7 @@ public final class MetricsServiceGrpc { io.grpc.testing.integration.Metrics.EmptyMessage.getDefaultInstance())) .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller( io.grpc.testing.integration.Metrics.GaugeResponse.getDefaultInstance())) + .setSchemaDescriptor(new MetricsServiceMethodDescriptorSupplier("GetAllGauges")) .build(); @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/1901") public static final io.grpc.MethodDescriptor