public static <FnT extends DoFn<?, ?>> DoFnSignature getSignature(Class<FnT> fn) {
    return signatureCache.computeIfAbsent(fn, DoFnSignatures::parseSignature);
  }
@Test
  public void testOnWindowExpirationDisallowedParameter() throws Exception {
    // Timers are not allowed in OnWindowExpiration
    thrown.expect(IllegalArgumentException.class);
    thrown.expectMessage("Illegal parameter type");
    thrown.expectMessage("TimerParameter");
    thrown.expectMessage("myTimer");
    DoFnSignatures.getSignature(
        new DoFn<String, String>() {

          @TimerId("foo")
          private final TimerSpec myTimer = TimerSpecs.timer(TimeDomain.EVENT_TIME);

          @ProcessElement
          public void foo() {}

          @OnTimer("foo")
          public void onFoo() {}

          @OnWindowExpiration
          public void bar(@TimerId("foo") Timer t) {}
        }.getClass());
  }