public static WindowingStrategy<?, BoundedWindow> getWindowStrategy(
      String collectionId, RunnerApi.Components components) {
    RehydratedComponents rehydratedComponents = RehydratedComponents.forComponents(components);

    RunnerApi.WindowingStrategy windowingStrategyProto =
        components.getWindowingStrategiesOrThrow(
            components.getPcollectionsOrThrow(collectionId).getWindowingStrategyId());

    WindowingStrategy<?, ?> windowingStrategy;
    try {
      windowingStrategy =
          WindowingStrategyTranslation.fromProto(windowingStrategyProto, rehydratedComponents);
    } catch (Exception e) {
      throw new IllegalStateException(
          String.format(
              "Unable to hydrate GroupByKey windowing strategy %s.", windowingStrategyProto),
          e);
    }

    @SuppressWarnings("unchecked")
    WindowingStrategy<?, BoundedWindow> ret =
        (WindowingStrategy<?, BoundedWindow>) windowingStrategy;
    return ret;
  }
@Test
  public void testGetWindowStrategy() throws IOException {
    SdkComponents components = SdkComponents.create();
    String environmentId =
        components.registerEnvironment(Environments.createDockerEnvironment("java"));
    WindowingStrategy<Object, IntervalWindow> expected =
        WindowingStrategy.of(FixedWindows.of(Duration.standardMinutes(1)))
            .withMode(WindowingStrategy.AccumulationMode.DISCARDING_FIRED_PANES)
            .withTimestampCombiner(TimestampCombiner.END_OF_WINDOW)
            .withAllowedLateness(Duration.ZERO)
            .withEnvironmentId(environmentId);
    components.registerWindowingStrategy(expected);
    String collectionId =
        components.registerPCollection(
            PCollection.createPrimitiveOutputInternal(
                    Pipeline.create(), expected, PCollection.IsBounded.BOUNDED, VoidCoder.of())
                .setName("name"));

    WindowingStrategy<?, ?> actual =
        WindowUtils.getWindowStrategy(collectionId, components.toComponents());

    assertEquals(expected, actual);
  }