List<?> apply(
      final GenericRow row,
      final ProcessingLogger processingLogger
  ) {
    final Object[] args = new Object[parameterExtractors.size()];

    for (int i = 0; i < parameterExtractors.size(); i++) {
      args[i] = evalParam(row, processingLogger, i);
    }

    try {
      final List<?> result = tableFunction.apply(args);
      if (result == null) {
        processingLogger.error(RecordProcessingError.recordProcessingError(nullMsg, row));
        return ImmutableList.of();
      }
      return result;
    } catch (final Exception e) {
      processingLogger.error(RecordProcessingError.recordProcessingError(exceptionMsg, e, row));
      return ImmutableList.of();
    }
  }
@Test
  public void shouldLogIfUdtfReturnsNull() {
    // Given:
    when(tableFunction.apply(any())).thenReturn(null);

    // When:
    applier.apply(VALUE, processingLogger);

    // Then:
    verify(processingLogger).error(RecordProcessingError.recordProcessingError(
        "Table function SOME_FUNC returned null. This is invalid. "
            + "Table functions should always return a valid list.",
        VALUE
    ));
  }