You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2020/02/17 12:05:13 UTC

[camel] 01/10: CAMEL-14553 - Create an AWS-SQS component based on SDK v2

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

acosentino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git

commit cff4110270ee07a1bf3149ab058099ea73455e5d
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Mon Feb 17 11:51:17 2020 +0100

    CAMEL-14553 - Create an AWS-SQS component based on SDK v2
---
 components/camel-aws2-sqs/pom.xml                  |  86 +++
 .../aws2/sqs/Sqs2ComponentConfigurer.java          |  35 ++
 .../component/aws2/sqs/Sqs2EndpointConfigurer.java | 131 +++++
 .../services/org/apache/camel/component.properties |   7 +
 .../services/org/apache/camel/component/aws2-sqs   |   2 +
 .../org/apache/camel/configurer/aws2-sqs-component |   2 +
 .../org/apache/camel/configurer/aws2-sqs-endpoint  |   2 +
 .../apache/camel/component/aws2/sqs/aws2-sqs.json  |  91 ++++
 .../src/main/docs/aws-sqs-component.adoc           | 361 +++++++++++++
 .../aws2/sqs/ConstantMessageGroupIdStrategy.java   |  28 +
 .../ExchangeIdMessageDeduplicationIdStrategy.java  |  28 +
 .../aws2/sqs/ExchangeIdMessageGroupIdStrategy.java |  28 +
 .../aws2/sqs/MessageDeduplicationIdStrategy.java   |  25 +
 .../component/aws2/sqs/MessageGroupIdStrategy.java |  25 +
 .../sqs/NullMessageDeduplicationIdStrategy.java    |  28 +
 .../sqs/PropertyValueMessageGroupIdStrategy.java   |  28 +
 .../camel/component/aws2/sqs/Sqs2Component.java    | 140 +++++
 .../aws2/sqs/Sqs2ComponentVerifierExtension.java   |  85 +++
 .../component/aws2/sqs/Sqs2Configuration.java      | 574 +++++++++++++++++++++
 .../camel/component/aws2/sqs/Sqs2Constants.java    |  33 ++
 .../camel/component/aws2/sqs/Sqs2Consumer.java     | 334 ++++++++++++
 .../camel/component/aws2/sqs/Sqs2Endpoint.java     | 393 ++++++++++++++
 .../aws2/sqs/Sqs2HeaderFilterStrategy.java         |  30 ++
 .../camel/component/aws2/sqs/Sqs2Operations.java   |  22 +
 .../camel/component/aws2/sqs/Sqs2Producer.java     | 309 +++++++++++
 .../component/aws2/sqs/AmazonSQSClientMock.java    | 227 ++++++++
 .../component/aws2/sqs/SqsBatchConsumerTest.java   |  80 +++
 .../aws2/sqs/SqsComponentClientRegistryTest.java   |  43 ++
 .../aws2/sqs/SqsComponentConfigurationTest.java    | 306 +++++++++++
 .../component/aws2/sqs/SqsComponentSpringTest.java | 134 +++++
 .../camel/component/aws2/sqs/SqsComponentTest.java | 106 ++++
 .../sqs/SqsComponentVerifierExtensionTest.java     |  71 +++
 .../aws2/sqs/SqsConcurrentConsumerTest.java        |  91 ++++
 .../component/aws2/sqs/SqsConfigurationTest.java   |  50 ++
 .../aws2/sqs/SqsConsumerIdleMessageTest.java       |  54 ++
 .../sqs/SqsDoesNotExtendMessageVisibilityTest.java |  73 +++
 .../aws2/sqs/SqsEndpointExplicitQueueUrlTest.java  |  52 ++
 .../component/aws2/sqs/SqsProducerBatchTest.java   |  77 +++
 .../component/aws2/sqs/SqsProducerDeleteTest.java  |  69 +++
 .../aws2/sqs/SqsProducerListQueuesTest.java        |  70 +++
 .../integration/SqsComponentIntegrationTest.java   | 109 ++++
 .../SqsConsumerMessageIntegrationTest.java         |  72 +++
 .../SqsProducerBatchSendFifoIntegrationTest.java   |  76 +++
 .../SqsProducerBatchSendIntegrationTest.java       |  75 +++
 .../SqsProducerDeleteMessageIntegrationTest.java   |  67 +++
 .../src/test/resources/log4j2.properties           |  28 +
 .../aws2/sqs/SqsComponentSpringTest-context.xml    |  51 ++
 core/camel-allcomponents/pom.xml                   |   4 +
 .../component/ComponentsBuilderFactory.java        |  12 +
 .../dsl/Aws2SqsComponentBuilderFactory.java        | 181 +++++++
 .../src/generated/resources/metadata.json          |  20 +
 51 files changed, 5025 insertions(+)

