Posted at

AWS LambdaではMANIFEST.MFの内容が捨てられる

More than 1 year has passed since last update.


TL;DR

AWS LambdaでJavaを実行する場合 jarファイルをlambda環境にアップロードするが、そのjarファイルの MANIFEST.MF に情報を入れていたとしても実行時に消されてしまう。おそらくLambda環境内でjarファイルが生成し直され、そのときに捨てられると推測される。

MANIFEST.MFに例えば jarファイルのバージョン番号を保存する設計だと Lambdaでは取得できない。別の場所に保存する必要がある。(プロパティファイルなど)


検証


サンプルソース


Main.java

package testmanifest;

import com.amazonaws.services.lambda.runtime.Context;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.stream.Collectors;

public class Main {
/** 自パッケージと、MANIFEST.MFの内容を収集して返す。*/
static String getManifestInfo() throws IOException {
StringBuilder sb = new StringBuilder();
Package thisPack = Package.getPackage("testmanifest");
sb.append(String.format("ImplementationVersion -> %s%n", thisPack.getImplementationVersion()));
sb.append(String.format("ImplementationTitle -> %s%n", thisPack.getImplementationTitle()));
sb.append("-------------\n");
try (BufferedReader buffer = new BufferedReader(
new InputStreamReader(
Main.class.getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF"),
StandardCharsets.UTF_8))) {
sb.append(buffer.lines().collect(Collectors.joining("\n")));
}
return sb.toString();
}

public static void main(String[] args) throws Exception {
System.out.println(getManifestInfo());
}

/** ハンドラ名 testmanifest.Main::awsStart */
public void awsStart(Map<?, ?> name, Context context) throws IOException {
context.getLogger().log(getManifestInfo());
}
}



build.gradle

apply plugin: 'java'

apply plugin: 'com.github.johnrengelman.shadow'

version = '1.2.3'

sourceCompatibility = '1.8'
targetCompatibility = '1.8'

def defaultEncoding = 'UTF-8'

tasks.withType(AbstractCompile) each { it.options.encoding = defaultEncoding }

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3'
}
}
repositories {
jcenter()
}

dependencies {
compile 'com.amazonaws:aws-lambda-java-core:1.1.0'
}

jar {
manifest {
attributes(
"Implementation-Title": "testmanifest",
"Implementation-Version": "1.2.3",
"Implementation-Vendor": "nantoka vender",
"hoge": "fuga"
)
}
}



ビルド

>gradlew.bat shadowJar

:compileJava
:processResources UP-TO-DATE
:classes
:shadowJar

BUILD SUCCESSFUL

Total time: 3.26 secs
>dir /b build\libs
testManifest-1.2.3-all.jar

>

コネタ:com.github.johnrengelman.shadowにて、いわゆるUber JARを作ることができる。


コンソール実行

>java -cp build\libs\testManifest-1.2.3-all.jar testmanifest.Main

ImplementationVersion -> 1.2.3
ImplementationTitle -> testmanifest
-------------
Manifest-Version: 1.0
Implementation-Title: testmanifest
Implementation-Version: 1.2.3
hoge: fuga
Implementation-Vendor: nantoka vender

>


Lambdaでの実行

CloudWatchにて出力を確認した。

lambda.png

ImplementationVersion などgradleで設定した値が消えていて、Ant-Versionや、Main-Class: が設定されている。


まとめ

MANIFEST.MFに情報をもたせられないので、別の場所に情報を保持させましょう。