How to read my META-INF/MANIFEST.MF file in a Spring Boot app?

后端 未结 7 1377
后悔当初
后悔当初 2020-12-30 02:31

I\'m trying to read my META-INF/MANIFEST.MF file from my Spring Boot web app (contained in a jar file).

I\'m trying the following code:

        Input         


        
相关标签:
7条回答
  • 2020-12-30 02:56

    I use java.lang.Package to read the Implementation-Version attribute in spring boot from the manifest.

    String version = Application.class.getPackage().getImplementationVersion();
    

    The Implementation-Version attribute should be configured in build.gradle

    jar {
        baseName = "my-app"
        version =  "0.0.1"
        manifest {
            attributes("Implementation-Version": version)
        }
    }
    
    0 讨论(0)
  • 2020-12-30 03:10
        try {
            final JarFile jarFile = (JarFile) this.getClass().getProtectionDomain().getCodeSource().getLocation().getContent();
            final Manifest manifest = jarFile.getManifest();
            final Map<Object, Object> manifestProps = manifest.getMainAttributes().entrySet().stream()
                    .collect(Collectors.toMap(entry -> entry.getKey(), entry -> entry.getValue()));
        ...
        } catch (final IOException e) {
            LOG.error("Unable to read MANIFEST.MF", e);
            ...
        }
    

    This will work only if you launch your app via java -jar command, it won't work if one create an integration test.

    0 讨论(0)
  • 2020-12-30 03:11

    Pretty much all jar files come with a manifest file, so your code is returning the first file it can find in the classpath.

    Why would you want the manifest anyway? It's a file used by Java. Put any custom values you need somewhere else, like in a .properties file next to you .class file.

    Update 2

    As mentioned in a comment below, not in the question, the real goal is the version information from the manifest. Java already supplies that information with the java.lang.Package class.

    Don't try to read the manifest yourself, even if you could find it.

    Update 1

    Note that the manifest file is not a Properties file. It's structure is much more complex than that.

    See the example in the java documentation of the JAR File Specification.

    Manifest-Version: 1.0
    Created-By: 1.7.0 (Sun Microsystems Inc.)
    
    Name: common/class1.class
    SHA-256-Digest: (base64 representation of SHA-256 digest)
    
    Name: common/class2.class
    SHA1-Digest: (base64 representation of SHA1 digest)
    SHA-256-Digest: (base64 representation of SHA-256 digest)
    

    As you can see, Name and SHA-256-Digest occurs more than once. The Properties class cannot handle that, since it's just a Map and the keys have to be unique.

    0 讨论(0)
  • 2020-12-30 03:16

    It's simple just add this

        InputStream is = this.getClass().getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF");
    
        Properties prop = new Properties();
        try {
            prop.load( is );
        } catch (IOException ex) {
            Logger.getLogger(IndexController.class.getName()).log(Level.SEVERE, null, ex);
        }
    

    Working for me.

    Note:

    getClass().getClassLoader() is important

    and

    "META-INF/MANIFEST.MF" not "/META-INF/MANIFEST.MF"

    Thanks Aleksandar

    0 讨论(0)
  • 2020-12-30 03:17

    I have it exploiting Spring's resource resolution:

    @Service
    public class ManifestService {
    
        protected String ciBuild;
    
        public String getCiBuild() { return ciBuild; }
    
        @Value("${manifest.basename:/META-INF/MANIFEST.MF}")
        protected void setManifestBasename(Resource resource) {
            if (!resource.exists()) return;
            try (final InputStream stream = resource.getInputStream()) {
                final Manifest manifest = new Manifest(stream);
                ciBuild = manifest.getMainAttributes().getValue("CI-Build");
            }
            catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
    }
    

    Here we're getting CI-Build, and you can easily extend the example to load other attributes.

    0 讨论(0)
  • 2020-12-30 03:18
    public Properties readManifest() throws IOException {
        Object inputStream = this.getClass().getProtectionDomain().getCodeSource().getLocation().getContent();
        JarInputStream jarInputStream = new JarInputStream((InputStream) inputStream);
        Manifest manifest = jarInputStream.getManifest();
        Attributes attributes = manifest.getMainAttributes();
        Properties properties = new Properties();
        properties.putAll(attributes);
        return properties;
    }
    
    0 讨论(0)
提交回复
热议问题