This is an automated email from the ASF dual-hosted git repository.

pvillard31 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/main by this push:
     new 851de8d838b NIFI-16546 Deprecated ConsumeKinesisStream for Removal 
(#11889)
851de8d838b is described below

commit 851de8d838bdbfe33c179351c573ca98165d9a86
Author: David Handermann <[email protected]>
AuthorDate: Mon Nov 9 03:19:50 2026 -0600

    NIFI-16546 Deprecated ConsumeKinesisStream for Removal (#11889)
    
    - Removed KCL references from Logback configuration
    - Removed Integration Test for ConsumeKinesisStream
    - Removed unit tests for subcomponents of ConsumeKinesisStream
---
 .../nifi/processors/aws/AbstractAwsProcessor.java  |   6 +-
 .../aws/kinesis/stream/ConsumeKinesisStream.java   |   5 +
 .../aws/kinesis/stream/PutKinesisStream.java       |   2 +-
 .../additionalDetails.md                           |  46 --
 .../aws/kinesis/stream/ITConsumeKinesisStream.java | 149 ------
 .../kinesis/stream/TestConsumeKinesisStream.java   |   2 +-
 .../pause/TestStandardRecordProcessorBlocker.java  | 205 --------
 .../record/TestAbstractKinesisRecordProcessor.java | 200 --------
 .../record/TestKinesisRecordProcessorRaw.java      | 245 ----------
 .../record/TestKinesisRecordProcessorRecord.java   | 530 ---------------------
 .../src/main/resources/conf/logback.xml            |   3 -
 .../src/main/resources/conf/stateless-logback.xml  |   3 -
 .../resources/conf/clustered/node1/logback.xml     |   3 -
 .../resources/conf/clustered/node2/logback.xml     |   3 -
 .../src/test/resources/conf/default/logback.xml    |   3 -
 .../src/test/resources/conf/pythonic/logback.xml   |   3 -
 16 files changed, 9 insertions(+), 1399 deletions(-)

diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/src/main/java/org/apache/nifi/processors/aws/AbstractAwsProcessor.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/src/main/java/org/apache/nifi/processors/aws/AbstractAwsProcessor.java
index a0dd073dd13..1024b525d82 100644
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/src/main/java/org/apache/nifi/processors/aws/AbstractAwsProcessor.java
+++ 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-abstract-processors/src/main/java/org/apache/nifi/processors/aws/AbstractAwsProcessor.java
@@ -156,10 +156,8 @@ public abstract class AbstractAwsProcessor<C extends 
AwsClient, B extends AwsCli
      */
     protected abstract void configureHttpClient(AwsClientBuilder<?, ?> 
clientBuilder, ProcessContext context);
 
-    /*
-     * Allow optional override of onTrigger with the ProcessSessionFactory 
where required for AWS processors (e.g. ConsumeKinesisStream)
-     *
-     * @see AbstractProcessor
+    /**
+     * Allow optional override of onTrigger with the ProcessSessionFactory 
where required for AWS processors
      */
     @Override
     public void onTrigger(final ProcessContext context, final 
ProcessSessionFactory sessionFactory) throws ProcessException {
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/kinesis/stream/ConsumeKinesisStream.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/kinesis/stream/ConsumeKinesisStream.java
index 54660873fb2..8afa3320b19 100644
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/kinesis/stream/ConsumeKinesisStream.java
+++ 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/kinesis/stream/ConsumeKinesisStream.java
@@ -32,6 +32,7 @@ import 
org.apache.nifi.annotation.behavior.TriggerWhenAnyDestinationAvailable;
 import org.apache.nifi.annotation.behavior.WritesAttribute;
 import org.apache.nifi.annotation.behavior.WritesAttributes;
 import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.DeprecationNotice;
 import org.apache.nifi.annotation.documentation.SeeAlso;
 import org.apache.nifi.annotation.documentation.Tags;
 import org.apache.nifi.annotation.lifecycle.OnScheduled;
@@ -160,6 +161,10 @@ import static 
org.apache.nifi.processors.aws.region.RegionUtil.getRegion;
 @SystemResourceConsideration(resource = SystemResource.NETWORK, description = 
"Kinesis Client Library will continually poll for new Records, " +
         "requesting up to a maximum number of Records/bytes per call. This can 
result in sustained network usage.")
 @SeeAlso(PutKinesisStream.class)
+@DeprecationNotice(
+        reason = "NIFI-16546: Depends on the AWS Kinesis Client Library 
requiring buffering and locking outside of framework flow control",
+        classNames = {"org.apache.nifi.processors.aws.kinesis.ConsumeKinesis"}
+)
 public class ConsumeKinesisStream extends 
AbstractAwsAsyncProcessor<KinesisAsyncClient, KinesisAsyncClientBuilder> {
 
     private static final int INITIAL_WINDOW_SIZE_BYTES = 512 * 1024; // 512 KB 
- suggested by KinesisClientUtil
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/kinesis/stream/PutKinesisStream.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/kinesis/stream/PutKinesisStream.java
index b9aeb2a03ac..6f42d6b87c9 100644
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/kinesis/stream/PutKinesisStream.java
+++ 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/java/org/apache/nifi/processors/aws/kinesis/stream/PutKinesisStream.java
@@ -63,7 +63,7 @@ import static 
org.apache.nifi.processors.aws.region.RegionUtil.REGION;
     @WritesAttribute(attribute = "aws.kinesis.error.code", description = 
"Error code for the message when posting to AWS Kinesis"),
     @WritesAttribute(attribute = "aws.kinesis.sequence.number", description = 
"Sequence number for the message when posting to AWS Kinesis"),
     @WritesAttribute(attribute = "aws.kinesis.shard.id", description = "Shard 
id of the message posted to AWS Kinesis")})
-@SeeAlso(ConsumeKinesisStream.class)
+@SeeAlso(classNames = 
{"org.apache.nifi.processors.aws.kinesis.ConsumeKinesis"})
 public class PutKinesisStream extends AbstractAwsSyncProcessor<KinesisClient, 
KinesisClientBuilder> {
     /**
      * Kinesis put record response error message
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/resources/docs/org.apache.nifi.processors.aws.kinesis.stream.ConsumeKinesisStream/additionalDetails.md
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/resources/docs/org.apache.nifi.processors.aws.kinesis.stream.ConsumeKinesisStream/additionalDetails.md
deleted file mode 100644
index 3f310ec0bb0..00000000000
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/main/resources/docs/org.apache.nifi.processors.aws.kinesis.stream.ConsumeKinesisStream/additionalDetails.md
+++ /dev/null
@@ -1,46 +0,0 @@
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
-      http://www.apache.org/licenses/LICENSE-2.0
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
-
-# ConsumeKinesisStream
-
-## Streaming Versus Batch Processing
-
-ConsumeKinesisStream retrieves all Kinesis Records that it encounters in the 
configured Kinesis Stream. There are two
-common, broadly defined use cases.
-
-### Per-Message Use Case
-
-By default, the Processor will create a separate FlowFile for each Kinesis 
Record (message) in the Stream and add
-attributes for shard id, sequence number, etc.
-
-### Per-Batch Use Case
-
-Another common use case is the desire to process all Kinesis Records retrieved 
from the Stream in a batch as a single
-FlowFile.
-
-The ConsumeKinesisStream Processor can optionally be configured with a Record 
Reader and Record Writer. When a Record
-Reader and Record Writer are configured, a single FlowFile will be created 
that will contain a Record for each Record
-within the batch of Kinesis Records (messages), instead of a separate FlowFile 
per Kinesis Record.
-
-The FlowFiles emitted in this mode will include the standard `record.*` 
attributes along with the same Kinesis Shard ID,
-Sequence Number and Approximate Arrival Timestamp; but the values will relate 
to the **last** Kinesis Record that was
-processed in the batch of messages constituting the content of the FlowFile.
-
-Once a Record Writer is set the Output Strategy can be set to `Use Wrapper` or 
`Use Content`. When `Use Wrapper` is 
-picked the original content of the Kinesis Record will be wrapped under 
`value` key and an additional `metadata`
-key will be populated with Stream Name, Shard ID, Partition Key, Sequence 
Number, Sub Sequence Number, Approximate 
-Arrival Timestamp and a Sharded Sequence Number that is a concatenation of 
Sequence and Sub Sequence Numbers that allows
-a single comparison record ordering. 
-When `Use Content` is picked the original content of the Kinesis Record will 
be used as is.
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/ITConsumeKinesisStream.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/ITConsumeKinesisStream.java
deleted file mode 100644
index 1c8786bc85a..00000000000
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/ITConsumeKinesisStream.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.processors.aws.kinesis.stream;
-
-import 
org.apache.nifi.processors.aws.kinesis.stream.record.AbstractKinesisRecordProcessor;
-import org.apache.nifi.util.MockFlowFile;
-import org.apache.nifi.util.TestRunner;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Test;
-import software.amazon.awssdk.core.SdkBytes;
-import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
-import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
-import software.amazon.awssdk.services.dynamodb.model.ListTablesResponse;
-import software.amazon.awssdk.services.kinesis.KinesisClient;
-import software.amazon.awssdk.services.kinesis.model.DeleteStreamRequest;
-import software.amazon.awssdk.services.kinesis.model.ListStreamsResponse;
-import software.amazon.awssdk.services.kinesis.model.PutRecordRequest;
-import software.amazon.kinesis.common.InitialPositionInStream;
-
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.List;
-import java.util.concurrent.Executors;
-
-public abstract class ITConsumeKinesisStream {
-
-    static final String KINESIS_STREAM_NAME = "test-stream";
-    static final String APPLICATION_NAME = "test-application";
-
-    protected TestRunner runner;
-
-    KinesisClient kinesis;
-    DynamoDbClient dynamoDB;
-
-    @Test
-    public void readHorizon() throws InterruptedException, IOException {
-        String partitionKey = "1";
-
-        final PutRecordRequest request = PutRecordRequest.builder()
-                .streamName(KINESIS_STREAM_NAME)
-                .data(SdkBytes.fromString("horizon", Charset.defaultCharset()))
-                .partitionKey(partitionKey)
-                .build();
-        kinesis.putRecord(request);
-
-        startKCL(runner, InitialPositionInStream.TRIM_HORIZON);
-
-        runner.assertAllFlowFilesTransferred(ConsumeKinesisStream.REL_SUCCESS, 
1);
-
-        final List<MockFlowFile> ffs = 
runner.getFlowFilesForRelationship(PutKinesisStream.REL_SUCCESS);
-        final MockFlowFile out = ffs.iterator().next();
-
-        
out.assertAttributeEquals(AbstractKinesisRecordProcessor.AWS_KINESIS_PARTITION_KEY,
 partitionKey);
-
-        out.assertContentEquals("horizon".getBytes());
-    }
-
-    @Test
-    public void readLatest() throws InterruptedException, IOException {
-        String partitionKey = "1";
-
-        final PutRecordRequest request = PutRecordRequest.builder()
-                .streamName(KINESIS_STREAM_NAME)
-                .data(SdkBytes.fromString("horizon", Charset.defaultCharset()))
-                .partitionKey(partitionKey)
-                .build();
-        kinesis.putRecord(request);
-
-        startKCL(runner, InitialPositionInStream.LATEST);
-
-        final PutRecordRequest request2 = PutRecordRequest.builder()
-                .streamName(KINESIS_STREAM_NAME)
-                .data(SdkBytes.fromString("latest", Charset.defaultCharset()))
-                .partitionKey(partitionKey)
-                .build();
-        kinesis.putRecord(request2);
-
-        waitForKCLToProcessTheLatestMessage();
-
-        runner.assertAllFlowFilesTransferred(ConsumeKinesisStream.REL_SUCCESS, 
1);
-
-        final List<MockFlowFile> ffs = 
runner.getFlowFilesForRelationship(PutKinesisStream.REL_SUCCESS);
-        final MockFlowFile out = ffs.iterator().next();
-
-        
out.assertAttributeEquals(AbstractKinesisRecordProcessor.AWS_KINESIS_PARTITION_KEY,
 partitionKey);
-
-        out.assertContentEquals("latest".getBytes());
-    }
-
-    private void waitForKCLToProcessTheLatestMessage() throws 
InterruptedException {
-        Thread.sleep(10_000);
-    }
-
-    private void startKCL(TestRunner runner, InitialPositionInStream 
initialPositionInStream) throws InterruptedException {
-        runner.setProperty(ConsumeKinesisStream.INITIAL_STREAM_POSITION, 
initialPositionInStream.name());
-
-        runner.assertValid();
-
-        Executors.newSingleThreadScheduledExecutor().submit((Runnable) 
runner::run);
-
-        Thread.sleep(30_000);
-    }
-
-    @AfterEach
-    public void tearDown() throws InterruptedException {
-        cleanupKinesis();
-        cleanupDynamoDB();
-
-        runner = null;
-
-        Thread.sleep(2_000);
-    }
-
-    private void cleanupDynamoDB() {
-        if (dynamoDB != null) {
-            ListTablesResponse tableResults = dynamoDB.listTables();
-            List<String> tableName = tableResults.tableNames();
-            if (tableName.contains(APPLICATION_NAME)) {
-                
dynamoDB.deleteTable(DeleteTableRequest.builder().tableName(APPLICATION_NAME).build());
-            }
-        }
-        dynamoDB = null;
-    }
-
-    private void cleanupKinesis() {
-        if (kinesis != null) {
-            final ListStreamsResponse streamsResult = kinesis.listStreams();
-            List<String> streamNames = streamsResult.streamNames();
-            if (streamNames.contains(KINESIS_STREAM_NAME)) {
-                
kinesis.deleteStream(DeleteStreamRequest.builder().streamName(KINESIS_STREAM_NAME).build());
-            }
-        }
-        kinesis = null;
-    }
-}
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/TestConsumeKinesisStream.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/TestConsumeKinesisStream.java
index e937c9b786c..40e0758efaf 100644
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/TestConsumeKinesisStream.java
+++ 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/TestConsumeKinesisStream.java
@@ -316,7 +316,7 @@ public class TestConsumeKinesisStream {
 
     /*
      * Trigger a run of the ConsumeKinesisStream processor, but expect the KCL 
Worker to fail (it needs connections to AWS resources)
-     * Assert that our code is being called by checking log output. The 
ITConsumeKinesisStream integration tests prove actual AWS connectivity
+     * Assert that our code is being called by checking log output.
      */
     private void runWorker(final boolean withCredentials, final boolean 
waitForFailure) throws UnknownHostException, InitializationException, 
InterruptedException {
         final TestRunner mockConsumeKinesisStreamRunner = 
TestRunners.newTestRunner(MockConsumeKinesisStream.class);
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/pause/TestStandardRecordProcessorBlocker.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/pause/TestStandardRecordProcessorBlocker.java
deleted file mode 100644
index 592aecacf6f..00000000000
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/pause/TestStandardRecordProcessorBlocker.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.processors.aws.kinesis.stream.pause;
-
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-
-import java.time.Duration;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Supplier;
-
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-public class TestStandardRecordProcessorBlocker {
-
-    @Nested
-    class ExplicitBlock {
-
-        @Test
-        public void testBlockAndUnblock() {
-            final TestThreadInspector blockerInspector = new 
TestThreadInspector();
-
-            final StandardRecordProcessorBlocker recordProcessorBlocker = 
StandardRecordProcessorBlocker.create();
-
-            recordProcessorBlocker.block();
-            final Thread thread = new 
Thread(createRunnableWithInspector(recordProcessorBlocker, blockerInspector));
-            thread.start();
-
-            blockerInspector.awaitBlockAwaited();
-            assertTrue(thread.isAlive());
-
-            blockerInspector.awaitThreadParked(thread);
-            recordProcessorBlocker.unblock();
-            blockerInspector.awaitBlockExited();
-        }
-
-        @Test
-        public void testNoBlock() {
-            final TestThreadInspector blockerInspector = new 
TestThreadInspector();
-
-            final StandardRecordProcessorBlocker recordProcessorBlocker = 
StandardRecordProcessorBlocker.create();
-
-            recordProcessorBlocker.unblock();
-            final Thread thread = new 
Thread(createRunnableWithInspector(recordProcessorBlocker, blockerInspector));
-            thread.start();
-
-            blockerInspector.awaitBlockExited();
-        }
-
-        @Test
-        public void testBlock() {
-            final TestThreadInspector blockerInspector = new 
TestThreadInspector();
-
-            final StandardRecordProcessorBlocker recordProcessorBlocker = 
StandardRecordProcessorBlocker.create();
-            recordProcessorBlocker.block();
-            final Thread thread = new 
Thread(createRunnableWithInspector(recordProcessorBlocker, blockerInspector));
-            thread.start();
-
-            blockerInspector.awaitBlockAwaited();
-            assertTrue(thread.isAlive());
-
-            recordProcessorBlocker.unblock();
-        }
-    }
-
-    @Nested
-    class TimeoutBlock {
-
-        final AtomicLong currentTimeMillis = new AtomicLong();
-
-        @Test
-        public void testBlockAndUnblock() {
-            final TestThreadInspector blockerInspector = new 
TestThreadInspector();
-
-            final StandardRecordProcessorBlocker recordProcessorBlocker = new 
StandardRecordProcessorBlocker(currentTimeMillis::get);
-
-            currentTimeMillis.set(0L);
-            recordProcessorBlocker.unblock();
-            
currentTimeMillis.addAndGet(StandardRecordProcessorBlocker.BLOCK_AFTER_DURATION.toMillis()
 + 1);
-            final Thread thread = new 
Thread(createRunnableWithInspector(recordProcessorBlocker, blockerInspector));
-            thread.start();
-
-            blockerInspector.awaitBlockAwaited();
-            assertTrue(thread.isAlive());
-
-            blockerInspector.awaitThreadParked(thread);
-            recordProcessorBlocker.unblock();
-            blockerInspector.awaitBlockExited();
-        }
-
-        @Test
-        public void testNoBlock() {
-            final TestThreadInspector blockerInspector = new 
TestThreadInspector();
-
-            final StandardRecordProcessorBlocker recordProcessorBlocker = new 
StandardRecordProcessorBlocker(currentTimeMillis::get);
-
-            currentTimeMillis.set(0L);
-            recordProcessorBlocker.unblock();
-            
currentTimeMillis.addAndGet(StandardRecordProcessorBlocker.BLOCK_AFTER_DURATION.toMillis());
-            final Thread thread = new 
Thread(createRunnableWithInspector(recordProcessorBlocker, blockerInspector));
-            thread.start();
-
-            blockerInspector.awaitBlockExited();
-        }
-
-        @Test
-        public void testNoBlockAfterClose() {
-            final TestThreadInspector blockerInspector = new 
TestThreadInspector();
-
-            final StandardRecordProcessorBlocker recordProcessorBlocker = new 
StandardRecordProcessorBlocker(currentTimeMillis::get);
-
-            recordProcessorBlocker.unblock();
-            recordProcessorBlocker.unblockIndefinitely();
-            currentTimeMillis.set(Long.MAX_VALUE);
-            final Thread thread = new 
Thread(createRunnableWithInspector(recordProcessorBlocker, blockerInspector));
-            thread.start();
-
-            blockerInspector.awaitBlockExited();
-        }
-
-        @Test
-        public void testBlock() {
-            final TestThreadInspector blockerInspector = new 
TestThreadInspector();
-
-            final StandardRecordProcessorBlocker recordProcessorBlocker = new 
StandardRecordProcessorBlocker(currentTimeMillis::get);
-            currentTimeMillis.set(0L);
-            recordProcessorBlocker.unblock();
-            
currentTimeMillis.addAndGet(StandardRecordProcessorBlocker.BLOCK_AFTER_DURATION.toMillis()
 + 1);
-            final Thread thread = new 
Thread(createRunnableWithInspector(recordProcessorBlocker, blockerInspector));
-            thread.start();
-
-            blockerInspector.awaitBlockAwaited();
-            assertTrue(thread.isAlive());
-
-            recordProcessorBlocker.unblock();
-        }
-    }
-
-    private static Runnable createRunnableWithInspector(final 
StandardRecordProcessorBlocker recordProcessorBlocker, TestThreadInspector 
blockerInspector) {
-        return () -> {
-            try {
-                blockerInspector.onBlockAwaited();
-                recordProcessorBlocker.await();
-            } catch (final InterruptedException e) {
-                throw new RuntimeException(e);
-            } finally {
-                blockerInspector.onBlockExited();
-            }
-        };
-    }
-
-    private static class TestThreadInspector {
-        private static final Duration BUSY_WAIT_MAX_DURATION = 
Duration.ofSeconds(5);
-        private volatile boolean blockAwaited = false;
-        private volatile boolean blockExited = false;
-
-        public void onBlockAwaited() {
-            blockAwaited = true;
-        }
-
-        public void onBlockExited() {
-            blockExited = true;
-        }
-
-        public void awaitBlockAwaited() {
-            busyWait(() -> !blockAwaited);
-        }
-
-        public void awaitBlockExited() {
-            busyWait(() -> !blockExited);
-        }
-
-        public void awaitThreadParked(final Thread thread) {
-            busyWait(() -> thread.getState() != Thread.State.WAITING);
-        }
-
-        private void busyWait(final Supplier<Boolean> condition) {
-            final long maxWait = System.currentTimeMillis() + 
BUSY_WAIT_MAX_DURATION.toMillis();
-            do {
-                if (System.currentTimeMillis() > maxWait) {
-                    throw new RuntimeException("Timed out waiting for 
condition");
-                }
-                try {
-                    Thread.sleep(10L); // Sleep to avoid busy waiting too 
aggressively
-                } catch (final InterruptedException e) {
-                    throw new RuntimeException("Thread interrupted while 
waiting for condition", e);
-                }
-            } while (condition.get());
-        }
-    }
-}
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/record/TestAbstractKinesisRecordProcessor.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/record/TestAbstractKinesisRecordProcessor.java
deleted file mode 100644
index c6fca27f008..00000000000
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/record/TestAbstractKinesisRecordProcessor.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.processors.aws.kinesis.stream.record;
-
-import org.apache.nifi.processor.ProcessSessionFactory;
-import org.apache.nifi.processors.aws.kinesis.stream.ConsumeKinesisStream;
-import 
org.apache.nifi.processors.aws.kinesis.stream.pause.StandardRecordProcessorBlocker;
-import org.apache.nifi.util.MockProcessSession;
-import org.apache.nifi.util.SharedSessionState;
-import org.apache.nifi.util.TestRunner;
-import org.apache.nifi.util.TestRunners;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import software.amazon.kinesis.common.InitialPositionInStream;
-import software.amazon.kinesis.exceptions.InvalidStateException;
-import software.amazon.kinesis.exceptions.ShutdownException;
-import software.amazon.kinesis.exceptions.ThrottlingException;
-import software.amazon.kinesis.lifecycle.events.InitializationInput;
-import software.amazon.kinesis.lifecycle.events.ShutdownRequestedInput;
-import software.amazon.kinesis.processor.RecordProcessorCheckpointer;
-import software.amazon.kinesis.retrieval.KinesisClientRecord;
-import software.amazon.kinesis.retrieval.kpl.ExtendedSequenceNumber;
-
-import java.time.format.DateTimeFormatter;
-import java.util.concurrent.atomic.AtomicLong;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-public class TestAbstractKinesisRecordProcessor {
-    private static final DateTimeFormatter DATE_TIME_FORMATTER = 
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
-    private static final StandardRecordProcessorBlocker 
NOOP_RECORD_PROCESSOR_BLOCKER = StandardRecordProcessorBlocker.create();
-
-    private final TestRunner runner = 
TestRunners.newTestRunner(ConsumeKinesisStream.class);
-
-    private final ProcessSessionFactory processSessionFactory = 
mock(ProcessSessionFactory.class);
-
-    private final MockProcessSession session = new MockProcessSession(new 
SharedSessionState(runner.getProcessor(), new AtomicLong(0)), 
runner.getProcessor());
-    private AbstractKinesisRecordProcessor fixture;
-    private final RecordProcessorCheckpointer checkpointer = 
mock(RecordProcessorCheckpointer.class);
-
-    private final KinesisClientRecord kinesisRecord = 
mock(KinesisClientRecord.class);
-
-    @BeforeEach
-    public void setUp() {
-        NOOP_RECORD_PROCESSOR_BLOCKER.unblockIndefinitely();
-        when(processSessionFactory.createSession()).thenReturn(session);
-
-        // default test fixture will try operations twice with very little 
wait in between
-        fixture = new AbstractKinesisRecordProcessor(processSessionFactory, 
runner.getLogger(), "kinesis-test",
-                "endpoint-prefix", null, 10_000L, 1L, 2, DATE_TIME_FORMATTER, 
NOOP_RECORD_PROCESSOR_BLOCKER) {
-            @Override
-            void processRecord(KinesisClientRecord kinesisRecord, 
BatchProcessingContext batchProcessingContext) {
-                // intentionally blank
-            }
-        };
-    }
-
-    @AfterEach
-    public void tearDown() {
-        verifyNoMoreInteractions(checkpointer, kinesisRecord, 
processSessionFactory);
-        reset(checkpointer, kinesisRecord, processSessionFactory);
-    }
-
-    @Test
-    public void testInitialisation() {
-        final ExtendedSequenceNumber esn = new 
ExtendedSequenceNumber(InitialPositionInStream.AT_TIMESTAMP.toString(), 123L);
-        final InitializationInput initializationInput = 
InitializationInput.builder()
-                .extendedSequenceNumber(esn)
-                .shardId("shard-id")
-                .build();
-
-        fixture.initialize(initializationInput);
-
-        assertTrue(fixture.getNextCheckpointTimeInMillis() > 
System.currentTimeMillis());
-        assertEquals("shard-id", fixture.getKinesisShardId());
-    }
-
-    @Test
-    public void testInitialisationWithPendingCheckpoint() {
-        final ExtendedSequenceNumber esn = new 
ExtendedSequenceNumber(InitialPositionInStream.AT_TIMESTAMP.toString(), 123L);
-        final ExtendedSequenceNumber prev = new 
ExtendedSequenceNumber(InitialPositionInStream.LATEST.toString(), 456L);
-        final InitializationInput initializationInput = 
InitializationInput.builder()
-                .extendedSequenceNumber(esn)
-                .pendingCheckpointSequenceNumber(prev)
-                .shardId("shard-id")
-                .build();
-
-        fixture.initialize(initializationInput);
-
-        assertTrue(fixture.getNextCheckpointTimeInMillis() > 
System.currentTimeMillis());
-        assertEquals("shard-id", fixture.getKinesisShardId());
-    }
-
-    @Test
-    public void testShutdown() throws InvalidStateException, ShutdownException 
{
-        final ShutdownRequestedInput shutdownInput = 
ShutdownRequestedInput.builder()
-                .checkpointer(checkpointer)
-                .build();
-
-        fixture.setKinesisShardId("test-shard");
-        fixture.shutdownRequested(shutdownInput);
-
-        verify(checkpointer, times(1)).checkpoint();
-    }
-
-    @Test
-    public void testShutdownWithThrottlingFailures() throws 
InvalidStateException, ShutdownException {
-        final ShutdownRequestedInput shutdownInput = 
ShutdownRequestedInput.builder()
-                .checkpointer(checkpointer)
-                .build();
-
-        doThrow(new 
ThrottlingException("throttled")).when(checkpointer).checkpoint();
-
-        fixture.shutdownRequested(shutdownInput);
-
-        verify(checkpointer, times(2)).checkpoint();
-    }
-
-    @Test
-    public void testShutdownWithShutdownFailure() throws 
InvalidStateException, ShutdownException {
-        final ShutdownRequestedInput shutdownInput = 
ShutdownRequestedInput.builder()
-                .checkpointer(checkpointer)
-                .build();
-
-        doThrow(new 
ShutdownException("shutdown")).when(checkpointer).checkpoint();
-
-        fixture.shutdownRequested(shutdownInput);
-
-        verify(checkpointer, times(1)).checkpoint();
-    }
-
-    @Test
-    public void testShutdownWithInvalidStateFailure() throws 
InvalidStateException, ShutdownException {
-        final ShutdownRequestedInput shutdownInput = 
ShutdownRequestedInput.builder()
-                .checkpointer(checkpointer)
-                .build();
-
-        doThrow(new InvalidStateException("invalid 
state")).when(checkpointer).checkpoint();
-
-        fixture.shutdownRequested(shutdownInput);
-
-        verify(checkpointer, times(1)).checkpoint();
-
-        assertFalse(runner.getLogger().getErrorMessages().isEmpty());
-    }
-
-    @Test
-    public void testShutdownTerminateRecordsNotProcessing() throws 
InvalidStateException, ShutdownException {
-        final ShutdownRequestedInput shutdownInput = 
ShutdownRequestedInput.builder()
-                .checkpointer(checkpointer)
-                .build();
-
-        fixture.setKinesisShardId("test-shard");
-        fixture.setProcessingRecords(false);
-        fixture.shutdownRequested(shutdownInput);
-
-        verify(checkpointer, times(1)).checkpoint();
-
-        assertTrue(runner.getLogger().getWarnMessages().isEmpty());
-    }
-
-    @Test
-    public void testShutdownTerminateRecordsProcessing() throws 
InvalidStateException, ShutdownException {
-        final ShutdownRequestedInput shutdownInput = 
ShutdownRequestedInput.builder()
-                .checkpointer(checkpointer)
-                .build();
-
-        fixture.setKinesisShardId("test-shard");
-        fixture.setProcessingRecords(true);
-        fixture.shutdownRequested(shutdownInput);
-
-        verify(checkpointer, times(1)).checkpoint();
-
-        assertFalse(runner.getLogger().getWarnMessages().isEmpty());
-    }
-}
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/record/TestKinesisRecordProcessorRaw.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/record/TestKinesisRecordProcessorRaw.java
deleted file mode 100644
index fe4c68357c5..00000000000
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/record/TestKinesisRecordProcessorRaw.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.processors.aws.kinesis.stream.record;
-
-import org.apache.nifi.processor.ProcessSessionFactory;
-import org.apache.nifi.processors.aws.kinesis.stream.ConsumeKinesisStream;
-import 
org.apache.nifi.processors.aws.kinesis.stream.pause.StandardRecordProcessorBlocker;
-import org.apache.nifi.util.MockFlowFile;
-import org.apache.nifi.util.MockProcessSession;
-import org.apache.nifi.util.SharedSessionState;
-import org.apache.nifi.util.TestRunner;
-import org.apache.nifi.util.TestRunners;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-import software.amazon.kinesis.exceptions.InvalidStateException;
-import software.amazon.kinesis.exceptions.ShutdownException;
-import software.amazon.kinesis.lifecycle.events.ProcessRecordsInput;
-import software.amazon.kinesis.processor.RecordProcessorCheckpointer;
-import software.amazon.kinesis.retrieval.KinesisClientRecord;
-
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.time.Instant;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.temporal.ChronoUnit;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicLong;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-public class TestKinesisRecordProcessorRaw {
-    private static final DateTimeFormatter DATE_TIME_FORMATTER = 
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
-    private static final StandardRecordProcessorBlocker 
NOOP_RECORD_PROCESSOR_BLOCKER = StandardRecordProcessorBlocker.create();
-
-    private final TestRunner runner = 
TestRunners.newTestRunner(ConsumeKinesisStream.class);
-
-    private final ProcessSessionFactory processSessionFactory = 
mock(ProcessSessionFactory.class);
-
-    private final SharedSessionState sharedState = new 
SharedSessionState(runner.getProcessor(), new AtomicLong(0));
-    private final MockProcessSession session = new 
MockProcessSession(sharedState, runner.getProcessor());
-
-    private AbstractKinesisRecordProcessor fixture;
-
-    @Mock
-    private final RecordProcessorCheckpointer checkpointer = 
mock(RecordProcessorCheckpointer.class);
-
-    @Mock
-    private final KinesisClientRecord kinesisRecord = 
mock(KinesisClientRecord.class);
-
-    @BeforeEach
-    public void setUp() {
-        NOOP_RECORD_PROCESSOR_BLOCKER.unblockIndefinitely();
-        // default test fixture will try operations twice with very little 
wait in between
-        fixture = new KinesisRecordProcessorRaw(processSessionFactory, 
runner.getLogger(), "kinesis-test",
-                "endpoint-prefix", null, 10_000L, 1L, 2, DATE_TIME_FORMATTER, 
NOOP_RECORD_PROCESSOR_BLOCKER);
-    }
-
-    @AfterEach
-    public void tearDown() {
-        verifyNoMoreInteractions(checkpointer, kinesisRecord, 
processSessionFactory);
-        reset(checkpointer, kinesisRecord, processSessionFactory);
-    }
-
-    @Test
-    public void testProcessRecordsEmpty() {
-        final ProcessRecordsInput processRecordsInput = 
ProcessRecordsInput.builder()
-                .records(Collections.emptyList())
-                .checkpointer(checkpointer)
-                .cacheEntryTime(Instant.now().minus(1, ChronoUnit.MINUTES))
-                .cacheExitTime(Instant.now().minus(1, ChronoUnit.SECONDS))
-                .millisBehindLatest(100L)
-                .build();
-
-        // would checkpoint (but should skip because there are no records 
processed)
-        fixture.setNextCheckpointTimeInMillis(System.currentTimeMillis() - 
10_000L);
-
-        fixture.processRecords(processRecordsInput);
-
-        session.assertTransferCount(ConsumeKinesisStream.REL_SUCCESS, 0);
-        assertEquals(0, sharedState.getProvenanceEvents().size());
-        session.assertNotCommitted();
-        session.assertNotRolledBack();
-    }
-
-    @Test
-    public void testProcessRecordsNoCheckpoint() {
-        processMultipleRecordsAssertProvenance(false);
-    }
-
-    @Test
-    public void testProcessRecordsWithEndpointOverride() {
-        processMultipleRecordsAssertProvenance(true);
-    }
-
-    private void processMultipleRecordsAssertProvenance(final boolean 
endpointOverridden) {
-        final Date firstDate = Date.from(Instant.now().minus(1, 
ChronoUnit.MINUTES));
-        final Date secondDate = new Date();
-
-        final ProcessRecordsInput processRecordsInput = 
ProcessRecordsInput.builder()
-                .records(Arrays.asList(
-                        
KinesisClientRecord.builder().approximateArrivalTimestamp(firstDate.toInstant())
-                                .partitionKey("partition-1")
-                                .sequenceNumber("1")
-                                
.data(ByteBuffer.wrap("record-1".getBytes(StandardCharsets.UTF_8)))
-                                .build(),
-                        
KinesisClientRecord.builder().approximateArrivalTimestamp(secondDate.toInstant())
-                                .partitionKey("partition-2")
-                                .sequenceNumber("2")
-                                
.data(ByteBuffer.wrap("record-2".getBytes(StandardCharsets.UTF_8)))
-                                .build(),
-                        
KinesisClientRecord.builder().approximateArrivalTimestamp(null)
-                                .partitionKey("partition-no-date")
-                                .sequenceNumber("no-date")
-                                
.data(ByteBuffer.wrap("record-no-date".getBytes(StandardCharsets.UTF_8)))
-                                .build()
-                ))
-                .checkpointer(checkpointer)
-                .cacheEntryTime(null)
-                .cacheExitTime(null)
-                .millisBehindLatest(null)
-                .build();
-
-        final String transitUriPrefix = endpointOverridden ? 
"https://another-endpoint.com:8443"; : "http://endpoint-prefix.amazonaws.com";;
-        if (endpointOverridden) {
-            fixture = new KinesisRecordProcessorRaw(processSessionFactory, 
runner.getLogger(), "kinesis-test",
-                    "endpoint-prefix", "https://another-endpoint.com:8443";, 
10_000L, 1L, 2, DATE_TIME_FORMATTER, NOOP_RECORD_PROCESSOR_BLOCKER);
-        }
-
-        // skip checkpoint
-        fixture.setNextCheckpointTimeInMillis(System.currentTimeMillis() + 
10_000L);
-        fixture.setKinesisShardId("test-shard");
-
-        when(processSessionFactory.createSession()).thenReturn(session);
-        fixture.processRecords(processRecordsInput);
-        verify(processSessionFactory, times(1)).createSession();
-
-        session.assertTransferCount(ConsumeKinesisStream.REL_SUCCESS, 
processRecordsInput.records().size());
-        assertEquals(sharedState.getProvenanceEvents().size(), 
processRecordsInput.records().size());
-        assertEquals(sharedState.getProvenanceEvents().get(0).getTransitUri(), 
String.format("%s/test-shard/partition-1#1", transitUriPrefix));
-        assertEquals(sharedState.getProvenanceEvents().get(1).getTransitUri(), 
String.format("%s/test-shard/partition-2#2", transitUriPrefix));
-        assertEquals(sharedState.getProvenanceEvents().get(2).getTransitUri(), 
String.format("%s/test-shard/partition-no-date#no-date", transitUriPrefix));
-
-        final List<MockFlowFile> flowFiles = 
session.getFlowFilesForRelationship(ConsumeKinesisStream.REL_SUCCESS);
-        assertFlowFile(flowFiles.get(0), firstDate, "partition-1", "1", 
"record-1");
-        assertFlowFile(flowFiles.get(1), secondDate, "partition-2", "2", 
"record-2");
-        assertFlowFile(flowFiles.get(2), null, "partition-no-date", "no-date", 
"record-no-date");
-
-        session.assertCommitted();
-        session.assertNotRolledBack();
-    }
-
-    @Test
-    public void testProcessPoisonPillRecordWithCheckpoint() throws 
ShutdownException, InvalidStateException {
-        final ProcessRecordsInput processRecordsInput = 
ProcessRecordsInput.builder()
-                .records(Arrays.asList(
-                        
KinesisClientRecord.builder().approximateArrivalTimestamp(null)
-                                .partitionKey("partition-1")
-                                .sequenceNumber("1")
-                                
.data(ByteBuffer.wrap("record-1".getBytes(StandardCharsets.UTF_8)))
-                                .build(),
-                        kinesisRecord,
-                        
KinesisClientRecord.builder().approximateArrivalTimestamp(null)
-                                .partitionKey("partition-3")
-                                .sequenceNumber("3")
-                                
.data(ByteBuffer.wrap("record-3".getBytes(StandardCharsets.UTF_8)))
-                                .build()
-                ))
-                .checkpointer(checkpointer)
-                .cacheEntryTime(Instant.now().minus(1, ChronoUnit.MINUTES))
-                .cacheExitTime(Instant.now().minus(1, ChronoUnit.SECONDS))
-                .millisBehindLatest(100L)
-                .build();
-
-        when(kinesisRecord.data()).thenThrow(new 
IllegalStateException("illegal state"));
-        when(kinesisRecord.toString()).thenReturn("poison-pill");
-
-        fixture.setKinesisShardId("test-shard");
-
-        when(processSessionFactory.createSession()).thenReturn(session);
-        fixture.processRecords(processRecordsInput);
-        verify(processSessionFactory, times(1)).createSession();
-
-        // check non-poison pill records are output successfully
-        session.assertTransferCount(ConsumeKinesisStream.REL_SUCCESS, 2);
-        final List<MockFlowFile> flowFiles = 
session.getFlowFilesForRelationship(ConsumeKinesisStream.REL_SUCCESS);
-        assertFlowFile(flowFiles.get(0), null, "partition-1", "1", "record-1");
-        assertFlowFile(flowFiles.get(1), null, "partition-3", "3", "record-3");
-
-        // check the "poison pill" record was retried a 2nd time
-        assertNull(verify(kinesisRecord, times(2)).partitionKey());
-        assertNull(verify(kinesisRecord, times(2)).sequenceNumber());
-        assertNull(verify(kinesisRecord, 
times(2)).approximateArrivalTimestamp());
-        assertNull(verify(kinesisRecord, times(2)).data());
-        verify(checkpointer, times(1)).checkpoint();
-
-        assertFalse(runner.getLogger().getErrorMessages().isEmpty());
-        assertFalse(runner.getLogger().getErrorMessages().isEmpty());
-
-        session.assertCommitted();
-        session.assertNotRolledBack();
-    }
-
-    private void assertFlowFile(final MockFlowFile flowFile, final Date 
approxTimestamp, final String partitionKey,
-                                final String sequenceNumber, final String 
content) {
-        if (approxTimestamp != null) {
-            
flowFile.assertAttributeEquals(AbstractKinesisRecordProcessor.AWS_KINESIS_APPROXIMATE_ARRIVAL_TIMESTAMP,
-                    
DATE_TIME_FORMATTER.format(ZonedDateTime.ofInstant(approxTimestamp.toInstant(), 
ZoneId.systemDefault())));
-        } else {
-            
flowFile.assertAttributeNotExists(AbstractKinesisRecordProcessor.AWS_KINESIS_APPROXIMATE_ARRIVAL_TIMESTAMP);
-        }
-        
flowFile.assertAttributeEquals(AbstractKinesisRecordProcessor.AWS_KINESIS_PARTITION_KEY,
 partitionKey);
-        
flowFile.assertAttributeEquals(AbstractKinesisRecordProcessor.AWS_KINESIS_SEQUENCE_NUMBER,
 sequenceNumber);
-        
flowFile.assertAttributeEquals(AbstractKinesisRecordProcessor.AWS_KINESIS_SHARD_ID,
 "test-shard");
-        flowFile.assertContentEquals(content);
-    }
-}
diff --git 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/record/TestKinesisRecordProcessorRecord.java
 
b/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/record/TestKinesisRecordProcessorRecord.java
deleted file mode 100644
index 5b39e97411c..00000000000
--- 
a/nifi-extension-bundles/nifi-aws-bundle/nifi-aws-processors/src/test/java/org/apache/nifi/processors/aws/kinesis/stream/record/TestKinesisRecordProcessorRecord.java
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.nifi.processors.aws.kinesis.stream.record;
-
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.nifi.flowfile.attributes.CoreAttributes;
-import org.apache.nifi.json.JsonRecordSetWriter;
-import org.apache.nifi.json.JsonTreeReader;
-import org.apache.nifi.processor.ProcessSessionFactory;
-import 
org.apache.nifi.processors.aws.kinesis.property.SchemaDifferenceHandlingStrategy;
-import org.apache.nifi.processors.aws.kinesis.stream.ConsumeKinesisStream;
-import 
org.apache.nifi.processors.aws.kinesis.stream.pause.StandardRecordProcessorBlocker;
-import 
org.apache.nifi.processors.aws.kinesis.stream.record.converter.RecordConverterIdentity;
-import 
org.apache.nifi.processors.aws.kinesis.stream.record.converter.RecordConverterWrapper;
-import org.apache.nifi.reporting.InitializationException;
-import org.apache.nifi.schema.access.SchemaAccessUtils;
-import org.apache.nifi.schema.inference.SchemaInferenceUtil;
-import org.apache.nifi.serialization.RecordReaderFactory;
-import org.apache.nifi.serialization.RecordSetWriterFactory;
-import org.apache.nifi.util.MockFlowFile;
-import org.apache.nifi.util.MockProcessSession;
-import org.apache.nifi.util.SharedSessionState;
-import org.apache.nifi.util.TestRunner;
-import org.apache.nifi.util.TestRunners;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Nested;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.EnumSource;
-import org.junit.jupiter.params.provider.MethodSource;
-import org.mockito.Mock;
-import software.amazon.kinesis.exceptions.InvalidStateException;
-import software.amazon.kinesis.exceptions.ShutdownException;
-import software.amazon.kinesis.lifecycle.events.ProcessRecordsInput;
-import software.amazon.kinesis.processor.RecordProcessorCheckpointer;
-import software.amazon.kinesis.retrieval.KinesisClientRecord;
-
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.time.Instant;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.temporal.ChronoUnit;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.stream.Stream;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-public class TestKinesisRecordProcessorRecord {
-    private static final DateTimeFormatter DATE_TIME_FORMATTER = 
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
-    private static final StandardRecordProcessorBlocker 
NOOP_RECORD_PROCESSOR_BLOCKER = StandardRecordProcessorBlocker.create();
-
-    private final TestRunner runner = 
TestRunners.newTestRunner(ConsumeKinesisStream.class);
-
-    private final ProcessSessionFactory processSessionFactory = 
mock(ProcessSessionFactory.class);
-
-    private final SharedSessionState sharedState = new 
SharedSessionState(runner.getProcessor(), new AtomicLong(0));
-    private final MockProcessSession session = new 
MockProcessSession(sharedState, runner.getProcessor());
-
-    private AbstractKinesisRecordProcessor fixture;
-    private final RecordReaderFactory reader = new JsonTreeReader();
-    private final RecordSetWriterFactory writer = new JsonRecordSetWriter();
-
-    @Mock
-    private final RecordProcessorCheckpointer checkpointer = 
mock(RecordProcessorCheckpointer.class);
-
-    @Mock
-    private final KinesisClientRecord kinesisRecord = 
mock(KinesisClientRecord.class);
-
-    @BeforeEach
-    public void setUp() throws InitializationException {
-        NOOP_RECORD_PROCESSOR_BLOCKER.unblockIndefinitely();
-
-        runner.addControllerService("record-reader", reader);
-        runner.setProperty(reader, SchemaAccessUtils.SCHEMA_ACCESS_STRATEGY, 
SchemaInferenceUtil.INFER_SCHEMA.getValue());
-        runner.enableControllerService(reader);
-        runner.setProperty(ConsumeKinesisStream.RECORD_READER, 
"record-reader");
-
-        runner.addControllerService("record-writer", writer);
-        runner.setProperty(writer, SchemaAccessUtils.SCHEMA_ACCESS_STRATEGY, 
SchemaAccessUtils.INHERIT_RECORD_SCHEMA.getValue());
-        runner.setProperty(writer, JsonRecordSetWriter.OUTPUT_GROUPING, 
"output-oneline");
-        runner.enableControllerService(writer);
-        runner.setProperty(ConsumeKinesisStream.RECORD_WRITER, 
"record-writer");
-    }
-
-    private KinesisRecordProcessorRecord defaultFixtureWithStrategy(final 
SchemaDifferenceHandlingStrategy strategy) {
-        // default test fixture will try operations twice with very little 
wait in between
-        return new KinesisRecordProcessorRecord(processSessionFactory, 
runner.getLogger(), "kinesis-test",
-                "endpoint-prefix", null, 10_000L, 1L, 2, DATE_TIME_FORMATTER,
-                reader, writer, new RecordConverterIdentity(), 
NOOP_RECORD_PROCESSOR_BLOCKER, strategy);
-    }
-
-    @AfterEach
-    public void tearDown() {
-        verifyNoMoreInteractions(checkpointer, kinesisRecord, 
processSessionFactory);
-        reset(checkpointer, kinesisRecord, processSessionFactory);
-    }
-
-    @ParameterizedTest
-    @EnumSource(SchemaDifferenceHandlingStrategy.class)
-    public void testProcessRecordsEmpty(final SchemaDifferenceHandlingStrategy 
strategy) {
-        fixture = defaultFixtureWithStrategy(strategy);
-        final ProcessRecordsInput processRecordsInput = 
ProcessRecordsInput.builder()
-                .records(Collections.emptyList())
-                .checkpointer(checkpointer)
-                .cacheEntryTime(Instant.now().minus(1, ChronoUnit.MINUTES))
-                .cacheExitTime(Instant.now().minus(1, ChronoUnit.SECONDS))
-                .millisBehindLatest(100L)
-                .build();
-
-        // would checkpoint (but should skip because there are no records 
processed)
-        fixture.setNextCheckpointTimeInMillis(System.currentTimeMillis() - 
10_000L);
-
-        fixture.processRecords(processRecordsInput);
-
-        session.assertTransferCount(ConsumeKinesisStream.REL_SUCCESS, 0);
-        assertTrue(sharedState.getProvenanceEvents().isEmpty());
-        session.assertNotCommitted();
-        session.assertNotRolledBack();
-    }
-
-    private static Stream<Arguments.ArgumentSet> testProcessRecordsArgs() {
-        final List<Pair<String, Boolean>> endpointOverridden = List.of(
-                Pair.of("Overriden Endpoint", true),
-                Pair.of("Default Endpoint", false)
-        );
-        final List<Pair<String, Boolean>> usingWrapper = List.of(
-                Pair.of("Using Schema Wrapper", true),
-                Pair.of("Default Schema", false)
-        );
-        final List<Pair<String, SchemaDifferenceHandlingStrategy>> 
schemaChangeStrategy = Arrays.stream(SchemaDifferenceHandlingStrategy.values())
-                .map(strategy -> Pair.of(strategy.name(), strategy))
-                .toList();
-        return endpointOverridden.stream()
-                .flatMap(endpoint -> schemaChangeStrategy.stream()
-                        .flatMap(strategy -> usingWrapper.stream()
-                                .map(wrapper -> Arguments.argumentSet(
-                                        String.format("%s, %s, %s", 
endpoint.getLeft(), wrapper.getLeft(), strategy.getLeft()),
-                                        endpoint.getRight(),
-                                        wrapper.getRight(),
-                                        strategy.getRight()
-                                ))));
-    }
-
-    @ParameterizedTest
-    @MethodSource("testProcessRecordsArgs")
-    void processMultipleRecordsAssertProvenance(final boolean 
endpointOverridden, final boolean useWrapper, final 
SchemaDifferenceHandlingStrategy strategy) {
-        fixture = defaultFixtureWithStrategy(strategy);
-        final Instant referenceInstant = 
Instant.parse("2021-01-01T00:00:00.000Z");
-        final Date firstDate = Date.from(referenceInstant.minus(1, 
ChronoUnit.MINUTES));
-        final Date secondDate = Date.from(referenceInstant);
-
-        final ProcessRecordsInput processRecordsInput = 
ProcessRecordsInput.builder()
-                .records(Arrays.asList(
-                        
KinesisClientRecord.builder().approximateArrivalTimestamp(firstDate.toInstant())
-                                .partitionKey("partition-1")
-                                .sequenceNumber("1")
-                                
.data(ByteBuffer.wrap("{\"record\":\"1\"}\n{\"record\":\"1b\"}".getBytes(StandardCharsets.UTF_8)))
-                                .build(),
-                        
KinesisClientRecord.builder().approximateArrivalTimestamp(null)
-                                .partitionKey("partition-no-date")
-                                .sequenceNumber("no-date")
-                                
.data(ByteBuffer.wrap("{\"record\":\"no-date\"}".getBytes(StandardCharsets.UTF_8)))
-                                .build(),
-                        
KinesisClientRecord.builder().approximateArrivalTimestamp(secondDate.toInstant())
-                                .partitionKey("partition-2")
-                                .sequenceNumber("2")
-                                
.data(ByteBuffer.wrap("{\"record\":\"2\"}".getBytes(StandardCharsets.UTF_8)))
-                                .build()
-                ))
-                .checkpointer(checkpointer)
-                .cacheEntryTime(null)
-                .cacheExitTime(null)
-                .millisBehindLatest(null)
-                .build();
-
-        final String transitUriPrefix = endpointOverridden ? 
"https://another-endpoint.com:8443"; : "http://endpoint-prefix.amazonaws.com";;
-        fixture = new KinesisRecordProcessorRecord(processSessionFactory, 
runner.getLogger(), "kinesis-test",
-                "endpoint-prefix", transitUriPrefix, 10_000L, 1L, 2, 
DATE_TIME_FORMATTER,
-                reader, writer, useWrapper ? new RecordConverterWrapper() : 
new RecordConverterIdentity(), NOOP_RECORD_PROCESSOR_BLOCKER, strategy);
-
-        // skip checkpoint
-        fixture.setNextCheckpointTimeInMillis(System.currentTimeMillis() + 
10_000L);
-        fixture.setKinesisShardId("another-shard");
-
-        when(processSessionFactory.createSession()).thenReturn(session);
-        fixture.processRecords(processRecordsInput);
-        verify(processSessionFactory, times(1)).createSession();
-
-        session.assertTransferCount(ConsumeKinesisStream.REL_SUCCESS, 1);
-        assertEquals(1, sharedState.getProvenanceEvents().size());
-        assertEquals(String.format("%s/another-shard", transitUriPrefix), 
sharedState.getProvenanceEvents().getFirst().getTransitUri());
-
-        final List<MockFlowFile> flowFiles = 
session.getFlowFilesForRelationship(ConsumeKinesisStream.REL_SUCCESS);
-        // 4 records in single output file, attributes equating to that of the 
last record
-        final String expectedContent = useWrapper ? 
expectRecordContentWrapper() : expectRecordContentIdentity();
-        assertFlowFile(flowFiles.getFirst(), secondDate, "partition-2", "2", 
"another-shard", expectedContent, 4);
-        session.assertTransferCount(ConsumeKinesisStream.REL_PARSE_FAILURE, 0);
-
-        session.assertCommitted();
-        session.assertNotRolledBack();
-    }
-
-    private String expectRecordContentIdentity() {
-        return """
-                {"record":"1"}
-                {"record":"1b"}
-                {"record":"no-date"}
-                {"record":"2"}""";
-    }
-
-    private String expectRecordContentWrapper() {
-        return """
-                
{"metadata":{"stream":"kinesis-test","shardId":"another-shard","sequenceNumber":"1","subSequenceNumber":0,\
-                
"shardedSequenceNumber":"100000000000000000000","partitionKey":"partition-1","approximateArrival":1609459140000},"value":{"record":"1"}}
-                
{"metadata":{"stream":"kinesis-test","shardId":"another-shard","sequenceNumber":"1","subSequenceNumber":0,\
-                
"shardedSequenceNumber":"100000000000000000000","partitionKey":"partition-1","approximateArrival":1609459140000},"value":{"record":"1b"}}
-                
{"metadata":{"stream":"kinesis-test","shardId":"another-shard","sequenceNumber":"no-date","subSequenceNumber":0,\
-                
"shardedSequenceNumber":"no-date00000000000000000000","partitionKey":"partition-no-date","approximateArrival":null},"value":{"record":"no-date"}}
-                
{"metadata":{"stream":"kinesis-test","shardId":"another-shard","sequenceNumber":"2","subSequenceNumber":0,\
-                
"shardedSequenceNumber":"200000000000000000000","partitionKey":"partition-2","approximateArrival":1609459200000},"value":{"record":"2"}}""";
-    }
-
-    @ParameterizedTest
-    @EnumSource(SchemaDifferenceHandlingStrategy.class)
-    public void testProcessPoisonPillRecordButNoRawOutputWithCheckpoint(final 
SchemaDifferenceHandlingStrategy strategy) throws ShutdownException, 
InvalidStateException {
-        fixture = defaultFixtureWithStrategy(strategy);
-        final ProcessRecordsInput processRecordsInput = 
ProcessRecordsInput.builder()
-                .records(Arrays.asList(
-                        
KinesisClientRecord.builder().approximateArrivalTimestamp(null)
-                                .partitionKey("partition-1")
-                                .sequenceNumber("1")
-                                
.data(ByteBuffer.wrap("{\"record\":\"1\"}".getBytes(StandardCharsets.UTF_8)))
-                                .build(),
-                        kinesisRecord,
-                        
KinesisClientRecord.builder().approximateArrivalTimestamp(null)
-                                .partitionKey("partition-3")
-                                .sequenceNumber("3")
-                                
.data(ByteBuffer.wrap("{\"record\":\"3\"}".getBytes(StandardCharsets.UTF_8)))
-                                .build()
-                ))
-                .checkpointer(checkpointer)
-                .cacheEntryTime(Instant.now().minus(1, ChronoUnit.MINUTES))
-                .cacheExitTime(Instant.now().minus(1, ChronoUnit.SECONDS))
-                .millisBehindLatest(100L)
-                .build();
-
-        when(kinesisRecord.data()).thenThrow(new 
IllegalStateException("illegal state"));
-        when(kinesisRecord.toString()).thenReturn("poison-pill");
-
-        fixture.setKinesisShardId("test-shard");
-
-        when(processSessionFactory.createSession()).thenReturn(session);
-        fixture.processRecords(processRecordsInput);
-        verify(processSessionFactory, times(1)).createSession();
-
-        // check non-poison pill records are output successfully
-        session.assertTransferCount(ConsumeKinesisStream.REL_SUCCESS, 1);
-        final List<MockFlowFile> flowFiles = 
session.getFlowFilesForRelationship(ConsumeKinesisStream.REL_SUCCESS);
-        // 2 successful records in single output file, attributes equating to 
that of the last successful record
-        assertFlowFile(flowFiles.getFirst(), null, "partition-3", "3", 
"test-shard", "{\"record\":\"1\"}\n" +
-                "{\"record\":\"3\"}", 2);
-
-        // check no poison-pill output (as the raw data could not be retrieved)
-        session.assertTransferCount(ConsumeKinesisStream.REL_PARSE_FAILURE, 0);
-
-        // check the "poison pill" record was retried a 2nd time
-        assertNull(verify(kinesisRecord, times(2)).data());
-        verify(checkpointer, times(1)).checkpoint();
-
-        assertFalse(runner.getLogger().getErrorMessages().isEmpty());
-
-        session.assertCommitted();
-        session.assertNotRolledBack();
-    }
-
-    private static Stream<Arguments.ArgumentSet> unparsableRecordsLists() {
-        final KinesisClientRecord unparsableRecordMock = 
mock(KinesisClientRecord.class);
-        final KinesisClientRecord parsableRecord1 = 
KinesisClientRecord.builder().approximateArrivalTimestamp(null)
-                .partitionKey("partition-1")
-                .sequenceNumber("1")
-                
.data(ByteBuffer.wrap("{\"record\":\"1\"}".getBytes(StandardCharsets.UTF_8)))
-                .build();
-        final KinesisClientRecord parsableRecord3 = 
KinesisClientRecord.builder().approximateArrivalTimestamp(null)
-                .partitionKey("partition-3")
-                .sequenceNumber("3")
-                
.data(ByteBuffer.wrap("{\"record\":\"3\"}".getBytes(StandardCharsets.UTF_8)))
-                .build();
-        final List<List<KinesisClientRecord>> recordLists = List.of(
-                Arrays.asList(
-                        unparsableRecordMock,
-                        parsableRecord1,
-                        parsableRecord3
-                ),
-                Arrays.asList(
-                        parsableRecord1,
-                        unparsableRecordMock,
-                        parsableRecord3
-                ),
-                Arrays.asList(
-                        parsableRecord1,
-                        parsableRecord3,
-                        unparsableRecordMock
-                )
-        );
-        return Arrays.stream(SchemaDifferenceHandlingStrategy.values())
-                .flatMap(strategy -> recordLists.stream().map(recordList -> 
Pair.of(strategy, recordList)))
-                .map(pair -> {
-                    final SchemaDifferenceHandlingStrategy strategy = 
pair.getLeft();
-                    final List<KinesisClientRecord> inputRecords = 
pair.getRight();
-                    String position = "Middle";
-                    if (inputRecords.getFirst() == unparsableRecordMock) {
-                        position = "Beginning";
-                    }
-                    if (inputRecords.getLast() == unparsableRecordMock) {
-                        position = "End";
-                    }
-                    return Arguments.argumentSet(
-                            String.format("Strategy=%s, Unparsable Record 
Position=%s", strategy, position),
-                            inputRecords,
-                            unparsableRecordMock,
-                            strategy
-                    );
-                })
-                .peek(it -> {
-                    parsableRecord1.data().rewind();
-                    parsableRecord3.data().rewind();
-                    reset(unparsableRecordMock);
-                });
-    }
-
-    @ParameterizedTest
-    @MethodSource("unparsableRecordsLists")
-    void testProcessUnparsableRecordWithRawOutputWithCheckpoint(
-            final List<KinesisClientRecord> inputRecords,
-            final KinesisClientRecord kinesisRecord,
-            final SchemaDifferenceHandlingStrategy strategy) throws 
ShutdownException, InvalidStateException {
-        fixture = defaultFixtureWithStrategy(strategy);
-        final ProcessRecordsInput processRecordsInput = 
ProcessRecordsInput.builder()
-                .records(inputRecords)
-                .checkpointer(checkpointer)
-                .cacheEntryTime(Instant.now().minus(1, ChronoUnit.MINUTES))
-                .cacheExitTime(Instant.now().minus(1, ChronoUnit.SECONDS))
-                .millisBehindLatest(100L)
-                .build();
-
-        
when(kinesisRecord.data()).thenReturn(ByteBuffer.wrap("invalid-json".getBytes(StandardCharsets.UTF_8)));
-        when(kinesisRecord.partitionKey()).thenReturn("unparsable-partition");
-        when(kinesisRecord.sequenceNumber()).thenReturn("unparsable-sequence");
-        when(kinesisRecord.approximateArrivalTimestamp()).thenReturn(null);
-
-        fixture.setKinesisShardId("test-shard");
-
-        when(processSessionFactory.createSession()).thenReturn(session);
-        fixture.processRecords(processRecordsInput);
-        verify(processSessionFactory, times(1)).createSession();
-
-        // check non-poison pill records are output successfully
-        session.assertTransferCount(ConsumeKinesisStream.REL_SUCCESS, 1);
-        final List<MockFlowFile> flowFiles = 
session.getFlowFilesForRelationship(ConsumeKinesisStream.REL_SUCCESS);
-        // 2 successful records in single output file, attributes equating to 
that of the last successful record
-        assertFlowFile(flowFiles.getFirst(), null, "partition-3", "3", 
"test-shard", "{\"record\":\"1\"}\n" +
-                "{\"record\":\"3\"}", 2);
-
-        // check poison-pill output (as the raw data could not be retrieved)
-        session.assertTransferCount(ConsumeKinesisStream.REL_PARSE_FAILURE, 1);
-        final List<MockFlowFile> failureFlowFiles = 
session.getFlowFilesForRelationship(ConsumeKinesisStream.REL_PARSE_FAILURE);
-        assertFlowFile(failureFlowFiles.getFirst(), null, 
"unparsable-partition", "unparsable-sequence", "test-shard", "invalid-json", 0);
-        
failureFlowFiles.getFirst().assertAttributeExists("record.error.message");
-
-        // check the invalid json record was *not* retried a 2nd time
-        assertNull(verify(kinesisRecord, times(1)).partitionKey());
-        assertNull(verify(kinesisRecord, times(1)).sequenceNumber());
-        assertNull(verify(kinesisRecord, 
times(1)).approximateArrivalTimestamp());
-        assertNull(verify(kinesisRecord, times(1)).data());
-        verify(checkpointer, times(1)).checkpoint();
-
-        assertEquals(1, runner.getLogger().getErrorMessages().size());
-
-        session.assertCommitted();
-        session.assertNotRolledBack();
-    }
-
-    @ParameterizedTest
-    @EnumSource(SchemaDifferenceHandlingStrategy.class)
-    void testProcessMultipleRecordInSingleKinesisRecord(final 
SchemaDifferenceHandlingStrategy strategy) throws ShutdownException, 
InvalidStateException {
-        fixture = defaultFixtureWithStrategy(strategy);
-        
testFlowFileContents(List.of("[{\"record\":1},{\"record\":2},{\"record\":3}]"), 
List.of(EmittedFlowFile.of("{\"record\":1}\n{\"record\":2}\n{\"record\":3}", 
3)));
-    }
-
-    @Nested
-    class StateHandlerStrategyTest {
-
-        private static List<String> inputJsonRecords() {
-            return List.of(
-                    "{\"colA\":1}", // inferred to ["colA":int]
-                    "{\"colA\":%d}".formatted(Long.MAX_VALUE), // inferred to 
["colA":long]
-                    "{\"colA\":3}"
-            );
-        }
-
-        @Test
-        void testProcessIncompatibleSchemaKinesisRecordsStrategyGrouping() 
throws ShutdownException, InvalidStateException {
-            fixture = 
defaultFixtureWithStrategy(SchemaDifferenceHandlingStrategy.GROUP_RECORDS);
-            final List<String> inputJsonRecords = inputJsonRecords();
-            testFlowFileContents(
-                    inputJsonRecords,
-                    List.of(
-                            EmittedFlowFile.of(String.join("\n", 
inputJsonRecords.get(0), inputJsonRecords.get(2)), 2),
-                            EmittedFlowFile.of(inputJsonRecords.get(1), 1)
-                    )
-            );
-        }
-
-        @Test
-        void testProcessIncompatibleSchemaKinesisRecordsStrategyRolling() 
throws ShutdownException, InvalidStateException {
-            fixture = 
defaultFixtureWithStrategy(SchemaDifferenceHandlingStrategy.CREATE_FLOW_FILE);
-            final List<String> inputJsonRecords = inputJsonRecords();
-            testFlowFileContents(
-                    inputJsonRecords,
-                    List.of(
-                            EmittedFlowFile.of(inputJsonRecords.get(0), 1),
-                            EmittedFlowFile.of(inputJsonRecords.get(1), 1),
-                            EmittedFlowFile.of(inputJsonRecords.get(2), 1)
-                    )
-            );
-        }
-    }
-
-    void testFlowFileContents(final List<String> kinesisRecordJsonContents, 
final List<EmittedFlowFile> emittedFlowFiles) throws ShutdownException, 
InvalidStateException {
-        final List<KinesisClientRecord> kinesisRecords = 
kinesisRecordJsonContents.stream()
-                .map(json -> KinesisClientRecord.builder()
-                        .approximateArrivalTimestamp(null)
-                        .partitionKey("partition-1")
-                        .sequenceNumber("1")
-                        
.data(ByteBuffer.wrap(json.getBytes(StandardCharsets.UTF_8)))
-                        .build())
-                .toList();
-        final ProcessRecordsInput processRecordsInput = 
ProcessRecordsInput.builder()
-                .records(kinesisRecords)
-                .checkpointer(checkpointer)
-                .cacheEntryTime(Instant.now().minus(1, ChronoUnit.MINUTES))
-                .cacheExitTime(Instant.now().minus(1, ChronoUnit.SECONDS))
-                .millisBehindLatest(100L)
-                .build();
-
-        
when(kinesisRecord.data()).thenReturn(ByteBuffer.wrap("invalid-json".getBytes(StandardCharsets.UTF_8)));
-        when(kinesisRecord.partitionKey()).thenReturn("unparsable-partition");
-        when(kinesisRecord.sequenceNumber()).thenReturn("unparsable-sequence");
-        when(kinesisRecord.approximateArrivalTimestamp()).thenReturn(null);
-
-        fixture.setKinesisShardId("test-shard");
-
-        when(processSessionFactory.createSession()).thenReturn(session);
-        fixture.processRecords(processRecordsInput);
-        verify(processSessionFactory, times(1)).createSession();
-
-        // check non-poison pill records are output successfully
-        session.assertTransferCount(ConsumeKinesisStream.REL_SUCCESS, 
emittedFlowFiles.size());
-        final List<MockFlowFile> flowFiles = 
session.getFlowFilesForRelationship(ConsumeKinesisStream.REL_SUCCESS);
-        for (int i = 0; i < emittedFlowFiles.size(); i++) {
-            final EmittedFlowFile emittedFlowFile = emittedFlowFiles.get(i);
-            assertFlowFile(flowFiles.get(i), null, "partition-1", "1", 
"test-shard", emittedFlowFile.content, emittedFlowFile.recordCount);
-        }
-
-        verify(checkpointer, times(1)).checkpoint();
-
-        session.assertCommitted();
-        session.assertNotRolledBack();
-    }
-
-    private record EmittedFlowFile(String content, int recordCount) {
-        public static EmittedFlowFile of(final String content, final int 
recordCount) {
-            return new EmittedFlowFile(content, recordCount);
-        }
-    }
-
-    private void assertFlowFile(final MockFlowFile flowFile, final Date 
approxTimestamp, final String partitionKey,
-                                final String sequenceNumber, final String 
shard, final String content, final int recordCount) {
-        if (approxTimestamp != null) {
-            
flowFile.assertAttributeEquals(AbstractKinesisRecordProcessor.AWS_KINESIS_APPROXIMATE_ARRIVAL_TIMESTAMP,
-                    
DATE_TIME_FORMATTER.format(ZonedDateTime.ofInstant(approxTimestamp.toInstant(), 
ZoneId.systemDefault())));
-        } else {
-            
flowFile.assertAttributeNotExists(AbstractKinesisRecordProcessor.AWS_KINESIS_APPROXIMATE_ARRIVAL_TIMESTAMP);
-        }
-        
flowFile.assertAttributeEquals(AbstractKinesisRecordProcessor.AWS_KINESIS_PARTITION_KEY,
 partitionKey);
-        
flowFile.assertAttributeEquals(AbstractKinesisRecordProcessor.AWS_KINESIS_SEQUENCE_NUMBER,
 sequenceNumber);
-        
flowFile.assertAttributeEquals(AbstractKinesisRecordProcessor.AWS_KINESIS_SHARD_ID,
 shard);
-
-        if (recordCount > 0) {
-            flowFile.assertAttributeEquals("record.count", 
String.valueOf(recordCount));
-            flowFile.assertAttributeEquals(CoreAttributes.MIME_TYPE.key(), 
"application/json");
-        } else {
-            flowFile.assertAttributeNotExists("record.count");
-            flowFile.assertAttributeNotExists(CoreAttributes.MIME_TYPE.key());
-        }
-
-        flowFile.assertContentEquals(content);
-    }
-}
diff --git 
a/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/logback.xml
 
b/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/logback.xml
index d42d71bcac4..1ed2bef1b69 100644
--- 
a/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/logback.xml
+++ 
b/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/logback.xml
@@ -210,9 +210,6 @@
     <!-- Suppress non-error messages due to Jetty AnnotationParser emitting a 
large amount of WARNS. Issue described in NIFI-5479. -->
     <logger name="org.eclipse.jetty.annotations.AnnotationParser" 
level="ERROR"/>
 
-    <!-- Suppress non-error messages from AWS KCL which was emitting large 
amounts of INFO logs by default -->
-    <logger name="software.amazon.awssdk.kinesis" level="WARN" />
-
     <!-- Suppress non-error messages from Apache Atlas which was emitting 
large amounts of INFO logs by default -->
     <logger name="org.apache.atlas" level="WARN"/>
 
diff --git 
a/nifi-stateless/nifi-stateless-resources/src/main/resources/conf/stateless-logback.xml
 
b/nifi-stateless/nifi-stateless-resources/src/main/resources/conf/stateless-logback.xml
index ad915a96d3d..6ea9a5c28f4 100644
--- 
a/nifi-stateless/nifi-stateless-resources/src/main/resources/conf/stateless-logback.xml
+++ 
b/nifi-stateless/nifi-stateless-resources/src/main/resources/conf/stateless-logback.xml
@@ -60,9 +60,6 @@
 
     <logger name="org.apache.calcite.runtime.CalciteException" level="OFF" />
 
-    <!-- Suppress non-error messages from AWS KCL which was emitting large 
amounts of INFO logs by default -->
-    <logger name="software.amazon.awssdk.kinesis" level="WARN" />
-
     <root level="INFO">
         <appender-ref ref="CONSOLE" />
         <appender-ref ref="APP_FILE" />
diff --git 
a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node1/logback.xml
 
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node1/logback.xml
index 263aaca4843..ee1f1d7802b 100644
--- 
a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node1/logback.xml
+++ 
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node1/logback.xml
@@ -136,9 +136,6 @@
     <!-- Suppress non-error messages from SMBJ which was emitting large 
amounts of INFO logs by default -->
     <logger name="com.hierynomus.smbj" level="WARN" />
 
-    <!-- Suppress non-error messages from AWS KCL which was emitting large 
amounts of INFO logs by default -->
-    <logger name="software.amazon.awssdk.kinesis" level="WARN" />
-
     <!-- Suppress non-error messages from Apache Atlas which was emitting 
large amounts of INFO logs by default -->
     <logger name="org.apache.atlas" level="WARN"/>
 
diff --git 
a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node2/logback.xml
 
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node2/logback.xml
index 263aaca4843..ee1f1d7802b 100644
--- 
a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node2/logback.xml
+++ 
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/clustered/node2/logback.xml
@@ -136,9 +136,6 @@
     <!-- Suppress non-error messages from SMBJ which was emitting large 
amounts of INFO logs by default -->
     <logger name="com.hierynomus.smbj" level="WARN" />
 
-    <!-- Suppress non-error messages from AWS KCL which was emitting large 
amounts of INFO logs by default -->
-    <logger name="software.amazon.awssdk.kinesis" level="WARN" />
-
     <!-- Suppress non-error messages from Apache Atlas which was emitting 
large amounts of INFO logs by default -->
     <logger name="org.apache.atlas" level="WARN"/>
 
diff --git 
a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/default/logback.xml
 
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/default/logback.xml
index d965f00d60e..dd09821a140 100644
--- 
a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/default/logback.xml
+++ 
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/default/logback.xml
@@ -136,9 +136,6 @@
     <!-- Suppress non-error messages from SMBJ which was emitting large 
amounts of INFO logs by default -->
     <logger name="com.hierynomus.smbj" level="WARN" />
 
-    <!-- Suppress non-error messages from AWS KCL which was emitting large 
amounts of INFO logs by default -->
-    <logger name="software.amazon.awssdk.kinesis" level="WARN" />
-
     <!-- Suppress non-error messages from Apache Atlas which was emitting 
large amounts of INFO logs by default -->
     <logger name="org.apache.atlas" level="WARN"/>
 
diff --git 
a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/pythonic/logback.xml
 
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/pythonic/logback.xml
index 637c570239b..7fc296f8146 100644
--- 
a/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/pythonic/logback.xml
+++ 
b/nifi-system-tests/nifi-system-test-suite/src/test/resources/conf/pythonic/logback.xml
@@ -142,9 +142,6 @@
     <!-- Suppress non-error messages from SMBJ which was emitting large 
amounts of INFO logs by default -->
     <logger name="com.hierynomus.smbj" level="WARN" />
 
-    <!-- Suppress non-error messages from AWS KCL which was emitting large 
amounts of INFO logs by default -->
-    <logger name="com.amazonaws.services.kinesis" level="WARN" />
-
     <!-- Suppress non-error messages from Apache Atlas which was emitting 
large amounts of INFO logs by default -->
     <logger name="org.apache.atlas" level="WARN"/>
 

Reply via email to