diff --git a/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java b/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java index 7a2d53fe44..1fb9191346 100644 --- a/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java +++ b/src/main/java/com/google/api/generator/gapic/composer/defaultvalue/DefaultValueComposer.java @@ -145,9 +145,10 @@ public static Expr createValue( String nestedFieldName = field.name(); Map nestedValuePatterns = new HashMap<>(); for (Map.Entry entry : valuePatterns.entrySet()) { - if (entry.getKey().startsWith(nestedFieldName + '.')) { + String lowerCamelNestedFieldName = JavaStyle.toLowerCamelCase(nestedFieldName); + if (entry.getKey().startsWith(lowerCamelNestedFieldName + '.')) { nestedValuePatterns.put( - entry.getKey().substring(nestedFieldName.length() + 1), entry.getValue()); + entry.getKey().substring(lowerCamelNestedFieldName.length() + 1), entry.getValue()); } } diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClient.golden b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClient.golden index 8d0880523e..31fdeed3cd 100644 --- a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClient.golden +++ b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClient.golden @@ -360,7 +360,7 @@ public class EchoClient implements BackgroundResource { * .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString()) * .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString()) * .setSeverity(Severity.forNumber(0)) - * .setFoobar(Foobar.newBuilder().build()) + * .setFooBar(Foobar.newBuilder().build()) * .build(); * EchoResponse response = echoClient.echo(request); * } @@ -386,7 +386,7 @@ public class EchoClient implements BackgroundResource { * .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString()) * .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString()) * .setSeverity(Severity.forNumber(0)) - * .setFoobar(Foobar.newBuilder().build()) + * .setFooBar(Foobar.newBuilder().build()) * .build(); * ApiFuture future = echoClient.echoCallable().futureCall(request); * // Do something. @@ -772,7 +772,7 @@ public class EchoClient implements BackgroundResource { * .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString()) * .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString()) * .setSeverity(Severity.forNumber(0)) - * .setFoobar(Foobar.newBuilder().build()) + * .setFooBar(Foobar.newBuilder().build()) * .build(); * Object response = echoClient.collideName(request); * } @@ -798,7 +798,7 @@ public class EchoClient implements BackgroundResource { * .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString()) * .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString()) * .setSeverity(Severity.forNumber(0)) - * .setFoobar(Foobar.newBuilder().build()) + * .setFooBar(Foobar.newBuilder().build()) * .build(); * ApiFuture future = echoClient.collideNameCallable().futureCall(request); * // Do something. @@ -810,6 +810,57 @@ public class EchoClient implements BackgroundResource { return stub.collideNameCallable(); } + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Sample code: + * + *
{@code
+   * // This snippet has been automatically generated for illustrative purposes only.
+   * // It may require modifications to work in your environment.
+   * try (EchoClient echoClient = EchoClient.create()) {
+   *   EchoRequest request =
+   *       EchoRequest.newBuilder()
+   *           .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+   *           .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+   *           .setSeverity(Severity.forNumber(0))
+   *           .setFooBar(Foobar.newBuilder().build())
+   *           .build();
+   *   Object response = echoClient.nestedBinding(request);
+   * }
+   * }
+ * + * @param request The request object containing all of the parameters for the API call. + * @throws com.google.api.gax.rpc.ApiException if the remote call fails + */ + public final Object nestedBinding(EchoRequest request) { + return nestedBindingCallable().call(request); + } + + // AUTO-GENERATED DOCUMENTATION AND METHOD. + /** + * Sample code: + * + *
{@code
+   * // This snippet has been automatically generated for illustrative purposes only.
+   * // It may require modifications to work in your environment.
+   * try (EchoClient echoClient = EchoClient.create()) {
+   *   EchoRequest request =
+   *       EchoRequest.newBuilder()
+   *           .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+   *           .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+   *           .setSeverity(Severity.forNumber(0))
+   *           .setFooBar(Foobar.newBuilder().build())
+   *           .build();
+   *   ApiFuture future = echoClient.nestedBindingCallable().futureCall(request);
+   *   // Do something.
+   *   Object response = future.get();
+   * }
+   * }
+   */
+  public final UnaryCallable nestedBindingCallable() {
+    return stub.nestedBindingCallable();
+  }
+
   @Override
   public final void close() {
     stub.close();
diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClientHttpJsonTest.golden b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClientHttpJsonTest.golden
index 14a0782783..b3a5f9c63d 100644
--- a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClientHttpJsonTest.golden
+++ b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClientHttpJsonTest.golden
@@ -106,7 +106,7 @@ public class EchoClientHttpJsonTest {
               .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
               .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
               .setSeverity(Severity.forNumber(0))
-              .setFoobar(Foobar.newBuilder().build())
+              .setFooBar(Foobar.newBuilder().build())
               .build();
       client.echo(request);
       Assert.fail("No exception raised");
@@ -702,7 +702,7 @@ public class EchoClientHttpJsonTest {
             .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
             .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
             .setSeverity(Severity.forNumber(0))
-            .setFoobar(Foobar.newBuilder().build())
+            .setFooBar(Foobar.newBuilder().build())
             .build();
 
     Object actualResponse = client.collideName(request);
@@ -736,7 +736,7 @@ public class EchoClientHttpJsonTest {
               .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
               .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
               .setSeverity(Severity.forNumber(0))
-              .setFoobar(Foobar.newBuilder().build())
+              .setFooBar(Foobar.newBuilder().build())
               .build();
       client.collideName(request);
       Assert.fail("No exception raised");
@@ -744,4 +744,65 @@ public class EchoClientHttpJsonTest {
       // Expected exception.
     }
   }
+
+  @Test
+  public void nestedBindingTest() throws Exception {
+    Object expectedResponse = Object.newBuilder().setContent("content951530617").build();
+    mockService.addResponse(expectedResponse);
+
+    EchoRequest request =
+        EchoRequest.newBuilder()
+            .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+            .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+            .setSeverity(Severity.forNumber(0))
+            .setFooBar(
+                Foobar.newBuilder()
+                    .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+                    .setInfo("info3237038")
+                    .build())
+            .build();
+
+    Object actualResponse = client.nestedBinding(request);
+    Assert.assertEquals(expectedResponse, actualResponse);
+
+    List actualRequests = mockService.getRequestPaths();
+    Assert.assertEquals(1, actualRequests.size());
+
+    String apiClientHeaderKey =
+        mockService
+            .getRequestHeaders()
+            .get(ApiClientHeaderProvider.getDefaultApiClientHeaderKey())
+            .iterator()
+            .next();
+    Assert.assertTrue(
+        GaxHttpJsonProperties.getDefaultApiClientHeaderPattern()
+            .matcher(apiClientHeaderKey)
+            .matches());
+  }
+
+  @Test
+  public void nestedBindingExceptionTest() throws Exception {
+    ApiException exception =
+        ApiExceptionFactory.createException(
+            new Exception(), FakeStatusCode.of(StatusCode.Code.INVALID_ARGUMENT), false);
+    mockService.addException(exception);
+
+    try {
+      EchoRequest request =
+          EchoRequest.newBuilder()
+              .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+              .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+              .setSeverity(Severity.forNumber(0))
+              .setFooBar(
+                  Foobar.newBuilder()
+                      .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+                      .setInfo("info3237038")
+                      .build())
+              .build();
+      client.nestedBinding(request);
+      Assert.fail("No exception raised");
+    } catch (InvalidArgumentException e) {
+      // Expected exception.
+    }
+  }
 }
diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClientTest.golden b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClientTest.golden
index a3bf758c6c..99dfb8c534 100644
--- a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClientTest.golden
+++ b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoClientTest.golden
@@ -107,7 +107,7 @@ public class EchoClientTest {
               .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
               .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
               .setSeverity(Severity.forNumber(0))
-              .setFoobar(Foobar.newBuilder().build())
+              .setFooBar(Foobar.newBuilder().build())
               .build();
       client.echo(request);
       Assert.fail("No exception raised");
@@ -679,7 +679,7 @@ public class EchoClientTest {
             .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
             .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
             .setSeverity(Severity.forNumber(0))
-            .setFoobar(Foobar.newBuilder().build())
+            .setFooBar(Foobar.newBuilder().build())
             .build();
 
     Object actualResponse = client.collideName(request);
@@ -694,7 +694,7 @@ public class EchoClientTest {
     Assert.assertEquals(request.getContent(), actualRequest.getContent());
     Assert.assertEquals(request.getError(), actualRequest.getError());
     Assert.assertEquals(request.getSeverity(), actualRequest.getSeverity());
-    Assert.assertEquals(request.getFoobar(), actualRequest.getFoobar());
+    Assert.assertEquals(request.getFooBar(), actualRequest.getFooBar());
     Assert.assertTrue(
         channelProvider.isHeaderSent(
             ApiClientHeaderProvider.getDefaultApiClientHeaderKey(),
@@ -712,7 +712,7 @@ public class EchoClientTest {
               .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
               .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
               .setSeverity(Severity.forNumber(0))
-              .setFoobar(Foobar.newBuilder().build())
+              .setFooBar(Foobar.newBuilder().build())
               .build();
       client.collideName(request);
       Assert.fail("No exception raised");
@@ -720,4 +720,56 @@ public class EchoClientTest {
       // Expected exception.
     }
   }
+
+  @Test
+  public void nestedBindingTest() throws Exception {
+    Object expectedResponse = Object.newBuilder().setContent("content951530617").build();
+    mockEcho.addResponse(expectedResponse);
+
+    EchoRequest request =
+        EchoRequest.newBuilder()
+            .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+            .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+            .setSeverity(Severity.forNumber(0))
+            .setFooBar(Foobar.newBuilder().build())
+            .build();
+
+    Object actualResponse = client.nestedBinding(request);
+    Assert.assertEquals(expectedResponse, actualResponse);
+
+    List actualRequests = mockEcho.getRequests();
+    Assert.assertEquals(1, actualRequests.size());
+    EchoRequest actualRequest = ((EchoRequest) actualRequests.get(0));
+
+    Assert.assertEquals(request.getName(), actualRequest.getName());
+    Assert.assertEquals(request.getParent(), actualRequest.getParent());
+    Assert.assertEquals(request.getContent(), actualRequest.getContent());
+    Assert.assertEquals(request.getError(), actualRequest.getError());
+    Assert.assertEquals(request.getSeverity(), actualRequest.getSeverity());
+    Assert.assertEquals(request.getFooBar(), actualRequest.getFooBar());
+    Assert.assertTrue(
+        channelProvider.isHeaderSent(
+            ApiClientHeaderProvider.getDefaultApiClientHeaderKey(),
+            GaxGrpcProperties.getDefaultApiClientHeaderPattern()));
+  }
+
+  @Test
+  public void nestedBindingExceptionTest() throws Exception {
+    StatusRuntimeException exception = new StatusRuntimeException(io.grpc.Status.INVALID_ARGUMENT);
+    mockEcho.addException(exception);
+
+    try {
+      EchoRequest request =
+          EchoRequest.newBuilder()
+              .setName(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+              .setParent(FoobarName.ofProjectFoobarName("[PROJECT]", "[FOOBAR]").toString())
+              .setSeverity(Severity.forNumber(0))
+              .setFooBar(Foobar.newBuilder().build())
+              .build();
+      client.nestedBinding(request);
+      Assert.fail("No exception raised");
+    } catch (InvalidArgumentException e) {
+      // Expected exception.
+    }
+  }
 }
diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoSettings.golden b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoSettings.golden
index fa61fd6819..9485329b47 100644
--- a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoSettings.golden
+++ b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoSettings.golden
@@ -103,6 +103,11 @@ public class EchoSettings extends ClientSettings {
     return ((EchoStubSettings) getStubSettings()).collideNameSettings();
   }
 
+  /** Returns the object with the settings used for calls to nestedBinding. */
+  public UnaryCallSettings nestedBindingSettings() {
+    return ((EchoStubSettings) getStubSettings()).nestedBindingSettings();
+  }
+
   public static final EchoSettings create(EchoStubSettings stub) throws IOException {
     return new EchoSettings.Builder(stub.toBuilder()).build();
   }
@@ -262,6 +267,11 @@ public class EchoSettings extends ClientSettings {
       return getStubSettingsBuilder().collideNameSettings();
     }
 
+    /** Returns the builder for the settings used for calls to nestedBinding. */
+    public UnaryCallSettings.Builder nestedBindingSettings() {
+      return getStubSettingsBuilder().nestedBindingSettings();
+    }
+
     @Override
     public EchoSettings build() throws IOException {
       return new EchoSettings(this);
diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoStubSettings.golden b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoStubSettings.golden
index fa61fd6819..9485329b47 100644
--- a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoStubSettings.golden
+++ b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/EchoStubSettings.golden
@@ -103,6 +103,11 @@ public class EchoSettings extends ClientSettings {
     return ((EchoStubSettings) getStubSettings()).collideNameSettings();
   }
 
+  /** Returns the object with the settings used for calls to nestedBinding. */
+  public UnaryCallSettings nestedBindingSettings() {
+    return ((EchoStubSettings) getStubSettings()).nestedBindingSettings();
+  }
+
   public static final EchoSettings create(EchoStubSettings stub) throws IOException {
     return new EchoSettings.Builder(stub.toBuilder()).build();
   }
@@ -262,6 +267,11 @@ public class EchoSettings extends ClientSettings {
       return getStubSettingsBuilder().collideNameSettings();
     }
 
+    /** Returns the builder for the settings used for calls to nestedBinding. */
+    public UnaryCallSettings.Builder nestedBindingSettings() {
+      return getStubSettingsBuilder().nestedBindingSettings();
+    }
+
     @Override
     public EchoSettings build() throws IOException {
       return new EchoSettings(this);
diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/GrpcEchoStub.golden b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/GrpcEchoStub.golden
index eefefb4aaa..959f48d7a2 100644
--- a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/GrpcEchoStub.golden
+++ b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/GrpcEchoStub.golden
@@ -12,6 +12,7 @@ import com.google.api.gax.rpc.ClientContext;
 import com.google.api.gax.rpc.OperationCallable;
 import com.google.api.gax.rpc.ServerStreamingCallable;
 import com.google.api.gax.rpc.UnaryCallable;
+import com.google.common.collect.ImmutableMap;
 import com.google.longrunning.Operation;
 import com.google.longrunning.stub.GrpcOperationsStub;
 import com.google.showcase.grpcrest.v1beta1.BlockRequest;
@@ -28,6 +29,7 @@ import com.google.showcase.grpcrest.v1beta1.WaitResponse;
 import io.grpc.MethodDescriptor;
 import io.grpc.protobuf.ProtoUtils;
 import java.io.IOException;
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import javax.annotation.Generated;
 
@@ -100,6 +102,14 @@ public class GrpcEchoStub extends EchoStub {
           .setResponseMarshaller(ProtoUtils.marshaller(Object.getDefaultInstance()))
           .build();
 
+  private static final MethodDescriptor nestedBindingMethodDescriptor =
+      MethodDescriptor.newBuilder()
+          .setType(MethodDescriptor.MethodType.UNARY)
+          .setFullMethodName("google.showcase.grpcrest.v1beta1.Echo/NestedBinding")
+          .setRequestMarshaller(ProtoUtils.marshaller(EchoRequest.getDefaultInstance()))
+          .setResponseMarshaller(ProtoUtils.marshaller(Object.getDefaultInstance()))
+          .build();
+
   private final UnaryCallable echoCallable;
   private final ServerStreamingCallable expandCallable;
   private final UnaryCallable pagedExpandCallable;
@@ -112,6 +122,7 @@ public class GrpcEchoStub extends EchoStub {
   private final OperationCallable waitOperationCallable;
   private final UnaryCallable blockCallable;
   private final UnaryCallable collideNameCallable;
+  private final UnaryCallable nestedBindingCallable;
 
   private final BackgroundResource backgroundResources;
   private final GrpcOperationsStub operationsStub;
@@ -179,6 +190,16 @@ public class GrpcEchoStub extends EchoStub {
         GrpcCallSettings.newBuilder()
             .setMethodDescriptor(collideNameMethodDescriptor)
             .build();
+    GrpcCallSettings nestedBindingTransportSettings =
+        GrpcCallSettings.newBuilder()
+            .setMethodDescriptor(nestedBindingMethodDescriptor)
+            .setParamsExtractor(
+                request -> {
+                  ImmutableMap.Builder params = ImmutableMap.builder();
+                  params.put("foo_bar.name", String.valueOf(request.getFooBar().getName()));
+                  return params.build();
+                })
+            .build();
 
     this.echoCallable =
         callableFactory.createUnaryCallable(
@@ -214,6 +235,9 @@ public class GrpcEchoStub extends EchoStub {
     this.collideNameCallable =
         callableFactory.createUnaryCallable(
             collideNameTransportSettings, settings.collideNameSettings(), clientContext);
+    this.nestedBindingCallable =
+        callableFactory.createUnaryCallable(
+            nestedBindingTransportSettings, settings.nestedBindingSettings(), clientContext);
 
     this.backgroundResources =
         new BackgroundResourceAggregation(clientContext.getBackgroundResources());
@@ -274,6 +298,11 @@ public class GrpcEchoStub extends EchoStub {
     return collideNameCallable;
   }
 
+  @Override
+  public UnaryCallable nestedBindingCallable() {
+    return nestedBindingCallable;
+  }
+
   @Override
   public final void close() {
     try {
diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/HttpJsonEchoStub.golden b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/HttpJsonEchoStub.golden
index f0c7db88f6..9dd1f47647 100644
--- a/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/HttpJsonEchoStub.golden
+++ b/src/test/java/com/google/api/generator/gapic/composer/grpcrest/goldens/HttpJsonEchoStub.golden
@@ -286,6 +286,39 @@ public class HttpJsonEchoStub extends EchoStub {
                   .build())
           .build();
 
+  private static final ApiMethodDescriptor nestedBindingMethodDescriptor =
+      ApiMethodDescriptor.newBuilder()
+          .setFullMethodName("google.showcase.grpcrest.v1beta1.Echo/NestedBinding")
+          .setHttpMethod(HttpMethods.POST)
+          .setType(ApiMethodDescriptor.MethodType.UNARY)
+          .setRequestFormatter(
+              ProtoMessageRequestFormatter.newBuilder()
+                  .setPath(
+                      "/v1beta1/{fooBar.name=projects/*/foobars/*}/echo:foo",
+                      request -> {
+                        Map fields = new HashMap<>();
+                        ProtoRestSerializer serializer = ProtoRestSerializer.create();
+                        serializer.putPathParam(
+                            fields, "fooBar.name", request.getFooBar().getName());
+                        return fields;
+                      })
+                  .setQueryParamsExtractor(
+                      request -> {
+                        Map> fields = new HashMap<>();
+                        ProtoRestSerializer serializer = ProtoRestSerializer.create();
+                        return fields;
+                      })
+                  .setRequestBodyExtractor(
+                      request ->
+                          ProtoRestSerializer.create().toBody("*", request.toBuilder().build()))
+                  .build())
+          .setResponseParser(
+              ProtoMessageResponseParser.newBuilder()
+                  .setDefaultInstance(Object.getDefaultInstance())
+                  .setDefaultTypeRegistry(typeRegistry)
+                  .build())
+          .build();
+
   private final UnaryCallable echoCallable;
   private final ServerStreamingCallable expandCallable;
   private final UnaryCallable pagedExpandCallable;
@@ -298,6 +331,7 @@ public class HttpJsonEchoStub extends EchoStub {
   private final OperationCallable waitOperationCallable;
   private final UnaryCallable blockCallable;
   private final UnaryCallable collideNameCallable;
+  private final UnaryCallable nestedBindingCallable;
 
   private final BackgroundResource backgroundResources;
   private final HttpJsonOperationsStub httpJsonOperationsStub;
@@ -375,6 +409,11 @@ public class HttpJsonEchoStub extends EchoStub {
             .setMethodDescriptor(collideNameMethodDescriptor)
             .setTypeRegistry(typeRegistry)
             .build();
+    HttpJsonCallSettings nestedBindingTransportSettings =
+        HttpJsonCallSettings.newBuilder()
+            .setMethodDescriptor(nestedBindingMethodDescriptor)
+            .setTypeRegistry(typeRegistry)
+            .build();
 
     this.echoCallable =
         callableFactory.createUnaryCallable(
@@ -413,6 +452,9 @@ public class HttpJsonEchoStub extends EchoStub {
     this.collideNameCallable =
         callableFactory.createUnaryCallable(
             collideNameTransportSettings, settings.collideNameSettings(), clientContext);
+    this.nestedBindingCallable =
+        callableFactory.createUnaryCallable(
+            nestedBindingTransportSettings, settings.nestedBindingSettings(), clientContext);
 
     this.backgroundResources =
         new BackgroundResourceAggregation(clientContext.getBackgroundResources());
@@ -428,6 +470,7 @@ public class HttpJsonEchoStub extends EchoStub {
     methodDescriptors.add(waitMethodDescriptor);
     methodDescriptors.add(blockMethodDescriptor);
     methodDescriptors.add(collideNameMethodDescriptor);
+    methodDescriptors.add(nestedBindingMethodDescriptor);
     return methodDescriptors;
   }
 
@@ -486,6 +529,11 @@ public class HttpJsonEchoStub extends EchoStub {
     return collideNameCallable;
   }
 
+  @Override
+  public UnaryCallable nestedBindingCallable() {
+    return nestedBindingCallable;
+  }
+
   @Override
   public final void close() {
     try {
diff --git a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceClientTest.golden b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceClientTest.golden
index 5f8e703f43..9f72651e9c 100644
--- a/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceClientTest.golden
+++ b/src/test/java/com/google/api/generator/gapic/composer/rest/goldens/ComplianceClientTest.golden
@@ -335,7 +335,21 @@ public class ComplianceClientTest {
                     .setFFloat(-1146609341)
                     .setFBool(true)
                     .setFBytes(ByteString.EMPTY)
-                    .setFChild(ComplianceDataChild.newBuilder().build())
+                    .setFChild(
+                        ComplianceDataChild.newBuilder()
+                            .setFString("second/secon-5446")
+                            .setFFloat(-1146609341)
+                            .setFDouble(-1239459382)
+                            .setFBool(true)
+                            .setFContinent(Continent.forNumber(0))
+                            .setFChild(ComplianceDataGrandchild.newBuilder().build())
+                            .setPString("pString-1191954271")
+                            .setPFloat(-861507123)
+                            .setPDouble(-991225216)
+                            .setPBool(true)
+                            .setPContinent(Continent.forNumber(0))
+                            .setPChild(ComplianceDataGrandchild.newBuilder().build())
+                            .build())
                     .setPString("pString-1191954271")
                     .setPInt32(-858673665)
                     .setPDouble(-991225216)
@@ -391,7 +405,21 @@ public class ComplianceClientTest {
                       .setFFloat(-1146609341)
                       .setFBool(true)
                       .setFBytes(ByteString.EMPTY)
-                      .setFChild(ComplianceDataChild.newBuilder().build())
+                      .setFChild(
+                          ComplianceDataChild.newBuilder()
+                              .setFString("second/secon-5446")
+                              .setFFloat(-1146609341)
+                              .setFDouble(-1239459382)
+                              .setFBool(true)
+                              .setFContinent(Continent.forNumber(0))
+                              .setFChild(ComplianceDataGrandchild.newBuilder().build())
+                              .setPString("pString-1191954271")
+                              .setPFloat(-861507123)
+                              .setPDouble(-991225216)
+                              .setPBool(true)
+                              .setPContinent(Continent.forNumber(0))
+                              .setPChild(ComplianceDataGrandchild.newBuilder().build())
+                              .build())
                       .setPString("pString-1191954271")
                       .setPInt32(-858673665)
                       .setPDouble(-991225216)
@@ -433,7 +461,21 @@ public class ComplianceClientTest {
                     .setFFloat(-1146609341)
                     .setFBool(true)
                     .setFBytes(ByteString.EMPTY)
-                    .setFChild(ComplianceDataChild.newBuilder().build())
+                    .setFChild(
+                        ComplianceDataChild.newBuilder()
+                            .setFString("second/secon-3276")
+                            .setFFloat(-1146609341)
+                            .setFDouble(-1239459382)
+                            .setFBool(true)
+                            .setFContinent(Continent.forNumber(0))
+                            .setFChild(ComplianceDataGrandchild.newBuilder().build())
+                            .setPString("pString-1191954271")
+                            .setPFloat(-861507123)
+                            .setPDouble(-991225216)
+                            .setPBool(true)
+                            .setPContinent(Continent.forNumber(0))
+                            .setPChild(ComplianceDataGrandchild.newBuilder().build())
+                            .build())
                     .setPString("pString-1191954271")
                     .setPInt32(-858673665)
                     .setPDouble(-991225216)
@@ -489,7 +531,21 @@ public class ComplianceClientTest {
                       .setFFloat(-1146609341)
                       .setFBool(true)
                       .setFBytes(ByteString.EMPTY)
-                      .setFChild(ComplianceDataChild.newBuilder().build())
+                      .setFChild(
+                          ComplianceDataChild.newBuilder()
+                              .setFString("second/secon-3276")
+                              .setFFloat(-1146609341)
+                              .setFDouble(-1239459382)
+                              .setFBool(true)
+                              .setFContinent(Continent.forNumber(0))
+                              .setFChild(ComplianceDataGrandchild.newBuilder().build())
+                              .setPString("pString-1191954271")
+                              .setPFloat(-861507123)
+                              .setPDouble(-991225216)
+                              .setPBool(true)
+                              .setPContinent(Continent.forNumber(0))
+                              .setPChild(ComplianceDataGrandchild.newBuilder().build())
+                              .build())
                       .setPString("pString-1191954271")
                       .setPInt32(-858673665)
                       .setPDouble(-991225216)
diff --git a/src/test/proto/echo_grpcrest.proto b/src/test/proto/echo_grpcrest.proto
index 21b5a6e40c..21a62c575b 100644
--- a/src/test/proto/echo_grpcrest.proto
+++ b/src/test/proto/echo_grpcrest.proto
@@ -120,6 +120,13 @@ service Echo {
       body: "*"
     };
   }
+
+  rpc NestedBinding(EchoRequest) returns (Object) {
+    option (google.api.http) = {
+      post: "/v1beta1/{foo_bar.name=projects/*/foobars/*}/echo:foo"
+      body: "*"
+    };
+  }
 }
 
 // Generator should not fail when encounter a service without methods
@@ -176,7 +183,7 @@ message EchoRequest {
   // The severity to be echoed by the server.
   Severity severity = 3;
 
-  Foobar foobar = 4;
+  Foobar foo_bar = 4;
 }
 
 // The response message for the Echo methods.