aws / aws-sdk-java-v2

The official AWS SDK for Java - Version 2
Apache License 2.0
2.12k stars 804 forks source link

SQS TagQueue and Tag(s) parameter #2524

Open jpinsolle-bc opened 3 years ago

jpinsolle-bc commented 3 years ago

Hello,

I noticed Java SDK behaves differently than the AWS CLI 2 and than the documentation about Tag argument names for method SQS TagQueue

Java SDK send tags with an "s" whereas documentation mention no "s" at the end of the word

You can see the difference bellow with a CLI request and an Java SDK request:

CLI = Action=TagQueue&Version=2012-11-05&QueueUrl=XXX&Tag.1.Key=Name&Tag.1.Value=my-queue  
SDK = Action=TagQueue&Version=2012-11-05&QueueUrl=XXX&Tags.1.Key=Name&Tags.1.Value=my-queue

I tried to investigate without success but let me share my results. I took a look in the jar file sqs-2.16.82.jar.

File sqs-2.16.82.jar!/codegen-resources/service-2.json

"TagMap":{
      "type":"map",
      "key":{
        "shape":"TagKey",
        "locationName":"Key"
      },
      "value":{
        "shape":"TagValue",
        "locationName":"Value"
      },
      "flattened":true,
      "locationName":"Tag"
    }

File sqs-2.16.82.jar!/software/amazon/awssdk/services/sqs/model/TagQueueRequest.class

private static final SdkField<Map<String, String>> TAGS_FIELD = SdkField
            .<Map<String, String>> builder(MarshallingType.MAP)
            .memberName("Tags")
            .getter(getter(TagQueueRequest::tags))
            .setter(setter(Builder::tags))
            .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD).locationName("Tags").build(),
                    MapTrait.builder()
                            .keyLocationName("Key")
                            .valueLocationName("Value")
                            .valueFieldInfo(
                                    SdkField.<String> builder(MarshallingType.STRING)
                                            .traits(LocationTrait.builder().location(MarshallLocation.PAYLOAD)
                                                    .locationName("Value").build()).build()).isFlattened(true).build()).build();

Why is the value of locationName in the Java code equal to Tagsand not Tag as specified in the file service-2.json

debora-ito commented 3 years ago

@jpinsolle-betclic I see the difference but I'm not sure why it's there. I confirmed the API call is successful in v2 though:

>> "Action=TagQueue&Version=2012-11-05&QueueUrl=xxx&Tags.1.Key=tagKey&Tags.1.Value=tagValue"

Are you having issues? Can you give more context?

jpinsolle-bc commented 3 years ago

I don't have any issue with the real AWS SQS, but I have an issue with localstack with SQS mock based on moto.

I'm wondering why Java SDK doesn't respect the documentation whereas AWS CLI yes.

Is it a bug (as Elasticmq seems to say) or is it on purpose ?

dagnir commented 2 years ago

Hi @jpinsolle-betclic, interesting question!

According to official documentation we have on the "Query" protocol that SQS uses, Java v2's behavior follows the spec correctly here:

Each key and value in each pair provided in the map is serialized as a separate key with a "." separator, the string "entry", a "." separator, a "1" indexed incrementing counter, a "." separator, and the string "key" or "value" (for member keys or values, respectively) appended to the container's key.

Why is the value of locationName in the Java code equal to Tagsand not Tag as specified in the file service-2.json

The SDK is taking the name of the TagsMap member on the request structure which is "Tags" as the locationName: https://github.com/aws/aws-sdk-java-v2/blob/3b6ee392f27e9d0b4aedddf0ad059120ebcd95e3/services/sqs/src/main/resources/codegen-resources/service-2.json#L1464-L1480

Note that if TagQueueRequest$Tags did have a location name, like this

         "Tags":{
           "shape":"TagMap",
           "documentation":"<p>The list of tags to be added to the specified queue.</p>"
          "locationName":"Tag"
         }

Then it would show up as the CLI's request. I suspect the CLI is using the top-level TagMap$locationName here, which is why it's Tag in the request, but I'm not sure if this is technically valid. I will check with the rest of the SDKs and report back with what I learn.

CC: @mtdowling @kstich

dagnir commented 2 years ago

After speaking with @mtdowling, I've determined that the right behavior is for the SDK to use Tag and not Tags. Marking this as a bug.