Summary
This post describes a "recipe" for building a deployment package for an Amazon AWS Lambda function authored in Java. The current AWS Lambda documentation (links below in the "references" section) suggest using the "shade" plugin with Maven, which produces an "uber-jar", or using Gradle to produce a zip file containing classes and a "lib" subdirectory with dependency jars. Neither of those approaches is ideal. "Uber-jars" cause problems with any code that uses reflection, and using Gradle seems to assume you've completely set Maven aside as a build tool. This "recipe" assumes you want to use Maven, but you'd still like the zip-containing-jars style deployment package instead of an "uber-jar."
Use Maven's Assembly Plugin
This should be at least a good 90%+ head start on configuring Maven to produce an AWS Lambda deployment package with the dependency libraries still in their original jars and your AWS Lambda function code included in package-directory / class-file format.
Create Assmembly Descriptor
Within the Maven project directory structure, create a file named:
src/assembly/lambda_deployment_package_assembly.xml
...containing the following content...
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
<id>lambda_deployment_package_assembly</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.build.directory}/classes</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>**/*.class</include>
</includes>
</fileSet>
<fileSet>
<outputDirectory>extras</outputDirectory>
<includes>
<include>readme.md</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet>
<outputDirectory>lib</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
</dependencySet>
</dependencySets>
</assembly>
Add Plugin Configuration to pom.xml
Note: If this is a multi-module project, with each module producing its own AWS Lambda function deployment package (.zip), then this goes in the sub-module's pom.xml, not the parent. If you have a lot of AWS Lambda function sub-modules, it might be worth trying to use pluginManagement in the parent pom, but that's outside the scope of this post.
pom.xml (excerpt)
<project>
<dependencies>
...
</dependencies>
...
<plugins>
<plugin>
<!-- Note: Normally, this plugin would be run using
"mvn compile assembly:single" but the execution
clause below binds it to the normal 'package' lifecycle phase
-->
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/assembly/lambda_deployment_package_assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>lambda_deployment_package_execution</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
...
</project>
References
- http://docs.aws.amazon.com/lambda/latest/dg/create-deployment-pkg-zip-java.html
- http://docs.aws.amazon.com/lambda/latest/dg/java-create-jar-pkg-maven-no-ide.html