@Override
  public UpdateApplicationTimeoutsResponse updateApplicationTimeouts(
      UpdateApplicationTimeoutsRequest request)
      throws YarnException, IOException {
    if (request == null || request.getApplicationId() == null
            || request.getApplicationTimeouts() == null) {
      routerMetrics.incrUpdateApplicationTimeoutsRetrieved();
      String msg = "Missing updateApplicationTimeouts request or applicationId or " +
          "applicationTimeouts information.";
      RouterAuditLogger.logFailure(user.getShortUserName(), UPDATE_APPLICATIONTIMEOUTS, UNKNOWN,
          TARGET_CLIENT_RM_SERVICE, msg);
      RouterServerUtil.logAndThrowException(msg, null);
    }

    long startTime = clock.getTime();
    SubClusterId subClusterId = null;
    ApplicationId applicationId = request.getApplicationId();
    try {
      subClusterId = getApplicationHomeSubCluster(applicationId);
    } catch (YarnException e) {
      routerMetrics.incrFailAppAttemptFailedRetrieved();
      String msg = "Application " + applicationId + " does not exist in FederationStateStore.";
      RouterAuditLogger.logFailure(user.getShortUserName(), UPDATE_APPLICATIONTIMEOUTS, UNKNOWN,
          TARGET_CLIENT_RM_SERVICE, msg);
      RouterServerUtil.logAndThrowException(msg, e);
    }

    ApplicationClientProtocol clientRMProxy = getClientRMProxyForSubCluster(subClusterId);
    UpdateApplicationTimeoutsResponse response = null;
    try {
      response = clientRMProxy.updateApplicationTimeouts(request);
    } catch (Exception e) {
      routerMetrics.incrFailAppAttemptFailedRetrieved();
      String msg = "Unable to update application timeout for " + applicationId +
          " to SubCluster " + subClusterId;
      RouterAuditLogger.logFailure(user.getShortUserName(), UPDATE_APPLICATIONTIMEOUTS, UNKNOWN,
          TARGET_CLIENT_RM_SERVICE, msg);
      RouterServerUtil.logAndThrowException(msg, e);
    }

    if (response == null) {
      LOG.error("No response when update application timeout of " +
          "the applicationId {} to SubCluster {}.",
          applicationId, subClusterId.getId());
    }

    long stopTime = clock.getTime();
    routerMetrics.succeededUpdateAppTimeoutsRetrieved(stopTime - startTime);
    RouterAuditLogger.logSuccess(user.getShortUserName(), UPDATE_APPLICATIONTIMEOUTS,
        TARGET_CLIENT_RM_SERVICE, applicationId, subClusterId);
    return response;
  }
@Test
  public void testUpdateApplicationTimeouts() throws Exception {
    LOG.info("Test FederationClientInterceptor : Update Application Timeouts request.");

    // null request
    LambdaTestUtils.intercept(YarnException.class, "Missing updateApplicationTimeouts request " +
        "or applicationId or applicationTimeouts information.",
        () -> interceptor.updateApplicationTimeouts(null));

    // normal request
    ApplicationId appId = ApplicationId.newInstance(System.currentTimeMillis(), 1);
    SubmitApplicationRequest request = mockSubmitApplicationRequest(appId);

    // Submit the application
    SubmitApplicationResponse response = interceptor.submitApplication(request);

    Assert.assertNotNull(response);
    Assert.assertNotNull(stateStoreUtil.queryApplicationHomeSC(appId));

    SubClusterId subClusterId = interceptor.getApplicationHomeSubCluster(appId);
    Assert.assertNotNull(subClusterId);

    MockRM mockRM = interceptor.getMockRMs().get(subClusterId);
    mockRM.waitForState(appId, RMAppState.ACCEPTED);
    RMApp rmApp = mockRM.getRMContext().getRMApps().get(appId);
    mockRM.waitForState(rmApp.getCurrentAppAttempt().getAppAttemptId(),
        RMAppAttemptState.SCHEDULED);

    // Call GetApplicationAttempts
    GetApplicationAttemptsRequest attemptsRequest =
        GetApplicationAttemptsRequest.newInstance(appId);
    GetApplicationAttemptsResponse attemptsResponse =
        interceptor.getApplicationAttempts(attemptsRequest);
    Assert.assertNotNull(attemptsResponse);

    String appTimeout =
        Times.formatISO8601(System.currentTimeMillis() + 5 * 1000);
    Map<ApplicationTimeoutType, String> applicationTimeouts = new HashMap<>();
    applicationTimeouts.put(ApplicationTimeoutType.LIFETIME, appTimeout);

    UpdateApplicationTimeoutsRequest timeoutsRequest =
        UpdateApplicationTimeoutsRequest.newInstance(appId, applicationTimeouts);
    UpdateApplicationTimeoutsResponse timeoutsResponse =
        interceptor.updateApplicationTimeouts(timeoutsRequest);

    String responseTimeOut =
        timeoutsResponse.getApplicationTimeouts().get(ApplicationTimeoutType.LIFETIME);
    Assert.assertNotNull(timeoutsResponse);
    Assert.assertEquals(appTimeout, responseTimeOut);
  }