Search code examples
mavenaws-lambdamaven-shade-pluginuberjaraws-codebuild

AWS CodeBuild failed to create Fat jar


I have created AWS Lambda function and now I am trying to setup deployment on AWS. I have created buildspec.yml file with following content:

version: 0.1

phases:
  build:
    commands:
      - echo Entering build phase...
      - echo Build started on `date`
      - mvn package shade:shade
      - mv target/classes/* .
      - rm -rf target src buildspec.yml pom.xml
      - aws cloudformation package --template template.json --s3-bucket $S3_BUCKET --output-template template-export.json
artifacts:
  type: zip
  files:
    - template-export.json

Now when I push my code to AWS CodeCommit, build process is run successfully but in output s3 bucket there is output file of only 130 kb. This means that my dependencies are missing from created package, and when I try running my Lambda I got following error:

Error loading class com.test.handler: org/apache/log4j/Logger: class java.lang.NoClassDefFoundError

In my pom.xml file I added shade plugin:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
    <createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
    <execution>
        <phase>package</phase>
        <goals>
            <goal>shade</goal>
        </goals>
    </execution>
</executions>
</plugin>

When I run command mvn package on my PC everything is OK and I get jar file containing all my dependencies (size is little over 10mb) and if I manually deploy this jar to AWS lambda function everything is working as expected.

I also tried following this tutorial: Link, but nothing changed.

Can someone please help, I really don't know what I am missing here :/


Solution

  • During runtime your application is unable to find the jar.

    Taken from this answer by Jared:

    It is important to keep two different exceptions straight in our head in this case:

    java.lang.ClassNotFoundException This exception indicates that the class was not found on the classpath. This indicates that we were trying to load the class definition, and the class did not exist on the classpath.

    java.lang.NoClassDefFoundError This exception indicates that the JVM looked in its internal class definition data structure for the definition of a class and did not find it. This is different than saying that it could not be loaded from the classpath. Usually this indicates that we previously attempted to load a class from the classpath, but it failed for some reason - now we're trying again, but we're not even going to try to load it, because we failed loading it earlier. The earlier failure could be a ClassNotFoundException or an ExceptionInInitializerError (indicating a failure in the static initialization block) or any number of other problems. The point is, a NoClassDefFoundError is not necessarily a classpath problem.

    for similarities and differences refer :

    What causes and what are the differences between NoClassDefFoundError and ClassNotFoundException?

    You can use the following maven dependency in your pom file. Otherwise, you can download the following two jars from net and add it to your build path.

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.6.4</version>
    

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.4</version>
    </dependency>