How to view the actual java dependencies / library on AWS Lambda runtimes

Viewed 322

I have custom logic which defines how jackson should serialize and deserialize a domain object in a AWS lambda function. The AWS lambda function is deployed on AWS using the AWS lambda runtime java 11(amazon-corretto-11). The serialization works fine when tested locally but not in AWS.

How do you find out which java dependencies and which version of the dependencies that are actually used in the AWS lambda runtime?

In my specific case it's the version of the jackson dependency that I would like to find out.

2 Answers

Instead of trying to reverse-engineer the runtime, which is probably hardly doable, try to focus on your problem: the serialization provided by the runtime does not work.

What you can do is to refactor your handler function to accept not an object of your class (this way, the deserialization takes place in the runtime and you get the POJO), but raw request (using APIGatewayProxyRequestEvent from com.amazonaws:aws-lambda-java-events if you're using API Gateway) or an InputStream. This way, you'll get raw payload and then you can parse it as you wish. Read more in AWS Lambda function handler in Java. You'll also need to include your dependencies in your deployment package (google for "fat jar").

@madhead:s answere should be the way forward. But I think there is a way to get an idea of what dependencies are involved with just a little bit of reverse engineering.

But first, as @jccampos mentions

You shouldn't rely on any other features of serialization frameworks such as annotations. If you need to customize the serialization behavior, you can use the raw byte stream to use your own serialization.

As I understand it, that text was taken from https://docs.aws.amazon.com/lambda/latest/dg/java-programming-model-req-resp.html

You have no control when letting the AWS Lambda environment handling the serialization and deserialization. The deserialization will happen outside your lambda function but within the lambda environment. AWS Lambda environment will use it's own dependency that is not packaged within your lambda function. That's why an InputStream is a better option since you are then in control of which library is used when desalinizing.

AWS uses it's own customized version of Jackson when deserializing and it's package in com.amazonaws.thirdparty.jackson. If you are interested in what version that is being used you can download the maven project aws-java-sdk-bundle which contains the jar that contains the third party library (and extract the jar to find out the version of third party libraries). I would guess that the lambda environment uses one of the later versions of that dependency (maybe some could help with confirming this with a source).

Lastly, I have tried to include aws-java-sdk-bundle as scope provided in maven and then print out the package information of com.amazonaws.thirdparty.jackson.databind.ObjectReader from within a lambda. It resulted in NoClassDefFoudError which should indicate that the third party jackson dependency is only accessible from the AWS lambda environment outside the lambda function.

Related