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

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

commit c87d14572b7f8796f669bb6d1d2c3302fee2dcd2
Author: Andrea Cosentino <[email protected]>
AuthorDate: Wed Dec 31 17:50:23 2025 +0100

    CAMEL-22806 - Camel-AWS components: Avoid duplicated code and add 
pagination to producer operation where it makes sense - AWS IAM
    
    Signed-off-by: Andrea Cosentino <[email protected]>
---
 .../apache/camel/catalog/components/aws2-iam.json  |  10 +-
 .../apache/camel/component/aws2/iam/aws2-iam.json  |  10 +-
 .../camel/component/aws2/iam/IAM2Constants.java    |  20 +
 .../camel/component/aws2/iam/IAM2Producer.java     | 717 +++++++++------------
 .../component/aws2/iam/AmazonIAMClientMock.java    |  15 +
 .../endpoint/dsl/IAM2EndpointBuilderFactory.java   |  96 +++
 6 files changed, 460 insertions(+), 408 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-iam.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-iam.json
index 00cee1030a02..c3214a03072b 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-iam.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/aws2-iam.json
@@ -53,7 +53,15 @@
     "CamelAwsIAMAccessKeyID": { "index": 2, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The accessKey you want to manage", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#ACCESS_KEY_ID" },
     "CamelAwsIAMAccessKeyStatus": { "index": 3, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Status of the AccessKey you want to 
set, possible value are active and inactive", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#ACCESS_KEY_STATUS" },
     "CamelAwsIAMGroupName": { "index": 4, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The name of an AWS IAM Group", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#GROUP_NAME" },
-    "CamelAwsIAMGroupPath": { "index": 5, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The path of an AWS IAM Group", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#GROUP_PATH" }
+    "CamelAwsIAMGroupPath": { "index": 5, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The path of an AWS IAM Group", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#GROUP_PATH" },
+    "CamelAwsIAMMarker": { "index": 6, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The marker to use for pagination in list operations", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#MARKER" },
+    "CamelAwsIAMMaxItems": { "index": 7, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "Integer", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The maximum number of items to return in list 
operations", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#MAX_ITEMS" },
+    "CamelAwsIAMIsTruncated": { "index": 8, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "Boolean", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Whether the list response is truncated (has more 
results)", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#IS_TRUNCATED" },
+    "CamelAwsIAMNextMarker": { "index": 9, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The marker to use for the next page of results", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#NEXT_MARKER" 
},
+    "CamelAwsIAMUserArn": { "index": 10, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The ARN of the created or retrieved user", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#USER_ARN" },
+    "CamelAwsIAMUserId": { "index": 11, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The ID of the created or retrieved user", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#USER_ID" },
+    "CamelAwsIAMGroupArn": { "index": 12, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The ARN of the created or retrieved group", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#GROUP_ARN" },
+    "CamelAwsIAMGroupId": { "index": 13, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The ID of the created or retrieved group", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#GROUP_ID" }
   },
   "properties": {
     "label": { "index": 0, "kind": "path", "displayName": "Label", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.aws2.iam.IAM2Configuration", "configurationField": 
"configuration", "description": "Logical name" },
diff --git 
a/components/camel-aws/camel-aws2-iam/src/generated/resources/META-INF/org/apache/camel/component/aws2/iam/aws2-iam.json
 
b/components/camel-aws/camel-aws2-iam/src/generated/resources/META-INF/org/apache/camel/component/aws2/iam/aws2-iam.json
index 00cee1030a02..c3214a03072b 100644
--- 
a/components/camel-aws/camel-aws2-iam/src/generated/resources/META-INF/org/apache/camel/component/aws2/iam/aws2-iam.json
+++ 
b/components/camel-aws/camel-aws2-iam/src/generated/resources/META-INF/org/apache/camel/component/aws2/iam/aws2-iam.json
@@ -53,7 +53,15 @@
     "CamelAwsIAMAccessKeyID": { "index": 2, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The accessKey you want to manage", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#ACCESS_KEY_ID" },
     "CamelAwsIAMAccessKeyStatus": { "index": 3, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "The Status of the AccessKey you want to 
set, possible value are active and inactive", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#ACCESS_KEY_STATUS" },
     "CamelAwsIAMGroupName": { "index": 4, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The name of an AWS IAM Group", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#GROUP_NAME" },
-    "CamelAwsIAMGroupPath": { "index": 5, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The path of an AWS IAM Group", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#GROUP_PATH" }
+    "CamelAwsIAMGroupPath": { "index": 5, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The path of an AWS IAM Group", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#GROUP_PATH" },
+    "CamelAwsIAMMarker": { "index": 6, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The marker to use for pagination in list operations", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#MARKER" },
+    "CamelAwsIAMMaxItems": { "index": 7, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "Integer", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The maximum number of items to return in list 
operations", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#MAX_ITEMS" },
+    "CamelAwsIAMIsTruncated": { "index": 8, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "Boolean", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Whether the list response is truncated (has more 
results)", "constantName": 
"org.apache.camel.component.aws2.iam.IAM2Constants#IS_TRUNCATED" },
+    "CamelAwsIAMNextMarker": { "index": 9, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The marker to use for the next page of results", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#NEXT_MARKER" 
},
+    "CamelAwsIAMUserArn": { "index": 10, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The ARN of the created or retrieved user", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#USER_ARN" },
+    "CamelAwsIAMUserId": { "index": 11, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The ID of the created or retrieved user", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#USER_ID" },
+    "CamelAwsIAMGroupArn": { "index": 12, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The ARN of the created or retrieved group", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#GROUP_ARN" },
+    "CamelAwsIAMGroupId": { "index": 13, "kind": "header", "displayName": "", 
"group": "producer", "label": "", "required": false, "javaType": "String", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "The ID of the created or retrieved group", 
"constantName": "org.apache.camel.component.aws2.iam.IAM2Constants#GROUP_ID" }
   },
   "properties": {
     "label": { "index": 0, "kind": "path", "displayName": "Label", "group": 
"producer", "label": "", "required": true, "type": "string", "javaType": 
"java.lang.String", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "configurationClass": 
"org.apache.camel.component.aws2.iam.IAM2Configuration", "configurationField": 
"configuration", "description": "Logical name" },
diff --git 
a/components/camel-aws/camel-aws2-iam/src/main/java/org/apache/camel/component/aws2/iam/IAM2Constants.java
 
b/components/camel-aws/camel-aws2-iam/src/main/java/org/apache/camel/component/aws2/iam/IAM2Constants.java
index acf66c56f373..6acc42d5ff41 100644
--- 
a/components/camel-aws/camel-aws2-iam/src/main/java/org/apache/camel/component/aws2/iam/IAM2Constants.java
+++ 
b/components/camel-aws/camel-aws2-iam/src/main/java/org/apache/camel/component/aws2/iam/IAM2Constants.java
@@ -35,4 +35,24 @@ public interface IAM2Constants {
     String GROUP_NAME = "CamelAwsIAMGroupName";
     @Metadata(description = "The path of an AWS IAM Group", javaType = 
"String")
     String GROUP_PATH = "CamelAwsIAMGroupPath";
+
+    // Pagination support
+    @Metadata(description = "The marker to use for pagination in list 
operations", javaType = "String")
+    String MARKER = "CamelAwsIAMMarker";
+    @Metadata(description = "The maximum number of items to return in list 
operations", javaType = "Integer")
+    String MAX_ITEMS = "CamelAwsIAMMaxItems";
+
+    // Response metadata
+    @Metadata(description = "Whether the list response is truncated (has more 
results)", javaType = "Boolean")
+    String IS_TRUNCATED = "CamelAwsIAMIsTruncated";
+    @Metadata(description = "The marker to use for the next page of results", 
javaType = "String")
+    String NEXT_MARKER = "CamelAwsIAMNextMarker";
+    @Metadata(description = "The ARN of the created or retrieved user", 
javaType = "String")
+    String USER_ARN = "CamelAwsIAMUserArn";
+    @Metadata(description = "The ID of the created or retrieved user", 
javaType = "String")
+    String USER_ID = "CamelAwsIAMUserId";
+    @Metadata(description = "The ARN of the created or retrieved group", 
javaType = "String")
+    String GROUP_ARN = "CamelAwsIAMGroupArn";
+    @Metadata(description = "The ID of the created or retrieved group", 
javaType = "String")
+    String GROUP_ID = "CamelAwsIAMGroupId";
 }
diff --git 
a/components/camel-aws/camel-aws2-iam/src/main/java/org/apache/camel/component/aws2/iam/IAM2Producer.java
 
b/components/camel-aws/camel-aws2-iam/src/main/java/org/apache/camel/component/aws2/iam/IAM2Producer.java
index 51919305aab6..dcebdf013988 100644
--- 
a/components/camel-aws/camel-aws2-iam/src/main/java/org/apache/camel/component/aws2/iam/IAM2Producer.java
+++ 
b/components/camel-aws/camel-aws2-iam/src/main/java/org/apache/camel/component/aws2/iam/IAM2Producer.java
@@ -16,6 +16,10 @@
  */
 package org.apache.camel.component.aws2.iam;
 
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
 import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
 import org.apache.camel.InvalidPayloadException;
@@ -31,19 +35,14 @@ import org.slf4j.LoggerFactory;
 import software.amazon.awssdk.awscore.exception.AwsServiceException;
 import software.amazon.awssdk.services.iam.IamClient;
 import software.amazon.awssdk.services.iam.model.AddUserToGroupRequest;
-import software.amazon.awssdk.services.iam.model.AddUserToGroupResponse;
 import software.amazon.awssdk.services.iam.model.CreateAccessKeyRequest;
-import software.amazon.awssdk.services.iam.model.CreateAccessKeyResponse;
 import software.amazon.awssdk.services.iam.model.CreateGroupRequest;
 import software.amazon.awssdk.services.iam.model.CreateGroupResponse;
 import software.amazon.awssdk.services.iam.model.CreateUserRequest;
 import software.amazon.awssdk.services.iam.model.CreateUserResponse;
 import software.amazon.awssdk.services.iam.model.DeleteAccessKeyRequest;
-import software.amazon.awssdk.services.iam.model.DeleteAccessKeyResponse;
 import software.amazon.awssdk.services.iam.model.DeleteGroupRequest;
-import software.amazon.awssdk.services.iam.model.DeleteGroupResponse;
 import software.amazon.awssdk.services.iam.model.DeleteUserRequest;
-import software.amazon.awssdk.services.iam.model.DeleteUserResponse;
 import software.amazon.awssdk.services.iam.model.GetUserRequest;
 import software.amazon.awssdk.services.iam.model.GetUserResponse;
 import software.amazon.awssdk.services.iam.model.ListAccessKeysRequest;
@@ -53,10 +52,8 @@ import 
software.amazon.awssdk.services.iam.model.ListGroupsResponse;
 import software.amazon.awssdk.services.iam.model.ListUsersRequest;
 import software.amazon.awssdk.services.iam.model.ListUsersResponse;
 import software.amazon.awssdk.services.iam.model.RemoveUserFromGroupRequest;
-import software.amazon.awssdk.services.iam.model.RemoveUserFromGroupResponse;
 import software.amazon.awssdk.services.iam.model.StatusType;
 import software.amazon.awssdk.services.iam.model.UpdateAccessKeyRequest;
-import software.amazon.awssdk.services.iam.model.UpdateAccessKeyResponse;
 
 /**
  * A Producer which sends messages to the Amazon IAM Service <a 
href="http://aws.amazon.com/iam/";>AWS IAM</a>
@@ -152,456 +149,364 @@ public class IAM2Producer extends DefaultProducer {
     }
 
     private void listAccessKeys(IamClient iamClient, Exchange exchange) throws 
InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof ListAccessKeysRequest) {
-                ListAccessKeysResponse response;
-                try {
-                    response = 
iamClient.listAccessKeys((ListAccessKeysRequest) payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("List Access Keys command returned the error 
code {}", ase.getMessage());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(response);
-            }
-        } else {
-            ListAccessKeysResponse response;
-            try {
-                response = iamClient.listAccessKeys();
-            } catch (AwsServiceException ase) {
-                LOG.trace("List Access Keys command returned the error code 
{}", ase.getMessage());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(response);
-        }
+        executeOperation(
+                exchange,
+                ListAccessKeysRequest.class,
+                iamClient::listAccessKeys,
+                () -> {
+                    ListAccessKeysRequest.Builder builder = 
ListAccessKeysRequest.builder();
+                    String marker = getOptionalHeader(exchange, 
IAM2Constants.MARKER, String.class);
+                    if (marker != null) {
+                        builder.marker(marker);
+                    }
+                    Integer maxItems = getOptionalHeader(exchange, 
IAM2Constants.MAX_ITEMS, Integer.class);
+                    if (maxItems != null) {
+                        builder.maxItems(maxItems);
+                    }
+                    String userName = getOptionalHeader(exchange, 
IAM2Constants.USERNAME, String.class);
+                    if (userName != null) {
+                        builder.userName(userName);
+                    }
+                    return iamClient.listAccessKeys(builder.build());
+                },
+                "List Access Keys",
+                (ListAccessKeysResponse response, Message message) -> {
+                    message.setHeader(IAM2Constants.IS_TRUNCATED, 
response.isTruncated());
+                    if (response.marker() != null) {
+                        message.setHeader(IAM2Constants.NEXT_MARKER, 
response.marker());
+                    }
+                });
     }
 
     private void createUser(IamClient iamClient, Exchange exchange) throws 
InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof CreateUserRequest) {
-                CreateUserResponse result;
-                try {
-                    result = iamClient.createUser((CreateUserRequest) payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("Create user command returned the error code 
{}", ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            CreateUserRequest.Builder builder = CreateUserRequest.builder();
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.USERNAME))) {
-                String userName = 
exchange.getIn().getHeader(IAM2Constants.USERNAME, String.class);
-                builder.userName(userName);
-            } else {
-                throw new IllegalArgumentException(MISSING_USER_NAME);
-            }
-            CreateUserResponse result;
-            try {
-                result = iamClient.createUser(builder.build());
-            } catch (AwsServiceException ase) {
-                LOG.trace("Create user command returned the error code {}", 
ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                CreateUserRequest.class,
+                iamClient::createUser,
+                () -> {
+                    String userName = getRequiredHeader(exchange, 
IAM2Constants.USERNAME, String.class, MISSING_USER_NAME);
+                    return 
iamClient.createUser(CreateUserRequest.builder().userName(userName).build());
+                },
+                "Create user",
+                (CreateUserResponse response, Message message) -> {
+                    if (response.user() != null) {
+                        message.setHeader(IAM2Constants.USER_ARN, 
response.user().arn());
+                        message.setHeader(IAM2Constants.USER_ID, 
response.user().userId());
+                    }
+                });
     }
 
     private void deleteUser(IamClient iamClient, Exchange exchange) throws 
InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof DeleteUserRequest) {
-                DeleteUserResponse result;
-                try {
-                    result = iamClient.deleteUser((DeleteUserRequest) payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("Delete user command returned the error code 
{}", ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            DeleteUserRequest.Builder builder = DeleteUserRequest.builder();
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.USERNAME))) {
-                String userName = 
exchange.getIn().getHeader(IAM2Constants.USERNAME, String.class);
-                builder.userName(userName);
-            } else {
-                throw new IllegalArgumentException(MISSING_USER_NAME);
-            }
-            DeleteUserResponse result;
-            try {
-                result = iamClient.deleteUser(builder.build());
-            } catch (AwsServiceException ase) {
-                LOG.trace("Delete user command returned the error code {}", 
ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                DeleteUserRequest.class,
+                iamClient::deleteUser,
+                () -> {
+                    String userName = getRequiredHeader(exchange, 
IAM2Constants.USERNAME, String.class, MISSING_USER_NAME);
+                    return 
iamClient.deleteUser(DeleteUserRequest.builder().userName(userName).build());
+                },
+                "Delete user");
     }
 
     private void getUser(IamClient iamClient, Exchange exchange) throws 
InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof GetUserRequest) {
-                GetUserResponse result;
-                try {
-                    result = iamClient.getUser((GetUserRequest) payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("get user command returned the error code {}", 
ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            GetUserRequest.Builder builder = GetUserRequest.builder();
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.USERNAME))) {
-                String userName = 
exchange.getIn().getHeader(IAM2Constants.USERNAME, String.class);
-                builder.userName(userName);
-            } else {
-                throw new IllegalArgumentException(MISSING_USER_NAME);
-            }
-            GetUserResponse result;
-            try {
-                result = iamClient.getUser(builder.build());
-            } catch (AwsServiceException ase) {
-                LOG.trace("get user command returned the error code {}", 
ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                GetUserRequest.class,
+                iamClient::getUser,
+                () -> {
+                    String userName = getRequiredHeader(exchange, 
IAM2Constants.USERNAME, String.class, MISSING_USER_NAME);
+                    return 
iamClient.getUser(GetUserRequest.builder().userName(userName).build());
+                },
+                "Get user",
+                (GetUserResponse response, Message message) -> {
+                    if (response.user() != null) {
+                        message.setHeader(IAM2Constants.USER_ARN, 
response.user().arn());
+                        message.setHeader(IAM2Constants.USER_ID, 
response.user().userId());
+                    }
+                });
     }
 
     private void listUsers(IamClient iamClient, Exchange exchange) throws 
InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof ListUsersRequest) {
-                ListUsersResponse result;
-                try {
-                    result = iamClient.listUsers((ListUsersRequest) payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("List users command returned the error code {}", 
ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            ListUsersResponse result;
-            try {
-                result = iamClient.listUsers();
-            } catch (AwsServiceException ase) {
-                LOG.trace("List users command returned the error code {}", 
ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                ListUsersRequest.class,
+                iamClient::listUsers,
+                () -> {
+                    ListUsersRequest.Builder builder = 
ListUsersRequest.builder();
+                    String marker = getOptionalHeader(exchange, 
IAM2Constants.MARKER, String.class);
+                    if (marker != null) {
+                        builder.marker(marker);
+                    }
+                    Integer maxItems = getOptionalHeader(exchange, 
IAM2Constants.MAX_ITEMS, Integer.class);
+                    if (maxItems != null) {
+                        builder.maxItems(maxItems);
+                    }
+                    return iamClient.listUsers(builder.build());
+                },
+                "List users",
+                (ListUsersResponse response, Message message) -> {
+                    message.setHeader(IAM2Constants.IS_TRUNCATED, 
response.isTruncated());
+                    if (response.marker() != null) {
+                        message.setHeader(IAM2Constants.NEXT_MARKER, 
response.marker());
+                    }
+                });
     }
 
     private void createAccessKey(IamClient iamClient, Exchange exchange) 
throws InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof CreateAccessKeyRequest) {
-                CreateAccessKeyResponse result;
-                try {
-                    result = 
iamClient.createAccessKey((CreateAccessKeyRequest) payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("Create Access Key command returned the error 
code {}", ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            CreateAccessKeyRequest.Builder builder = 
CreateAccessKeyRequest.builder();
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.USERNAME))) {
-                String userName = 
exchange.getIn().getHeader(IAM2Constants.USERNAME, String.class);
-                builder.userName(userName);
-            }
-            CreateAccessKeyResponse result;
-            try {
-                result = iamClient.createAccessKey(builder.build());
-            } catch (AwsServiceException ase) {
-                LOG.trace("Create Access Key command returned the error code 
{}", ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                CreateAccessKeyRequest.class,
+                iamClient::createAccessKey,
+                () -> {
+                    CreateAccessKeyRequest.Builder builder = 
CreateAccessKeyRequest.builder();
+                    String userName = getOptionalHeader(exchange, 
IAM2Constants.USERNAME, String.class);
+                    if (userName != null) {
+                        builder.userName(userName);
+                    }
+                    return iamClient.createAccessKey(builder.build());
+                },
+                "Create Access Key");
     }
 
     private void deleteAccessKey(IamClient iamClient, Exchange exchange) 
throws InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof DeleteAccessKeyRequest) {
-                DeleteAccessKeyResponse result;
-                try {
-                    result = 
iamClient.deleteAccessKey((DeleteAccessKeyRequest) payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("Delete Access Key command returned the error 
code {}", ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            DeleteAccessKeyRequest.Builder builder = 
DeleteAccessKeyRequest.builder();
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.ACCESS_KEY_ID)))
 {
-                String accessKeyId = 
exchange.getIn().getHeader(IAM2Constants.ACCESS_KEY_ID, String.class);
-                builder.accessKeyId(accessKeyId);
-            } else {
-                throw new IllegalArgumentException("Key Id must be specified");
-            }
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.USERNAME))) {
-                String userName = 
exchange.getIn().getHeader(IAM2Constants.USERNAME, String.class);
-                builder.userName(userName);
-            }
-            DeleteAccessKeyResponse result;
-            try {
-                result = iamClient.deleteAccessKey(builder.build());
-            } catch (AwsServiceException ase) {
-                LOG.trace("Delete Access Key command returned the error code 
{}", ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                DeleteAccessKeyRequest.class,
+                iamClient::deleteAccessKey,
+                () -> {
+                    String accessKeyId = getRequiredHeader(exchange, 
IAM2Constants.ACCESS_KEY_ID, String.class,
+                            "Key Id must be specified");
+                    DeleteAccessKeyRequest.Builder builder = 
DeleteAccessKeyRequest.builder().accessKeyId(accessKeyId);
+                    String userName = getOptionalHeader(exchange, 
IAM2Constants.USERNAME, String.class);
+                    if (userName != null) {
+                        builder.userName(userName);
+                    }
+                    return iamClient.deleteAccessKey(builder.build());
+                },
+                "Delete Access Key");
     }
 
     private void updateAccessKey(IamClient iamClient, Exchange exchange) 
throws InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof UpdateAccessKeyRequest) {
-                UpdateAccessKeyResponse result;
-                try {
-                    result = 
iamClient.updateAccessKey((UpdateAccessKeyRequest) payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("Update Access Key command returned the error 
code {}", ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            UpdateAccessKeyRequest.Builder builder = 
UpdateAccessKeyRequest.builder();
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.ACCESS_KEY_ID)))
 {
-                String accessKeyId = 
exchange.getIn().getHeader(IAM2Constants.ACCESS_KEY_ID, String.class);
-                builder.accessKeyId(accessKeyId);
-            } else {
-                throw new IllegalArgumentException("Key Id must be specified");
-            }
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.ACCESS_KEY_STATUS)))
 {
-                String status = 
exchange.getIn().getHeader(IAM2Constants.ACCESS_KEY_STATUS, String.class);
-                builder.status(StatusType.fromValue(status));
-            } else {
-                throw new IllegalArgumentException("Access Key status must be 
specified");
-            }
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.USERNAME))) {
-                String userName = 
exchange.getIn().getHeader(IAM2Constants.USERNAME, String.class);
-                builder.userName(userName);
-            }
-            UpdateAccessKeyResponse result;
-            try {
-                result = iamClient.updateAccessKey(builder.build());
-            } catch (AwsServiceException ase) {
-                LOG.trace("Update Access Key command returned the error code 
{}", ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                UpdateAccessKeyRequest.class,
+                iamClient::updateAccessKey,
+                () -> {
+                    String accessKeyId = getRequiredHeader(exchange, 
IAM2Constants.ACCESS_KEY_ID, String.class,
+                            "Key Id must be specified");
+                    String status = getRequiredHeader(exchange, 
IAM2Constants.ACCESS_KEY_STATUS, String.class,
+                            "Access Key status must be specified");
+                    UpdateAccessKeyRequest.Builder builder = 
UpdateAccessKeyRequest.builder()
+                            .accessKeyId(accessKeyId)
+                            .status(StatusType.fromValue(status));
+                    String userName = getOptionalHeader(exchange, 
IAM2Constants.USERNAME, String.class);
+                    if (userName != null) {
+                        builder.userName(userName);
+                    }
+                    return iamClient.updateAccessKey(builder.build());
+                },
+                "Update Access Key");
     }
 
     private void createGroup(IamClient iamClient, Exchange exchange) throws 
InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof CreateGroupRequest) {
-                CreateGroupResponse result;
-                try {
-                    result = iamClient.createGroup((CreateGroupRequest) 
payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("Create Group command returned the error code 
{}", ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            CreateGroupRequest.Builder builder = CreateGroupRequest.builder();
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.GROUP_NAME))) 
{
-                String groupName = 
exchange.getIn().getHeader(IAM2Constants.GROUP_NAME, String.class);
-                builder.groupName(groupName);
-            } else {
-                throw new IllegalArgumentException(MISSING_GROUP_NAME);
-            }
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.GROUP_PATH))) 
{
-                String groupPath = 
exchange.getIn().getHeader(IAM2Constants.GROUP_PATH, String.class);
-                builder.path(groupPath);
-            }
-            CreateGroupResponse result;
-            try {
-                result = iamClient.createGroup(builder.build());
-            } catch (AwsServiceException ase) {
-                LOG.trace("Create Group command returned the error code {}", 
ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                CreateGroupRequest.class,
+                iamClient::createGroup,
+                () -> {
+                    String groupName = getRequiredHeader(exchange, 
IAM2Constants.GROUP_NAME, String.class, MISSING_GROUP_NAME);
+                    CreateGroupRequest.Builder builder = 
CreateGroupRequest.builder().groupName(groupName);
+                    String groupPath = getOptionalHeader(exchange, 
IAM2Constants.GROUP_PATH, String.class);
+                    if (groupPath != null) {
+                        builder.path(groupPath);
+                    }
+                    return iamClient.createGroup(builder.build());
+                },
+                "Create Group",
+                (CreateGroupResponse response, Message message) -> {
+                    if (response.group() != null) {
+                        message.setHeader(IAM2Constants.GROUP_ARN, 
response.group().arn());
+                        message.setHeader(IAM2Constants.GROUP_ID, 
response.group().groupId());
+                    }
+                });
     }
 
     private void deleteGroup(IamClient iamClient, Exchange exchange) throws 
InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof DeleteGroupResponse) {
-                DeleteGroupResponse result;
-                try {
-                    result = iamClient.deleteGroup((DeleteGroupRequest) 
payload); // TODO this cast is impossible and will produce ClassCastException 
for non-null value
-                } catch (AwsServiceException ase) {
-                    LOG.trace("Delete Group command returned the error code 
{}", ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            DeleteGroupRequest.Builder builder = DeleteGroupRequest.builder();
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.GROUP_NAME))) 
{
-                String groupName = 
exchange.getIn().getHeader(IAM2Constants.GROUP_NAME, String.class);
-                builder.groupName(groupName);
-            } else {
-                throw new IllegalArgumentException(MISSING_GROUP_NAME);
-            }
-            DeleteGroupResponse result;
-            try {
-                result = iamClient.deleteGroup(builder.build());
-            } catch (AwsServiceException ase) {
-                LOG.trace("Delete Group command returned the error code {}", 
ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                DeleteGroupRequest.class,
+                iamClient::deleteGroup,
+                () -> {
+                    String groupName = getRequiredHeader(exchange, 
IAM2Constants.GROUP_NAME, String.class, MISSING_GROUP_NAME);
+                    return 
iamClient.deleteGroup(DeleteGroupRequest.builder().groupName(groupName).build());
+                },
+                "Delete Group");
     }
 
     private void listGroups(IamClient iamClient, Exchange exchange) throws 
InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof ListGroupsRequest) {
-                ListGroupsResponse result;
-                try {
-                    result = iamClient.listGroups((ListGroupsRequest) payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("List Groups command returned the error code 
{}", ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            ListGroupsResponse result;
-            try {
-                result = iamClient.listGroups();
-            } catch (AwsServiceException ase) {
-                LOG.trace("List Groups command returned the error code {}", 
ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                ListGroupsRequest.class,
+                iamClient::listGroups,
+                () -> {
+                    ListGroupsRequest.Builder builder = 
ListGroupsRequest.builder();
+                    String marker = getOptionalHeader(exchange, 
IAM2Constants.MARKER, String.class);
+                    if (marker != null) {
+                        builder.marker(marker);
+                    }
+                    Integer maxItems = getOptionalHeader(exchange, 
IAM2Constants.MAX_ITEMS, Integer.class);
+                    if (maxItems != null) {
+                        builder.maxItems(maxItems);
+                    }
+                    return iamClient.listGroups(builder.build());
+                },
+                "List Groups",
+                (ListGroupsResponse response, Message message) -> {
+                    message.setHeader(IAM2Constants.IS_TRUNCATED, 
response.isTruncated());
+                    if (response.marker() != null) {
+                        message.setHeader(IAM2Constants.NEXT_MARKER, 
response.marker());
+                    }
+                });
     }
 
     private void addUserToGroup(IamClient iamClient, Exchange exchange) throws 
InvalidPayloadException {
-        if (getConfiguration().isPojoRequest()) {
-            Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof AddUserToGroupRequest) {
-                AddUserToGroupResponse result;
-                try {
-                    result = iamClient.addUserToGroup((AddUserToGroupRequest) 
payload);
-                } catch (AwsServiceException ase) {
-                    LOG.trace("Add User To Group command returned the error 
code {}", ase.awsErrorDetails().errorCode());
-                    throw ase;
-                }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            AddUserToGroupRequest.Builder builder = 
AddUserToGroupRequest.builder();
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.GROUP_NAME))) 
{
-                String groupName = 
exchange.getIn().getHeader(IAM2Constants.GROUP_NAME, String.class);
-                builder.groupName(groupName);
-            } else {
-                throw new IllegalArgumentException(MISSING_GROUP_NAME);
-            }
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.USERNAME))) {
-                String userName = 
exchange.getIn().getHeader(IAM2Constants.USERNAME, String.class);
-                builder.userName(userName);
-            } else {
-                throw new IllegalArgumentException(MISSING_USER_NAME);
-            }
-            AddUserToGroupResponse result;
-            try {
-                result = iamClient.addUserToGroup(builder.build());
-            } catch (AwsServiceException ase) {
-                LOG.trace("Add User To Group command returned the error code 
{}", ase.awsErrorDetails().errorCode());
-                throw ase;
-            }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
-        }
+        executeOperation(
+                exchange,
+                AddUserToGroupRequest.class,
+                iamClient::addUserToGroup,
+                () -> {
+                    String groupName = getRequiredHeader(exchange, 
IAM2Constants.GROUP_NAME, String.class, MISSING_GROUP_NAME);
+                    String userName = getRequiredHeader(exchange, 
IAM2Constants.USERNAME, String.class, MISSING_USER_NAME);
+                    return 
iamClient.addUserToGroup(AddUserToGroupRequest.builder()
+                            .groupName(groupName)
+                            .userName(userName)
+                            .build());
+                },
+                "Add User To Group");
     }
 
     private void removeUserFromGroup(IamClient iamClient, Exchange exchange) 
throws InvalidPayloadException {
+        executeOperation(
+                exchange,
+                RemoveUserFromGroupRequest.class,
+                iamClient::removeUserFromGroup,
+                () -> {
+                    String groupName = getRequiredHeader(exchange, 
IAM2Constants.GROUP_NAME, String.class, MISSING_GROUP_NAME);
+                    String userName = getRequiredHeader(exchange, 
IAM2Constants.USERNAME, String.class, MISSING_USER_NAME);
+                    return 
iamClient.removeUserFromGroup(RemoveUserFromGroupRequest.builder()
+                            .groupName(groupName)
+                            .userName(userName)
+                            .build());
+                },
+                "Remove User From Group");
+    }
+
+    public static Message getMessageForResponse(final Exchange exchange) {
+        return exchange.getMessage();
+    }
+
+    /**
+     * Executes an IAM operation with POJO request support.
+     *
+     * @param exchange       the Camel exchange
+     * @param requestClass   the expected request class type
+     * @param pojoExecutor   function to execute when using POJO request
+     * @param headerExecutor supplier to execute when using header-based 
request
+     * @param operationName  name of the operation for logging
+     * @param <REQ>          the request type
+     * @param <RES>          the response type
+     */
+    private <REQ, RES> void executeOperation(
+            Exchange exchange,
+            Class<REQ> requestClass,
+            Function<REQ, RES> pojoExecutor,
+            Supplier<RES> headerExecutor,
+            String operationName)
+            throws InvalidPayloadException {
+        executeOperation(exchange, requestClass, pojoExecutor, headerExecutor, 
operationName, null);
+    }
+
+    /**
+     * Executes an IAM operation with POJO request support and optional 
response post-processing.
+     *
+     * @param exchange          the Camel exchange
+     * @param requestClass      the expected request class type
+     * @param pojoExecutor      function to execute when using POJO request
+     * @param headerExecutor    supplier to execute when using header-based 
request
+     * @param operationName     name of the operation for logging
+     * @param responseProcessor optional consumer to process the response and 
set headers
+     * @param <REQ>             the request type
+     * @param <RES>             the response type
+     */
+    private <REQ, RES> void executeOperation(
+            Exchange exchange,
+            Class<REQ> requestClass,
+            Function<REQ, RES> pojoExecutor,
+            Supplier<RES> headerExecutor,
+            String operationName,
+            BiConsumer<RES, Message> responseProcessor)
+            throws InvalidPayloadException {
+
+        RES result;
         if (getConfiguration().isPojoRequest()) {
             Object payload = exchange.getIn().getMandatoryBody();
-            if (payload instanceof RemoveUserFromGroupRequest) {
-                RemoveUserFromGroupResponse result;
+            if (requestClass.isInstance(payload)) {
                 try {
-                    result = 
iamClient.removeUserFromGroup((RemoveUserFromGroupRequest) payload);
+                    result = pojoExecutor.apply(requestClass.cast(payload));
                 } catch (AwsServiceException ase) {
-                    LOG.trace("Remove User From Group command returned the 
error code {}", ase.awsErrorDetails().errorCode());
+                    LOG.trace("{} command returned the error code {}", 
operationName, ase.awsErrorDetails().errorCode());
                     throw ase;
                 }
-                Message message = getMessageForResponse(exchange);
-                message.setBody(result);
-            }
-        } else {
-            RemoveUserFromGroupRequest.Builder builder = 
RemoveUserFromGroupRequest.builder();
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.GROUP_NAME))) 
{
-                String groupName = 
exchange.getIn().getHeader(IAM2Constants.GROUP_NAME, String.class);
-                builder.groupName(groupName);
             } else {
-                throw new IllegalArgumentException(MISSING_GROUP_NAME);
+                throw new IllegalArgumentException(
+                        String.format("Expected body of type %s but was %s",
+                                requestClass.getName(),
+                                payload != null ? payload.getClass().getName() 
: "null"));
             }
-            if 
(ObjectHelper.isNotEmpty(exchange.getIn().getHeader(IAM2Constants.USERNAME))) {
-                String userName = 
exchange.getIn().getHeader(IAM2Constants.USERNAME, String.class);
-                builder.userName(userName);
-            } else {
-                throw new IllegalArgumentException(MISSING_USER_NAME);
-            }
-            RemoveUserFromGroupResponse result;
+        } else {
             try {
-                result = iamClient.removeUserFromGroup(builder.build());
+                result = headerExecutor.get();
             } catch (AwsServiceException ase) {
-                LOG.trace("Remove User From Group command returned the error 
code {}", ase.awsErrorDetails().errorCode());
+                LOG.trace("{} command returned the error code {}", 
operationName, ase.awsErrorDetails().errorCode());
                 throw ase;
             }
-            Message message = getMessageForResponse(exchange);
-            message.setBody(result);
+        }
+        Message message = getMessageForResponse(exchange);
+        message.setBody(result);
+        if (responseProcessor != null) {
+            responseProcessor.accept(result, message);
         }
     }
 
-    public static Message getMessageForResponse(final Exchange exchange) {
-        return exchange.getMessage();
+    /**
+     * Retrieves a required header value or throws an IllegalArgumentException.
+     *
+     * @param  exchange     the Camel exchange
+     * @param  headerName   the header name constant
+     * @param  headerType   the expected type
+     * @param  errorMessage the error message if header is missing
+     * @param  <T>          the header value type
+     * @return              the header value
+     */
+    private <T> T getRequiredHeader(Exchange exchange, String headerName, 
Class<T> headerType, String errorMessage) {
+        T value = exchange.getIn().getHeader(headerName, headerType);
+        if (ObjectHelper.isEmpty(value)) {
+            throw new IllegalArgumentException(errorMessage);
+        }
+        return value;
+    }
+
+    /**
+     * Retrieves an optional header value.
+     *
+     * @param  exchange   the Camel exchange
+     * @param  headerName the header name constant
+     * @param  headerType the expected type
+     * @param  <T>        the header value type
+     * @return            the header value or null if not present
+     */
+    private <T> T getOptionalHeader(Exchange exchange, String headerName, 
Class<T> headerType) {
+        return exchange.getIn().getHeader(headerName, headerType);
     }
 
     @Override
diff --git 
a/components/camel-aws/camel-aws2-iam/src/test/java/org/apache/camel/component/aws2/iam/AmazonIAMClientMock.java
 
b/components/camel-aws/camel-aws2-iam/src/test/java/org/apache/camel/component/aws2/iam/AmazonIAMClientMock.java
index 2c602049576a..9e08029537c2 100644
--- 
a/components/camel-aws/camel-aws2-iam/src/test/java/org/apache/camel/component/aws2/iam/AmazonIAMClientMock.java
+++ 
b/components/camel-aws/camel-aws2-iam/src/test/java/org/apache/camel/component/aws2/iam/AmazonIAMClientMock.java
@@ -41,9 +41,11 @@ import 
software.amazon.awssdk.services.iam.model.DeleteUserResponse;
 import software.amazon.awssdk.services.iam.model.GetUserRequest;
 import software.amazon.awssdk.services.iam.model.GetUserResponse;
 import software.amazon.awssdk.services.iam.model.Group;
+import software.amazon.awssdk.services.iam.model.ListAccessKeysRequest;
 import software.amazon.awssdk.services.iam.model.ListAccessKeysResponse;
 import software.amazon.awssdk.services.iam.model.ListGroupsRequest;
 import software.amazon.awssdk.services.iam.model.ListGroupsResponse;
+import software.amazon.awssdk.services.iam.model.ListUsersRequest;
 import software.amazon.awssdk.services.iam.model.ListUsersResponse;
 import software.amazon.awssdk.services.iam.model.RemoveUserFromGroupRequest;
 import software.amazon.awssdk.services.iam.model.RemoveUserFromGroupResponse;
@@ -115,6 +117,11 @@ public class AmazonIAMClientMock implements IamClient {
 
     @Override
     public ListAccessKeysResponse listAccessKeys() {
+        return listAccessKeys(ListAccessKeysRequest.builder().build());
+    }
+
+    @Override
+    public ListAccessKeysResponse listAccessKeys(ListAccessKeysRequest 
listAccessKeysRequest) {
         ListAccessKeysResponse.Builder result = 
ListAccessKeysResponse.builder();
         Collection<AccessKeyMetadata> accessKeyMetadata = new ArrayList<>();
         AccessKeyMetadata.Builder meta = AccessKeyMetadata.builder();
@@ -124,6 +131,7 @@ public class AmazonIAMClientMock implements IamClient {
         meta.userName("test");
         accessKeyMetadata.add(meta.build());
         result.accessKeyMetadata(accessKeyMetadata);
+        result.isTruncated(false);
         return result.build();
     }
 
@@ -134,17 +142,24 @@ public class AmazonIAMClientMock implements IamClient {
         group.groupName("Test");
         ListGroupsResponse.Builder res = ListGroupsResponse.builder();
         res.groups(Collections.singleton(group.build()));
+        res.isTruncated(false);
         return res.build();
     }
 
     @Override
     public ListUsersResponse listUsers() {
+        return listUsers(ListUsersRequest.builder().build());
+    }
+
+    @Override
+    public ListUsersResponse listUsers(ListUsersRequest listUsersRequest) {
         ListUsersResponse.Builder res = ListUsersResponse.builder();
         List<User> list = new ArrayList<>();
         User.Builder user = User.builder();
         user.userName("test");
         list.add(user.build());
         res.users(list);
+        res.isTruncated(false);
         return res.build();
     }
 
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/IAM2EndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/IAM2EndpointBuilderFactory.java
index 5ab24987a04c..6880ada43b72 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/IAM2EndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/IAM2EndpointBuilderFactory.java
@@ -667,6 +667,102 @@ public interface IAM2EndpointBuilderFactory {
         public String awsIAMGroupPath() {
             return "CamelAwsIAMGroupPath";
         }
+        /**
+         * The marker to use for pagination in list operations.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code AwsIAMMarker}.
+         */
+        public String awsIAMMarker() {
+            return "CamelAwsIAMMarker";
+        }
+        /**
+         * The maximum number of items to return in list operations.
+         * 
+         * The option is a: {@code Integer} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code AwsIAMMaxItems}.
+         */
+        public String awsIAMMaxItems() {
+            return "CamelAwsIAMMaxItems";
+        }
+        /**
+         * Whether the list response is truncated (has more results).
+         * 
+         * The option is a: {@code Boolean} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code AwsIAMIsTruncated}.
+         */
+        public String awsIAMIsTruncated() {
+            return "CamelAwsIAMIsTruncated";
+        }
+        /**
+         * The marker to use for the next page of results.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code AwsIAMNextMarker}.
+         */
+        public String awsIAMNextMarker() {
+            return "CamelAwsIAMNextMarker";
+        }
+        /**
+         * The ARN of the created or retrieved user.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code AwsIAMUserArn}.
+         */
+        public String awsIAMUserArn() {
+            return "CamelAwsIAMUserArn";
+        }
+        /**
+         * The ID of the created or retrieved user.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code AwsIAMUserId}.
+         */
+        public String awsIAMUserId() {
+            return "CamelAwsIAMUserId";
+        }
+        /**
+         * The ARN of the created or retrieved group.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code AwsIAMGroupArn}.
+         */
+        public String awsIAMGroupArn() {
+            return "CamelAwsIAMGroupArn";
+        }
+        /**
+         * The ID of the created or retrieved group.
+         * 
+         * The option is a: {@code String} type.
+         * 
+         * Group: producer
+         * 
+         * @return the name of the header {@code AwsIAMGroupId}.
+         */
+        public String awsIAMGroupId() {
+            return "CamelAwsIAMGroupId";
+        }
     }
     static IAM2EndpointBuilder endpointBuilder(String componentName, String 
path) {
         class IAM2EndpointBuilderImpl extends AbstractEndpointBuilder 
implements IAM2EndpointBuilder, AdvancedIAM2EndpointBuilder {

Reply via email to