LambdaをKotlinのjarで動かそうとしたらNoClassDefFoundErrorが出たので
起きたこと
いっちょ、KotlinのサンプルプログラムをLambdaで動かしたるかいーッとGradleでJarを作って、いつものServerlessFrameworkでデプロイ。
その後、AWSのコンソールからLambdaのテストを実行。
あれ、失敗。
Error loading class com.serverless.Handler: org/apache/logging/log4j/LogManager: java.lang.NoClassDefFoundError java.lang.NoClassDefFoundError: org/apache/logging/log4j/LogManager at com.serverless.Handler.<clinit>(Handler.kt:19) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) Caused by: java.lang.ClassNotFoundException: org.apache.logging.log4j.LogManager at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 3 more
log4jがないと申すか。
確認するか。
あるやんけ。
libも含めてjarなりzipなりで固めてデプロイしなきゃいけないらしい
ライブラリを含めてデプロイしなさいと、当たり前ですね。ハイ
加えてLambdaの場合は一つのファイルにまとめる必要があるので、Gradleで頑張らなきゃいけないっぽい。
ちなみに、Jarの中身を見てもlib配下が全く入ってございませんでした。ハイ
というわけでbuild.gradle
を編集してlib配下も含むzipを作成しましょう。
これの下のほうにあるのをコピペでドン。
.zip デプロイパッケージの作成 (Java) - AWS Lambda
task buildZip(type: Zip) { from compileJava from processResources into('lib') { from configurations.runtime } }
from configurations.compile.Classpath
は、そんなもん無いぞとIDEに怒られたのでfrom configurations.runtime
に変更。
これ、実行時に依存するライブラリ達を保持しているようですね。
とりあえずそれっぽいzipができたのでもう一回deploy。
あれ、失敗。
Class not found: com.serverless.Handler: java.lang.ClassNotFoundException java.lang.ClassNotFoundException: com.serverless.Handler at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348)
自分で作ったクラスがないと申すか。
zipを解凍して中身を確認してみる。
うん、Handlerクラスが入っているはずの、comフォルダがないですね。
from compileJava
じゃなくてfrom compileKotlin
らしい。
うん、確かに…!確かに…ね!そうだね!!
task buildZip(type: Zip) { from compileKotlin from processResources into('lib') { from configurations.runtime } }
今度こそということで、デプロイ。
勝った。