diff --git a/components/camel-aws2-sqs/pom.xml b/components/camel-aws2-sqs/pom.xml
new file mode 100644
index 0000000..fb71b69
--- /dev/null
+++ b/components/camel-aws2-sqs/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>components</artifactId>
+        <version>3.1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-aws2-sqs</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Camel :: AWS2 SQS</name>
+    <description>A Camel Amazon SQS Web Service Component Version 2</description>
+
+    <properties>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>sqs</artifactId>
+            <version>${aws-java-sdk2-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>software.amazon.awssdk</groupId>
+            <artifactId>apache-client</artifactId>
+            <version>${aws-java-sdk2-version}</version>
+        </dependency>
+
+        <!-- for testing -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-spring</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/components/camel-aws2-sqs/src/generated/java/org/apache/camel/component/aws2/sqs/Sqs2ComponentConfigurer.java b/components/camel-aws2-sqs/src/generated/java/org/apache/camel/component/aws2/sqs/Sqs2ComponentConfigurer.java
new file mode 100644
index 0000000..ebcc415
--- /dev/null
+++ b/components/camel-aws2-sqs/src/generated/java/org/apache/camel/component/aws2/sqs/Sqs2ComponentConfigurer.java
@@ -0,0 +1,35 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.aws2.sqs;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class Sqs2ComponentConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+        Sqs2Component target = (Sqs2Component) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "accesskey":
+        case "accessKey": target.setAccessKey(property(camelContext, java.lang.String.class, value)); return true;
+        case "region": target.setRegion(property(camelContext, java.lang.String.class, value)); return true;
+        case "secretkey":
+        case "secretKey": target.setSecretKey(property(camelContext, java.lang.String.class, value)); return true;
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true;
+        case "lazystartproducer":
+        case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+        case "basicpropertybinding":
+        case "basicPropertyBinding": target.setBasicPropertyBinding(property(camelContext, boolean.class, value)); return true;
+        case "configuration": target.setConfiguration(property(camelContext, org.apache.camel.component.aws2.sqs.Sqs2Configuration.class, value)); return true;
+        default: return false;
+        }
+    }
+
+}
+
diff --git a/components/camel-aws2-sqs/src/generated/java/org/apache/camel/component/aws2/sqs/Sqs2EndpointConfigurer.java b/components/camel-aws2-sqs/src/generated/java/org/apache/camel/component/aws2/sqs/Sqs2EndpointConfigurer.java
new file mode 100644
index 0000000..ff6d80c
--- /dev/null
+++ b/components/camel-aws2-sqs/src/generated/java/org/apache/camel/component/aws2/sqs/Sqs2EndpointConfigurer.java
@@ -0,0 +1,131 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.component.aws2.sqs;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.support.component.PropertyConfigurerSupport;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class Sqs2EndpointConfigurer extends PropertyConfigurerSupport implements GeneratedPropertyConfigurer {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) {
+        Sqs2Endpoint target = (Sqs2Endpoint) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "amazonawshost":
+        case "amazonAWSHost": target.getConfiguration().setAmazonAWSHost(property(camelContext, java.lang.String.class, value)); return true;
+        case "amazonsqsclient":
+        case "amazonSQSClient": target.getConfiguration().setAmazonSQSClient(property(camelContext, software.amazon.awssdk.services.sqs.SqsClient.class, value)); return true;
+        case "autocreatequeue":
+        case "autoCreateQueue": target.getConfiguration().setAutoCreateQueue(property(camelContext, boolean.class, value)); return true;
+        case "headerfilterstrategy":
+        case "headerFilterStrategy": target.setHeaderFilterStrategy(property(camelContext, org.apache.camel.spi.HeaderFilterStrategy.class, value)); return true;
+        case "protocol": target.getConfiguration().setProtocol(property(camelContext, java.lang.String.class, value)); return true;
+        case "proxyprotocol":
+        case "proxyProtocol": target.getConfiguration().setProxyProtocol(property(camelContext, software.amazon.awssdk.core.Protocol.class, value)); return true;
+        case "queueownerawsaccountid":
+        case "queueOwnerAWSAccountId": target.getConfiguration().setQueueOwnerAWSAccountId(property(camelContext, java.lang.String.class, value)); return true;
+        case "region": target.getConfiguration().setRegion(property(camelContext, java.lang.String.class, value)); return true;
+        case "attributenames":
+        case "attributeNames": target.getConfiguration().setAttributeNames(property(camelContext, java.lang.String.class, value)); return true;
+        case "bridgeerrorhandler":
+        case "bridgeErrorHandler": target.setBridgeErrorHandler(property(camelContext, boolean.class, value)); return true;
+        case "concurrentconsumers":
+        case "concurrentConsumers": target.getConfiguration().setConcurrentConsumers(property(camelContext, int.class, value)); return true;
+        case "defaultvisibilitytimeout":
+        case "defaultVisibilityTimeout": target.getConfiguration().setDefaultVisibilityTimeout(property(camelContext, java.lang.Integer.class, value)); return true;
+        case "deleteafterread":
+        case "deleteAfterRead": target.getConfiguration().setDeleteAfterRead(property(camelContext, boolean.class, value)); return true;
+        case "deleteiffiltered":
+        case "deleteIfFiltered": target.getConfiguration().setDeleteIfFiltered(property(camelContext, boolean.class, value)); return true;
+        case "extendmessagevisibility":
+        case "extendMessageVisibility": target.getConfiguration().setExtendMessageVisibility(property(camelContext, boolean.class, value)); return true;
+        case "kmsdatakeyreuseperiodseconds":
+        case "kmsDataKeyReusePeriodSeconds": target.getConfiguration().setKmsDataKeyReusePeriodSeconds(property(camelContext, java.lang.Integer.class, value)); return true;
+        case "kmsmasterkeyid":
+        case "kmsMasterKeyId": target.getConfiguration().setKmsMasterKeyId(property(camelContext, java.lang.String.class, value)); return true;
+        case "maxmessagesperpoll":
+        case "maxMessagesPerPoll": target.setMaxMessagesPerPoll(property(camelContext, int.class, value)); return true;
+        case "messageattributenames":
+        case "messageAttributeNames": target.getConfiguration().setMessageAttributeNames(property(camelContext, java.lang.String.class, value)); return true;
+        case "sendemptymessagewhenidle":
+        case "sendEmptyMessageWhenIdle": target.setSendEmptyMessageWhenIdle(property(camelContext, boolean.class, value)); return true;
+        case "serversideencryptionenabled":
+        case "serverSideEncryptionEnabled": target.getConfiguration().setServerSideEncryptionEnabled(property(camelContext, boolean.class, value)); return true;
+        case "visibilitytimeout":
+        case "visibilityTimeout": target.getConfiguration().setVisibilityTimeout(property(camelContext, java.lang.Integer.class, value)); return true;
+        case "waittimeseconds":
+        case "waitTimeSeconds": target.getConfiguration().setWaitTimeSeconds(property(camelContext, java.lang.Integer.class, value)); return true;
+        case "exceptionhandler":
+        case "exceptionHandler": target.setExceptionHandler(property(camelContext, org.apache.camel.spi.ExceptionHandler.class, value)); return true;
+        case "exchangepattern":
+        case "exchangePattern": target.setExchangePattern(property(camelContext, org.apache.camel.ExchangePattern.class, value)); return true;
+        case "pollstrategy":
+        case "pollStrategy": target.setPollStrategy(property(camelContext, org.apache.camel.spi.PollingConsumerPollStrategy.class, value)); return true;
+        case "delayseconds":
+        case "delaySeconds": target.getConfiguration().setDelaySeconds(property(camelContext, java.lang.Integer.class, value)); return true;
+        case "lazystartproducer":
+        case "lazyStartProducer": target.setLazyStartProducer(property(camelContext, boolean.class, value)); return true;
+        case "messagededuplicationidstrategy":
+        case "messageDeduplicationIdStrategy": target.getConfiguration().setMessageDeduplicationIdStrategy(property(camelContext, org.apache.camel.component.aws2.sqs.MessageDeduplicationIdStrategy.class, value)); return true;
+        case "messagegroupidstrategy":
+        case "messageGroupIdStrategy": target.getConfiguration().setMessageGroupIdStrategy(property(camelContext, org.apache.camel.component.aws2.sqs.MessageGroupIdStrategy.class, value)); return true;
+        case "operation": target.getConfiguration().setOperation(property(camelContext, org.apache.camel.component.aws2.sqs.Sqs2Operations.class, value)); return true;
+        case "basicpropertybinding":
+        case "basicPropertyBinding": target.setBasicPropertyBinding(property(camelContext, boolean.class, value)); return true;
+        case "delayqueue":
+        case "delayQueue": target.getConfiguration().setDelayQueue(property(camelContext, boolean.class, value)); return true;
+        case "queueurl":
+        case "queueUrl": target.getConfiguration().setQueueUrl(property(camelContext, java.lang.String.class, value)); return true;
+        case "synchronous": target.setSynchronous(property(camelContext, boolean.class, value)); return true;
+        case "backofferrorthreshold":
+        case "backoffErrorThreshold": target.setBackoffErrorThreshold(property(camelContext, int.class, value)); return true;
+        case "backoffidlethreshold":
+        case "backoffIdleThreshold": target.setBackoffIdleThreshold(property(camelContext, int.class, value)); return true;
+        case "backoffmultiplier":
+        case "backoffMultiplier": target.setBackoffMultiplier(property(camelContext, int.class, value)); return true;
+        case "delay": target.setDelay(property(camelContext, long.class, value)); return true;
+        case "greedy": target.setGreedy(property(camelContext, boolean.class, value)); return true;
+        case "initialdelay":
+        case "initialDelay": target.setInitialDelay(property(camelContext, long.class, value)); return true;
+        case "repeatcount":
+        case "repeatCount": target.setRepeatCount(property(camelContext, long.class, value)); return true;
+        case "runlogginglevel":
+        case "runLoggingLevel": target.setRunLoggingLevel(property(camelContext, org.apache.camel.LoggingLevel.class, value)); return true;
+        case "scheduledexecutorservice":
+        case "scheduledExecutorService": target.setScheduledExecutorService(property(camelContext, java.util.concurrent.ScheduledExecutorService.class, value)); return true;
+        case "scheduler": target.setScheduler(property(camelContext, java.lang.String.class, value)); return true;
+        case "schedulerproperties":
+        case "schedulerProperties": target.setSchedulerProperties(property(camelContext, java.util.Map.class, value)); return true;
+        case "startscheduler":
+        case "startScheduler": target.setStartScheduler(property(camelContext, boolean.class, value)); return true;
+        case "timeunit":
+        case "timeUnit": target.setTimeUnit(property(camelContext, java.util.concurrent.TimeUnit.class, value)); return true;
+        case "usefixeddelay":
+        case "useFixedDelay": target.setUseFixedDelay(property(camelContext, boolean.class, value)); return true;
+        case "proxyhost":
+        case "proxyHost": target.getConfiguration().setProxyHost(property(camelContext, java.lang.String.class, value)); return true;
+        case "proxyport":
+        case "proxyPort": target.getConfiguration().setProxyPort(property(camelContext, java.lang.Integer.class, value)); return true;
+        case "maximummessagesize":
+        case "maximumMessageSize": target.getConfiguration().setMaximumMessageSize(property(camelContext, java.lang.Integer.class, value)); return true;
+        case "messageretentionperiod":
+        case "messageRetentionPeriod": target.getConfiguration().setMessageRetentionPeriod(property(camelContext, java.lang.Integer.class, value)); return true;
+        case "policy": target.getConfiguration().setPolicy(property(camelContext, java.lang.String.class, value)); return true;
+        case "receivemessagewaittimeseconds":
+        case "receiveMessageWaitTimeSeconds": target.getConfiguration().setReceiveMessageWaitTimeSeconds(property(camelContext, java.lang.Integer.class, value)); return true;
+        case "redrivepolicy":
+        case "redrivePolicy": target.getConfiguration().setRedrivePolicy(property(camelContext, java.lang.String.class, value)); return true;
+        case "accesskey":
+        case "accessKey": target.getConfiguration().setAccessKey(property(camelContext, java.lang.String.class, value)); return true;
+        case "secretkey":
+        case "secretKey": target.getConfiguration().setSecretKey(property(camelContext, java.lang.String.class, value)); return true;
+        default: return false;
+        }
+    }
+
+}
+
diff --git a/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/component.properties b/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/component.properties
new file mode 100644
index 0000000..79b8e85
--- /dev/null
+++ b/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/component.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+components=aws2-sqs
+groupId=org.apache.camel
+artifactId=camel-aws2-sqs
+version=3.1.0-SNAPSHOT
+projectName=Camel :: AWS2 SQS
+projectDescription=A Camel Amazon SQS Web Service Component Version 2
diff --git a/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/component/aws2-sqs b/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/component/aws2-sqs
new file mode 100644
index 0000000..acb7538
--- /dev/null
+++ b/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/component/aws2-sqs
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.aws2.sqs.Sqs2Component
diff --git a/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-sqs-component b/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-sqs-component
new file mode 100644
index 0000000..52c2fca
--- /dev/null
+++ b/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-sqs-component
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.aws2.sqs.Sqs2ComponentConfigurer
diff --git a/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-sqs-endpoint b/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-sqs-endpoint
new file mode 100644
index 0000000..9b4151c
--- /dev/null
+++ b/components/camel-aws2-sqs/src/generated/resources/META-INF/services/org/apache/camel/configurer/aws2-sqs-endpoint
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.aws2.sqs.Sqs2EndpointConfigurer
diff --git a/components/camel-aws2-sqs/src/generated/resources/org/apache/camel/component/aws2/sqs/aws2-sqs.json b/components/camel-aws2-sqs/src/generated/resources/org/apache/camel/component/aws2/sqs/aws2-sqs.json
new file mode 100644
index 0000000..69b07ad
--- /dev/null
+++ b/components/camel-aws2-sqs/src/generated/resources/org/apache/camel/component/aws2/sqs/aws2-sqs.json
@@ -0,0 +1,91 @@
+{
+  "component": {
+    "kind": "component",
+    "scheme": "aws2-sqs",
+    "extendsScheme": "",
+    "syntax": "aws2-sqs:queueNameOrArn",
+    "title": "AWS 2 Simple Queue Service",
+    "description": "The aws-sqs component is used for sending and receiving messages to Amazon's SQS service.",
+    "label": "cloud,messaging",
+    "deprecated": false,
+    "async": false,
+    "consumerOnly": false,
+    "producerOnly": false,
+    "lenientProperties": false,
+    "javaType": "org.apache.camel.component.aws2.sqs.Sqs2Component",
+    "firstVersion": "3.1.0",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-aws2-sqs",
+    "version": "3.1.0-SNAPSHOT"
+  },
+  "componentProperties": {
+    "accessKey": { "kind": "property", "displayName": "Access Key", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "description": "Amazon AWS Access Key" },
+    "region": { "kind": "property", "displayName": "Region", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "description": "Specify the queue region which could be used with queueOwnerAWSAccountId to build the service URL." },
+    "secretKey": { "kind": "property", "displayName": "Secret Key", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "description": "Amazon AWS Secret Key" },
+    "bridgeErrorHandler": { "kind": "property", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by [...]
+    "lazyStartProducer": { "kind": "property", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the r [...]
+    "basicPropertyBinding": { "kind": "property", "displayName": "Basic Property Binding", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities" },
+    "configuration": { "kind": "property", "displayName": "Configuration", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "deprecated": false, "secret": false, "description": "The AWS SQS default configuration" }
+  },
+  "properties": {
+    "queueNameOrArn": { "kind": "path", "displayName": "Queue Name Or Arn", "group": "common", "label": "", "required": true, "type": "string", "javaType": "java.lang.String", "deprecated": false, "deprecationNote": "", "secret": false, "description": "Queue name or ARN" },
+    "amazonAWSHost": { "kind": "parameter", "displayName": "Amazon AWSHost", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "defaultValue": "amazonaws.com", "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The hostname of the Amazon AWS cloud." },
+    "amazonSQSClient": { "kind": "parameter", "displayName": "Amazon SQSClient", "group": "common", "label": "", "required": false, "type": "object", "javaType": "software.amazon.awssdk.services.sqs.SqsClient", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "To use the AmazonSQS as client" },
+    "autoCreateQueue": { "kind": "parameter", "displayName": "Auto Create Queue", "group": "common", "label": "", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": "true", "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Setting the autocreation of the queue" },
+    "headerFilterStrategy": { "kind": "parameter", "displayName": "Header Filter Strategy", "group": "common", "label": "", "required": false, "type": "object", "javaType": "org.apache.camel.spi.HeaderFilterStrategy", "deprecated": false, "secret": false, "description": "To use a custom HeaderFilterStrategy to map headers to\/from Camel." },
+    "protocol": { "kind": "parameter", "displayName": "Protocol", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "defaultValue": "https", "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The underlying protocol used to communicate with SQS" },
+    "proxyProtocol": { "kind": "parameter", "displayName": "Proxy Protocol", "group": "common", "label": "", "required": false, "type": "object", "javaType": "software.amazon.awssdk.core.Protocol", "enum": [ "HTTP", "HTTPS" ], "deprecated": false, "secret": false, "defaultValue": "HTTPS", "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "To define a proxy protocol when instantiating the SQS client" },
+    "queueOwnerAWSAccountId": { "kind": "parameter", "displayName": "Queue Owner AWSAccount Id", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Specify the queue owner aws account id when you need to connect the queue with different account owner." },
+    "region": { "kind": "parameter", "displayName": "Region", "group": "common", "label": "", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Specify the queue region which could be used with queueOwnerAWSAccountId to build the service URL. When using this parameter, the configuration will expect t [...]
+    "attributeNames": { "kind": "parameter", "displayName": "Attribute Names", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "A list of attribute names to receive when consuming. Multiple names can be separated by comma." },
+    "bridgeErrorHandler": { "kind": "parameter", "displayName": "Bridge Error Handler", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled b [...]
+    "concurrentConsumers": { "kind": "parameter", "displayName": "Concurrent Consumers", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "secret": false, "defaultValue": "1", "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Allows you to use multiple threads to poll the sqs queue to increase throughput" },
+    "defaultVisibilityTimeout": { "kind": "parameter", "displayName": "Default Visibility Timeout", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The default visibility timeout (in seconds)" },
+    "deleteAfterRead": { "kind": "parameter", "displayName": "Delete After Read", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": "true", "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Delete message from SQS after it has been read" },
+    "deleteIfFiltered": { "kind": "parameter", "displayName": "Delete If Filtered", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": "true", "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Whether or not to send the DeleteMessage to the SQS queue if an exchange fails to get through a filter. If 'f [...]
+    "extendMessageVisibility": { "kind": "parameter", "displayName": "Extend Message Visibility", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "If enabled then a scheduled background task will keep extending the message visibility on SQS. T [...]
+    "kmsDataKeyReusePeriodSeconds": { "kind": "parameter", "displayName": "Kms Data Key Reuse Period Seconds", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The length of time, in seconds, for which Amazon SQS can reuse a data key to encrypt or decrypt  [...]
+    "kmsMasterKeyId": { "kind": "parameter", "displayName": "Kms Master Key Id", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The ID of an AWS-managed customer master key (CMK) for Amazon SQS or a custom CMK." },
+    "maxMessagesPerPoll": { "kind": "parameter", "displayName": "Max Messages Per Poll", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "secret": false, "description": "Gets the maximum number of messages as a limit to poll at each polling. Is default unlimited, but use 0 or negative number to disable it as unlimited." },
+    "messageAttributeNames": { "kind": "parameter", "displayName": "Message Attribute Names", "group": "consumer", "label": "consumer", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "A list of message attribute names to receive when consuming. Multiple names can be separated by comma." },
+    "sendEmptyMessageWhenIdle": { "kind": "parameter", "displayName": "Send Empty Message When Idle", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead." },
+    "serverSideEncryptionEnabled": { "kind": "parameter", "displayName": "Server Side Encryption Enabled", "group": "consumer", "label": "consumer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Define if Server Side Encryption is enabled or not on the queue" },
+    "visibilityTimeout": { "kind": "parameter", "displayName": "Visibility Timeout", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The duration (in seconds) that the received messages are hidden from subsequent retrieve requests after being retrieved by [...]
+    "waitTimeSeconds": { "kind": "parameter", "displayName": "Wait Time Seconds", "group": "consumer", "label": "consumer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Duration in seconds (0 to 20) that the ReceiveMessage action call will wait until a message is in the queue to include in the [...]
+    "exceptionHandler": { "kind": "parameter", "displayName": "Exception Handler", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.ExceptionHandler", "optionalPrefix": "consumer.", "deprecated": false, "secret": false, "description": "To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with [...]
+    "exchangePattern": { "kind": "parameter", "displayName": "Exchange Pattern", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.ExchangePattern", "enum": [ "InOnly", "InOut", "InOptionalOut" ], "deprecated": false, "secret": false, "description": "Sets the exchange pattern when the consumer creates an exchange." },
+    "pollStrategy": { "kind": "parameter", "displayName": "Poll Strategy", "group": "consumer (advanced)", "label": "consumer,advanced", "required": false, "type": "object", "javaType": "org.apache.camel.spi.PollingConsumerPollStrategy", "deprecated": false, "secret": false, "description": "A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange h [...]
+    "delaySeconds": { "kind": "parameter", "displayName": "Delay Seconds", "group": "producer", "label": "producer", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Delay sending messages for a number of seconds." },
+    "lazyStartProducer": { "kind": "parameter", "displayName": "Lazy Start Producer", "group": "producer", "label": "producer", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the  [...]
+    "messageDeduplicationIdStrategy": { "kind": "parameter", "displayName": "Message Deduplication Id Strategy", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.aws2.sqs.MessageDeduplicationIdStrategy", "enum": [ "useExchangeId", "useContentBasedDeduplication" ], "deprecated": false, "secret": false, "defaultValue": "useExchangeId", "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "config [...]
+    "messageGroupIdStrategy": { "kind": "parameter", "displayName": "Message Group Id Strategy", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.aws2.sqs.MessageGroupIdStrategy", "enum": [ "useConstant", "useExchangeId", "usePropertyValue" ], "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Only f [...]
+    "operation": { "kind": "parameter", "displayName": "Operation", "group": "producer", "label": "producer", "required": false, "type": "object", "javaType": "org.apache.camel.component.aws2.sqs.Sqs2Operations", "enum": [ "sendBatchMessage", "deleteMessage", "listQueues" ], "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The operation to do in case the user don't w [...]
+    "basicPropertyBinding": { "kind": "parameter", "displayName": "Basic Property Binding", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities" },
+    "delayQueue": { "kind": "parameter", "displayName": "Delay Queue", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Define if you want to apply delaySeconds option to the queue or on single messages" },
+    "queueUrl": { "kind": "parameter", "displayName": "Queue Url", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "To define the queueUrl explicitly. All other parameters, which would influence the queueUrl, are ignored. This parameter is intended to be use [...]
+    "synchronous": { "kind": "parameter", "displayName": "Synchronous", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": "false", "description": "Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported)." },
+    "backoffErrorThreshold": { "kind": "parameter", "displayName": "Backoff Error Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "secret": false, "description": "The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in." },
+    "backoffIdleThreshold": { "kind": "parameter", "displayName": "Backoff Idle Threshold", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "secret": false, "description": "The number of subsequent idle polls that should happen before the backoffMultipler should kick-in." },
+    "backoffMultiplier": { "kind": "parameter", "displayName": "Backoff Multiplier", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "int", "deprecated": false, "secret": false, "description": "To let the scheduled polling consumer backoff if there has been a number of subsequent idles\/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option  [...]
+    "delay": { "kind": "parameter", "displayName": "Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "secret": false, "defaultValue": "500", "description": "Milliseconds before the next poll. You can also specify time values using units, such as 60s (60 seconds), 5m30s (5 minutes and 30 seconds), and 1h (1 hour)." },
+    "greedy": { "kind": "parameter", "displayName": "Greedy", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": false, "description": "If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages." },
+    "initialDelay": { "kind": "parameter", "displayName": "Initial Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "secret": false, "defaultValue": "1000", "description": "Milliseconds before the first poll starts. You can also specify time values using units, such as 60s (60 seconds), 5m30s (5 minutes and 30 seconds), and 1h (1 hour)." },
+    "repeatCount": { "kind": "parameter", "displayName": "Repeat Count", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "integer", "javaType": "long", "deprecated": false, "secret": false, "defaultValue": "0", "description": "Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever." },
+    "runLoggingLevel": { "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the logging level for that." },
+    "scheduledExecutorService": { "kind": "parameter", "displayName": "Scheduled Executor Service", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.ScheduledExecutorService", "deprecated": false, "secret": false, "description": "Allows for configuring a custom\/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool." },
+    "scheduler": { "kind": "parameter", "displayName": "Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "string", "javaType": "java.lang.String", "enum": [ "none", "spring", "quartz" ], "deprecated": false, "secret": false, "defaultValue": "none", "description": "To use a cron scheduler from either camel-spring or camel-quartz component" },
+    "schedulerProperties": { "kind": "parameter", "displayName": "Scheduler Properties", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.Map<java.lang.String, java.lang.Object>", "prefix": "scheduler.", "multiValue": true, "deprecated": false, "secret": false, "description": "To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler." },
+    "startScheduler": { "kind": "parameter", "displayName": "Start Scheduler", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": "true", "description": "Whether the scheduler should be auto started." },
+    "timeUnit": { "kind": "parameter", "displayName": "Time Unit", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "java.util.concurrent.TimeUnit", "enum": [ "NANOSECONDS", "MICROSECONDS", "MILLISECONDS", "SECONDS", "MINUTES", "HOURS", "DAYS" ], "deprecated": false, "secret": false, "defaultValue": "MILLISECONDS", "description": "Time unit for initialDelay and delay options." },
+    "useFixedDelay": { "kind": "parameter", "displayName": "Use Fixed Delay", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "secret": false, "defaultValue": "true", "description": "Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details." },
+    "proxyHost": { "kind": "parameter", "displayName": "Proxy Host", "group": "proxy", "label": "proxy", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "To define a proxy host when instantiating the SQS client" },
+    "proxyPort": { "kind": "parameter", "displayName": "Proxy Port", "group": "proxy", "label": "proxy", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "To define a proxy port when instantiating the SQS client" },
+    "maximumMessageSize": { "kind": "parameter", "displayName": "Maximum Message Size", "group": "queue", "label": "queue", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The maximumMessageSize (in bytes) an SQS message can contain for this queue." },
+    "messageRetentionPeriod": { "kind": "parameter", "displayName": "Message Retention Period", "group": "queue", "label": "queue", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The messageRetentionPeriod (in seconds) a message will be retained by SQS for this queue." },
+    "policy": { "kind": "parameter", "displayName": "Policy", "group": "queue", "label": "queue", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "The policy for this queue" },
+    "receiveMessageWaitTimeSeconds": { "kind": "parameter", "displayName": "Receive Message Wait Time Seconds", "group": "queue", "label": "queue", "required": false, "type": "integer", "javaType": "java.lang.Integer", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "If you do not specify WaitTimeSeconds in the request, the queue attribute ReceiveMessageWaitTimeSecon [...]
+    "redrivePolicy": { "kind": "parameter", "displayName": "Redrive Policy", "group": "queue", "label": "queue", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": false, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Specify the policy that send message to DeadLetter queue. See detail at Amazon docs." },
+    "accessKey": { "kind": "parameter", "displayName": "Access Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Amazon AWS Access Key" },
+    "secretKey": { "kind": "parameter", "displayName": "Secret Key", "group": "security", "label": "security", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "secret": true, "configurationClass": "org.apache.camel.component.aws2.sqs.Sqs2Configuration", "configurationField": "configuration", "description": "Amazon AWS Secret Key" }
+  }
+}
diff --git a/components/camel-aws2-sqs/src/main/docs/aws-sqs-component.adoc b/components/camel-aws2-sqs/src/main/docs/aws-sqs-component.adoc
new file mode 100644
index 0000000..0ef2a20
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/docs/aws-sqs-component.adoc
@@ -0,0 +1,361 @@
+[[aws-sqs-component]]
+= AWS Simple Queue Service Component
+
+*Since Camel 2.6*
+
+// HEADER START
+*Both producer and consumer is supported*
+// HEADER END
+
+The sqs component supports sending and receiving messages to
+https://aws.amazon.com/sqs[Amazon's SQS] service.
+
+Prerequisites
+
+You must have a valid Amazon Web Services developer account, and be
+signed up to use Amazon SQS. More information is available at
+https://aws.amazon.com/sqs[Amazon SQS].
+
+== URI Format
+
+[source,java]
+------------------------------
+aws-sqs://queueNameOrArn[?options]
+------------------------------
+
+The queue will be created if they don't already exists. +
+ You can append query options to the URI in the following format,
+?options=value&option2=value&...
+
+== URI Options
+
+
+// component options: START
+The AWS Simple Queue Service component supports 7 options, which are listed below.
+
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *accessKey* (common) | Amazon AWS Access Key |  | String
+| *region* (common) | Specify the queue region which could be used with queueOwnerAWSAccountId to build the service URL. |  | String
+| *secretKey* (common) | Amazon AWS Secret Key |  | String
+| *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
+| *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
+| *basicPropertyBinding* (advanced) | Whether the component should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities | false | boolean
+| *configuration* (advanced) | The AWS SQS default configuration |  | SqsConfiguration
+|===
+// component options: END
+
+
+
+
+
+
+
+
+// endpoint options: START
+The AWS Simple Queue Service endpoint is configured using URI syntax:
+
+----
+aws-sqs:queueNameOrArn
+----
+
+with the following path and query parameters:
+
+=== Path Parameters (1 parameters):
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *queueNameOrArn* | *Required* Queue name or ARN |  | String
+|===
+
+
+=== Query Parameters (58 parameters):
+
+
+[width="100%",cols="2,5,^1,2",options="header"]
+|===
+| Name | Description | Default | Type
+| *amazonAWSHost* (common) | The hostname of the Amazon AWS cloud. | amazonaws.com | String
+| *amazonSQSClient* (common) | To use the AmazonSQS as client |  | AmazonSQS
+| *autoCreateQueue* (common) | Setting the autocreation of the queue | true | boolean
+| *headerFilterStrategy* (common) | To use a custom HeaderFilterStrategy to map headers to/from Camel. |  | HeaderFilterStrategy
+| *protocol* (common) | The underlying protocol used to communicate with SQS | https | String
+| *proxyProtocol* (common) | To define a proxy protocol when instantiating the SQS client. The value can be one of: HTTP, HTTPS | HTTPS | Protocol
+| *queueOwnerAWSAccountId* (common) | Specify the queue owner aws account id when you need to connect the queue with different account owner. |  | String
+| *region* (common) | Specify the queue region which could be used with queueOwnerAWSAccountId to build the service URL. When using this parameter, the configuration will expect the capitalized name of the region (for example AP_EAST_1) You'll need to use the name Regions.EU_WEST_1.name() |  | String
+| *attributeNames* (consumer) | A list of attribute names to receive when consuming. Multiple names can be separated by comma. |  | String
+| *bridgeErrorHandler* (consumer) | Allows for bridging the consumer to the Camel routing Error Handler, which mean any exceptions occurred while the consumer is trying to pickup incoming messages, or the likes, will now be processed as a message and handled by the routing Error Handler. By default the consumer will use the org.apache.camel.spi.ExceptionHandler to deal with exceptions, that will be logged at WARN or ERROR level and ignored. | false | boolean
+| *concurrentConsumers* (consumer) | Allows you to use multiple threads to poll the sqs queue to increase throughput | 1 | int
+| *defaultVisibilityTimeout* (consumer) | The default visibility timeout (in seconds) |  | Integer
+| *deleteAfterRead* (consumer) | Delete message from SQS after it has been read | true | boolean
+| *deleteIfFiltered* (consumer) | Whether or not to send the DeleteMessage to the SQS queue if an exchange fails to get through a filter. If 'false' and exchange does not make it through a Camel filter upstream in the route, then don't send DeleteMessage. | true | boolean
+| *extendMessageVisibility* (consumer) | If enabled then a scheduled background task will keep extending the message visibility on SQS. This is needed if it takes a long time to process the message. If set to true defaultVisibilityTimeout must be set. See details at Amazon docs. | false | boolean
+| *kmsDataKeyReusePeriodSeconds* (consumer) | The length of time, in seconds, for which Amazon SQS can reuse a data key to encrypt or decrypt messages before calling AWS KMS again. An integer representing seconds, between 60 seconds (1 minute) and 86,400 seconds (24 hours). Default: 300 (5 minutes). |  | Integer
+| *kmsMasterKeyId* (consumer) | The ID of an AWS-managed customer master key (CMK) for Amazon SQS or a custom CMK. |  | String
+| *maxMessagesPerPoll* (consumer) | Gets the maximum number of messages as a limit to poll at each polling. Is default unlimited, but use 0 or negative number to disable it as unlimited. |  | int
+| *messageAttributeNames* (consumer) | A list of message attribute names to receive when consuming. Multiple names can be separated by comma. |  | String
+| *sendEmptyMessageWhenIdle* (consumer) | If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead. | false | boolean
+| *serverSideEncryptionEnabled* (consumer) | Define if Server Side Encryption is enabled or not on the queue | false | boolean
+| *visibilityTimeout* (consumer) | The duration (in seconds) that the received messages are hidden from subsequent retrieve requests after being retrieved by a ReceiveMessage request to set in the com.amazonaws.services.sqs.model.SetQueueAttributesRequest. This only make sense if its different from defaultVisibilityTimeout. It changes the queue visibility timeout attribute permanently. |  | Integer
+| *waitTimeSeconds* (consumer) | Duration in seconds (0 to 20) that the ReceiveMessage action call will wait until a message is in the queue to include in the response. |  | Integer
+| *exceptionHandler* (consumer) | To let the consumer use a custom ExceptionHandler. Notice if the option bridgeErrorHandler is enabled then this option is not in use. By default the consumer will deal with exceptions, that will be logged at WARN or ERROR level and ignored. |  | ExceptionHandler
+| *exchangePattern* (consumer) | Sets the exchange pattern when the consumer creates an exchange. The value can be one of: InOnly, InOut, InOptionalOut |  | ExchangePattern
+| *pollStrategy* (consumer) | A pluggable org.apache.camel.PollingConsumerPollingStrategy allowing you to provide your custom implementation to control error handling usually occurred during the poll operation before an Exchange have been created and being routed in Camel. |  | PollingConsumerPollStrategy
+| *delaySeconds* (producer) | Delay sending messages for a number of seconds. |  | Integer
+| *lazyStartProducer* (producer) | Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first message is processed then creating and [...]
+| *messageDeduplicationIdStrategy* (producer) | Only for FIFO queues. Strategy for setting the messageDeduplicationId on the message. Can be one of the following options: useExchangeId, useContentBasedDeduplication. For the useContentBasedDeduplication option, no messageDeduplicationId will be set on the message. The value can be one of: useExchangeId, useContentBasedDeduplication | useExchangeId | MessageDeduplicationIdStrategy
+| *messageGroupIdStrategy* (producer) | Only for FIFO queues. Strategy for setting the messageGroupId on the message. Can be one of the following options: useConstant, useExchangeId, usePropertyValue. For the usePropertyValue option, the value of property CamelAwsMessageGroupId will be used. The value can be one of: useConstant, useExchangeId, usePropertyValue |  | MessageGroupIdStrategy
+| *operation* (producer) | The operation to do in case the user don't want to send only a message. The value can be one of: sendBatchMessage, deleteMessage, listQueues |  | SqsOperations
+| *basicPropertyBinding* (advanced) | Whether the endpoint should use basic property binding (Camel 2.x) or the newer property binding with additional capabilities | false | boolean
+| *delayQueue* (advanced) | Define if you want to apply delaySeconds option to the queue or on single messages | false | boolean
+| *queueUrl* (advanced) | To define the queueUrl explicitly. All other parameters, which would influence the queueUrl, are ignored. This parameter is intended to be used, to connect to a mock implementation of SQS, for testing purposes. |  | String
+| *synchronous* (advanced) | Sets whether synchronous processing should be strictly used, or Camel is allowed to use asynchronous processing (if supported). | false | boolean
+| *backoffErrorThreshold* (scheduler) | The number of subsequent error polls (failed due some error) that should happen before the backoffMultipler should kick-in. |  | int
+| *backoffIdleThreshold* (scheduler) | The number of subsequent idle polls that should happen before the backoffMultipler should kick-in. |  | int
+| *backoffMultiplier* (scheduler) | To let the scheduled polling consumer backoff if there has been a number of subsequent idles/errors in a row. The multiplier is then the number of polls that will be skipped before the next actual attempt is happening again. When this option is in use then backoffIdleThreshold and/or backoffErrorThreshold must also be configured. |  | int
+| *delay* (scheduler) | Milliseconds before the next poll. You can also specify time values using units, such as 60s (60 seconds), 5m30s (5 minutes and 30 seconds), and 1h (1 hour). | 500 | long
+| *greedy* (scheduler) | If greedy is enabled, then the ScheduledPollConsumer will run immediately again, if the previous run polled 1 or more messages. | false | boolean
+| *initialDelay* (scheduler) | Milliseconds before the first poll starts. You can also specify time values using units, such as 60s (60 seconds), 5m30s (5 minutes and 30 seconds), and 1h (1 hour). | 1000 | long
+| *repeatCount* (scheduler) | Specifies a maximum limit of number of fires. So if you set it to 1, the scheduler will only fire once. If you set it to 5, it will only fire five times. A value of zero or negative means fire forever. | 0 | long
+| *runLoggingLevel* (scheduler) | The consumer logs a start/complete log line when it polls. This option allows you to configure the logging level for that. The value can be one of: TRACE, DEBUG, INFO, WARN, ERROR, OFF | TRACE | LoggingLevel
+| *scheduledExecutorService* (scheduler) | Allows for configuring a custom/shared thread pool to use for the consumer. By default each consumer has its own single threaded thread pool. |  | ScheduledExecutorService
+| *scheduler* (scheduler) | To use a cron scheduler from either camel-spring or camel-quartz component. The value can be one of: none, spring, quartz | none | String
+| *schedulerProperties* (scheduler) | To configure additional properties when using a custom scheduler or any of the Quartz, Spring based scheduler. |  | Map
+| *startScheduler* (scheduler) | Whether the scheduler should be auto started. | true | boolean
+| *timeUnit* (scheduler) | Time unit for initialDelay and delay options. The value can be one of: NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS | MILLISECONDS | TimeUnit
+| *useFixedDelay* (scheduler) | Controls if fixed delay or fixed rate is used. See ScheduledExecutorService in JDK for details. | true | boolean
+| *proxyHost* (proxy) | To define a proxy host when instantiating the SQS client |  | String
+| *proxyPort* (proxy) | To define a proxy port when instantiating the SQS client |  | Integer
+| *maximumMessageSize* (queue) | The maximumMessageSize (in bytes) an SQS message can contain for this queue. |  | Integer
+| *messageRetentionPeriod* (queue) | The messageRetentionPeriod (in seconds) a message will be retained by SQS for this queue. |  | Integer
+| *policy* (queue) | The policy for this queue |  | String
+| *receiveMessageWaitTimeSeconds* (queue) | If you do not specify WaitTimeSeconds in the request, the queue attribute ReceiveMessageWaitTimeSeconds is used to determine how long to wait. |  | Integer
+| *redrivePolicy* (queue) | Specify the policy that send message to DeadLetter queue. See detail at Amazon docs. |  | String
+| *accessKey* (security) | Amazon AWS Access Key |  | String
+| *secretKey* (security) | Amazon AWS Secret Key |  | String
+|===
+// endpoint options: END
+
+
+
+
+
+
+
+
+Required SQS component options
+
+You have to provide the amazonSQSClient in the
+Registry or your accessKey and secretKey to access
+the https://aws.amazon.com/sqs[Amazon's SQS].
+
+== Batch Consumer
+
+This component implements the Batch Consumer.
+
+This allows you for instance to know how many messages exists in this
+batch and for instance let the Aggregator
+aggregate this number of messages.
+
+== Usage
+
+=== Message headers set by the SQS producer
+
+[width="100%",cols="10%,10%,80%",options="header",]
+|=======================================================================
+|Header |Type |Description
+
+|`CamelAwsSqsMD5OfBody` |`String` |The MD5 checksum of the Amazon SQS message.
+
+|`CamelAwsSqsMessageId` |`String` |The Amazon SQS message ID.
+
+|`CamelAwsSqsDelaySeconds` |`Integer` |The delay seconds that the Amazon SQS message can be
+see by others.
+|=======================================================================
+
+=== Message headers set by the SQS consumer
+
+[width="100%",cols="10%,10%,80%",options="header",]
+|=======================================================================
+|Header |Type |Description
+
+|`CamelAwsSqsMD5OfBody` |`String` |The MD5 checksum of the Amazon SQS message.
+
+|`CamelAwsSqsMessageId` |`String` |The Amazon SQS message ID. 
+
+|`CamelAwsSqsReceiptHandle` |`String` |The Amazon SQS message receipt handle.
+
+|`CamelAwsSqsMessageAttributes` |`Map<String, String>` |The Amazon SQS message attributes.
+|=======================================================================
+
+=== Advanced AmazonSQS configuration
+
+If your Camel Application is running behind a firewall or if you need to
+have more control over the AmazonSQS instance configuration, you can
+create your own instance:
+
+[source,java]
+--------------------------------------------------------------------------------------
+AWSCredentials awsCredentials = new BasicAWSCredentials("myAccessKey", "mySecretKey");
+
+ClientConfiguration clientConfiguration = new ClientConfiguration();
+clientConfiguration.setProxyHost("http://myProxyHost");
+clientConfiguration.setProxyPort(8080);
+
+AmazonSQS client = new AmazonSQSClient(awsCredentials, clientConfiguration);
+
+registry.bind("client", client);
+--------------------------------------------------------------------------------------
+
+and refer to it in your Camel aws-sqs component configuration:
+
+[source,java]
+---------------------------------------------------------------------------------
+from("aws-sqs://MyQueue?amazonSQSClient=#client&delay=5000&maxMessagesPerPoll=5")
+.to("mock:result");
+---------------------------------------------------------------------------------
+
+=== Creating or updating an SQS Queue
+
+In the SQS Component, when an endpoint is started, a check is executed to obtain information 
+about the existence of the queue or not. You're able to customize the creation through the QueueAttributeName 
+mapping with the SQSConfiguration option.
+
+[source,java]
+---------------------------------------------------------------------------------
+from("aws-sqs://MyQueue?amazonSQSClient=#client&delay=5000&maxMessagesPerPoll=5")
+.to("mock:result");
+---------------------------------------------------------------------------------
+
+In this example if the MyQueue queue is not already created on AWS (and the autoCreateQueue option is set to true), it will be created with default parameters from the 
+SQS configuration. If it's already up on AWS, the SQS configuration options will be used to override the existent AWS configuration.
+
+=== DelayQueue VS Delay for Single message
+
+When the option delayQueue is set to true, the SQS Queue will be a DelayQueue with the
+DelaySeconds option as delay. For more information about DelayQueue you can read the https://docs.aws.amazon.com/en_us/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-delay-queues.html[AWS SQS documentation].
+One important information to take into account is the following:
+
+- For standard queues, the per-queue delay setting is not retroactive—changing the setting doesn't affect the delay of messages already in the queue.
+- For FIFO queues, the per-queue delay setting is retroactive—changing the setting affects the delay of messages already in the queue.
+
+as stated in the official documentation. If you want to specify a delay on single messages, you can ignore the delayQueue option, while you can set this option 
+to true, if you need to add a fixed delay to all messages enqueued.
+
+=== Server Side Encryption
+
+There is a set of Server Side Encryption attributes for a queue. The related option are serverSideEncryptionEnabled, keyMasterKeyId and kmsDataKeyReusePeriod.
+The SSE is disabled by default. You need to explicitly set the option to true and set the related parameters as queue attributes.
+
+== Dependencies
+
+Maven users will need to add the following dependency to their pom.xml.
+
+*pom.xml*
+
+[source,xml]
+---------------------------------------
+<dependency>
+    <groupId>org.apache.camel</groupId>
+    <artifactId>camel-aws-sqs</artifactId>
+    <version>${camel-version}</version>
+</dependency>
+---------------------------------------
+
+where `$\{camel-version\}` must be replaced by the actual version of Camel.
+
+== JMS-style Selectors
+
+SQS does not allow selectors, but you can effectively achieve this by
+using the Camel Filter EIP and setting an
+appropriate `visibilityTimeout`. When SQS dispatches a message, it will
+wait up to the visibility timeout before it will try to dispatch the
+message to a different consumer unless a DeleteMessage is received. By
+default, Camel will always send the DeleteMessage at the end of the
+route, unless the route ended in failure. To achieve appropriate
+filtering and not send the DeleteMessage even on successful completion
+of the route, use a Filter:
+
+[source,java]
+------------------------------------------------------------------------------------------------------
+from("aws-sqs://MyQueue?amazonSQSClient=#client&defaultVisibilityTimeout=5000&deleteIfFiltered=false&deleteAfterRead=false")
+.filter("${header.login} == true")
+.to("mock:result");
+------------------------------------------------------------------------------------------------------
+
+In the above code, if an exchange doesn't have an appropriate header, it
+will not make it through the filter AND also not be deleted from the SQS
+queue. After 5000 milliseconds, the message will become visible to other
+consumers.
+
+== Available Producer Operations
+- single message (default)
+- sendBatchMessage
+- deleteMessage
+- listQueues
+
+== Send Batch Message
+
+You can set a `SendMessageBatchRequest` or an `Iterable`
+
+------------------------------------------------------------------------------------------------------
+from("direct:start")
+  .setHeader(SqsConstants.SQS_OPERATION, constant("sendBatchMessage")).to("aws-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)&region=EU_WEST_1");
+------------------------------------------------------------------------------------------------------
+
+As result you'll get an exchange containing a `SendMessageBatchResult` instance, that you can examinate to check what messages were successfull and what not.
+The id set on each message of the batch will be a Random UUID.
+
+== Delete single Message
+
+Use deleteMessage operation to delete a single message. You'll need to set a receipt handle header for the message you want to delete.
+
+------------------------------------------------------------------------------------------------------
+from("direct:start")
+  .setHeader(SqsConstants.SQS_OPERATION, constant("deleteMessage"))
+  .setHeader(SqsConstants.RECEIPT_HANDLE, constant("123456"))
+  .to("aws-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)&region=EU_WEST_1");
+------------------------------------------------------------------------------------------------------
+
+As result you'll get an exchange containing a `DeleteMessageResult` instance, that you can use to check if the message was deleted or not.
+
+== List Queues
+
+Use listQueues operation to list queues.
+
+------------------------------------------------------------------------------------------------------
+from("direct:start")
+  .setHeader(SqsConstants.SQS_OPERATION, constant("listQueues")).to("aws-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)&region=EU_WEST_1");
+------------------------------------------------------------------------------------------------------
+
+As result you'll get an exchange containing a `ListQueuesResult` instance, that you can examinate to check the actual queues.
+
+== Queue Autocreation
+
+With the option `autoCreateQueue` users are able to avoid the autocreation of an SQS Queue in case it doesn't exist. The default for this option is `true`.
+If set to false any operation on a not-existent queue in AWS won't be successful and an error will be returned.
+
+== Automatic detection of AmazonSQS client in registry
+
+The component is capable of detecting the presence of an AmazonSQS bean into the registry.
+If it's the only instance of that type it will be used as client and you won't have to define it as uri parameter.
+This may be really useful for smarter configuration of the endpoint.
+
+== Send Batch Message and Message Deduplication Strategy
+
+In case you're using a SendBatchMessage Operation, you can set two different kind of Message Deduplication Strategy:
+- useExchangeId
+- useContentBasedDeduplication
+
+The first one will use a ExchangeIdMessageDeduplicationIdStrategy, that will use the Exchange ID as parameter
+The other one will use a NullMessageDeduplicationIdStrategy, that will use the body as deduplication element.
+
+In case of send batch message operation, you'll need to use the `useContentBasedDeduplication` and on the Queue you're pointing you'll need to enable the `content based deduplication` option.
+
+
+include::camel-spring-boot::page$aws-sqs-starter.adoc[]
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/ConstantMessageGroupIdStrategy.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/ConstantMessageGroupIdStrategy.java
new file mode 100644
index 0000000..15978b6
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/ConstantMessageGroupIdStrategy.java
@@ -0,0 +1,28 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.Exchange;
+
+public class ConstantMessageGroupIdStrategy implements MessageGroupIdStrategy {
+
+    @Override
+    public String getMessageGroupId(Exchange exchange) {
+        return "CamelSingleMessageGroup";
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/ExchangeIdMessageDeduplicationIdStrategy.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/ExchangeIdMessageDeduplicationIdStrategy.java
new file mode 100644
index 0000000..8202650
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/ExchangeIdMessageDeduplicationIdStrategy.java
@@ -0,0 +1,28 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.Exchange;
+
+public class ExchangeIdMessageDeduplicationIdStrategy implements MessageDeduplicationIdStrategy {
+
+    @Override
+    public String getMessageDeduplicationId(Exchange exchange) {
+        return exchange.getExchangeId();
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/ExchangeIdMessageGroupIdStrategy.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/ExchangeIdMessageGroupIdStrategy.java
new file mode 100644
index 0000000..1792939
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/ExchangeIdMessageGroupIdStrategy.java
@@ -0,0 +1,28 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.Exchange;
+
+public class ExchangeIdMessageGroupIdStrategy implements MessageGroupIdStrategy {
+
+    @Override
+    public String getMessageGroupId(Exchange exchange) {
+        return exchange.getExchangeId();
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/MessageDeduplicationIdStrategy.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/MessageDeduplicationIdStrategy.java
new file mode 100644
index 0000000..1dc811f
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/MessageDeduplicationIdStrategy.java
@@ -0,0 +1,25 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.Exchange;
+
+public interface MessageDeduplicationIdStrategy {
+
+    String getMessageDeduplicationId(Exchange exchange);
+
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/MessageGroupIdStrategy.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/MessageGroupIdStrategy.java
new file mode 100644
index 0000000..478d957
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/MessageGroupIdStrategy.java
@@ -0,0 +1,25 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.Exchange;
+
+public interface MessageGroupIdStrategy {
+
+    String getMessageGroupId(Exchange exchange);
+
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/NullMessageDeduplicationIdStrategy.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/NullMessageDeduplicationIdStrategy.java
new file mode 100644
index 0000000..a5ce7fd
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/NullMessageDeduplicationIdStrategy.java
@@ -0,0 +1,28 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.Exchange;
+
+public class NullMessageDeduplicationIdStrategy implements MessageDeduplicationIdStrategy {
+
+    @Override
+    public String getMessageDeduplicationId(Exchange exchange) {
+        return null;
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/PropertyValueMessageGroupIdStrategy.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/PropertyValueMessageGroupIdStrategy.java
new file mode 100644
index 0000000..bec6842
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/PropertyValueMessageGroupIdStrategy.java
@@ -0,0 +1,28 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.Exchange;
+
+public class PropertyValueMessageGroupIdStrategy implements MessageGroupIdStrategy {
+
+    @Override
+    public String getMessageGroupId(Exchange exchange) {
+        return exchange.getProperty(Sqs2Constants.MESSAGE_GROUP_ID_PROPERTY, String.class);
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Component.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Component.java
new file mode 100644
index 0000000..6acad08
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Component.java
@@ -0,0 +1,140 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.Component;
+import org.apache.camel.support.DefaultComponent;
+
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.sqs.SqsClient;
+
+@Component("aws2-sqs")
+public class Sqs2Component extends DefaultComponent {
+
+    @Metadata
+    private String accessKey;
+    @Metadata
+    private String secretKey;
+    @Metadata
+    private String region;
+    @Metadata(label = "advanced")
+    private Sqs2Configuration configuration;
+
+    public Sqs2Component() {
+        this(null);
+    }
+
+    public Sqs2Component(CamelContext context) {
+        super(context);
+
+        registerExtension(new Sqs2ComponentVerifierExtension());
+    }
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
+
+        if (remaining == null || remaining.trim().length() == 0) {
+            throw new IllegalArgumentException("Queue name must be specified.");
+        }
+        Sqs2Configuration configuration = this.configuration != null ? this.configuration.copy() : new Sqs2Configuration();
+        if (remaining.startsWith("arn:")) {
+            String[] parts = remaining.split(":");
+            if (parts.length != 6 || !parts[2].equals("sqs")) {
+                throw new IllegalArgumentException("Queue arn must be in format arn:aws:sqs:region:account:name.");
+            }
+            configuration.setRegion(Region.of(parts[3]).toString());
+            configuration.setQueueOwnerAWSAccountId(parts[4]);
+            configuration.setQueueName(parts[5]);
+        } else {
+            configuration.setQueueName(remaining);
+        }
+        Sqs2Endpoint sqsEndpoint = new Sqs2Endpoint(uri, this, configuration);
+        sqsEndpoint.getConfiguration().setAccessKey(accessKey);
+        sqsEndpoint.getConfiguration().setSecretKey(secretKey);
+        sqsEndpoint.getConfiguration().setRegion(region);
+        setProperties(sqsEndpoint, parameters);
+        checkAndSetRegistryClient(configuration);
+        if (configuration.getAmazonSQSClient() == null && (configuration.getAccessKey() == null || configuration.getSecretKey() == null)) {
+            throw new IllegalArgumentException("AmazonSQSClient or accessKey and secretKey must be specified.");
+        }
+
+        // Verify that visibilityTimeout is set if extendMessageVisibility is
+        // set to true.
+        if (configuration.isExtendMessageVisibility() && (configuration.getVisibilityTimeout() == null)) {
+            throw new IllegalArgumentException("Extending message visibility (extendMessageVisibility) requires visibilityTimeout to be set on the Endpoint.");
+        }
+        return sqsEndpoint;
+    }
+
+    public Sqs2Configuration getConfiguration() {
+        return configuration;
+    }
+
+    /**
+     * The AWS SQS default configuration
+     */
+    public void setConfiguration(Sqs2Configuration configuration) {
+        this.configuration = configuration;
+    }
+
+    public String getAccessKey() {
+        return accessKey;
+    }
+
+    /**
+     * Amazon AWS Access Key
+     */
+    public void setAccessKey(String accessKey) {
+        this.accessKey = accessKey;
+    }
+
+    public String getSecretKey() {
+        return secretKey;
+    }
+
+    /**
+     * Amazon AWS Secret Key
+     */
+    public void setSecretKey(String secretKey) {
+        this.secretKey = secretKey;
+    }
+
+    public String getRegion() {
+        return region;
+    }
+
+    /**
+     * Specify the queue region which could be used with queueOwnerAWSAccountId
+     * to build the service URL.
+     */
+    public void setRegion(String region) {
+        this.region = region;
+    }
+
+    private void checkAndSetRegistryClient(Sqs2Configuration configuration) {
+        Set<SqsClient> clients = getCamelContext().getRegistry().findByType(SqsClient.class);
+        if (clients.size() == 1) {
+            configuration.setAmazonSQSClient(clients.stream().findFirst().get());
+        }
+    }
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2ComponentVerifierExtension.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2ComponentVerifierExtension.java
new file mode 100644
index 0000000..f0d79c0
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2ComponentVerifierExtension.java
@@ -0,0 +1,85 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import java.util.Map;
+
+import org.apache.camel.component.extension.verifier.DefaultComponentVerifierExtension;
+import org.apache.camel.component.extension.verifier.ResultBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorBuilder;
+import org.apache.camel.component.extension.verifier.ResultErrorHelper;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.core.exception.SdkClientException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.SqsClientBuilder;
+
+public class Sqs2ComponentVerifierExtension extends DefaultComponentVerifierExtension {
+
+    public Sqs2ComponentVerifierExtension() {
+        this("aws2-sqs");
+    }
+
+    public Sqs2ComponentVerifierExtension(String scheme) {
+        super(scheme);
+    }
+
+    // *********************************
+    // Parameters validation
+    // *********************************
+
+    @Override
+    protected Result verifyParameters(Map<String, Object> parameters) {
+
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.PARAMETERS).error(ResultErrorHelper.requiresOption("accessKey", parameters))
+            .error(ResultErrorHelper.requiresOption("secretKey", parameters)).error(ResultErrorHelper.requiresOption("region", parameters));
+
+        // Validate using the catalog
+
+        super.verifyParametersAgainstCatalog(builder, parameters);
+
+        return builder.build();
+    }
+
+    // *********************************
+    // Connectivity validation
+    // *********************************
+
+    @Override
+    protected Result verifyConnectivity(Map<String, Object> parameters) {
+        ResultBuilder builder = ResultBuilder.withStatusAndScope(Result.Status.OK, Scope.CONNECTIVITY);
+
+        try {
+            Sqs2Configuration configuration = setProperties(new Sqs2Configuration(), parameters);
+            AwsBasicCredentials cred = AwsBasicCredentials.create(configuration.getAccessKey(), configuration.getSecretKey());
+            SqsClientBuilder clientBuilder = SqsClient.builder();
+            SqsClient client = clientBuilder.credentialsProvider(StaticCredentialsProvider.create(cred)).region(Region.of(configuration.getRegion())).build();
+            client.listQueues();
+        } catch (SdkClientException e) {
+            ResultErrorBuilder errorBuilder = ResultErrorBuilder.withCodeAndDescription(VerificationError.StandardCode.AUTHENTICATION, e.getMessage())
+                .detail("aws_sqs_exception_message", e.getMessage()).detail(VerificationError.ExceptionAttribute.EXCEPTION_CLASS, e.getClass().getName())
+                .detail(VerificationError.ExceptionAttribute.EXCEPTION_INSTANCE, e);
+
+            builder.error(errorBuilder.build());
+        } catch (Exception e) {
+            builder.error(ResultErrorBuilder.withException(e).build());
+        }
+        return builder.build();
+    }
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Configuration.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Configuration.java
new file mode 100644
index 0000000..df0e194
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Configuration.java
@@ -0,0 +1,574 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriParams;
+
+import software.amazon.awssdk.core.Protocol;
+import software.amazon.awssdk.services.sqs.SqsClient;
+
+@UriParams
+public class Sqs2Configuration implements Cloneable {
+
+    // common properties
+    private String queueName;
+    @UriParam
+    private SqsClient amazonSQSClient;
+    @UriParam(label = "security", secret = true)
+    private String accessKey;
+    @UriParam(label = "security", secret = true)
+    private String secretKey;
+    @UriParam(defaultValue = "amazonaws.com")
+    private String amazonAWSHost = "amazonaws.com";
+    @UriParam(secret = true)
+    private String queueOwnerAWSAccountId;
+    @UriParam
+    private String region;
+    @UriParam(enums = "HTTP,HTTPS", defaultValue = "HTTPS")
+    private Protocol proxyProtocol = Protocol.HTTPS;
+    @UriParam(label = "proxy")
+    private String proxyHost;
+    @UriParam(label = "proxy")
+    private Integer proxyPort;
+    @UriParam(defaultValue = "true")
+    private boolean autoCreateQueue = true;
+
+    // consumer properties
+    @UriParam(label = "consumer", defaultValue = "true")
+    private boolean deleteAfterRead = true;
+    @UriParam(label = "consumer", defaultValue = "true")
+    private boolean deleteIfFiltered = true;
+    @UriParam(label = "consumer")
+    private Integer visibilityTimeout;
+    @UriParam(label = "consumer")
+    private String attributeNames;
+    @UriParam(label = "consumer")
+    private String messageAttributeNames;
+    @UriParam(label = "consumer")
+    private Integer waitTimeSeconds;
+    @UriParam(label = "consumer")
+    private Integer defaultVisibilityTimeout;
+    @UriParam(label = "consumer")
+    private boolean extendMessageVisibility;
+    @UriParam(label = "consumer")
+    private String kmsMasterKeyId;
+    @UriParam(label = "consumer")
+    private Integer kmsDataKeyReusePeriodSeconds;
+    @UriParam(label = "consumer")
+    private boolean serverSideEncryptionEnabled;
+    @UriParam(label = "consumer", defaultValue = "1")
+    private int concurrentConsumers = 1;
+    @UriParam(label = "advanced")
+    private String queueUrl;
+
+    // producer properties
+    @UriParam(label = "producer")
+    private Integer delaySeconds;
+    // producer properties
+    @UriParam(label = "advanced")
+    private boolean delayQueue;
+    @UriParam(label = "producer", enums = "useConstant,useExchangeId,usePropertyValue")
+    private MessageGroupIdStrategy messageGroupIdStrategy;
+    @UriParam(label = "producer", defaultValue = "useExchangeId", enums = "useExchangeId,useContentBasedDeduplication")
+    private MessageDeduplicationIdStrategy messageDeduplicationIdStrategy = new ExchangeIdMessageDeduplicationIdStrategy();
+    @UriParam(label = "producer")
+    private Sqs2Operations operation;
+
+    // queue properties
+    @UriParam(label = "queue")
+    private Integer maximumMessageSize;
+    @UriParam(label = "queue")
+    private Integer messageRetentionPeriod;
+    @UriParam(label = "queue")
+    private Integer receiveMessageWaitTimeSeconds;
+    @UriParam(label = "queue")
+    private String policy;
+
+    // dead letter queue properties
+    @UriParam(label = "queue")
+    private String redrivePolicy;
+
+    // Likely used only for testing
+    @UriParam(defaultValue = "https")
+    private String protocol = "https";
+
+    /**
+     * Whether or not the queue is a FIFO queue
+     */
+    boolean isFifoQueue() {
+        // AWS docs suggest this is valid derivation.
+        // FIFO queue names must end with .fifo, and standard queues cannot
+        return queueName.endsWith(".fifo");
+    }
+
+    public String getAmazonAWSHost() {
+        return amazonAWSHost;
+    }
+
+    /**
+     * The hostname of the Amazon AWS cloud.
+     */
+    public void setAmazonAWSHost(String amazonAWSHost) {
+        this.amazonAWSHost = amazonAWSHost;
+    }
+
+    public String getQueueName() {
+        return queueName;
+    }
+
+    /**
+     * Name of queue. The queue will be created if they don't already exists.
+     */
+    public void setQueueName(String queueName) {
+        this.queueName = queueName;
+    }
+
+    public String getAccessKey() {
+        return accessKey;
+    }
+
+    /**
+     * Amazon AWS Access Key
+     */
+    public void setAccessKey(String accessKey) {
+        this.accessKey = accessKey;
+    }
+
+    public String getSecretKey() {
+        return secretKey;
+    }
+
+    /**
+     * Amazon AWS Secret Key
+     */
+    public void setSecretKey(String secretKey) {
+        this.secretKey = secretKey;
+    }
+
+    public boolean isDeleteAfterRead() {
+        return deleteAfterRead;
+    }
+
+    /**
+     * Delete message from SQS after it has been read
+     */
+    public void setDeleteAfterRead(boolean deleteAfterRead) {
+        this.deleteAfterRead = deleteAfterRead;
+    }
+
+    public SqsClient getAmazonSQSClient() {
+        return amazonSQSClient;
+    }
+
+    /**
+     * To use the AmazonSQS as client
+     */
+    public void setAmazonSQSClient(SqsClient amazonSQSClient) {
+        this.amazonSQSClient = amazonSQSClient;
+    }
+
+    public Integer getVisibilityTimeout() {
+        return visibilityTimeout;
+    }
+
+    /**
+     * The duration (in seconds) that the received messages are hidden from
+     * subsequent retrieve requests after being retrieved by a ReceiveMessage
+     * request to set in the
+     * com.amazonaws.services.sqs.model.SetQueueAttributesRequest. This only
+     * make sense if its different from defaultVisibilityTimeout. It changes the
+     * queue visibility timeout attribute permanently.
+     */
+    public void setVisibilityTimeout(Integer visibilityTimeout) {
+        this.visibilityTimeout = visibilityTimeout;
+    }
+
+    public String getAttributeNames() {
+        return attributeNames;
+    }
+
+    /**
+     * A list of attribute names to receive when consuming. Multiple names can
+     * be separated by comma.
+     */
+    public void setAttributeNames(String attributeNames) {
+        this.attributeNames = attributeNames;
+    }
+
+    public String getMessageAttributeNames() {
+        return messageAttributeNames;
+    }
+
+    /**
+     * A list of message attribute names to receive when consuming. Multiple
+     * names can be separated by comma.
+     */
+    public void setMessageAttributeNames(String messageAttributeNames) {
+        this.messageAttributeNames = messageAttributeNames;
+    }
+
+    public Integer getDefaultVisibilityTimeout() {
+        return defaultVisibilityTimeout;
+    }
+
+    /**
+     * The default visibility timeout (in seconds)
+     */
+    public void setDefaultVisibilityTimeout(Integer defaultVisibilityTimeout) {
+        this.defaultVisibilityTimeout = defaultVisibilityTimeout;
+    }
+
+    public Integer getDelaySeconds() {
+        return delaySeconds;
+    }
+
+    /**
+     * Delay sending messages for a number of seconds.
+     */
+    public void setDelaySeconds(Integer delaySeconds) {
+        this.delaySeconds = delaySeconds;
+    }
+
+    public boolean isDelayQueue() {
+        return delayQueue;
+    }
+
+    /**
+     * Define if you want to apply delaySeconds option to the queue or on single
+     * messages
+     */
+    public void setDelayQueue(boolean delayQueue) {
+        this.delayQueue = delayQueue;
+    }
+
+    public Integer getMaximumMessageSize() {
+        return maximumMessageSize;
+    }
+
+    /**
+     * The maximumMessageSize (in bytes) an SQS message can contain for this
+     * queue.
+     */
+    public void setMaximumMessageSize(Integer maximumMessageSize) {
+        this.maximumMessageSize = maximumMessageSize;
+    }
+
+    public Integer getMessageRetentionPeriod() {
+        return messageRetentionPeriod;
+    }
+
+    /**
+     * The messageRetentionPeriod (in seconds) a message will be retained by SQS
+     * for this queue.
+     */
+    public void setMessageRetentionPeriod(Integer messageRetentionPeriod) {
+        this.messageRetentionPeriod = messageRetentionPeriod;
+    }
+
+    public String getPolicy() {
+        return policy;
+    }
+
+    /**
+     * The policy for this queue
+     */
+    public void setPolicy(String policy) {
+        this.policy = policy;
+    }
+
+    public String getRedrivePolicy() {
+        return redrivePolicy;
+    }
+
+    /**
+     * Specify the policy that send message to DeadLetter queue. See detail at
+     * Amazon docs.
+     */
+    public void setRedrivePolicy(String redrivePolicy) {
+        this.redrivePolicy = redrivePolicy;
+    }
+
+    public boolean isExtendMessageVisibility() {
+        return this.extendMessageVisibility;
+    }
+
+    /**
+     * If enabled then a scheduled background task will keep extending the
+     * message visibility on SQS. This is needed if it takes a long time to
+     * process the message. If set to true defaultVisibilityTimeout must be set.
+     * See details at Amazon docs.
+     */
+    public void setExtendMessageVisibility(boolean extendMessageVisibility) {
+        this.extendMessageVisibility = extendMessageVisibility;
+    }
+
+    public Integer getReceiveMessageWaitTimeSeconds() {
+        return receiveMessageWaitTimeSeconds;
+    }
+
+    /**
+     * If you do not specify WaitTimeSeconds in the request, the queue attribute
+     * ReceiveMessageWaitTimeSeconds is used to determine how long to wait.
+     */
+    public void setReceiveMessageWaitTimeSeconds(Integer receiveMessageWaitTimeSeconds) {
+        this.receiveMessageWaitTimeSeconds = receiveMessageWaitTimeSeconds;
+    }
+
+    public Integer getWaitTimeSeconds() {
+        return waitTimeSeconds;
+    }
+
+    /**
+     * Duration in seconds (0 to 20) that the ReceiveMessage action call will
+     * wait until a message is in the queue to include in the response.
+     */
+    public void setWaitTimeSeconds(Integer waitTimeSeconds) {
+        this.waitTimeSeconds = waitTimeSeconds;
+    }
+
+    public String getQueueOwnerAWSAccountId() {
+        return queueOwnerAWSAccountId;
+    }
+
+    /**
+     * Specify the queue owner aws account id when you need to connect the queue
+     * with different account owner.
+     */
+    public void setQueueOwnerAWSAccountId(String queueOwnerAWSAccountId) {
+        this.queueOwnerAWSAccountId = queueOwnerAWSAccountId;
+    }
+
+    public boolean isDeleteIfFiltered() {
+        return deleteIfFiltered;
+    }
+
+    /**
+     * Whether or not to send the DeleteMessage to the SQS queue if an exchange
+     * fails to get through a filter. If 'false' and exchange does not make it
+     * through a Camel filter upstream in the route, then don't send
+     * DeleteMessage.
+     */
+    public void setDeleteIfFiltered(boolean deleteIfFiltered) {
+        this.deleteIfFiltered = deleteIfFiltered;
+    }
+
+    public String getRegion() {
+        return region;
+    }
+
+    /**
+     * Specify the queue region which could be used with queueOwnerAWSAccountId
+     * to build the service URL. When using this parameter, the configuration
+     * will expect the capitalized name of the region (for example AP_EAST_1)
+     * You'll need to use the name Regions.EU_WEST_1.name()
+     */
+    public void setRegion(String region) {
+        this.region = region;
+    }
+
+    public int getConcurrentConsumers() {
+        return concurrentConsumers;
+    }
+
+    /**
+     * Allows you to use multiple threads to poll the sqs queue to increase
+     * throughput
+     */
+    public void setConcurrentConsumers(int concurrentConsumers) {
+        this.concurrentConsumers = concurrentConsumers;
+    }
+
+    public String getQueueUrl() {
+        return queueUrl;
+    }
+
+    /**
+     * To define the queueUrl explicitly. All other parameters, which would
+     * influence the queueUrl, are ignored. This parameter is intended to be
+     * used, to connect to a mock implementation of SQS, for testing purposes.
+     */
+    public void setQueueUrl(String queueUrl) {
+        this.queueUrl = queueUrl;
+    }
+    
+    public Protocol getProxyProtocol() {
+        return proxyProtocol;
+    }
+
+    /**
+     * To define a proxy protocol when instantiating the SQS client
+     */
+    public void setProxyProtocol(Protocol proxyProtocol) {
+        this.proxyProtocol = proxyProtocol;
+    }
+
+    public String getProxyHost() {
+        return proxyHost;
+    }
+
+    /**
+     * To define a proxy host when instantiating the SQS client
+     */
+    public void setProxyHost(String proxyHost) {
+        this.proxyHost = proxyHost;
+    }
+
+    public Integer getProxyPort() {
+        return proxyPort;
+    }
+
+    /**
+     * To define a proxy port when instantiating the SQS client
+     */
+    public void setProxyPort(Integer proxyPort) {
+        this.proxyPort = proxyPort;
+    }
+
+    public String getKmsMasterKeyId() {
+        return kmsMasterKeyId;
+    }
+
+    /**
+     * The ID of an AWS-managed customer master key (CMK) for Amazon SQS or a
+     * custom CMK.
+     */
+    public void setKmsMasterKeyId(String kmsMasterKeyId) {
+        this.kmsMasterKeyId = kmsMasterKeyId;
+    }
+
+    public Integer getKmsDataKeyReusePeriodSeconds() {
+        return kmsDataKeyReusePeriodSeconds;
+    }
+
+    /**
+     * The length of time, in seconds, for which Amazon SQS can reuse a data key
+     * to encrypt or decrypt messages before calling AWS KMS again. An integer
+     * representing seconds, between 60 seconds (1 minute) and 86,400 seconds
+     * (24 hours). Default: 300 (5 minutes).
+     */
+    public void setKmsDataKeyReusePeriodSeconds(Integer kmsDataKeyReusePeriodSeconds) {
+        this.kmsDataKeyReusePeriodSeconds = kmsDataKeyReusePeriodSeconds;
+    }
+
+    public boolean isServerSideEncryptionEnabled() {
+        return serverSideEncryptionEnabled;
+    }
+
+    /**
+     * Define if Server Side Encryption is enabled or not on the queue
+     */
+    public void setServerSideEncryptionEnabled(boolean serverSideEncryptionEnabled) {
+        this.serverSideEncryptionEnabled = serverSideEncryptionEnabled;
+    }
+
+    /**
+     * Only for FIFO queues. Strategy for setting the messageGroupId on the
+     * message. Can be one of the following options: *useConstant*,
+     * *useExchangeId*, *usePropertyValue*. For the *usePropertyValue* option,
+     * the value of property "CamelAwsMessageGroupId" will be used.
+     */
+    public void setMessageGroupIdStrategy(String strategy) {
+        if ("useConstant".equalsIgnoreCase(strategy)) {
+            messageGroupIdStrategy = new ConstantMessageGroupIdStrategy();
+        } else if ("useExchangeId".equalsIgnoreCase(strategy)) {
+            messageGroupIdStrategy = new ExchangeIdMessageGroupIdStrategy();
+        } else if ("usePropertyValue".equalsIgnoreCase(strategy)) {
+            messageGroupIdStrategy = new PropertyValueMessageGroupIdStrategy();
+        } else {
+            throw new IllegalArgumentException("Unrecognised MessageGroupIdStrategy: " + strategy);
+        }
+    }
+
+    public void setMessageGroupIdStrategy(MessageGroupIdStrategy messageGroupIdStrategy) {
+        this.messageGroupIdStrategy = messageGroupIdStrategy;
+    }
+
+    public MessageGroupIdStrategy getMessageGroupIdStrategy() {
+        return messageGroupIdStrategy;
+    }
+
+    public MessageDeduplicationIdStrategy getMessageDeduplicationIdStrategy() {
+        return messageDeduplicationIdStrategy;
+    }
+
+    /**
+     * Only for FIFO queues. Strategy for setting the messageDeduplicationId on
+     * the message. Can be one of the following options: *useExchangeId*,
+     * *useContentBasedDeduplication*. For the *useContentBasedDeduplication*
+     * option, no messageDeduplicationId will be set on the message.
+     */
+    public void setMessageDeduplicationIdStrategy(String strategy) {
+        if ("useExchangeId".equalsIgnoreCase(strategy)) {
+            messageDeduplicationIdStrategy = new ExchangeIdMessageDeduplicationIdStrategy();
+        } else if ("useContentBasedDeduplication".equalsIgnoreCase(strategy)) {
+            messageDeduplicationIdStrategy = new NullMessageDeduplicationIdStrategy();
+        } else {
+            throw new IllegalArgumentException("Unrecognised MessageDeduplicationIdStrategy: " + strategy);
+        }
+    }
+
+    public void setMessageDeduplicationIdStrategy(MessageDeduplicationIdStrategy messageDeduplicationIdStrategy) {
+        this.messageDeduplicationIdStrategy = messageDeduplicationIdStrategy;
+    }
+
+    public Sqs2Operations getOperation() {
+        return operation;
+    }
+
+    /**
+     * The operation to do in case the user don't want to send only a message
+     */
+    public void setOperation(Sqs2Operations operation) {
+        this.operation = operation;
+    }
+
+    public boolean isAutoCreateQueue() {
+        return autoCreateQueue;
+    }
+
+    /**
+     * Setting the autocreation of the queue
+     */
+    public void setAutoCreateQueue(boolean autoCreateQueue) {
+        this.autoCreateQueue = autoCreateQueue;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    /**
+     * The underlying protocol used to communicate with SQS
+     */
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    // *************************************************
+    //
+    // *************************************************
+
+    public Sqs2Configuration copy() {
+        try {
+            return (Sqs2Configuration)super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new RuntimeCamelException(e);
+        }
+    }
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Constants.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Constants.java
new file mode 100644
index 0000000..439e2ca
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Constants.java
@@ -0,0 +1,33 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+/**
+ * Constants used in Camel AWS SQS module
+ */
+public interface Sqs2Constants {
+
+    String ATTRIBUTES = "CamelAwsSqsAttributes";
+    String MESSAGE_ATTRIBUTES = "CamelAwsSqsMessageAttributes";
+    String MD5_OF_BODY = "CamelAwsSqsMD5OfBody";
+    String MESSAGE_ID = "CamelAwsSqsMessageId";
+    String RECEIPT_HANDLE = "CamelAwsSqsReceiptHandle";
+    String DELAY_HEADER = "CamelAwsSqsDelaySeconds";
+    String MESSAGE_GROUP_ID_PROPERTY = "CamelAwsMessageGroupId";
+    String SQS_QUEUE_PREFIX = "CamelAwsSqsPrefix";
+    String SQS_OPERATION = "CamelAwsSqsOperation";
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Consumer.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Consumer.java
new file mode 100644
index 0000000..84c67db
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Consumer.java
@@ -0,0 +1,334 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.ExtendedExchange;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.Processor;
+import org.apache.camel.spi.Synchronization;
+import org.apache.camel.support.ScheduledBatchPollingConsumer;
+import org.apache.camel.util.CastUtils;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.URISupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.awscore.exception.AwsServiceException;
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.model.ChangeMessageVisibilityRequest;
+import software.amazon.awssdk.services.sqs.model.DeleteMessageRequest;
+import software.amazon.awssdk.services.sqs.model.MessageNotInflightException;
+import software.amazon.awssdk.services.sqs.model.QueueDeletedRecentlyException;
+import software.amazon.awssdk.services.sqs.model.QueueDoesNotExistException;
+import software.amazon.awssdk.services.sqs.model.ReceiptHandleIsInvalidException;
+import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest;
+import software.amazon.awssdk.services.sqs.model.ReceiveMessageResponse;
+
+/**
+ * A Consumer of messages from the Amazon Web Service Simple Queue Service
+ * <a href="http://aws.amazon.com/sqs/">AWS SQS</a>
+ */
+public class Sqs2Consumer extends ScheduledBatchPollingConsumer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(Sqs2Consumer.class);
+
+    private ScheduledExecutorService scheduledExecutor;
+    private transient String sqsConsumerToString;
+    private Collection<String> attributeNames;
+    private Collection<String> messageAttributeNames;
+
+    public Sqs2Consumer(Sqs2Endpoint endpoint, Processor processor) throws NoFactoryAvailableException {
+        super(endpoint, processor);
+
+        if (getConfiguration().getAttributeNames() != null) {
+            String[] names = getConfiguration().getAttributeNames().split(",");
+            attributeNames = Arrays.asList(names);
+        }
+        if (getConfiguration().getMessageAttributeNames() != null) {
+            String[] names = getConfiguration().getMessageAttributeNames().split(",");
+            messageAttributeNames = Arrays.asList(names);
+        }
+    }
+
+    @Override
+    protected int poll() throws Exception {
+        // must reset for each poll
+        shutdownRunningTask = null;
+        pendingExchanges = 0;
+
+        ReceiveMessageRequest.Builder request = ReceiveMessageRequest.builder().queueUrl(getQueueUrl());
+        request.maxNumberOfMessages(getMaxMessagesPerPoll() > 0 ? getMaxMessagesPerPoll() : null);
+        request.visibilityTimeout(getConfiguration().getVisibilityTimeout());
+        request.waitTimeSeconds(getConfiguration().getWaitTimeSeconds());
+
+        if (attributeNames != null) {
+            request.attributeNamesWithStrings(attributeNames);
+        }
+        if (messageAttributeNames != null) {
+            request.messageAttributeNames(messageAttributeNames);
+        }
+
+        LOG.trace("Receiving messages with request [{}]...", request);
+
+        ReceiveMessageResponse messageResult;
+        ReceiveMessageRequest requestBuild = request.build();
+        try {
+            messageResult = getClient().receiveMessage(requestBuild);
+        } catch (QueueDoesNotExistException e) {
+            LOG.info("Queue does not exist....recreating now...");
+            reConnectToQueue();
+            messageResult = getClient().receiveMessage(requestBuild);
+        }
+
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Received {} messages", messageResult.messages().size());
+        }
+
+        Queue<Exchange> exchanges = createExchanges(messageResult.messages());
+        return processBatch(CastUtils.cast(exchanges));
+    }
+
+    public void reConnectToQueue() {
+        try {
+            if (getEndpoint().getConfiguration().isAutoCreateQueue()) {
+                getEndpoint().createQueue(getClient());
+            }
+        } catch (QueueDeletedRecentlyException qdr) {
+            LOG.debug("Queue recently deleted, will retry in 30 seconds.");
+            try {
+                Thread.sleep(30000);
+                getEndpoint().createQueue(getClient());
+            } catch (Exception e) {
+                LOG.warn("failed to retry queue connection.", e);
+            }
+        } catch (Exception e) {
+            LOG.warn("Could not connect to queue in amazon.", e);
+        }
+    }
+
+    protected Queue<Exchange> createExchanges(List<software.amazon.awssdk.services.sqs.model.Message> messages) {
+        if (LOG.isTraceEnabled()) {
+            LOG.trace("Received {} messages in this poll", messages.size());
+        }
+
+        Queue<Exchange> answer = new LinkedList<>();
+        for (software.amazon.awssdk.services.sqs.model.Message message : messages) {
+            Exchange exchange = getEndpoint().createExchange(message);
+            answer.add(exchange);
+        }
+
+        return answer;
+    }
+
+    @Override
+    public int processBatch(Queue<Object> exchanges) throws Exception {
+        int total = exchanges.size();
+
+        for (int index = 0; index < total && isBatchAllowed(); index++) {
+            // only loop if we are started (allowed to run)
+            final Exchange exchange = ObjectHelper.cast(Exchange.class, exchanges.poll());
+            // add current index and total as properties
+            exchange.setProperty(Exchange.BATCH_INDEX, index);
+            exchange.setProperty(Exchange.BATCH_SIZE, total);
+            exchange.setProperty(Exchange.BATCH_COMPLETE, index == total - 1);
+
+            // update pending number of exchanges
+            pendingExchanges = total - index - 1;
+
+            // schedule task to extend visibility if enabled
+            Integer visibilityTimeout = getConfiguration().getVisibilityTimeout();
+            if (this.scheduledExecutor != null && visibilityTimeout != null && (visibilityTimeout.intValue() / 2) > 0) {
+                int delay = visibilityTimeout.intValue() / 2;
+                int period = visibilityTimeout.intValue();
+                int repeatSeconds = Double.valueOf(visibilityTimeout.doubleValue() * 1.5).intValue();
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Scheduled TimeoutExtender task to start after {} delay, and run with {}/{} period/repeat (seconds), to extend exchangeId: {}", delay, period,
+                              repeatSeconds, exchange.getExchangeId());
+                }
+                final ScheduledFuture<?> scheduledFuture = this.scheduledExecutor.scheduleAtFixedRate(new TimeoutExtender(exchange, repeatSeconds), delay, period,
+                                                                                                      TimeUnit.SECONDS);
+                exchange.adapt(ExtendedExchange.class).addOnCompletion(new Synchronization() {
+                    @Override
+                    public void onComplete(Exchange exchange) {
+                        cancelExtender(exchange);
+                    }
+
+                    @Override
+                    public void onFailure(Exchange exchange) {
+                        cancelExtender(exchange);
+                    }
+
+                    private void cancelExtender(Exchange exchange) {
+                        // cancel task as we are done
+                        LOG.trace("Processing done so cancelling TimeoutExtender task for exchangeId: {}", exchange.getExchangeId());
+                        scheduledFuture.cancel(true);
+                    }
+                });
+            }
+
+            // add on completion to handle after work when the exchange is done
+            exchange.adapt(ExtendedExchange.class).addOnCompletion(new Synchronization() {
+                public void onComplete(Exchange exchange) {
+                    processCommit(exchange);
+                }
+
+                public void onFailure(Exchange exchange) {
+                    processRollback(exchange);
+                }
+
+                @Override
+                public String toString() {
+                    return "SqsConsumerOnCompletion";
+                }
+            });
+
+            LOG.trace("Processing exchange [{}]...", exchange);
+            getAsyncProcessor().process(exchange, doneSync -> LOG.trace("Processing exchange [{}] done.", exchange));
+        }
+
+        return total;
+    }
+
+    /**
+     * Strategy to delete the message after being processed.
+     *
+     * @param exchange the exchange
+     */
+    protected void processCommit(Exchange exchange) {
+        try {
+
+            if (shouldDelete(exchange)) {
+                String receiptHandle = exchange.getIn().getHeader(Sqs2Constants.RECEIPT_HANDLE, String.class);
+                DeleteMessageRequest.Builder deleteRequest = DeleteMessageRequest.builder().queueUrl(getQueueUrl()).receiptHandle(receiptHandle);
+
+                LOG.trace("Deleting message with receipt handle {}...", receiptHandle);
+
+                getClient().deleteMessage(deleteRequest.build());
+
+                LOG.trace("Deleted message with receipt handle {}...", receiptHandle);
+            }
+        } catch (AwsServiceException e) {
+            getExceptionHandler().handleException("Error occurred during deleting message. This exception is ignored.", exchange, e);
+        }
+    }
+
+    private boolean shouldDelete(Exchange exchange) {
+        boolean shouldDeleteByFilter = exchange.getProperty(Exchange.FILTER_MATCHED) != null && getConfiguration().isDeleteIfFiltered() && passedThroughFilter(exchange);
+
+        return getConfiguration().isDeleteAfterRead() || shouldDeleteByFilter;
+    }
+
+    private boolean passedThroughFilter(Exchange exchange) {
+        return exchange.getProperty(Exchange.FILTER_MATCHED, false, Boolean.class);
+    }
+
+    /**
+     * Strategy when processing the exchange failed.
+     *
+     * @param exchange the exchange
+     */
+    protected void processRollback(Exchange exchange) {
+        Exception cause = exchange.getException();
+        if (cause != null) {
+            getExceptionHandler().handleException("Error during processing exchange. Will attempt to process the message on next poll.", exchange, cause);
+        }
+    }
+
+    protected Sqs2Configuration getConfiguration() {
+        return getEndpoint().getConfiguration();
+    }
+
+    protected SqsClient getClient() {
+        return getEndpoint().getClient();
+    }
+
+    protected String getQueueUrl() {
+        return getEndpoint().getQueueUrl();
+    }
+
+    @Override
+    public Sqs2Endpoint getEndpoint() {
+        return (Sqs2Endpoint)super.getEndpoint();
+    }
+
+    @Override
+    public String toString() {
+        if (sqsConsumerToString == null) {
+            sqsConsumerToString = "SqsConsumer[" + URISupport.sanitizeUri(getEndpoint().getEndpointUri()) + "]";
+        }
+        return sqsConsumerToString;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        // start scheduler first
+        if (getConfiguration().isExtendMessageVisibility() && scheduledExecutor == null) {
+            this.scheduledExecutor = getEndpoint().getCamelContext().getExecutorServiceManager().newSingleThreadScheduledExecutor(this, "SqsTimeoutExtender");
+        }
+
+        super.doStart();
+    }
+
+    @Override
+    protected void doShutdown() throws Exception {
+        if (scheduledExecutor != null) {
+            getEndpoint().getCamelContext().getExecutorServiceManager().shutdownNow(scheduledExecutor);
+            scheduledExecutor = null;
+        }
+
+        super.doShutdown();
+    }
+
+    private class TimeoutExtender implements Runnable {
+
+        private final Exchange exchange;
+        private final int repeatSeconds;
+
+        TimeoutExtender(Exchange exchange, int repeatSeconds) {
+            this.exchange = exchange;
+            this.repeatSeconds = repeatSeconds;
+        }
+
+        @Override
+        public void run() {
+            ChangeMessageVisibilityRequest.Builder request = ChangeMessageVisibilityRequest.builder().queueUrl(getQueueUrl()).visibilityTimeout(repeatSeconds).receiptHandle(exchange.getIn().getHeader(Sqs2Constants.RECEIPT_HANDLE, String.class));
+
+            try {
+                LOG.trace("Extending visibility window by {} seconds for exchange {}", this.repeatSeconds, this.exchange);
+                getEndpoint().getClient().changeMessageVisibility(request.build());
+                LOG.debug("Extended visibility window by {} seconds for exchange {}", this.repeatSeconds, this.exchange);
+            } catch (ReceiptHandleIsInvalidException e) {
+                // Ignore.
+            } catch (MessageNotInflightException e) {
+                // Ignore.
+            } catch (Exception e) {
+                LOG.warn("Extending visibility window failed for exchange " + exchange + ". Will not attempt to extend visibility further. This exception will be ignored.", e);
+            }
+        }
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java
new file mode 100644
index 0000000..80e702d
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Endpoint.java
@@ -0,0 +1,393 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.camel.Consumer;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.spi.HeaderFilterStrategy;
+import org.apache.camel.spi.HeaderFilterStrategyAware;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
+import org.apache.camel.spi.UriPath;
+import org.apache.camel.support.DefaultScheduledPollConsumerScheduler;
+import org.apache.camel.support.ScheduledPollEndpoint;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
+import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
+import software.amazon.awssdk.http.apache.ApacheHttpClient;
+import software.amazon.awssdk.http.apache.ProxyConfiguration;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.SqsClientBuilder;
+import software.amazon.awssdk.services.sqs.model.CreateQueueRequest;
+import software.amazon.awssdk.services.sqs.model.CreateQueueResponse;
+import software.amazon.awssdk.services.sqs.model.GetQueueUrlRequest;
+import software.amazon.awssdk.services.sqs.model.GetQueueUrlResponse;
+import software.amazon.awssdk.services.sqs.model.ListQueuesResponse;
+import software.amazon.awssdk.services.sqs.model.MessageAttributeValue;
+import software.amazon.awssdk.services.sqs.model.QueueAttributeName;
+import software.amazon.awssdk.services.sqs.model.SetQueueAttributesRequest;
+
+/**
+ * The aws-sqs component is used for sending and receiving messages to Amazon's
+ * SQS service.
+ */
+@UriEndpoint(firstVersion = "3.1.0", scheme = "aws2-sqs", title = "AWS 2 Simple Queue Service", syntax = "aws2-sqs:queueNameOrArn", label = "cloud,messaging")
+public class Sqs2Endpoint extends ScheduledPollEndpoint implements HeaderFilterStrategyAware {
+
+    private static final Logger LOG = LoggerFactory.getLogger(Sqs2Endpoint.class);
+
+    private SqsClient client;
+    private String queueUrl;
+
+    @UriPath(description = "Queue name or ARN")
+    @Metadata(required = true)
+    private String queueNameOrArn; // to support component docs
+    @UriParam
+    private Sqs2Configuration configuration;
+    @UriParam(label = "consumer")
+    private int maxMessagesPerPoll;
+    @UriParam
+    private HeaderFilterStrategy headerFilterStrategy;
+
+    public Sqs2Endpoint(String uri, Sqs2Component component, Sqs2Configuration configuration) {
+        super(uri, component);
+        this.configuration = configuration;
+    }
+
+    @Override
+    public HeaderFilterStrategy getHeaderFilterStrategy() {
+        return headerFilterStrategy;
+    }
+
+    /**
+     * To use a custom HeaderFilterStrategy to map headers to/from Camel.
+     */
+    @Override
+    public void setHeaderFilterStrategy(HeaderFilterStrategy strategy) {
+        this.headerFilterStrategy = strategy;
+    }
+
+    @Override
+    public Producer createProducer() throws Exception {
+        return new Sqs2Producer(this);
+    }
+
+    @Override
+    public Consumer createConsumer(Processor processor) throws Exception {
+        Sqs2Consumer sqsConsumer = new Sqs2Consumer(this, processor);
+        configureConsumer(sqsConsumer);
+        sqsConsumer.setMaxMessagesPerPoll(maxMessagesPerPoll);
+        DefaultScheduledPollConsumerScheduler scheduler = new DefaultScheduledPollConsumerScheduler();
+        scheduler.setConcurrentTasks(configuration.getConcurrentConsumers());
+        sqsConsumer.setScheduler(scheduler);
+        return sqsConsumer;
+    }
+
+    /*
+     If using a different AWS host, do not assume specific parts of the AWS host
+     and, instead, just return whatever is provided as the host.
+     */
+    private String getFullyQualifiedAWSHost() {
+        String host = configuration.getAmazonAWSHost();
+        host = FileUtil.stripTrailingSeparator(host);
+
+        if (host.equals("amazonaws.com")) {
+            return "sqs." + Region.of(configuration.getRegion()).id() + "." + host;
+        }
+
+        return host;
+    }
+
+    @Override
+    protected void doInit() throws Exception {
+        super.doInit();
+        client = getConfiguration().getAmazonSQSClient() != null ? getConfiguration().getAmazonSQSClient() : getClient();
+
+        // check the setting the headerFilterStrategy
+        if (headerFilterStrategy == null) {
+            headerFilterStrategy = new Sqs2HeaderFilterStrategy();
+        }
+
+        if (configuration.getQueueUrl() != null) {
+            queueUrl = configuration.getQueueUrl();
+        } else {
+            // If both region and Account ID is provided the queue URL can be
+            // built manually.
+            // This allows accessing queues where you don't have permission to
+            // list queues or query queues
+            if (configuration.getRegion() != null && configuration.getQueueOwnerAWSAccountId() != null) {
+                String protocol = configuration.getProtocol();
+
+                queueUrl = protocol + "://" + getFullyQualifiedAWSHost() + "/" + configuration.getQueueOwnerAWSAccountId() + "/"
+                           + configuration.getQueueName();
+            } else if (configuration.getQueueOwnerAWSAccountId() != null) {
+                GetQueueUrlRequest.Builder getQueueUrlRequest = GetQueueUrlRequest.builder();
+                getQueueUrlRequest.queueName(configuration.getQueueName());
+                getQueueUrlRequest.queueOwnerAWSAccountId(configuration.getQueueOwnerAWSAccountId());
+                GetQueueUrlResponse getQueueUrlResult = client.getQueueUrl(getQueueUrlRequest.build());
+                queueUrl = getQueueUrlResult.queueUrl();
+            } else {
+                // check whether the queue already exists
+                ListQueuesResponse listQueuesResult = client.listQueues();
+                for (String url : listQueuesResult.queueUrls()) {
+                    if (url.endsWith("/" + configuration.getQueueName())) {
+                        queueUrl = url;
+                        LOG.trace("Queue available at '{}'.", queueUrl);
+                        break;
+                    }
+                }
+            }
+        }
+
+        if (queueUrl == null && configuration.isAutoCreateQueue()) {
+            createQueue(client);
+        } else {
+            LOG.debug("Using Amazon SQS queue url: {}", queueUrl);
+            updateQueueAttributes(client);
+        }
+    }
+
+    protected void createQueue(SqsClient client) {
+        LOG.trace("Queue '{}' doesn't exist. Will create it...", configuration.getQueueName());
+
+        // creates a new queue, or returns the URL of an existing one
+        CreateQueueRequest.Builder request = CreateQueueRequest.builder().queueName(configuration.getQueueName());
+        Map<QueueAttributeName, String> attributes = new HashMap<QueueAttributeName, String>();
+        if (getConfiguration().isFifoQueue()) {
+            attributes.put(QueueAttributeName.FIFO_QUEUE, String.valueOf(true));
+            boolean useContentBasedDeduplication = getConfiguration().getMessageDeduplicationIdStrategy() instanceof NullMessageDeduplicationIdStrategy;
+            attributes.put(QueueAttributeName.CONTENT_BASED_DEDUPLICATION, String.valueOf(useContentBasedDeduplication));
+        }
+        if (getConfiguration().getDefaultVisibilityTimeout() != null) {
+        	attributes.put(QueueAttributeName.VISIBILITY_TIMEOUT, String.valueOf(getConfiguration().getDefaultVisibilityTimeout()));
+        }
+        if (getConfiguration().getMaximumMessageSize() != null) {
+        	attributes.put(QueueAttributeName.MAXIMUM_MESSAGE_SIZE, String.valueOf(getConfiguration().getMaximumMessageSize()));
+        }
+        if (getConfiguration().getMessageRetentionPeriod() != null) {
+        	attributes.put(QueueAttributeName.MESSAGE_RETENTION_PERIOD, String.valueOf(getConfiguration().getMessageRetentionPeriod()));
+        }
+        if (getConfiguration().getPolicy() != null) {
+            attributes.put(QueueAttributeName.POLICY, String.valueOf(getConfiguration().getPolicy()));
+        }
+        if (getConfiguration().getReceiveMessageWaitTimeSeconds() != null) {
+            attributes.put(QueueAttributeName.RECEIVE_MESSAGE_WAIT_TIME_SECONDS, String.valueOf(getConfiguration().getReceiveMessageWaitTimeSeconds()));
+        }
+        if (getConfiguration().getDelaySeconds() != null && getConfiguration().isDelayQueue()) {
+        	attributes.put(QueueAttributeName.DELAY_SECONDS, String.valueOf(getConfiguration().getDelaySeconds()));
+        }
+        if (getConfiguration().getRedrivePolicy() != null) {
+        	attributes.put(QueueAttributeName.REDRIVE_POLICY, getConfiguration().getRedrivePolicy());
+        }
+        if (getConfiguration().isServerSideEncryptionEnabled()) {
+            if (getConfiguration().getKmsMasterKeyId() != null) {
+            	attributes.put(QueueAttributeName.KMS_MASTER_KEY_ID, getConfiguration().getKmsMasterKeyId());
+            }
+            if (getConfiguration().getKmsDataKeyReusePeriodSeconds() != null) {
+            	attributes.put(QueueAttributeName.KMS_DATA_KEY_REUSE_PERIOD_SECONDS, String.valueOf(getConfiguration().getKmsDataKeyReusePeriodSeconds()));
+            }
+        }
+        LOG.trace("Creating queue [{}] with request [{}]...", configuration.getQueueName(), request);
+        request.attributes(attributes);
+
+        CreateQueueResponse queueResult = client.createQueue(request.build());
+        queueUrl = queueResult.queueUrl();
+
+        LOG.trace("Queue created and available at: {}", queueUrl);
+    }
+
+    private void updateQueueAttributes(SqsClient client) {
+        SetQueueAttributesRequest.Builder request = SetQueueAttributesRequest.builder().queueUrl(queueUrl);
+        Map<QueueAttributeName, String> attributes = new HashMap<QueueAttributeName, String>();
+        if (getConfiguration().getDefaultVisibilityTimeout() != null) {
+        	attributes.put(QueueAttributeName.VISIBILITY_TIMEOUT, String.valueOf(getConfiguration().getDefaultVisibilityTimeout()));
+        }
+        if (getConfiguration().getMaximumMessageSize() != null) {
+        	attributes.put(QueueAttributeName.MAXIMUM_MESSAGE_SIZE, String.valueOf(getConfiguration().getMaximumMessageSize()));
+        }
+        if (getConfiguration().getMessageRetentionPeriod() != null) {
+        	attributes.put(QueueAttributeName.MESSAGE_RETENTION_PERIOD, String.valueOf(getConfiguration().getMessageRetentionPeriod()));
+        }
+        if (getConfiguration().getPolicy() != null) {
+            attributes.put(QueueAttributeName.POLICY, String.valueOf(getConfiguration().getPolicy()));
+        }
+        if (getConfiguration().getReceiveMessageWaitTimeSeconds() != null) {
+            attributes.put(QueueAttributeName.RECEIVE_MESSAGE_WAIT_TIME_SECONDS, String.valueOf(getConfiguration().getReceiveMessageWaitTimeSeconds()));
+        }
+        if (getConfiguration().getDelaySeconds() != null && getConfiguration().isDelayQueue()) {
+        	attributes.put(QueueAttributeName.DELAY_SECONDS, String.valueOf(getConfiguration().getDelaySeconds()));
+        }
+        if (getConfiguration().getRedrivePolicy() != null) {
+        	attributes.put(QueueAttributeName.REDRIVE_POLICY, getConfiguration().getRedrivePolicy());
+        }
+        if (getConfiguration().isServerSideEncryptionEnabled()) {
+            if (getConfiguration().getKmsMasterKeyId() != null) {
+            	attributes.put(QueueAttributeName.KMS_MASTER_KEY_ID, getConfiguration().getKmsMasterKeyId());
+            }
+            if (getConfiguration().getKmsDataKeyReusePeriodSeconds() != null) {
+            	attributes.put(QueueAttributeName.KMS_DATA_KEY_REUSE_PERIOD_SECONDS, String.valueOf(getConfiguration().getKmsDataKeyReusePeriodSeconds()));
+            }
+        }
+        if (!attributes.isEmpty()) {
+        	request.attributes(attributes);
+            LOG.trace("Updating queue '{}' with the provided queue attributes...", configuration.getQueueName());
+            client.setQueueAttributes(request.build());
+            LOG.trace("Queue '{}' updated and available at {}'", configuration.getQueueName(), queueUrl);
+        }
+    }
+
+    @Override
+    public void doStop() throws Exception {
+        if (ObjectHelper.isEmpty(configuration.getAmazonSQSClient())) {
+            if (client != null) {
+                client.close();
+            }
+        }
+        super.doStop();
+    }
+
+    public Exchange createExchange(software.amazon.awssdk.services.sqs.model.Message msg) {
+        return createExchange(getExchangePattern(), msg);
+    }
+
+    private Exchange createExchange(ExchangePattern pattern, software.amazon.awssdk.services.sqs.model.Message msg) {
+        Exchange exchange = super.createExchange(pattern);
+        Message message = exchange.getIn();
+        message.setBody(msg.body());
+        message.setHeaders(new HashMap<>(msg.attributesAsStrings()));
+        message.setHeader(Sqs2Constants.MESSAGE_ID, msg.messageId());
+        message.setHeader(Sqs2Constants.MD5_OF_BODY, msg.md5OfBody());
+        message.setHeader(Sqs2Constants.RECEIPT_HANDLE, msg.receiptHandle());
+        message.setHeader(Sqs2Constants.ATTRIBUTES, msg.attributes());
+        message.setHeader(Sqs2Constants.MESSAGE_ATTRIBUTES, msg.messageAttributes());
+
+        // Need to apply the SqsHeaderFilterStrategy this time
+        HeaderFilterStrategy headerFilterStrategy = getHeaderFilterStrategy();
+        // add all sqs message attributes as camel message headers so that
+        // knowledge of
+        // the Sqs class MessageAttributeValue will not leak to the client
+        for (Entry<String, MessageAttributeValue> entry : msg.messageAttributes().entrySet()) {
+            String header = entry.getKey();
+            Object value = translateValue(entry.getValue());
+            if (!headerFilterStrategy.applyFilterToExternalHeaders(header, value, exchange)) {
+                message.setHeader(header, value);
+            }
+        }
+        return exchange;
+    }
+
+    public Sqs2Configuration getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(Sqs2Configuration configuration) {
+        this.configuration = configuration;
+    }
+
+    public SqsClient getClient() {
+        if (client == null) {
+            client = createClient();
+        }
+        return client;
+    }
+
+    public void setClient(SqsClient client) {
+        this.client = client;
+    }
+
+    /**
+     * Provide the possibility to override this method for an mock
+     * implementation
+     * 
+     * @return AmazonSQSClient
+     */
+    SqsClient createClient() {
+        SqsClient client = null;
+        SqsClientBuilder clientBuilder = SqsClient.builder();
+        ProxyConfiguration.Builder proxyConfig = null;
+        ApacheHttpClient.Builder httpClientBuilder = null;
+        boolean isClientConfigFound = false;
+        if (ObjectHelper.isNotEmpty(configuration.getProxyHost()) && ObjectHelper.isNotEmpty(configuration.getProxyPort())) {
+            proxyConfig = ProxyConfiguration.builder();
+            URI proxyEndpoint = URI.create(configuration.getProxyProtocol() + configuration.getProxyHost() + configuration.getProxyPort());
+            proxyConfig.endpoint(proxyEndpoint);
+            httpClientBuilder = ApacheHttpClient.builder().proxyConfiguration(proxyConfig.build());
+            isClientConfigFound = true;
+        }
+        if (configuration.getAccessKey() != null && configuration.getSecretKey() != null) {
+            AwsBasicCredentials cred = AwsBasicCredentials.create(configuration.getAccessKey(), configuration.getSecretKey());
+            if (isClientConfigFound) {
+                clientBuilder = clientBuilder.httpClientBuilder(httpClientBuilder).credentialsProvider(StaticCredentialsProvider.create(cred));
+            } else {
+                clientBuilder = clientBuilder.credentialsProvider(StaticCredentialsProvider.create(cred));
+            }
+        } else {
+            if (!isClientConfigFound) {
+                clientBuilder = clientBuilder.httpClientBuilder(httpClientBuilder);
+            }
+        }
+
+        if (ObjectHelper.isNotEmpty(configuration.getRegion())) {
+            clientBuilder = clientBuilder.region(Region.of(configuration.getRegion()));
+        }
+        client = clientBuilder.build();
+        return client;
+    }
+
+    protected String getQueueUrl() {
+        return queueUrl;
+    }
+
+    public int getMaxMessagesPerPoll() {
+        return maxMessagesPerPoll;
+    }
+
+    /**
+     * Gets the maximum number of messages as a limit to poll at each polling.
+     * <p/>
+     * Is default unlimited, but use 0 or negative number to disable it as
+     * unlimited.
+     */
+    public void setMaxMessagesPerPoll(int maxMessagesPerPoll) {
+        this.maxMessagesPerPoll = maxMessagesPerPoll;
+    }
+
+    private Object translateValue(MessageAttributeValue mav) {
+        Object result = null;
+        if (mav.stringValue() != null) {
+            result = mav.stringValue();
+        } else if (mav.binaryValue() != null) {
+            result = mav.binaryValue();
+        }
+        return result;
+    }
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2HeaderFilterStrategy.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2HeaderFilterStrategy.java
new file mode 100644
index 0000000..4eef115
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2HeaderFilterStrategy.java
@@ -0,0 +1,30 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.support.DefaultHeaderFilterStrategy;
+
+public class Sqs2HeaderFilterStrategy extends DefaultHeaderFilterStrategy {
+    public Sqs2HeaderFilterStrategy() {
+        initialize();
+    }
+
+    protected void initialize() {
+        // filter headers begin with "Camel" or "org.apache.camel"
+        setOutFilterPattern("(breadcrumbId|Camel|org\\.apache\\.camel)[\\.|a-z|A-z|0-9]*");
+    }
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Operations.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Operations.java
new file mode 100644
index 0000000..b066531
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Operations.java
@@ -0,0 +1,22 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+public enum Sqs2Operations {
+
+    sendBatchMessage, deleteMessage, listQueues
+}
diff --git a/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Producer.java b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Producer.java
new file mode 100644
index 0000000..ac1b0b7
--- /dev/null
+++ b/components/camel-aws2-sqs/src/main/java/org/apache/camel/component/aws2/sqs/Sqs2Producer.java
@@ -0,0 +1,309 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.spi.HeaderFilterStrategy;
+import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.URISupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import software.amazon.awssdk.core.SdkBytes;
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.model.DeleteMessageRequest;
+import software.amazon.awssdk.services.sqs.model.DeleteMessageResponse;
+import software.amazon.awssdk.services.sqs.model.ListQueuesRequest;
+import software.amazon.awssdk.services.sqs.model.ListQueuesResponse;
+import software.amazon.awssdk.services.sqs.model.MessageAttributeValue;
+import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest;
+import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequestEntry;
+import software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse;
+import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
+import software.amazon.awssdk.services.sqs.model.SendMessageResponse;
+
+/**
+ * A Producer which sends messages to the Amazon Web Service Simple Queue
+ * Service <a href="http://aws.amazon.com/sqs/">AWS SQS</a>
+ */
+public class Sqs2Producer extends DefaultProducer {
+
+    private static final Logger LOG = LoggerFactory.getLogger(Sqs2Producer.class);
+
+    private transient String sqsProducerToString;
+
+    public Sqs2Producer(Sqs2Endpoint endpoint) throws NoFactoryAvailableException {
+        super(endpoint);
+        if (endpoint.getConfiguration().isFifoQueue() && ObjectHelper.isEmpty(getEndpoint().getConfiguration().getMessageGroupIdStrategy())) {
+            throw new IllegalArgumentException("messageGroupIdStrategy must be set for FIFO queues.");
+        }
+    }
+
+    @Override
+    public void process(Exchange exchange) throws Exception {
+        Sqs2Operations operation = determineOperation(exchange);
+        if (ObjectHelper.isEmpty(operation)) {
+            processSingleMessage(exchange);
+        } else {
+            switch (operation) {
+                case sendBatchMessage:
+                    sendBatchMessage(getClient(), exchange);
+                    break;
+                case deleteMessage:
+                    deleteMessage(getClient(), exchange);
+                    break;
+                case listQueues:
+                    listQueues(getClient(), exchange);
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unsupported operation");
+            }
+        }
+    }
+
+    public void processSingleMessage(final Exchange exchange) {
+        String body = exchange.getIn().getBody(String.class);
+        SendMessageRequest.Builder request = SendMessageRequest.builder().queueUrl(getQueueUrl()).messageBody(body);
+        request.messageAttributes(translateAttributes(exchange.getIn().getHeaders(), exchange));
+        addDelay(request, exchange);
+        configureFifoAttributes(request, exchange);
+
+        LOG.trace("Sending request [{}] from exchange [{}]...", request, exchange);
+
+        SendMessageResponse result = getClient().sendMessage(request.build());
+
+        LOG.trace("Received result [{}]", result);
+
+        Message message = getMessageForResponse(exchange);
+        message.setHeader(Sqs2Constants.MESSAGE_ID, result.messageId());
+        message.setHeader(Sqs2Constants.MD5_OF_BODY, result.md5OfMessageBody());
+    }
+
+    private void sendBatchMessage(SqsClient amazonSQS, Exchange exchange) {
+        SendMessageBatchRequest.Builder request = SendMessageBatchRequest.builder().queueUrl(getQueueUrl());
+        Collection<SendMessageBatchRequestEntry> entries = new ArrayList<>();
+        if (exchange.getIn().getBody() instanceof Iterable) {
+            Iterable c = exchange.getIn().getBody(Iterable.class);
+            for (Object o : c) {
+                String object = (String)o;
+                SendMessageBatchRequestEntry.Builder entry = SendMessageBatchRequestEntry.builder();
+                entry.id(UUID.randomUUID().toString());
+                entry.messageAttributes(translateAttributes(exchange.getIn().getHeaders(), exchange));
+                entry.messageBody(object);
+                addDelay(entry, exchange);
+                configureFifoAttributes(entry, exchange);
+                entries.add(entry.build());
+            }
+            request.entries(entries);
+            SendMessageBatchResponse result = amazonSQS.sendMessageBatch(request.build());
+            Message message = getMessageForResponse(exchange);
+            message.setBody(result);
+        } else {
+        	SendMessageBatchRequest req = exchange.getIn().getBody(SendMessageBatchRequest.class);
+            SendMessageBatchResponse result = amazonSQS.sendMessageBatch(req);
+            Message message = getMessageForResponse(exchange);
+            message.setBody(result);
+        }
+    }
+
+    private void deleteMessage(SqsClient amazonSQS, Exchange exchange) {
+        String receiptHandle = exchange.getIn().getHeader(Sqs2Constants.RECEIPT_HANDLE, String.class);
+        DeleteMessageRequest.Builder request = DeleteMessageRequest.builder();
+        request.queueUrl(getQueueUrl());
+        if (ObjectHelper.isEmpty(receiptHandle)) {
+            throw new IllegalArgumentException("Receipt Handle must be specified for the operation deleteMessage");
+        }
+        request.receiptHandle(receiptHandle);
+        DeleteMessageResponse result = amazonSQS.deleteMessage(request.build());
+        Message message = getMessageForResponse(exchange);
+        message.setBody(result);
+    }
+
+    private void listQueues(SqsClient amazonSQS, Exchange exchange) {
+        ListQueuesRequest.Builder request = ListQueuesRequest.builder();
+        if (ObjectHelper.isNotEmpty(exchange.getIn().getHeader(Sqs2Constants.SQS_QUEUE_PREFIX))) {
+            request.queueNamePrefix(exchange.getIn().getHeader(Sqs2Constants.SQS_QUEUE_PREFIX, String.class));
+        }
+        ListQueuesResponse result = amazonSQS.listQueues(request.build());
+        Message message = getMessageForResponse(exchange);
+        message.setBody(result);
+    }
+
+    private void configureFifoAttributes(SendMessageRequest.Builder request, Exchange exchange) {
+        if (getEndpoint().getConfiguration().isFifoQueue()) {
+            // use strategies
+            MessageGroupIdStrategy messageGroupIdStrategy = getEndpoint().getConfiguration().getMessageGroupIdStrategy();
+            String messageGroupId = messageGroupIdStrategy.getMessageGroupId(exchange);
+            request.messageGroupId(messageGroupId);
+
+            MessageDeduplicationIdStrategy messageDeduplicationIdStrategy = getEndpoint().getConfiguration().getMessageDeduplicationIdStrategy();
+            String messageDeduplicationId = messageDeduplicationIdStrategy.getMessageDeduplicationId(exchange);
+            request.messageDeduplicationId(messageDeduplicationId);
+
+        }
+    }
+
+    private void configureFifoAttributes(SendMessageBatchRequestEntry.Builder request, Exchange exchange) {
+        if (getEndpoint().getConfiguration().isFifoQueue()) {
+            // use strategies
+            MessageGroupIdStrategy messageGroupIdStrategy = getEndpoint().getConfiguration().getMessageGroupIdStrategy();
+            String messageGroupId = messageGroupIdStrategy.getMessageGroupId(exchange);
+            request.messageGroupId(messageGroupId);
+
+            MessageDeduplicationIdStrategy messageDeduplicationIdStrategy = getEndpoint().getConfiguration().getMessageDeduplicationIdStrategy();
+            String messageDeduplicationId = messageDeduplicationIdStrategy.getMessageDeduplicationId(exchange);
+            request.messageDeduplicationId(messageDeduplicationId);
+
+        }
+    }
+
+    private void addDelay(SendMessageRequest.Builder request, Exchange exchange) {
+        Integer headerValue = exchange.getIn().getHeader(Sqs2Constants.DELAY_HEADER, Integer.class);
+        Integer delayValue;
+        if (headerValue == null) {
+            LOG.trace("Using the config delay");
+            delayValue = getEndpoint().getConfiguration().getDelaySeconds();
+        } else {
+            LOG.trace("Using the header delay");
+            delayValue = headerValue;
+        }
+        LOG.trace("found delay: {}", delayValue);
+        request.delaySeconds(delayValue == null ? Integer.valueOf(0) : delayValue);
+    }
+
+    private void addDelay(SendMessageBatchRequestEntry.Builder request, Exchange exchange) {
+        Integer headerValue = exchange.getIn().getHeader(Sqs2Constants.DELAY_HEADER, Integer.class);
+        Integer delayValue;
+        if (headerValue == null) {
+            LOG.trace("Using the config delay");
+            delayValue = getEndpoint().getConfiguration().getDelaySeconds();
+        } else {
+            LOG.trace("Using the header delay");
+            delayValue = headerValue;
+        }
+        LOG.trace("found delay: {}", delayValue);
+        request.delaySeconds(delayValue == null ? Integer.valueOf(0) : delayValue);
+    }
+
+    protected SqsClient getClient() {
+        return getEndpoint().getClient();
+    }
+
+    protected String getQueueUrl() {
+        return getEndpoint().getQueueUrl();
+    }
+
+    protected Sqs2Configuration getConfiguration() {
+        return getEndpoint().getConfiguration();
+    }
+
+    @Override
+    public Sqs2Endpoint getEndpoint() {
+        return (Sqs2Endpoint)super.getEndpoint();
+    }
+
+    @Override
+    public String toString() {
+        if (sqsProducerToString == null) {
+            sqsProducerToString = "SqsProducer[" + URISupport.sanitizeUri(getEndpoint().getEndpointUri()) + "]";
+        }
+        return sqsProducerToString;
+    }
+
+    Map<String, MessageAttributeValue> translateAttributes(Map<String, Object> headers, Exchange exchange) {
+        Map<String, MessageAttributeValue> result = new HashMap<>();
+        HeaderFilterStrategy headerFilterStrategy = getEndpoint().getHeaderFilterStrategy();
+        for (Entry<String, Object> entry : headers.entrySet()) {
+            // only put the message header which is not filtered into the
+            // message attribute
+            if (!headerFilterStrategy.applyFilterToCamelHeaders(entry.getKey(), entry.getValue(), exchange)) {
+                Object value = entry.getValue();
+                if (value instanceof String && !((String)value).isEmpty()) {
+                    MessageAttributeValue.Builder mav = MessageAttributeValue.builder();
+                    mav.dataType("String");
+                    mav.stringValue((String)value);
+                    result.put(entry.getKey(), mav.build());
+                } else if (value instanceof ByteBuffer) {
+                    MessageAttributeValue.Builder mav = MessageAttributeValue.builder();
+                    mav.dataType("Binary");
+                    mav.binaryValue(SdkBytes.fromByteBuffer((ByteBuffer) value));
+                    result.put(entry.getKey(), mav.build());
+                } else if (value instanceof Boolean) {
+                    MessageAttributeValue.Builder mav = MessageAttributeValue.builder();
+                    mav.dataType("Number.Boolean");
+                    mav.stringValue(((Boolean)value) ? "1" : "0");
+                    result.put(entry.getKey(), mav.build());
+                } else if (value instanceof Number) {
+                    MessageAttributeValue.Builder mav = MessageAttributeValue.builder();
+                    final String dataType;
+                    if (value instanceof Integer) {
+                        dataType = "Number.int";
+                    } else if (value instanceof Byte) {
+                        dataType = "Number.byte";
+                    } else if (value instanceof Double) {
+                        dataType = "Number.double";
+                    } else if (value instanceof Float) {
+                        dataType = "Number.float";
+                    } else if (value instanceof Long) {
+                        dataType = "Number.long";
+                    } else if (value instanceof Short) {
+                        dataType = "Number.short";
+                    } else {
+                        dataType = "Number";
+                    }
+                    mav.dataType(dataType);
+                    mav.stringValue(value.toString());
+                    result.put(entry.getKey(), mav.build());
+                } else if (value instanceof Date) {
+                    MessageAttributeValue.Builder mav = MessageAttributeValue.builder();
+                    mav.dataType("String");
+                    mav.stringValue(value.toString());
+                    result.put(entry.getKey(), mav.build());
+                } else {
+                    // cannot translate the message header to message attribute
+                    // value
+                    LOG.warn("Cannot put the message header key={}, value={} into Sqs MessageAttribute", entry.getKey(), entry.getValue());
+                }
+            }
+        }
+        return result;
+    }
+
+    public static Message getMessageForResponse(final Exchange exchange) {
+        return exchange.getMessage();
+    }
+
+    private Sqs2Operations determineOperation(Exchange exchange) {
+        Sqs2Operations operation = exchange.getIn().getHeader(Sqs2Constants.SQS_OPERATION, Sqs2Operations.class);
+        if (operation == null) {
+            operation = getConfiguration().getOperation();
+        }
+        return operation;
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/AmazonSQSClientMock.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/AmazonSQSClientMock.java
new file mode 100644
index 0000000..bb23de3
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/AmazonSQSClientMock.java
@@ -0,0 +1,227 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import software.amazon.awssdk.services.sqs.SqsClient;
+import software.amazon.awssdk.services.sqs.model.BatchResultErrorEntry;
+import software.amazon.awssdk.services.sqs.model.ChangeMessageVisibilityRequest;
+import software.amazon.awssdk.services.sqs.model.ChangeMessageVisibilityResponse;
+import software.amazon.awssdk.services.sqs.model.CreateQueueRequest;
+import software.amazon.awssdk.services.sqs.model.CreateQueueResponse;
+import software.amazon.awssdk.services.sqs.model.DeleteMessageRequest;
+import software.amazon.awssdk.services.sqs.model.DeleteMessageResponse;
+import software.amazon.awssdk.services.sqs.model.ListQueuesRequest;
+import software.amazon.awssdk.services.sqs.model.ListQueuesResponse;
+import software.amazon.awssdk.services.sqs.model.Message;
+import software.amazon.awssdk.services.sqs.model.ReceiveMessageRequest;
+import software.amazon.awssdk.services.sqs.model.ReceiveMessageResponse;
+import software.amazon.awssdk.services.sqs.model.SendMessageBatchRequest;
+import software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse;
+import software.amazon.awssdk.services.sqs.model.SendMessageBatchResultEntry;
+import software.amazon.awssdk.services.sqs.model.SendMessageRequest;
+import software.amazon.awssdk.services.sqs.model.SendMessageResponse;
+import software.amazon.awssdk.services.sqs.model.SetQueueAttributesRequest;
+import software.amazon.awssdk.services.sqs.model.SetQueueAttributesResponse;
+
+public class AmazonSQSClientMock implements SqsClient {
+
+    List<Message> messages = new ArrayList<>();
+    Map<String, Map<String, String>> queueAttributes = new HashMap<>();
+    List<ChangeMessageVisibilityRequest> changeMessageVisibilityRequests = new CopyOnWriteArrayList<>();
+    private Map<String, CreateQueueRequest> queues = new LinkedHashMap<>();
+    private Map<String, ScheduledFuture<?>> inFlight = new LinkedHashMap<>();
+    private ScheduledExecutorService scheduler;
+
+    public AmazonSQSClientMock() {
+    }
+
+    @Override
+    public ListQueuesResponse listQueues() {
+        return ListQueuesResponse.builder().build();
+    }
+
+    @Override
+    public ListQueuesResponse listQueues(ListQueuesRequest request) {
+    	ListQueuesResponse.Builder result = ListQueuesResponse.builder();
+        List<String> queues = new ArrayList<>();
+        queues.add("queue1");
+        queues.add("queue2");
+        result.queueUrls(queues);
+        return result.build();
+    }
+
+    @Override
+    public CreateQueueResponse createQueue(CreateQueueRequest createQueueRequest) {
+        String queueName = "https://queue.amazonaws.com/541925086079/" + createQueueRequest.queueName();
+        queues.put(queueName, createQueueRequest);
+        CreateQueueResponse.Builder result = CreateQueueResponse.builder();
+        result.queueUrl(queueName);
+        return result.build();
+    }
+
+    @Override
+    public SendMessageResponse sendMessage(SendMessageRequest sendMessageRequest) {
+        Message.Builder message = Message.builder();
+        message.body(sendMessageRequest.messageBody());
+        message.md5OfBody("6a1559560f67c5e7a7d5d838bf0272ee");
+        message.messageId("f6fb6f99-5eb2-4be4-9b15-144774141458");
+        message.receiptHandle("0NNAq8PwvXsyZkR6yu4nQ07FGxNmOBWi5zC9+4QMqJZ0DJ3gVOmjI2Gh/oFnb0IeJqy5Zc8kH4JX7GVpfjcEDjaAPSeOkXQZRcaBqt"
+                                 + "4lOtyfj0kcclVV/zS7aenhfhX5Ixfgz/rHhsJwtCPPvTAdgQFGYrqaHly+etJiawiNPVc=");
+
+        synchronized (messages) {
+            messages.add(message.build());
+        }
+
+        return SendMessageResponse.builder()
+        .messageId("f6fb6f99-5eb2-4be4-9b15-144774141458")
+        .md5OfMessageBody("6a1559560f67c5e7a7d5d838bf0272ee").build();
+    }
+
+    @Override
+    public ReceiveMessageResponse receiveMessage(ReceiveMessageRequest receiveMessageRequest) {
+        Integer maxNumberOfMessages = receiveMessageRequest.maxNumberOfMessages() != null ? receiveMessageRequest.maxNumberOfMessages() : Integer.MAX_VALUE;
+        ReceiveMessageResponse.Builder result = ReceiveMessageResponse.builder();
+        Collection<Message> resultMessages = new ArrayList<>();
+
+        synchronized (messages) {
+            int fetchSize = 0;
+            for (Iterator<Message> iterator = messages.iterator(); iterator.hasNext() && fetchSize < maxNumberOfMessages; fetchSize++) {
+                Message rc = iterator.next();
+                resultMessages.add(rc);
+                iterator.remove();
+                scheduleCancelInflight(receiveMessageRequest.queueUrl(), rc);
+            }
+        }
+
+        result.messages(resultMessages);
+        return result.build();
+    }
+
+    /*
+     * Cancel (put back onto queue) in flight messages if the visibility time
+     * has expired and has not been manually deleted (ack'd)
+     */
+    private void scheduleCancelInflight(final String queueUrl, final Message message) {
+        if (scheduler != null) {
+            int visibility = getVisibilityForQueue(queueUrl);
+            if (visibility > 0) {
+                ScheduledFuture<?> task = scheduler.schedule(new Runnable() {
+                    @Override
+                    public void run() {
+                        synchronized (messages) {
+                            // put it back!
+                            messages.add(message);
+                        }
+                    }
+                }, visibility, TimeUnit.SECONDS);
+
+                inFlight.put(message.receiptHandle(), task);
+            }
+        }
+    }
+
+    private int getVisibilityForQueue(String queueUrl) {
+        Map<String, String> queueAttr = queues.get(queueUrl).attributesAsStrings();
+        if (queueAttr.containsKey("VisibilityTimeout")) {
+            return Integer.parseInt(queueAttr.get("VisibilityTimeout"));
+        }
+        return 0;
+    }
+
+    public ScheduledExecutorService getScheduler() {
+        return scheduler;
+    }
+
+    public void setScheduler(ScheduledExecutorService scheduler) {
+        this.scheduler = scheduler;
+    }
+
+    @Override
+    public DeleteMessageResponse deleteMessage(DeleteMessageRequest deleteMessageRequest) {
+        String receiptHandle = deleteMessageRequest.receiptHandle();
+        if (inFlight.containsKey(receiptHandle)) {
+            ScheduledFuture<?> inFlightTask = inFlight.get(receiptHandle);
+            inFlightTask.cancel(true);
+        }
+        return DeleteMessageResponse.builder().build();
+    }
+
+    @Override
+    public SetQueueAttributesResponse setQueueAttributes(SetQueueAttributesRequest setQueueAttributesRequest) {
+        synchronized (queueAttributes) {
+            if (!queueAttributes.containsKey(setQueueAttributesRequest.queueUrl())) {
+                queueAttributes.put(setQueueAttributesRequest.queueUrl(), new HashMap<String, String>());
+            }
+            for (final Map.Entry<String, String> entry : setQueueAttributesRequest.attributesAsStrings().entrySet()) {
+                queueAttributes.get(setQueueAttributesRequest.queueUrl()).put(entry.getKey(), entry.getValue());
+            }
+        }
+        return SetQueueAttributesResponse.builder().build();
+    }
+
+    @Override
+    public ChangeMessageVisibilityResponse changeMessageVisibility(ChangeMessageVisibilityRequest changeMessageVisibilityRequest) {
+        this.changeMessageVisibilityRequests.add(changeMessageVisibilityRequest);
+        return ChangeMessageVisibilityResponse.builder().build();
+    }
+
+    @Override
+    public SendMessageBatchResponse sendMessageBatch(SendMessageBatchRequest request) {
+        SendMessageBatchResponse.Builder result = SendMessageBatchResponse.builder();
+        Collection<SendMessageBatchResultEntry> entriesSuccess = new ArrayList<>();
+        SendMessageBatchResultEntry.Builder entry1 = SendMessageBatchResultEntry.builder();
+        SendMessageBatchResultEntry.Builder entry2 = SendMessageBatchResultEntry.builder();
+        entry1.id("team1");
+        entry2.id("team2");
+        entriesSuccess.add(entry1.build());
+        entriesSuccess.add(entry2.build());
+        Collection<BatchResultErrorEntry> entriesFail = new ArrayList<>();
+        BatchResultErrorEntry.Builder entry3 = BatchResultErrorEntry.builder();
+        BatchResultErrorEntry.Builder entry4 = BatchResultErrorEntry.builder();
+        entry3.id("team1");
+        entry4.id("team4");
+        entriesFail.add(entry3.build());
+        entriesFail.add(entry4.build());
+        result.successful(entriesSuccess);
+        result.failed(entriesFail);
+        return result.build();
+    }
+
+	@Override
+	public String serviceName() {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public void close() {
+		// TODO Auto-generated method stub
+		
+	}
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsBatchConsumerTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsBatchConsumerTest.java
new file mode 100644
index 0000000..caad417
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsBatchConsumerTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+import software.amazon.awssdk.services.sqs.model.Message;
+
+public class SqsBatchConsumerTest extends CamelTestSupport {
+
+    @EndpointInject("mock:result")
+    private MockEndpoint mock;
+
+    @Test
+    public void receiveBatch() throws Exception {
+        mock.expectedMessageCount(5);
+        assertMockEndpointsSatisfied();
+
+        mock.message(0).exchangeProperty(Exchange.BATCH_INDEX).isEqualTo(0);
+        mock.message(1).exchangeProperty(Exchange.BATCH_INDEX).isEqualTo(1);
+        mock.message(2).exchangeProperty(Exchange.BATCH_INDEX).isEqualTo(2);
+        mock.message(3).exchangeProperty(Exchange.BATCH_INDEX).isEqualTo(3);
+        mock.message(4).exchangeProperty(Exchange.BATCH_INDEX).isEqualTo(4);
+        mock.message(0).exchangeProperty(Exchange.BATCH_COMPLETE).isEqualTo(false);
+        mock.message(1).exchangeProperty(Exchange.BATCH_COMPLETE).isEqualTo(false);
+        mock.message(2).exchangeProperty(Exchange.BATCH_COMPLETE).isEqualTo(false);
+        mock.message(3).exchangeProperty(Exchange.BATCH_COMPLETE).isEqualTo(false);
+        mock.message(3).exchangeProperty(Exchange.BATCH_COMPLETE).isEqualTo(false);
+        mock.message(4).exchangeProperty(Exchange.BATCH_COMPLETE).isEqualTo(true);
+        mock.expectedPropertyReceived(Exchange.BATCH_SIZE, 5);
+    }
+
+    @BindToRegistry("amazonSQSClient")
+    public AmazonSQSClientMock addClient() throws Exception {
+
+        AmazonSQSClientMock clientMock = new AmazonSQSClientMock();
+        // add 6 messages, one more we will poll
+        for (int counter = 0; counter < 6; counter++) {
+            Message.Builder message = Message.builder();
+            message.body("Message " + counter);
+            message.md5OfBody("6a1559560f67c5e7a7d5d838bf0272ee");
+            message.messageId("f6fb6f99-5eb2-4be4-9b15-144774141458");
+            message.receiptHandle("0NNAq8PwvXsyZkR6yu4nQ07FGxNmOBWi5");
+
+            clientMock.messages.add(message.build());
+        }
+
+        return clientMock;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient&delay=5000&maxMessagesPerPoll=5").to("mock:result");
+            }
+        };
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentClientRegistryTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentClientRegistryTest.java
new file mode 100644
index 0000000..5096289
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentClientRegistryTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.component.aws2.sqs.Sqs2Component;
+import org.apache.camel.component.aws2.sqs.Sqs2Endpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class SqsComponentClientRegistryTest extends CamelTestSupport {
+
+    @Test
+    public void createEndpointWithMinimalSQSClientConfiguration() throws Exception {
+
+        AmazonSQSClientMock awsSQSClient = new AmazonSQSClientMock();
+        context.getRegistry().bind("awsSQSClient", awsSQSClient);
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://MyQueue");
+
+        assertNotNull(endpoint.getConfiguration().getAmazonSQSClient());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void createEndpointWithMinimalSQSClientMisconfiguration() throws Exception {
+
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://MyQueue");
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentConfigurationTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentConfigurationTest.java
new file mode 100644
index 0000000..70acc03
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentConfigurationTest.java
@@ -0,0 +1,306 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.component.aws2.sqs.Sqs2Component;
+import org.apache.camel.component.aws2.sqs.Sqs2Consumer;
+import org.apache.camel.component.aws2.sqs.Sqs2Endpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+import software.amazon.awssdk.core.Protocol;
+import software.amazon.awssdk.regions.Region;
+
+public class SqsComponentConfigurationTest extends CamelTestSupport {
+
+    @Test
+    public void createEndpointWithMinimalConfiguration() throws Exception {
+        AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+        context.getRegistry().bind("amazonSQSClient", mock);
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient&accessKey=xxx&secretKey=yyy");
+
+        assertEquals("MyQueue", endpoint.getConfiguration().getQueueName());
+        assertEquals("xxx", endpoint.getConfiguration().getAccessKey());
+        assertEquals("yyy", endpoint.getConfiguration().getSecretKey());
+        assertNotNull(endpoint.getConfiguration().getAmazonSQSClient());
+        assertNull(endpoint.getConfiguration().getAttributeNames());
+        assertNull(endpoint.getConfiguration().getMessageAttributeNames());
+        assertNull(endpoint.getConfiguration().getDefaultVisibilityTimeout());
+        assertNull(endpoint.getConfiguration().getVisibilityTimeout());
+        assertNull(endpoint.getConfiguration().getMaximumMessageSize());
+        assertNull(endpoint.getConfiguration().getMessageRetentionPeriod());
+        assertNull(endpoint.getConfiguration().getPolicy());
+        assertNull(endpoint.getConfiguration().getRedrivePolicy());
+        assertNull(endpoint.getConfiguration().getRegion());
+    }
+
+    @Test
+    public void createEndpointWithOnlyAccessKeyAndSecretKey() throws Exception {
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://MyQueue?accessKey=xxx&secretKey=yyy");
+
+        assertEquals("MyQueue", endpoint.getConfiguration().getQueueName());
+        assertEquals("xxx", endpoint.getConfiguration().getAccessKey());
+        assertEquals("yyy", endpoint.getConfiguration().getSecretKey());
+        assertNull(endpoint.getConfiguration().getAmazonSQSClient());
+        assertNull(endpoint.getConfiguration().getAttributeNames());
+        assertNull(endpoint.getConfiguration().getMessageAttributeNames());
+        assertNull(endpoint.getConfiguration().getDefaultVisibilityTimeout());
+        assertNull(endpoint.getConfiguration().getVisibilityTimeout());
+        assertNull(endpoint.getConfiguration().getMaximumMessageSize());
+        assertNull(endpoint.getConfiguration().getMessageRetentionPeriod());
+        assertNull(endpoint.getConfiguration().getPolicy());
+        assertNull(endpoint.getConfiguration().getRedrivePolicy());
+        assertNull(endpoint.getConfiguration().getRegion());
+    }
+
+    @Test
+    public void createEndpointWithOnlyAccessKeyAndSecretKeyAndRegion() throws Exception {
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://MyQueue?accessKey=xxx&secretKey=yyy&region=US_WEST_1");
+
+        assertEquals("MyQueue", endpoint.getConfiguration().getQueueName());
+        assertEquals("xxx", endpoint.getConfiguration().getAccessKey());
+        assertEquals("yyy", endpoint.getConfiguration().getSecretKey());
+        assertEquals("US_WEST_1", endpoint.getConfiguration().getRegion());
+        assertNull(endpoint.getConfiguration().getAmazonSQSClient());
+        assertNull(endpoint.getConfiguration().getAttributeNames());
+        assertNull(endpoint.getConfiguration().getMessageAttributeNames());
+        assertNull(endpoint.getConfiguration().getDefaultVisibilityTimeout());
+        assertNull(endpoint.getConfiguration().getVisibilityTimeout());
+        assertNull(endpoint.getConfiguration().getMaximumMessageSize());
+        assertNull(endpoint.getConfiguration().getMessageRetentionPeriod());
+        assertNull(endpoint.getConfiguration().getPolicy());
+        assertNull(endpoint.getConfiguration().getRedrivePolicy());
+    }
+
+    @Test
+    public void createEndpointWithMinimalArnConfiguration() throws Exception {
+        AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+        context.getRegistry().bind("amazonSQSClient", mock);
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component
+            .createEndpoint("aws2-sqs://arn:aws:sqs:us-east-1:account:MyQueue?amazonSQSClient=#amazonSQSClient&accessKey=xxx&secretKey=yyy&region=US_EAST_1");
+
+        assertEquals("US_EAST_1", endpoint.getConfiguration().getRegion());
+        assertEquals("account", endpoint.getConfiguration().getQueueOwnerAWSAccountId());
+        assertEquals("MyQueue", endpoint.getConfiguration().getQueueName());
+        assertEquals("xxx", endpoint.getConfiguration().getAccessKey());
+    }
+
+    @Test
+    public void createEndpointAttributeNames() throws Exception {
+        AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+        context.getRegistry().bind("amazonSQSClient", mock);
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient&accessKey=xxx&secretKey=yyy&attributeNames=foo,bar");
+
+        assertEquals("MyQueue", endpoint.getConfiguration().getQueueName());
+        assertEquals("xxx", endpoint.getConfiguration().getAccessKey());
+        assertEquals("yyy", endpoint.getConfiguration().getSecretKey());
+        assertNotNull(endpoint.getConfiguration().getAmazonSQSClient());
+        assertEquals("foo,bar", endpoint.getConfiguration().getAttributeNames());
+    }
+
+    @Test
+    public void createEndpointWithMinimalConfigurationAndProvidedClient() throws Exception {
+        AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+        context.getRegistry().bind("amazonSQSClient", mock);
+
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient");
+
+        assertEquals("MyQueue", endpoint.getConfiguration().getQueueName());
+        assertNull(endpoint.getConfiguration().getAccessKey());
+        assertNull(endpoint.getConfiguration().getSecretKey());
+        assertSame(mock, endpoint.getConfiguration().getAmazonSQSClient());
+        assertNull(endpoint.getConfiguration().getAttributeNames());
+        assertNull(endpoint.getConfiguration().getMessageAttributeNames());
+        assertNull(endpoint.getConfiguration().getDefaultVisibilityTimeout());
+        assertNull(endpoint.getConfiguration().getVisibilityTimeout());
+        assertNull(endpoint.getConfiguration().getMaximumMessageSize());
+        assertNull(endpoint.getConfiguration().getMessageRetentionPeriod());
+        assertNull(endpoint.getConfiguration().getPolicy());
+        assertNull(endpoint.getConfiguration().getRedrivePolicy());
+        assertNull(endpoint.getConfiguration().getRegion());
+    }
+
+    @Test
+    public void createEndpointWithMaximalConfiguration() throws Exception {
+        AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+        context.getRegistry().bind("amazonSQSClient", mock);
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component
+            .createEndpoint("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient&accessKey=xxx" + "&secretKey=yyy&attributeNames=color,size"
+                            + "&messageAttributeNames=msgColor,msgSize&defaultVisibilityTimeout=1000&visibilityTimeout=2000&maximumMessageSize=65536&messageRetentionPeriod=1209600&policy="
+                            + "%7B%22Version%22%3A%222008-10-17%22%2C%22Id%22%3A%22%2F195004372649%2FMyQueue%2FSQSDefaultPolicy%22%2C%22Statement%22%3A%5B%7B%22Sid%22%3A%22Queue1ReceiveMessage%22%2C%22"
+                            + "Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22AWS%22%3A%22*%22%7D%2C%22Action%22%3A%22SQS%3AReceiveMessage%22%2C%22Resource%22%3A%22%2F195004372649%2FMyQueue%22%7D%5D%7D"
+                            + "&delaySeconds=123&receiveMessageWaitTimeSeconds=10&waitTimeSeconds=20" + "&queueOwnerAWSAccountId=111222333&region=us-east-1"
+                            + "&redrivePolicy={\"maxReceiveCount\":\"5\", \"deadLetterTargetArn\":\"arn:aws:sqs:us-east-1:195004372649:MyDeadLetterQueue\"}");
+
+        assertEquals("MyQueue", endpoint.getConfiguration().getQueueName());
+        assertEquals("xxx", endpoint.getConfiguration().getAccessKey());
+        assertEquals("yyy", endpoint.getConfiguration().getSecretKey());
+        assertNotNull(endpoint.getConfiguration().getAmazonSQSClient());
+        assertEquals("color,size", endpoint.getConfiguration().getAttributeNames());
+        assertEquals("msgColor,msgSize", endpoint.getConfiguration().getMessageAttributeNames());
+        assertEquals(new Integer(1000), endpoint.getConfiguration().getDefaultVisibilityTimeout());
+        assertEquals(new Integer(2000), endpoint.getConfiguration().getVisibilityTimeout());
+        assertEquals(new Integer(65536), endpoint.getConfiguration().getMaximumMessageSize());
+        assertEquals(new Integer(1209600), endpoint.getConfiguration().getMessageRetentionPeriod());
+        assertEquals("{\"Version\":\"2008-10-17\",\"Id\":\"/195004372649/MyQueue/SQSDefaultPolicy\",\"Statement\":[{\"Sid\":\"Queue1ReceiveMessage\",\"Effect\":\"Allow\",\"Principal\":"
+                     + "{\"AWS\":\"*\"},\"Action\":\"SQS:ReceiveMessage\",\"Resource\":\"/195004372649/MyQueue\"}]}", endpoint.getConfiguration().getPolicy());
+        assertEquals("{\"maxReceiveCount\":\"5\", \"deadLetterTargetArn\":\"arn:aws:sqs:us-east-1:195004372649:MyDeadLetterQueue\"}",
+                     endpoint.getConfiguration().getRedrivePolicy());
+        assertEquals(new Integer(123), endpoint.getConfiguration().getDelaySeconds());
+        assertEquals(Integer.valueOf(10), endpoint.getConfiguration().getReceiveMessageWaitTimeSeconds());
+        assertEquals(Integer.valueOf(20), endpoint.getConfiguration().getWaitTimeSeconds());
+        assertEquals("111222333", endpoint.getConfiguration().getQueueOwnerAWSAccountId());
+        assertEquals("us-east-1", endpoint.getConfiguration().getRegion());
+    }
+
+    @Test
+    public void createEndpointWithPollConsumerConfiguration() throws Exception {
+        AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+        context.getRegistry().bind("amazonSQSClient", mock);
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component
+            .createEndpoint("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient" + "&accessKey=xxx&secretKey=yyy&initialDelay=300&delay=400&maxMessagesPerPoll=50");
+        Sqs2Consumer consumer = (Sqs2Consumer)endpoint.createConsumer(null);
+
+        assertEquals(300, consumer.getInitialDelay());
+        assertEquals(400, consumer.getDelay());
+        assertEquals(50, consumer.getMaxMessagesPerPoll());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void createEndpointWithoutAccessKeyConfiguration() throws Exception {
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        component.createEndpoint("aws2-sqs://MyQueue?secretKey=yyy");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void createEndpointWithoutSecretKeyConfiguration() throws Exception {
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        component.createEndpoint("aws2-sqs://MyQueue?accessKey=xxx");
+    }
+
+    // Setting extendMessageVisibility on an SQS consumer should make
+    // visibilityTimeout compulsory
+    @Test(expected = IllegalArgumentException.class)
+    public void createEndpointWithExtendMessageVisibilityAndNoVisibilityTimeoutThrowsException() throws Exception {
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        component.createEndpoint("aws2-sqs://MyQueue?accessKey=xxx&secretKey=yyy&extendMessageVisibility=true");
+    }
+
+    @Test
+    public void createEndpointWithExtendMessageVisibilityTrueAndVisibilityTimeoutSet() throws Exception {
+        AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+        context.getRegistry().bind("amazonSQSClient", mock);
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        assertNotNull(component.createEndpoint("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient&accessKey=xxx&secretKey=yyy&visibilityTimeout=30&extendMessageVisibility=true"));
+    }
+
+    @Test
+    public void createEndpointWithExtendMessageVisibilityFalseAndVisibilityTimeoutSet() throws Exception {
+        AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+        context.getRegistry().bind("amazonSQSClient", mock);
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        assertNotNull(component
+            .createEndpoint("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient&accessKey=xxx&secretKey=yyy&visibilityTimeout=30&extendMessageVisibility=false"));
+    }
+
+    @Test
+    public void createEndpointWithoutSecretKeyAndAccessKeyConfiguration() throws Exception {
+        AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+        context.getRegistry().bind("amazonSQSClient", mock);
+
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        component.createEndpoint("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient");
+    }
+
+    @Test
+    public void createEndpointWithComponentElements() throws Exception {
+        AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+        context.getRegistry().bind("amazonSQSClient", mock);
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        component.setAccessKey("XXX");
+        component.setSecretKey("YYY");
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient");
+
+        assertEquals("MyQueue", endpoint.getConfiguration().getQueueName());
+        assertEquals("XXX", endpoint.getConfiguration().getAccessKey());
+        assertEquals("YYY", endpoint.getConfiguration().getSecretKey());
+    }
+
+    @Test
+    public void createEndpointWithComponentAndEndpointElements() throws Exception {
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        component.setAccessKey("XXX");
+        component.setSecretKey("YYY");
+        component.setRegion(Region.US_WEST_1.toString());
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://MyQueue?accessKey=xxxxxx&secretKey=yyyyy&region=US_EAST_1");
+
+        assertEquals("MyQueue", endpoint.getConfiguration().getQueueName());
+        assertEquals("xxxxxx", endpoint.getConfiguration().getAccessKey());
+        assertEquals("yyyyy", endpoint.getConfiguration().getSecretKey());
+        assertEquals("US_EAST_1", endpoint.getConfiguration().getRegion());
+    }
+
+    @Test
+    public void createEndpointWithoutAutoCreation() throws Exception {
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        component.setAccessKey("XXX");
+        component.setSecretKey("YYY");
+        component.setRegion(Region.US_WEST_1.toString());
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://MyQueue?accessKey=xxxxxx&secretKey=yyyyy&region=US_EAST_1&autoCreateQueue=false");
+
+        assertEquals("MyQueue", endpoint.getConfiguration().getQueueName());
+        assertEquals("xxxxxx", endpoint.getConfiguration().getAccessKey());
+        assertEquals("yyyyy", endpoint.getConfiguration().getSecretKey());
+        assertEquals("US_EAST_1", endpoint.getConfiguration().getRegion());
+        assertEquals(false, endpoint.getConfiguration().isAutoCreateQueue());
+    }
+    
+    @Test
+    public void createEndpointWithComponentEndpointElementsAndProxy() throws Exception {
+        Sqs2Component component = context.getComponent("aws2-sqs", Sqs2Component.class);
+        component.setAccessKey("XXX");
+        component.setSecretKey("YYY");
+        component.setRegion(Region.US_WEST_1.toString());
+        Sqs2Endpoint endpoint = (Sqs2Endpoint)component.createEndpoint("aws2-sqs://label?accessKey=xxxxxx&secretKey=yyyyy&region=US_EAST_1&proxyHost=localhost&proxyPort=9000&proxyProtocol=HTTP");
+        
+        assertEquals("xxxxxx", endpoint.getConfiguration().getAccessKey());
+        assertEquals("yyyyy", endpoint.getConfiguration().getSecretKey());
+        assertEquals("US_EAST_1", endpoint.getConfiguration().getRegion());
+        assertEquals(Protocol.HTTP, endpoint.getConfiguration().getProxyProtocol());
+        assertEquals("localhost", endpoint.getConfiguration().getProxyHost());
+        assertEquals(Integer.valueOf(9000), endpoint.getConfiguration().getProxyPort());
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentSpringTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentSpringTest.java
new file mode 100644
index 0000000..db0cf18
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentSpringTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import software.amazon.awssdk.services.sqs.model.DeleteMessageResponse;
+import software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.aws2.sqs.Sqs2Constants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.spring.CamelSpringTestSupport;
+import org.junit.Test;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+public class SqsComponentSpringTest extends CamelSpringTestSupport {
+
+    @EndpointInject("direct:start")
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendInOnly() throws Exception {
+        result.expectedMessageCount(1);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("This is my message text.");
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+
+        Exchange resultExchange = result.getExchanges().get(0);
+        assertEquals("This is my message text.", resultExchange.getIn().getBody());
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.RECEIPT_HANDLE));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", resultExchange.getIn().getHeader(Sqs2Constants.MD5_OF_BODY));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.ATTRIBUTES));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ATTRIBUTES));
+
+        assertNotNull(exchange.getIn().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", resultExchange.getIn().getHeader(Sqs2Constants.MD5_OF_BODY));
+    }
+
+    @Test
+    public void sendInOut() throws Exception {
+        result.expectedMessageCount(1);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOut, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("This is my message text.");
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+
+        Exchange resultExchange = result.getExchanges().get(0);
+        assertEquals("This is my message text.", resultExchange.getIn().getBody());
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.RECEIPT_HANDLE));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", resultExchange.getIn().getHeader(Sqs2Constants.MD5_OF_BODY));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.ATTRIBUTES));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ATTRIBUTES));
+
+        assertNotNull(exchange.getMessage().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", exchange.getMessage().getHeader(Sqs2Constants.MD5_OF_BODY));
+    }
+
+    @Test
+    public void sendBatchMessage() throws Exception {
+        result.expectedMessageCount(1);
+
+        template.send("direct:start-batch", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                Collection c = new ArrayList<Integer>();
+                c.add("team1");
+                c.add("team2");
+                c.add("team3");
+                c.add("team4");
+                exchange.getIn().setBody(c);
+            }
+        });
+        assertMockEndpointsSatisfied();
+        SendMessageBatchResponse res = result.getExchanges().get(0).getIn().getBody(SendMessageBatchResponse.class);
+        assertEquals(2, res.failed().size());
+        assertEquals(2, res.successful().size());
+    }
+
+    @Test
+    public void deleteMessage() throws Exception {
+        result.expectedMessageCount(1);
+
+        template.send("direct:start-delete", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Sqs2Constants.RECEIPT_HANDLE, "123456");
+            }
+        });
+        assertMockEndpointsSatisfied();
+        DeleteMessageResponse res = result.getExchanges().get(0).getIn().getBody(DeleteMessageResponse.class);
+        assertNotNull(res);
+    }
+
+    @Override
+    protected ClassPathXmlApplicationContext createApplicationContext() {
+        return new ClassPathXmlApplicationContext("org/apache/camel/component/aws2/sqs/SqsComponentSpringTest-context.xml");
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentTest.java
new file mode 100644
index 0000000..2016670
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.aws2.sqs.Sqs2Constants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+public class SqsComponentTest extends CamelTestSupport {
+
+    @EndpointInject("direct:start")
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @BindToRegistry("amazonSQSClient")
+    private AmazonSQSClientMock client = new AmazonSQSClientMock();
+
+    @Test
+    public void sendInOnly() throws Exception {
+        result.expectedMessageCount(1);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("This is my message text.");
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+
+        Exchange resultExchange = result.getExchanges().get(0);
+        assertEquals("This is my message text.", resultExchange.getIn().getBody());
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.RECEIPT_HANDLE));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", resultExchange.getIn().getHeader(Sqs2Constants.MD5_OF_BODY));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.ATTRIBUTES));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ATTRIBUTES));
+
+        assertEquals("This is my message text.", exchange.getIn().getBody());
+        assertNotNull(exchange.getIn().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", exchange.getIn().getHeader(Sqs2Constants.MD5_OF_BODY));
+    }
+
+    @Test
+    public void sendInOut() throws Exception {
+        result.expectedMessageCount(1);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOut, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("This is my message text.");
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+
+        Exchange resultExchange = result.getExchanges().get(0);
+        assertEquals("This is my message text.", resultExchange.getIn().getBody());
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.RECEIPT_HANDLE));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", resultExchange.getIn().getHeader(Sqs2Constants.MD5_OF_BODY));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.ATTRIBUTES));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ATTRIBUTES));
+
+        assertEquals("This is my message text.", exchange.getMessage().getBody());
+        assertNotNull(exchange.getMessage().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", exchange.getMessage().getHeader(Sqs2Constants.MD5_OF_BODY));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            final String sqsURI = String.format("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient&messageRetentionPeriod=%s&maximumMessageSize=%s&policy=%s", "1209600", "65536",
+                                                "");
+
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").to(sqsURI);
+
+                from(sqsURI).to("mock:result");
+            }
+        };
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentVerifierExtensionTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentVerifierExtensionTest.java
new file mode 100644
index 0000000..931e903
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsComponentVerifierExtensionTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.Component;
+import org.apache.camel.component.extension.ComponentVerifierExtension;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class SqsComponentVerifierExtensionTest extends CamelTestSupport {
+
+    // *************************************************
+    // Tests (parameters)
+    // *************************************************
+    @Override
+    public boolean isUseRouteBuilder() {
+        return false;
+    }
+
+    @Test
+    public void testParameters() throws Exception {
+        Component component = context().getComponent("aws2-sqs");
+
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("secretKey", "l");
+        parameters.put("accessKey", "k");
+        parameters.put("region", "l");
+        parameters.put("queueNameOrArn", "bucket1");
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.PARAMETERS, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.OK, result.getStatus());
+    }
+
+    @Test
+    public void testConnectivity() throws Exception {
+        Component component = context().getComponent("aws2-sqs");
+        ComponentVerifierExtension verifier = component.getExtension(ComponentVerifierExtension.class).orElseThrow(IllegalStateException::new);
+
+        Map<String, Object> parameters = new HashMap<>();
+        parameters.put("secretKey", "l");
+        parameters.put("accessKey", "k");
+        parameters.put("region", "US_EAST_1");
+        parameters.put("queueNameOrArn", "test12");
+
+        ComponentVerifierExtension.Result result = verifier.verify(ComponentVerifierExtension.Scope.CONNECTIVITY, parameters);
+
+        Assert.assertEquals(ComponentVerifierExtension.Result.Status.ERROR, result.getStatus());
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsConcurrentConsumerTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsConcurrentConsumerTest.java
new file mode 100644
index 0000000..197b333
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsConcurrentConsumerTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.NotifyBuilder;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+import software.amazon.awssdk.services.sqs.model.Message;
+
+public class SqsConcurrentConsumerTest extends CamelTestSupport {
+    private static final int NUM_CONCURRENT = 10;
+    private static final int NUM_MESSAGES = 100;
+
+    final Set<Long> threadNumbers = new HashSet<>();
+
+    @Test
+    public void consumeMessagesFromQueue() throws Exception {
+        // simple test to make sure that concurrent consumers were used in the
+        // test
+
+        NotifyBuilder notifier = new NotifyBuilder(context).whenCompleted(NUM_MESSAGES).create();
+        assertTrue("We didn't process " + NUM_MESSAGES + " messages as we expected!", notifier.matches(5, TimeUnit.SECONDS));
+
+        if (isPlatform("windows")) {
+            // threading is different on windows
+        } else {
+            // usually we use all threads evenly but sometimes threads are
+            // reused so just test that 50%+ was used
+            if (threadNumbers.size() < (NUM_CONCURRENT / 2)) {
+                fail(String.format("We were expecting to have about half of %d numbers of concurrent consumers, but only found %d", NUM_CONCURRENT, threadNumbers.size()));
+            }
+        }
+    }
+
+    @BindToRegistry("client")
+    public AmazonSQSClientMock addClient() throws Exception {
+        AmazonSQSClientMock client = new AmazonSQSClientMock();
+        createDummyMessages(client, NUM_MESSAGES);
+        return client;
+    }
+
+    private void createDummyMessages(AmazonSQSClientMock client, int numMessages) {
+        for (int counter = 0; counter < numMessages; counter++) {
+            Message.Builder message = Message.builder();
+            message.body("Message " + counter);
+            message.md5OfBody("6a1559560f67c5e7a7d5d838bf0272ee");
+            message.messageId("f6fb6f99-5eb2-4be4-9b15-144774141458");
+            message.receiptHandle("0NNAq8PwvXsyZkR6yu4nQ07FGxNmOBWi5");
+            client.messages.add(message.build());
+        }
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("aws2-sqs://demo?concurrentConsumers=" + NUM_CONCURRENT + "&maxMessagesPerPoll=10&amazonSQSClient=#client").process(new Processor() {
+                    @Override
+                    public void process(Exchange exchange) throws Exception {
+                        threadNumbers.add(Thread.currentThread().getId());
+                    }
+                }).log("processed a new message!");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsConfigurationTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsConfigurationTest.java
new file mode 100644
index 0000000..7a0a05c
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsConfigurationTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.camel.component.aws2.sqs.Sqs2Configuration;
+
+public class SqsConfigurationTest {
+
+    @Test
+    public void itReturnsAnInformativeErrorForBadMessageGroupIdStrategy() throws Exception {
+        Sqs2Configuration sqsConfiguration = new Sqs2Configuration();
+        try {
+            sqsConfiguration.setMessageGroupIdStrategy("useUnknownStrategy");
+            fail("Should have thrown exception");
+        } catch (Exception e) {
+            assertTrue("Bad error message: " + e.getMessage(), e.getMessage().startsWith("Unrecognised MessageGroupIdStrategy"));
+        }
+    }
+
+    @Test
+    public void itReturnsAnInformativeErrorForBadMessageDeduplicationIdStrategy() throws Exception {
+        Sqs2Configuration sqsConfiguration = new Sqs2Configuration();
+        try {
+            sqsConfiguration.setMessageDeduplicationIdStrategy("useUnknownStrategy");
+            fail("Should have thrown exception");
+        } catch (Exception e) {
+            assertTrue("Bad error message: " + e.getMessage(), e.getMessage().startsWith("Unrecognised MessageDeduplicationIdStrategy"));
+        }
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsConsumerIdleMessageTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsConsumerIdleMessageTest.java
new file mode 100644
index 0000000..c5696cf
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsConsumerIdleMessageTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+/**
+ * Test to verify that the polling consumer delivers an empty Exchange when the
+ * sendEmptyMessageWhenIdle property is set and a polling event yields no results.
+ */
+public class SqsConsumerIdleMessageTest extends CamelTestSupport {
+
+    @BindToRegistry("amazonSQSClient")
+    private AmazonSQSClientMock client = new AmazonSQSClientMock();
+
+    @Test
+    public void testConsumeIdleMessages() throws Exception {
+        Thread.sleep(110);
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMinimumMessageCount(2);
+        assertMockEndpointsSatisfied();
+        assertTrue(mock.getExchanges().get(0).getIn().getBody() == null);
+        assertTrue(mock.getExchanges().get(1).getIn().getBody() == null);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient&delay=50&maxMessagesPerPoll=5" + "&sendEmptyMessageWhenIdle=true").to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsDoesNotExtendMessageVisibilityTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsDoesNotExtendMessageVisibilityTest.java
new file mode 100644
index 0000000..8e83f95
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsDoesNotExtendMessageVisibilityTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+import software.amazon.awssdk.services.sqs.model.Message;
+
+public class SqsDoesNotExtendMessageVisibilityTest extends CamelTestSupport {
+
+    private static final int TIMEOUT = 4; // 4 seconds.
+    private static final String RECEIPT_HANDLE = "0NNAq8PwvXsyZkR6yu4nQ07FGxNmOBWi5";
+
+    @EndpointInject("mock:result")
+    private MockEndpoint mock;
+
+    @BindToRegistry("amazonSQSClient")
+    private AmazonSQSClientMock client = new AmazonSQSClientMock();
+
+    @Test
+    public void defaultsToDisabled() throws Exception {
+        this.mock.expectedMessageCount(1);
+        this.mock.whenAnyExchangeReceived(new Processor() {
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                // Simulate message that takes a while to receive.
+                Thread.sleep(TIMEOUT * 1500L); // 150% of TIMEOUT.
+            }
+        });
+
+        Message.Builder message = Message.builder();
+        message.body("Message 1");
+        message.md5OfBody("6a1559560f67c5e7a7d5d838bf0272ee");
+        message.messageId("f6fb6f99-5eb2-4be4-9b15-144774141458");
+        message.receiptHandle(RECEIPT_HANDLE);
+        this.client.messages.add(message.build());
+
+        assertMockEndpointsSatisfied(); // Wait for message to arrive.
+        assertTrue("Expected no changeMessageVisibility requests.", this.client.changeMessageVisibilityRequests.size() == 0);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient").to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsEndpointExplicitQueueUrlTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsEndpointExplicitQueueUrlTest.java
new file mode 100644
index 0000000..b8a601e
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsEndpointExplicitQueueUrlTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.component.aws2.sqs.Sqs2Component;
+import org.apache.camel.component.aws2.sqs.Sqs2Configuration;
+import org.apache.camel.component.aws2.sqs.Sqs2Endpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import software.amazon.awssdk.services.sqs.SqsClient;
+
+public class SqsEndpointExplicitQueueUrlTest extends Assert {
+
+    private static final String QUEUE_URL = "http://localhost:9324/queue/default";
+    private Sqs2Endpoint endpoint;
+    private SqsClient amazonSQSClient;
+
+    @Before
+    public void setUp() {
+        amazonSQSClient = new AmazonSQSClientMock();
+
+        Sqs2Configuration config = new Sqs2Configuration();
+        config.setQueueUrl(QUEUE_URL);
+        config.setAmazonSQSClient(amazonSQSClient);
+
+        endpoint = new Sqs2Endpoint("aws2-sqs://test-queue", new Sqs2Component(new DefaultCamelContext()), config);
+    }
+
+    @Test
+    public void doStartWithExplicitQueueUrlInConfigShouldNotCallSqsClientListQueues() throws Exception {
+        endpoint.doInit();
+
+        assertEquals(endpoint.getQueueUrl(), QUEUE_URL);
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsProducerBatchTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsProducerBatchTest.java
new file mode 100644
index 0000000..68671fa
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsProducerBatchTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+import software.amazon.awssdk.services.sqs.model.SendMessageBatchResponse;
+
+public class SqsProducerBatchTest extends CamelTestSupport {
+
+    @BindToRegistry("client")
+    AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+    @EndpointInject("direct:start")
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendBatchMessage() throws Exception {
+        result.expectedMessageCount(1);
+
+        template.send("direct:start", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                Collection c = new ArrayList<Integer>();
+                c.add("team1");
+                c.add("team2");
+                c.add("team3");
+                c.add("team4");
+                exchange.getIn().setBody(c);
+            }
+        });
+        assertMockEndpointsSatisfied();
+        SendMessageBatchResponse res = result.getExchanges().get(0).getIn().getBody(SendMessageBatchResponse.class);
+        assertEquals(2, res.failed().size());
+        assertEquals(2, res.successful().size());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").to("aws2-sqs://camel-1?amazonSQSClient=#client&operation=sendBatchMessage").to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsProducerDeleteTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsProducerDeleteTest.java
new file mode 100644
index 0000000..cb3f2e5
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsProducerDeleteTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.aws2.sqs.Sqs2Constants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+import software.amazon.awssdk.services.sqs.model.DeleteMessageResponse;
+
+public class SqsProducerDeleteTest extends CamelTestSupport {
+
+    @BindToRegistry("client")
+    AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+    @EndpointInject("direct:start")
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void deleteMessage() throws Exception {
+        result.expectedMessageCount(1);
+
+        template.send("direct:start", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Sqs2Constants.RECEIPT_HANDLE, "123456");
+            }
+        });
+        assertMockEndpointsSatisfied();
+        DeleteMessageResponse res = result.getExchanges().get(0).getIn().getBody(DeleteMessageResponse.class);
+        assertNotNull(res);
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").to("aws2-sqs://camel-1?amazonSQSClient=#client&operation=deleteMessage").to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsProducerListQueuesTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsProducerListQueuesTest.java
new file mode 100644
index 0000000..3f8d756
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/SqsProducerListQueuesTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.camel.component.aws2.sqs;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.aws2.sqs.Sqs2Constants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Test;
+
+import software.amazon.awssdk.services.sqs.model.ListQueuesResponse;
+
+public class SqsProducerListQueuesTest extends CamelTestSupport {
+
+    @BindToRegistry("client")
+    AmazonSQSClientMock mock = new AmazonSQSClientMock();
+
+    @EndpointInject("direct:start")
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void listQueues() throws Exception {
+        result.expectedMessageCount(1);
+
+        template.send("direct:start", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setHeader(Sqs2Constants.RECEIPT_HANDLE, "123456");
+            }
+        });
+        assertMockEndpointsSatisfied();
+        ListQueuesResponse res = result.getExchanges().get(0).getIn().getBody(ListQueuesResponse.class);
+        assertNotNull(res);
+        assertEquals(2, res.queueUrls().size());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").to("aws2-sqs://camel-1?amazonSQSClient=#client&operation=listQueues").to("mock:result");
+            }
+        };
+    }
+
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsComponentIntegrationTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsComponentIntegrationTest.java
new file mode 100644
index 0000000..58e150b
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsComponentIntegrationTest.java
@@ -0,0 +1,109 @@
+/*
+ * 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.camel.component.aws2.sqs.integration;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.aws2.sqs.Sqs2Constants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore("Must be manually tested. Provide your own accessKey and secretKey!")
+public class SqsComponentIntegrationTest extends CamelTestSupport {
+
+    private String accessKey = "xxx";
+    private String secretKey = "yyy";
+
+    @EndpointInject("direct:start")
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendInOnly() throws Exception {
+        result.expectedMessageCount(1);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("This is my message text.");
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+
+        Exchange resultExchange = result.getExchanges().get(0);
+        assertEquals("This is my message text.", resultExchange.getIn().getBody());
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.RECEIPT_HANDLE));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", resultExchange.getIn().getHeader(Sqs2Constants.MD5_OF_BODY));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.ATTRIBUTES));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ATTRIBUTES));
+
+        assertNotNull(exchange.getIn().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", exchange.getIn().getHeader(Sqs2Constants.MD5_OF_BODY));
+    }
+
+    @Test
+    public void sendInOut() throws Exception {
+        result.expectedMessageCount(1);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOut, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("This is my message text.");
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+
+        Exchange resultExchange = result.getExchanges().get(0);
+        assertEquals("This is my message text.", resultExchange.getIn().getBody());
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.RECEIPT_HANDLE));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", resultExchange.getIn().getHeader(Sqs2Constants.MD5_OF_BODY));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.ATTRIBUTES));
+        assertNotNull(resultExchange.getIn().getHeader(Sqs2Constants.MESSAGE_ATTRIBUTES));
+
+        assertNotNull(exchange.getMessage().getHeader(Sqs2Constants.MESSAGE_ID));
+        assertEquals("6a1559560f67c5e7a7d5d838bf0272ee", exchange.getMessage().getHeader(Sqs2Constants.MD5_OF_BODY));
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        final String sqsEndpointUri = String
+            .format("aws2-sqs://MyNewCamelQueue?accessKey=%s&secretKey=%s&messageRetentionPeriod=%s&maximumMessageSize=%s&visibilityTimeout=%s&policy=%s", accessKey, secretKey,
+                    "1209600", "65536", "60",
+                    "%7B%22Version%22%3A%222008-10-17%22%2C%22Id%22%3A%22%2F195004372649%2FMyNewCamelQueue%2FSQSDefaultPolicy%22%2C%22"
+                                              + "Statement%22%3A%5B%7B%22Sid%22%3A%22Queue1ReceiveMessage%22%2C%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22AWS%22%3A%22*%22%7D%2C%22"
+                                              + "Action%22%3A%22SQS%3AReceiveMessage%22%2C%22Resource%22%3A%22%2F195004372649%2FMyNewCamelQueue%22%7D%5D%7D");
+
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").to(sqsEndpointUri);
+
+                from(sqsEndpointUri).to("mock:result");
+            }
+        };
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsConsumerMessageIntegrationTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsConsumerMessageIntegrationTest.java
new file mode 100644
index 0000000..1155fc5
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsConsumerMessageIntegrationTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.camel.component.aws2.sqs.integration;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore("Must be manually tested. Provide your own accessKey and secretKey!")
+public class SqsConsumerMessageIntegrationTest extends CamelTestSupport {
+
+    @EndpointInject("direct:start")
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendInOnly() throws Exception {
+        result.expectedMessageCount(1);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("ignore");
+            }
+        });
+
+        exchange = template.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("test1");
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        final String sqsEndpointUri = String.format("aws2-sqs://camel-1?accessKey=RAW(xxxx)&secretKey=RAW(xxxx)&region=EU_WEST_1");
+
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").startupOrder(2).to(sqsEndpointUri);
+
+                from("aws2-sqs://camel-1?accessKey=RAW(xxxx)&secretKey=RAW(xxxx)&region=EU_WEST_1&deleteAfterRead=false&deleteIfFiltered=true").startupOrder(1)
+                    .filter(simple("${body} != 'ignore'")).log("${body}").log("${header.CamelAwsSqsReceiptHandle}").to("mock:result");
+            }
+        };
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsProducerBatchSendFifoIntegrationTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsProducerBatchSendFifoIntegrationTest.java
new file mode 100644
index 0000000..1645d24
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsProducerBatchSendFifoIntegrationTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.camel.component.aws2.sqs.integration;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.aws2.sqs.Sqs2Constants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore("Must be manually tested. Provide your own accessKey and secretKey!")
+public class SqsProducerBatchSendFifoIntegrationTest extends CamelTestSupport {
+
+    @EndpointInject("direct:start")
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendInOnly() throws Exception {
+        result.expectedMessageCount(5);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                Collection c = new ArrayList<Integer>();
+                c.add("2");
+                c.add("1");
+                c.add("3");
+                c.add("4");
+                c.add("5");
+                exchange.getIn().setBody(c);
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        final String sqsEndpointUri = String.format("aws2-sqs://camel-1.fifo?accessKey=RAW(xxx)&secretKey=RAW(xxx)&region=EU_WEST_1&messageGroupIdStrategy=useExchangeId"
+                                                    + "&messageDeduplicationIdStrategy=useContentBasedDeduplication");
+
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").startupOrder(2).setHeader(Sqs2Constants.SQS_OPERATION, constant("sendBatchMessage")).to(sqsEndpointUri);
+
+                from("aws2-sqs://camel-1.fifo?accessKey=RAW(xxx)&secretKey=RAW(xxxx)&region=EU_WEST_1&deleteAfterRead=false").startupOrder(1).log("${body}").to("mock:result");
+            }
+        };
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsProducerBatchSendIntegrationTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsProducerBatchSendIntegrationTest.java
new file mode 100644
index 0000000..ca615c6
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsProducerBatchSendIntegrationTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.camel.component.aws2.sqs.integration;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.aws2.sqs.Sqs2Constants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore("Must be manually tested. Provide your own accessKey and secretKey!")
+public class SqsProducerBatchSendIntegrationTest extends CamelTestSupport {
+
+    @EndpointInject("direct:start")
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendInOnly() throws Exception {
+        result.expectedMessageCount(5);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                Collection c = new ArrayList<Integer>();
+                c.add("1");
+                c.add("2");
+                c.add("3");
+                c.add("4");
+                c.add("5");
+                exchange.getIn().setBody(c);
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        final String sqsEndpointUri = String.format("aws2-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)&region=EU_WEST_1");
+
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").startupOrder(2).setHeader(Sqs2Constants.SQS_OPERATION, constant("sendBatchMessage")).to(sqsEndpointUri);
+
+                from("aws2-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)&region=EU_WEST_1&deleteAfterRead=true").startupOrder(1).log("${body}").to("mock:result");
+            }
+        };
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsProducerDeleteMessageIntegrationTest.java b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsProducerDeleteMessageIntegrationTest.java
new file mode 100644
index 0000000..d0557c7
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/java/org/apache/camel/component/aws2/sqs/integration/SqsProducerDeleteMessageIntegrationTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.camel.component.aws2.sqs.integration;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.junit.Ignore;
+import org.junit.Test;
+
+@Ignore("Must be manually tested. Provide your own accessKey and secretKey!")
+public class SqsProducerDeleteMessageIntegrationTest extends CamelTestSupport {
+
+    @EndpointInject("direct:start")
+    private ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendInOnly() throws Exception {
+        result.expectedMessageCount(1);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) throws Exception {
+                exchange.getIn().setBody("Test sqs");
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        final String sqsEndpointUri = String.format("aws2-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)&region=EU_WEST_1");
+
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").startupOrder(2).to(sqsEndpointUri);
+
+                from("aws2-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)&region=EU_WEST_1&deleteAfterRead=false").startupOrder(1).log("${body}")
+                    .to("aws2-sqs://camel-1?accessKey=RAW(xxx)&secretKey=RAW(xxx)&region=EU_WEST_1&operation=deleteMessage").log("${body}").log("${header.CamelAwsSqsReceiptHandle}")
+                    .to("mock:result");
+            }
+        };
+    }
+}
diff --git a/components/camel-aws2-sqs/src/test/resources/log4j2.properties b/components/camel-aws2-sqs/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..667a215
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-aws2-sqs-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git a/components/camel-aws2-sqs/src/test/resources/org/apache/camel/component/aws2/sqs/SqsComponentSpringTest-context.xml b/components/camel-aws2-sqs/src/test/resources/org/apache/camel/component/aws2/sqs/SqsComponentSpringTest-context.xml
new file mode 100644
index 0000000..95c286b
--- /dev/null
+++ b/components/camel-aws2-sqs/src/test/resources/org/apache/camel/component/aws2/sqs/SqsComponentSpringTest-context.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+    http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+    <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
+        <route>
+            <from uri="direct:start"/>
+            <to uri="aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient&amp;messageRetentionPeriod=1209600&amp;maximumMessageSize=65536&amp;receiveMessageWaitTimeSeconds=20&amp;policy="/>
+        </route>
+
+        <route>
+            <from uri="aws2-sqs://MyQueue?amazonSQSClient=#amazonSQSClient&amp;messageRetentionPeriod=1209600&amp;maximumMessageSize=65536&amp;receiveMessageWaitTimeSeconds=20&amp;policy="/>
+            <to uri="mock:result"/>
+        </route>
+        
+        <route>
+            <from uri="direct:start-batch"/>
+            <to uri="aws2-sqs://camel-1?amazonSQSClient=#amazonSQSClient&amp;operation=sendBatchMessage"/>
+            <to uri="mock:result"/>
+        </route>
+        
+        <route>
+            <from uri="direct:start-delete"/>
+            <to uri="aws2-sqs://camel-1?amazonSQSClient=#amazonSQSClient&amp;operation=deleteMessage"/>
+            <to uri="mock:result"/>
+        </route>
+    </camelContext>
+
+    <bean id="amazonSQSClient" class="org.apache.camel.component.aws2.sqs.AmazonSQSClientMock"/>
+</beans>
\ No newline at end of file
diff --git a/core/camel-allcomponents/pom.xml b/core/camel-allcomponents/pom.xml
index 3b23a1d..5ce92a0 100644
--- a/core/camel-allcomponents/pom.xml
+++ b/core/camel-allcomponents/pom.xml
@@ -208,6 +208,10 @@
 		</dependency>
 		<dependency>
 			<groupId>org.apache.camel</groupId>
+			<artifactId>camel-aws2-sqs</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.camel</groupId>
 			<artifactId>camel-aws2-translate</artifactId>
 		</dependency>
 		<dependency>
diff --git a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
index 911cdc8..dff3880 100644
--- a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
+++ b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/ComponentsBuilderFactory.java
@@ -598,6 +598,18 @@ public interface ComponentsBuilderFactory {
         return org.apache.camel.builder.component.dsl.Aws2SnsComponentBuilderFactory.aws2Sns();
     }
     /**
+     * AWS 2 Simple Queue Service (camel-aws2-sqs)
+     * The aws-sqs component is used for sending and receiving messages to
+     * Amazon's SQS service.
+     * 
+     * Category: cloud,messaging
+     * Since: 3.1
+     * Maven coordinates: org.apache.camel:camel-aws2-sqs
+     */
+    static org.apache.camel.builder.component.dsl.Aws2SqsComponentBuilderFactory.Aws2SqsComponentBuilder aws2Sqs() {
+        return org.apache.camel.builder.component.dsl.Aws2SqsComponentBuilderFactory.aws2Sqs();
+    }
+    /**
      * AWS 2 Translate (camel-aws2-translate)
      * The aws2-translate component is used for managing Amazon Translate
      * 
diff --git a/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Aws2SqsComponentBuilderFactory.java b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Aws2SqsComponentBuilderFactory.java
new file mode 100644
index 0000000..c5b574d
--- /dev/null
+++ b/core/camel-componentdsl/src/generated/java/org/apache/camel/builder/component/dsl/Aws2SqsComponentBuilderFactory.java
@@ -0,0 +1,181 @@
+/*
+ * 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.camel.builder.component.dsl;
+
+import javax.annotation.Generated;
+import org.apache.camel.Component;
+import org.apache.camel.builder.component.AbstractComponentBuilder;
+import org.apache.camel.builder.component.ComponentBuilder;
+import org.apache.camel.component.aws2.sqs.Sqs2Component;
+
+/**
+ * The aws-sqs component is used for sending and receiving messages to Amazon's
+ * SQS service.
+ * 
+ * Generated by camel-package-maven-plugin - do not edit this file!
+ */
+@Generated("org.apache.camel.maven.packaging.ComponentDslMojo")
+public interface Aws2SqsComponentBuilderFactory {
+
+    /**
+     * AWS 2 Simple Queue Service (camel-aws2-sqs)
+     * The aws-sqs component is used for sending and receiving messages to
+     * Amazon's SQS service.
+     * 
+     * Category: cloud,messaging
+     * Since: 3.1
+     * Maven coordinates: org.apache.camel:camel-aws2-sqs
+     */
+    static Aws2SqsComponentBuilder aws2Sqs() {
+        return new Aws2SqsComponentBuilderImpl();
+    }
+
+    /**
+     * Builder for the AWS 2 Simple Queue Service component.
+     */
+    interface Aws2SqsComponentBuilder extends ComponentBuilder<Sqs2Component> {
+        /**
+         * Amazon AWS Access Key.
+         * 
+         * The option is a: <code>java.lang.String</code> type.
+         * 
+         * Group: common
+         */
+        default Aws2SqsComponentBuilder accessKey(java.lang.String accessKey) {
+            doSetProperty("accessKey", accessKey);
+            return this;
+        }
+        /**
+         * Specify the queue region which could be used with
+         * queueOwnerAWSAccountId to build the service URL.
+         * 
+         * The option is a: <code>java.lang.String</code> type.
+         * 
+         * Group: common
+         */
+        default Aws2SqsComponentBuilder region(java.lang.String region) {
+            doSetProperty("region", region);
+            return this;
+        }
+        /**
+         * Amazon AWS Secret Key.
+         * 
+         * The option is a: <code>java.lang.String</code> type.
+         * 
+         * Group: common
+         */
+        default Aws2SqsComponentBuilder secretKey(java.lang.String secretKey) {
+            doSetProperty("secretKey", secretKey);
+            return this;
+        }
+        /**
+         * Allows for bridging the consumer to the Camel routing Error Handler,
+         * which mean any exceptions occurred while the consumer is trying to
+         * pickup incoming messages, or the likes, will now be processed as a
+         * message and handled by the routing Error Handler. By default the
+         * consumer will use the org.apache.camel.spi.ExceptionHandler to deal
+         * with exceptions, that will be logged at WARN or ERROR level and
+         * ignored.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: consumer
+         */
+        default Aws2SqsComponentBuilder bridgeErrorHandler(
+                boolean bridgeErrorHandler) {
+            doSetProperty("bridgeErrorHandler", bridgeErrorHandler);
+            return this;
+        }
+        /**
+         * Whether the producer should be started lazy (on the first message).
+         * By starting lazy you can use this to allow CamelContext and routes to
+         * startup in situations where a producer may otherwise fail during
+         * starting and cause the route to fail being started. By deferring this
+         * startup to be lazy then the startup failure can be handled during
+         * routing messages via Camel's routing error handlers. Beware that when
+         * the first message is processed then creating and starting the
+         * producer may take a little time and prolong the total processing time
+         * of the processing.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: producer
+         */
+        default Aws2SqsComponentBuilder lazyStartProducer(
+                boolean lazyStartProducer) {
+            doSetProperty("lazyStartProducer", lazyStartProducer);
+            return this;
+        }
+        /**
+         * Whether the component should use basic property binding (Camel 2.x)
+         * or the newer property binding with additional capabilities.
+         * 
+         * The option is a: <code>boolean</code> type.
+         * 
+         * Default: false
+         * Group: advanced
+         */
+        default Aws2SqsComponentBuilder basicPropertyBinding(
+                boolean basicPropertyBinding) {
+            doSetProperty("basicPropertyBinding", basicPropertyBinding);
+            return this;
+        }
+        /**
+         * The AWS SQS default configuration.
+         * 
+         * The option is a:
+         * <code>org.apache.camel.component.aws2.sqs.Sqs2Configuration</code>
+         * type.
+         * 
+         * Group: advanced
+         */
+        default Aws2SqsComponentBuilder configuration(
+                org.apache.camel.component.aws2.sqs.Sqs2Configuration configuration) {
+            doSetProperty("configuration", configuration);
+            return this;
+        }
+    }
+
+    class Aws2SqsComponentBuilderImpl
+            extends
+                AbstractComponentBuilder<Sqs2Component>
+            implements
+                Aws2SqsComponentBuilder {
+        @Override
+        protected Sqs2Component buildConcreteComponent() {
+            return new Sqs2Component();
+        }
+        @Override
+        protected boolean setPropertyOnComponent(
+                Component component,
+                String name,
+                Object value) {
+            switch (name) {
+            case "accessKey": ((Sqs2Component) component).setAccessKey((java.lang.String) value); return true;
+            case "region": ((Sqs2Component) component).setRegion((java.lang.String) value); return true;
+            case "secretKey": ((Sqs2Component) component).setSecretKey((java.lang.String) value); return true;
+            case "bridgeErrorHandler": ((Sqs2Component) component).setBridgeErrorHandler((boolean) value); return true;
+            case "lazyStartProducer": ((Sqs2Component) component).setLazyStartProducer((boolean) value); return true;
+            case "basicPropertyBinding": ((Sqs2Component) component).setBasicPropertyBinding((boolean) value); return true;
+            case "configuration": ((Sqs2Component) component).setConfiguration((org.apache.camel.component.aws2.sqs.Sqs2Configuration) value); return true;
+            default: return false;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/camel-componentdsl/src/generated/resources/metadata.json b/core/camel-componentdsl/src/generated/resources/metadata.json
index f1edc81..cf16940 100644
--- a/core/camel-componentdsl/src/generated/resources/metadata.json
+++ b/core/camel-componentdsl/src/generated/resources/metadata.json
@@ -601,6 +601,26 @@
     "artifactId": "camel-aws2-sns",
     "version": "3.1.0-SNAPSHOT"
   },
+  "Aws2SqsComponentBuilderFactory": {
+    "kind": "component",
+    "scheme": "aws2-sqs",
+    "extendsScheme": "",
+    "syntax": "aws2-sqs:queueNameOrArn",
+    "title": "AWS 2 Simple Queue Service",
+    "description": "The aws-sqs component is used for sending and receiving messages to Amazon's SQS service.",
+    "label": "cloud,messaging",
+    "deprecated": false,
+    "deprecationNote": "cloud,messaging",
+    "async": false,
+    "consumerOnly": false,
+    "producerOnly": false,
+    "lenientProperties": false,
+    "javaType": "org.apache.camel.component.aws2.sqs.Sqs2Component",
+    "firstVersion": "3.1.0",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-aws2-sqs",
+    "version": "3.1.0-SNAPSHOT"
+  },
   "Aws2TranslateComponentBuilderFactory": {
     "kind": "component",
     "scheme": "aws2-translate",