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

# 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](https://qiita-image-store.s3.amazonaws.com/0/44538/099f81fb-aef7-7a5d-6398-e2464f5d142d.png)



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


# まとめ

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