Skip to content
This repository was archived by the owner on Feb 23, 2023. It is now read-only.

Can't get CoreUtilites Example running (JDK 11) #67

Closed
rieckpil opened this issue Apr 8, 2022 · 4 comments
Closed

Can't get CoreUtilites Example running (JDK 11) #67

rieckpil opened this issue Apr 8, 2022 · 4 comments

Comments

@rieckpil
Copy link

rieckpil commented Apr 8, 2022

Hey 👋🏻

I'm trying to enrich my existing AWS Lambda Java setup with the structured logging functionality. However, I'm failing to get it running with Java 11.

To confirm that it's not something project-specific I forked this sample project and tried to run the helloworld.App on a Java 11 default AWS Lambda runtime and get the following error:

Error loading class helloworld.App: java.lang.ExceptionInInitializerError
java.lang.ExceptionInInitializerError
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Unknown Source)
Caused by: java.lang.UnsupportedOperationException: No class provided, and an appropriate one cannot be found.
	at org.apache.logging.log4j.LogManager.callerClass(LogManager.java:573)
	at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:598)
	at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:585)
	at helloworld.App.<clinit>(App.java:37)
	... 2 more

Some basic research pointed me to this issue https://issues.apache.org/jira/browse/LOG4J2-2834 that mentions a fix by adding Multi-Release:true to the Manifest.md.

I tried to add this by enriching the transformer setup but still get the same issue when running the sample Lambda of this repo.

What's weird is that this issue seems to only occur on the AWS Lambda runtime. If I manually add the Lambda handler as the Main-Class with a basic main method that invokes the function, and run java -jar target/... I don't see this exception locally.

Reproducible example: https://github.com/rieckpil/aws-lambda-powertools-examples

With a java8.al2 runtime it works fine, but I'd like to avoid downgrading all my lambdas to Java 8 in 2022 😅

Any ideas?

@pankajagrawal16
Copy link
Contributor

pankajagrawal16 commented Apr 8, 2022

Hi @rieckpil Thanks for opening the issue.

The utility for sure works well with java 11 and further too. Infact we have that validated as part of the build process of utility too, before we make a release.

That being said, I just tried the example as is and using aws sam template provided in the example and everything worked fine as it should have.

I also tried the serverless framework example you had, there off course it failed, like you mentioned above.

I tried changing the function code to

private final static Logger log = LogManager.getLogger(App.class);

instead of

private final static Logger log = LogManager.getLogger();

and then it works fine. So there has to be some difference for sure between how sam is packaging thing vs just deploying the jar directly.

I will recommend explicitly specifying the class when initializing logger until i see why log4j is not able to figure things out on its own when running as plain jar vs what SAM packages and builds

@pankajagrawal16
Copy link
Contributor

After digging a bit more, the real reason here is and this post was really helpful as well.

maven-shade-plugin is used to create an "uber"-jar containing all the dependencies of my lambda function. This approach is recommended one as well official AWS documentation. the maven-shade-plugin extracts all jar file dependencies and repackages them into a single, flat jar file. If one of your dependencies is a multi-release jar (as is log4j2), then you can configure the maven-shade-plugin to reconstruct an appropriate META-INF directory and if you run the jar as a jar file then everything still works.

But because AWS Lambda extracts the jar, the META-INF directory is not "seen" by the JVM anymore, and anything that was in META-INF/versions is ignored.

So basically, this is not just specific to powertools but basically, log4j2 and java lambda function configuration. That being said, what we are going to do in powertools specifically:

  • Update docs and samples to specify class names directly when initialising logger. Thats better from cold start perspective anyways.
  • Clarify and address this bit in FAQ section of doc as well with a workaround on what config might be needed, if users still want to depend on log4j to figure out class name.

I will copy this issue to powertools repo itself.

@pankajagrawal16
Copy link
Contributor

Here is the issue aws-powertools/powertools-lambda-java#825

@rieckpil
Copy link
Author

rieckpil commented Apr 8, 2022

Wow, thanks for the quick help @pankajagrawal16.

Oh yikes, I was digging so deep into this :D

Thanks for your investigation effort 🥳 I'll also take a closer look into favoring the assembly plugin over the shade plugin.

PS: I can confirm that with the suggested change it works 👍

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants