Code review comment: ``` String errorJsonMessage =               String.format(                   "{\"message\":\"java.io.IOException was thrown in batch flush: %s\"}",                   elasticResponseExceptionMessage); ``` Revised the error message from containing `org.elasticsearch.client.ResponseException` to `java.io.IOException` since we are now handling things within java.io.IOException.  I am asserting the error message contains `java.io.IOException was thrown in batch flush`. I think this is good enough. The rest of the message comes directly from the exception message originated from es client.

Code under review:
void testWriteWithElasticClientResponseException() throws Exception {
    Write write =
        ElasticsearchIO.write()
            .withConnectionConfiguration(connectionConfiguration)
            .withMaxBatchSize(1000L)
            .withMaxBatchSizeBytes(
                Long.MAX_VALUE) 
            .withThrowWriteErrors(false)
            .withIdFn(new ExtractValueFn("id"))
            .withUseStatefulBatches(true);

    List<String> data =
        ElasticsearchIOTestUtils.createDocuments(
            numDocs, ElasticsearchIOTestUtils.InjectionMode.INJECT_ONE_ID_TOO_LONG_DOC);

    PCollectionTuple outputs = pipeline.apply(Create.of(data)).apply(write);
    PCollection<String> success =
        outputs
            .get(Write.SUCCESSFUL_WRITES)
            .apply("Convert success to input ID", MapElements.via(mapToInputIdString));

    PCollection<String> fail =
        outputs
            .get(Write.FAILED_WRITES)
            .apply("Convert fails to input ID", MapElements.via(mapToInputIdString));

    Set<String> failedIds =
        IntStream.range(0, data.size() - 1).mapToObj(String::valueOf).collect(Collectors.toSet());
    failedIds.add(INVALID_LONG_ID);
    PAssert.that(success).empty();
    PAssert.that(fail).containsInAnyOrder(failedIds);
    pipeline.run();
  }

Line commented on: PAssert.that(fail).containsInAnyOrder(failedIds);

Revised code:
void testWriteWithElasticClientResponseException() throws Exception {
    Write write =
        ElasticsearchIO.write()
            .withConnectionConfiguration(connectionConfiguration)
            .withMaxBatchSize(numDocs + 1)
            .withMaxBatchSizeBytes(
                Long.MAX_VALUE) 
            .withThrowWriteErrors(false)
            .withIdFn(new ExtractValueFn("id"))
            .withUseStatefulBatches(true);

    List<String> data =
        ElasticsearchIOTestUtils.createDocuments(
            numDocs, ElasticsearchIOTestUtils.InjectionMode.INJECT_ONE_ID_TOO_LONG_DOC);

    PCollectionTuple outputs = pipeline.apply(Create.of(data)).apply(write);

    
    PCollection<String> success =
        outputs
            .get(Write.SUCCESSFUL_WRITES)
            .apply("Convert success to input ID", MapElements.via(mapToInputIdString));

    PCollection<String> fail =
        outputs
            .get(Write.FAILED_WRITES)
            .apply("Convert fails to input ID", MapElements.via(mapToInputIdString));

    Set<String> failedIds =
        IntStream.range(0, data.size() - 1).mapToObj(String::valueOf).collect(Collectors.toSet());
    failedIds.add(INVALID_LONG_ID);
    PAssert.that(success).empty();
    PAssert.that(fail).containsInAnyOrder(failedIds);

    
    PAssert.that(outputs.get(Write.FAILED_WRITES))
        .satisfies(responseItemJsonSubstringValidator("java.io.IOException"));
    pipeline.run();
  }