Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parsing clientContext header seems to be broken in quarkus-amazon-lambda extension #9395

Closed
arturs-cc opened this issue May 18, 2020 · 13 comments · Fixed by #9502
Closed

Parsing clientContext header seems to be broken in quarkus-amazon-lambda extension #9395

arturs-cc opened this issue May 18, 2020 · 13 comments · Fixed by #9502
Assignees
Labels
area/amazon-lambda kind/bug Something isn't working
Milestone

Comments

@arturs-cc
Copy link

Describe the bug
This issue concerns two classes overriding the startPollLoop(ShutdownContext context) method.
Namely:

1. AmazonLambdaRecorder
2. FunqyLambdaBindingRecorder

Both of them creates a AbstractLambdaPollLoop object which takes 3 arguments.
In both of those cases AbstractLambdaPollLoop is created with those arguments:
AmazonLambdaMapperRecorder.objectMapper, AmazonLambdaMapperRecorder.cognitoIdReader, AmazonLambdaMapperRecorder.cognitoIdReader

Last argument is supposed to be AmazonLambdaMapperRecorder.clientCtxReader

Expected behavior
ClientContext header is parsed and added to AWS Context.

Actual behavior
Exception is thrown:
{ "errorType": "com.fasterxml.jackson.databind.exc.InvalidDefinitionException", "errorMessage": "Cannot construct instance of `com.amazonaws.services.lambda.runtime.CognitoIdentity` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information\n at [Source: (String)"<clientContextJSON>"; line: 1, column: 1]" }

<clientContextJSON> is whatever JSON was sent trough client context
Issue seems to be coming from using the wrong ObjectMapper.

To Reproduce
Steps to reproduce the behavior:

  1. Make two AWS lambdas where one invokes another trough direct invokation.(not trough API-GW) Make one of them fill clientContext and another to read it. Then trigger the sender lambda.

Important note: Somehow this manages to work in java8 runtime right now which i am unable to explain. So this bug only occurs when running in native mode. If you could guys help me explain that I would appreciate it.
Also it only occurs when there is actual data exchanged between lambdas so just invoking one of them won't cause this bug to happen

Environment (please complete the following information):

  • Output of uname -a or ver: Darwin localhost 19.3.0 Darwin Kernel Version 19.3.0: Thu Jan 9 20:58:23 PST 2020; root:xnu-6153.81.5~1/RELEASE_X86_64 x86_64
  • Output of java -version: openjdk version "11.0.3" 2019-04-16
  • Quarkus version or git rev: One lambda was using 1.3.2.Final and other 1.4.2.Final.
  • Build tool (ie. output of mvnw --version or gradlew --version): Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)

If you require any other info or additional questions I will be happy to provide more.

@arturs-cc arturs-cc added the kind/bug Something isn't working label May 18, 2020
@quarkusbot
Copy link

/cc @patriot1burke

@miron4dev
Copy link

@jaikiran
Copy link
Member

Hello @miron4dev, would you like to open a PR with your proposed fix?

@miron4dev
Copy link

It looks like the actual issue is deeper than I expected. Replacing the third argument by AmazonLambdaMapperRecorder.clientCtxReader helps, but doesn't solve the problem.

So, now we're getting the actual error:

Cannot construct instance of `com.amazonaws.services.lambda.runtime.ClientContext` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information\n at [Source: (String)\"{\"custom\":{\"requestId\":\"3e421f9c-2084-49b4-8ce0-600e43c31927\"}}

Here https://github.com/quarkusio/quarkus/blob/master/extensions/amazon-lambda/common-runtime/src/main/java/io/quarkus/amazon/lambda/runtime/AmazonLambdaContext.java#L54
it tries to deserialize Lambda-Runtime-Client-Context but fails because ClientContext is an interface. But Jackson will never deserialize JSON to an interface without a special configuration. How it is supposed to work?
The important fact that the problem is reproducible only in native mode.

@patriot1burke
Copy link
Contributor

Working on a fix.

@patriot1burke
Copy link
Contributor

@patriot1burke
Copy link
Contributor

FYI, this doesn't work in native because Quarkus is parsing the context. In a JVM deployment the lambda runtime is parsing the context.

@patriot1burke
Copy link
Contributor

@arturs-cc How can I reproduce this? Not sure how to create the ClientContext header and the Java API accepts a string. This is the only docs I could find somehow that described the json.

https://docs.aws.amazon.com/mobileanalytics/latest/ug/PutEvents.html

@arturs-cc
Copy link
Author

@patriot1burke Just passing the json string to Java API will work.
Here is an example to generate it:

Map<String, Map<String, String>> root = new HashMap<>(); Map<String, String> custom = new HashMap<>(); custom.put("someKey", "someValue"); root.put("custom", custom); return Base64.getEncoder().encodeToString(objectMapper.writeValueAsBytes(root)); // important to Base64 encode the string

@patriot1burke
Copy link
Contributor

@miron4dev
Copy link

@arturs-cc @patriot1burke ClientContext must contain base64-encoded data, but AWS itself is responsible for decoding.

The fix works like a charm if you remove Base64.getDecoder().decode because on this step you have already decoded string. https://github.com/patriot1burke/quarkus/blob/cac6b2cd1bf8d2cc9814c7f9c9f946f97a3bb653/extensions/amazon-lambda/common-runtime/src/main/java/io/quarkus/amazon/lambda/runtime/AmazonLambdaContext.java#L55

@patriot1burke
Copy link
Contributor

Ok, took out the base64 decode should be good. Docs are horrible here. Either of you know how the Cognito header is passed? Couldn't find any info about it.

@arturs-cc
Copy link
Author

arturs-cc commented May 21, 2020

@patriot1burke
Documentation on those parts really is crap. I would search aws mobile sdk for clues. AFAIK it uses Cognito.
https://github.com/aws-amplify/aws-sdk-android

geoand added a commit that referenced this issue May 21, 2020
Read Lambda ClientContext correctly, Issue #9395
@gsmet gsmet added this to the 1.5.0.Final milestone May 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/amazon-lambda kind/bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants