diff --git a/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DatastreamClient.golden b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DatastreamClient.golden
new file mode 100644
index 00000000000..cf122b81b39
--- /dev/null
+++ b/src/test/java/com/google/api/generator/gapic/composer/grpc/goldens/DatastreamClient.golden
@@ -0,0 +1,372 @@
+package com.google.cloud.datastream.v1alpha1;
+
+import com.google.api.core.ApiFuture;
+import com.google.api.core.ApiFutures;
+import com.google.api.core.BetaApi;
+import com.google.api.gax.core.BackgroundResource;
+import com.google.api.gax.paging.AbstractFixedSizeCollection;
+import com.google.api.gax.paging.AbstractPage;
+import com.google.api.gax.paging.AbstractPagedListResponse;
+import com.google.api.gax.rpc.PageContext;
+import com.google.api.gax.rpc.UnaryCallable;
+import com.google.cloud.datastream.v1alpha1.stub.DatastreamStub;
+import com.google.cloud.datastream.v1alpha1.stub.DatastreamStubSettings;
+import com.google.common.util.concurrent.MoreExecutors;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Generated;
+
+// AUTO-GENERATED DOCUMENTATION AND CLASS.
+/**
+ * This class provides the ability to make remote calls to the backing service through method calls
+ * that map to API methods. Sample code to get started:
+ *
+ * <pre>{@code
+ * try (DatastreamClient datastreamClient = DatastreamClient.create()) {
+ *   PrivateConnectionName parent =
+ *       PrivateConnectionName.of("[PROJECT]", "[LOCATION]", "[PRIVATE_CONNECTION]");
+ *   for (Route element : datastreamClient.listRoutes(parent).iterateAll()) {
+ *     // doThingsWith(element);
+ *   }
+ * }
+ * }</pre>
+ *
+ * <p>Note: close() needs to be called on the DatastreamClient object to clean up resources such as
+ * threads. In the example above, try-with-resources is used, which automatically calls close().
+ *
+ * <p>The surface of this class includes several types of Java methods for each of the API's
+ * methods:
+ *
+ * <ol>
+ *   <li>A "flattened" method. With this type of method, the fields of the request type have been
+ *       converted into function parameters. It may be the case that not all fields are available as
+ *       parameters, and not every API method will have a flattened method entry point.
+ *   <li>A "request object" method. This type of method only takes one parameter, a request object,
+ *       which must be constructed before the call. Not every API method will have a request object
+ *       method.
+ *   <li>A "callable" method. This type of method takes no parameters and returns an immutable API
+ *       callable object, which can be used to initiate calls to the service.
+ * </ol>
+ *
+ * <p>See the individual methods for example code.
+ *
+ * <p>Many parameters require resource names to be formatted in a particular way. To assist with
+ * these names, this class includes a format method for each type of name, and additionally a parse
+ * method to extract the individual identifiers contained within names that are returned.
+ *
+ * <p>This class can be customized by passing in a custom instance of DatastreamSettings to
+ * create(). For example:
+ *
+ * <p>To customize credentials:
+ *
+ * <pre>{@code
+ * DatastreamSettings datastreamSettings =
+ *     DatastreamSettings.newBuilder()
+ *         .setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
+ *         .build();
+ * DatastreamClient datastreamClient = DatastreamClient.create(datastreamSettings);
+ * }</pre>
+ *
+ * <p>To customize the endpoint:
+ *
+ * <pre>{@code
+ * DatastreamSettings datastreamSettings =
+ *     DatastreamSettings.newBuilder().setEndpoint(myEndpoint).build();
+ * DatastreamClient datastreamClient = DatastreamClient.create(datastreamSettings);
+ * }</pre>
+ *
+ * <p>Please refer to the GitHub repository's samples for more quickstart code snippets.
+ */
+@BetaApi
+@Generated("by gapic-generator-java")
+public class DatastreamClient implements BackgroundResource {
+  private final DatastreamSettings settings;
+  private final DatastreamStub stub;
+
+  /** Constructs an instance of DatastreamClient with default settings. */
+  public static final DatastreamClient create() throws IOException {
+    return create(DatastreamSettings.newBuilder().build());
+  }
+
+  /**
+   * Constructs an instance of DatastreamClient, using the given settings. The channels are created
+   * based on the settings passed in, or defaults for any settings that are not set.
+   */
+  public static final DatastreamClient create(DatastreamSettings settings) throws IOException {
+    return new DatastreamClient(settings);
+  }
+
+  /**
+   * Constructs an instance of DatastreamClient, using the given stub for making calls. This is for
+   * advanced usage - prefer using create(DatastreamSettings).
+   */
+  @BetaApi("A restructuring of stub classes is planned, so this may break in the future")
+  public static final DatastreamClient create(DatastreamStub stub) {
+    return new DatastreamClient(stub);
+  }
+
+  /**
+   * Constructs an instance of DatastreamClient, using the given settings. This is protected so that
+   * it is easy to make a subclass, but otherwise, the static factory methods should be preferred.
+   */
+  protected DatastreamClient(DatastreamSettings settings) throws IOException {
+    this.settings = settings;
+    this.stub = ((DatastreamStubSettings) settings.getStubSettings()).createStub();
+  }
+
+  @BetaApi("A restructuring of stub classes is planned, so this may break in the future")
+  protected DatastreamClient(DatastreamStub stub) {
+    this.settings = null;
+    this.stub = stub;
+  }
+
+  public final DatastreamSettings getSettings() {
+    return settings;
+  }
+
+  @BetaApi("A restructuring of stub classes is planned, so this may break in the future")
+  public DatastreamStub getStub() {
+    return stub;
+  }
+
+  // AUTO-GENERATED DOCUMENTATION AND METHOD.
+  /**
+   * Sample code:
+   *
+   * <pre>{@code
+   * try (DatastreamClient datastreamClient = DatastreamClient.create()) {
+   *   PrivateConnectionName parent =
+   *       PrivateConnectionName.of("[PROJECT]", "[LOCATION]", "[PRIVATE_CONNECTION]");
+   *   for (Route element : datastreamClient.listRoutes(parent).iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }</pre>
+   *
+   * @param parent
+   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
+   */
+  public final ListRoutesPagedResponse listRoutes(PrivateConnectionName parent) {
+    ListRoutesRequest request =
+        ListRoutesRequest.newBuilder().setParent(parent == null ? null : parent.toString()).build();
+    return listRoutes(request);
+  }
+
+  // AUTO-GENERATED DOCUMENTATION AND METHOD.
+  /**
+   * Sample code:
+   *
+   * <pre>{@code
+   * try (DatastreamClient datastreamClient = DatastreamClient.create()) {
+   *   String parent =
+   *       PrivateConnectionName.of("[PROJECT]", "[LOCATION]", "[PRIVATE_CONNECTION]").toString();
+   *   for (Route element : datastreamClient.listRoutes(parent).iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }</pre>
+   *
+   * @param parent
+   * @throws com.google.api.gax.rpc.ApiException if the remote call fails
+   */
+  public final ListRoutesPagedResponse listRoutes(String parent) {
+    ListRoutesRequest request = ListRoutesRequest.newBuilder().setParent(parent).build();
+    return listRoutes(request);
+  }
+
+  // AUTO-GENERATED DOCUMENTATION AND METHOD.
+  /**
+   * Sample code:
+   *
+   * <pre>{@code
+   * try (DatastreamClient datastreamClient = DatastreamClient.create()) {
+   *   ListRoutesRequest request =
+   *       ListRoutesRequest.newBuilder()
+   *           .setParent(
+   *               RouteName.of("[PROJECT]", "[LOCATION]", "[PRIVATE_CONNECTION]", "[ROUTE]")
+   *                   .toString())
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .setFilter("filter-1274492040")
+   *           .setOrderBy("orderBy-1207110587")
+   *           .build();
+   *   for (Route element : datastreamClient.listRoutes(request).iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }</pre>
+   *
+   * @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 ListRoutesPagedResponse listRoutes(ListRoutesRequest request) {
+    return listRoutesPagedCallable().call(request);
+  }
+
+  // AUTO-GENERATED DOCUMENTATION AND METHOD.
+  /**
+   * Sample code:
+   *
+   * <pre>{@code
+   * try (DatastreamClient datastreamClient = DatastreamClient.create()) {
+   *   ListRoutesRequest request =
+   *       ListRoutesRequest.newBuilder()
+   *           .setParent(
+   *               RouteName.of("[PROJECT]", "[LOCATION]", "[PRIVATE_CONNECTION]", "[ROUTE]")
+   *                   .toString())
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .setFilter("filter-1274492040")
+   *           .setOrderBy("orderBy-1207110587")
+   *           .build();
+   *   ApiFuture<Route> future = datastreamClient.listRoutesPagedCallable().futureCall(request);
+   *   // Do something.
+   *   for (Route element : future.get().iterateAll()) {
+   *     // doThingsWith(element);
+   *   }
+   * }
+   * }</pre>
+   */
+  public final UnaryCallable<ListRoutesRequest, ListRoutesPagedResponse> listRoutesPagedCallable() {
+    return stub.listRoutesPagedCallable();
+  }
+
+  // AUTO-GENERATED DOCUMENTATION AND METHOD.
+  /**
+   * Sample code:
+   *
+   * <pre>{@code
+   * try (DatastreamClient datastreamClient = DatastreamClient.create()) {
+   *   ListRoutesRequest request =
+   *       ListRoutesRequest.newBuilder()
+   *           .setParent(
+   *               RouteName.of("[PROJECT]", "[LOCATION]", "[PRIVATE_CONNECTION]", "[ROUTE]")
+   *                   .toString())
+   *           .setPageSize(883849137)
+   *           .setPageToken("pageToken873572522")
+   *           .setFilter("filter-1274492040")
+   *           .setOrderBy("orderBy-1207110587")
+   *           .build();
+   *   while (true) {
+   *     ListRoutesResponse response = datastreamClient.listRoutesCallable().call(request);
+   *     for (Route element : response.getResponsesList()) {
+   *       // doThingsWith(element);
+   *     }
+   *     String nextPageToken = response.getNextPageToken();
+   *     if (!Strings.isNullOrEmpty(nextPageToken)) {
+   *       request = request.toBuilder().setPageToken(nextPageToken).build();
+   *     } else {
+   *       break;
+   *     }
+   *   }
+   * }
+   * }</pre>
+   */
+  public final UnaryCallable<ListRoutesRequest, ListRoutesResponse> listRoutesCallable() {
+    return stub.listRoutesCallable();
+  }
+
+  @Override
+  public final void close() {
+    stub.close();
+  }
+
+  @Override
+  public void shutdown() {
+    stub.shutdown();
+  }
+
+  @Override
+  public boolean isShutdown() {
+    return stub.isShutdown();
+  }
+
+  @Override
+  public boolean isTerminated() {
+    return stub.isTerminated();
+  }
+
+  @Override
+  public void shutdownNow() {
+    stub.shutdownNow();
+  }
+
+  @Override
+  public boolean awaitTermination(long duration, TimeUnit unit) throws InterruptedException {
+    return stub.awaitTermination(duration, unit);
+  }
+
+  public static class ListRoutesPagedResponse
+      extends AbstractPagedListResponse<
+          ListRoutesRequest,
+          ListRoutesResponse,
+          Route,
+          ListRoutesPage,
+          ListRoutesFixedSizeCollection> {
+
+    public static ApiFuture<ListRoutesPagedResponse> createAsync(
+        PageContext<ListRoutesRequest, ListRoutesResponse, Route> context,
+        ApiFuture<ListRoutesResponse> futureResponse) {
+      ApiFuture<ListRoutesPage> futurePage =
+          ListRoutesPage.createEmptyPage().createPageAsync(context, futureResponse);
+      return ApiFutures.transform(
+          futurePage, input -> new ListRoutesPagedResponse(input), MoreExecutors.directExecutor());
+    }
+
+    private ListRoutesPagedResponse(ListRoutesPage page) {
+      super(page, ListRoutesFixedSizeCollection.createEmptyCollection());
+    }
+  }
+
+  public static class ListRoutesPage
+      extends AbstractPage<ListRoutesRequest, ListRoutesResponse, Route, ListRoutesPage> {
+
+    private ListRoutesPage(
+        PageContext<ListRoutesRequest, ListRoutesResponse, Route> context,
+        ListRoutesResponse response) {
+      super(context, response);
+    }
+
+    private static ListRoutesPage createEmptyPage() {
+      return new ListRoutesPage(null, null);
+    }
+
+    @Override
+    protected ListRoutesPage createPage(
+        PageContext<ListRoutesRequest, ListRoutesResponse, Route> context,
+        ListRoutesResponse response) {
+      return new ListRoutesPage(context, response);
+    }
+
+    @Override
+    public ApiFuture<ListRoutesPage> createPageAsync(
+        PageContext<ListRoutesRequest, ListRoutesResponse, Route> context,
+        ApiFuture<ListRoutesResponse> futureResponse) {
+      return super.createPageAsync(context, futureResponse);
+    }
+  }
+
+  public static class ListRoutesFixedSizeCollection
+      extends AbstractFixedSizeCollection<
+          ListRoutesRequest,
+          ListRoutesResponse,
+          Route,
+          ListRoutesPage,
+          ListRoutesFixedSizeCollection> {
+
+    private ListRoutesFixedSizeCollection(List<ListRoutesPage> pages, int collectionSize) {
+      super(pages, collectionSize);
+    }
+
+    private static ListRoutesFixedSizeCollection createEmptyCollection() {
+      return new ListRoutesFixedSizeCollection(null, 0);
+    }
+
+    @Override
+    protected ListRoutesFixedSizeCollection createCollection(
+        List<ListRoutesPage> pages, int collectionSize) {
+      return new ListRoutesFixedSizeCollection(pages, collectionSize);
+    }
+  }
+}
diff --git a/src/test/java/com/google/api/generator/gapic/testdata/datastream.proto b/src/test/java/com/google/api/generator/gapic/testdata/datastream.proto
new file mode 100644
index 00000000000..d9a6314b1b7
--- /dev/null
+++ b/src/test/java/com/google/api/generator/gapic/testdata/datastream.proto
@@ -0,0 +1,164 @@
+// Copyright 2021 Google LLC
+//
+// Licensed 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
+//
+//     http://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.
+
+syntax = "proto3";
+
+package google.cloud.datastream.v1alpha1;
+
+import "google/api/annotations.proto";
+import "google/api/client.proto";
+import "google/api/field_behavior.proto";
+import "google/api/resource.proto";
+import "google/longrunning/operations.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/timestamp.proto";
+
+option csharp_namespace = "Google.Cloud.Datastream.V1Alpha1";
+option go_package = "google.golang.org/genproto/googleapis/cloud/datastream/v1alpha1;datastream";
+option java_multiple_files = true;
+option java_outer_classname = "CloudDatastreamServiceProto";
+option java_package = "com.google.cloud.datastream.v1alpha1";
+option php_namespace = "Google\\Cloud\\Datastream\\V1alpha1";
+option ruby_package = "Google::Cloud::Datastream::V1alpha1";
+
+// Datastream service
+service Datastream {
+  option (google.api.default_host) = "datastream.googleapis.com";
+  option (google.api.oauth_scopes) = "https://www.googleapis.com/auth/cloud-platform";
+
+  // Use this method to list routes created for a private connectivity in a
+  // project and location.
+  rpc ListRoutes(ListRoutesRequest) returns (ListRoutesResponse) {
+    option (google.api.http) = {
+      get: "/v1alpha1/{parent=projects/*/locations/*/privateConnections/*}/routes"
+    };
+    option (google.api.method_signature) = "parent";
+  }
+}
+
+
+// route list request
+message ListRoutesRequest {
+  // Required. The parent that owns the collection of Routess.
+  string parent = 1 [
+    (google.api.field_behavior) = REQUIRED,
+    (google.api.resource_reference) = {
+      child_type: "datastream.googleapis.com/Route"
+    }
+  ];
+
+  // Maximum number of Routes to return. The service may return
+  // fewer than this value. If unspecified, at most 50 Routes
+  // will be returned. The maximum value is 1000; values above 1000 will be
+  // coerced to 1000.
+  int32 page_size = 2;
+
+  // Page token received from a previous `ListRoutes` call.
+  // Provide this to retrieve the subsequent page.
+  //
+  // When paginating, all other parameters provided to
+  // `ListRoutes` must match the call that provided the page
+  // token.
+  string page_token = 3;
+
+  // Filter request.
+  string filter = 4;
+
+  // Order by fields for the result.
+  string order_by = 5;
+}
+
+// route list response
+message ListRoutesResponse {
+  // List of Routes.
+  repeated Route routes = 1;
+
+  // A token, which can be sent as `page_token` to retrieve the next page.
+  // If this field is omitted, there are no subsequent pages.
+  string next_page_token = 2;
+
+  // Locations that could not be reached.
+  repeated string unreachable = 3;
+}
+
+// The Route resource is the child of the PrivateConnection resource.
+// It used to define a route for a PrivateConnection setup.
+message Route {
+  option (google.api.resource) = {
+    type: "datastream.googleapis.com/Route"
+    pattern: "projects/{project}/locations/{location}/privateConnections/{private_connection}/routes/{route}"
+  };
+
+  // Output only. The resource's name.
+  string name = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+  // Output only. The create time of the resource.
+  google.protobuf.Timestamp create_time = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+  // Output only. The update time of the resource.
+  google.protobuf.Timestamp update_time = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+  // Labels.
+  map<string, string> labels = 4;
+
+  // Required. Display name.
+  string display_name = 5 [(google.api.field_behavior) = REQUIRED];
+
+  // Required. Destination address for connection
+  string destination_address = 6 [(google.api.field_behavior) = REQUIRED];
+
+  // Destination port for connection
+  int32 destination_port = 7;
+}
+
+// The PrivateConnection resource is used to establish private connectivity
+// between Datastream and a customer's network.
+message PrivateConnection {
+  option (google.api.resource) = {
+    type: "datastream.googleapis.com/PrivateConnection"
+    pattern: "projects/{project}/locations/{location}/privateConnections/{private_connection}"
+  };
+
+  // Private Connection state.
+  enum State {
+    STATE_UNSPECIFIED = 0;
+
+    // The private connection is in creation state - creating resources.
+    CREATING = 1;
+
+    // The private connection has been created with all of it's resources.
+    CREATED = 2;
+
+    // The private connection creation has failed.
+    FAILED = 3;
+  }
+
+  // Output only. The resource's name.
+  string name = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+  // Output only. The create time of the resource.
+  google.protobuf.Timestamp create_time = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+  // Output only. The update time of the resource.
+  google.protobuf.Timestamp update_time = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+  // Labels.
+  map<string, string> labels = 4;
+
+  // Required. Display name.
+  string display_name = 5 [(google.api.field_behavior) = REQUIRED];
+
+  // Output only. The state of the Private Connection.
+  State state = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
+}
\ No newline at end of file