How do you create a MANIFEST.MF that's available when you're testing and running from a jar in production?

前端 未结 9 999
失恋的感觉
失恋的感觉 2020-12-28 16:28

I\'ve spent far too much time trying to figure this out. This should be the simplest thing and everyone who distributes Java applications in jars must have to deal with it.

相关标签:
9条回答
  • 2020-12-28 17:02

    I will also usually use a version file. I will create one file per jar since each jar could have its own version.

    0 讨论(0)
  • 2020-12-28 17:11

    I've found the comment by McDowell to be true - which MANIFEST.MF file gets picked up depends on the classpath and might not be the one wanted. I use this

    String cp = PCAS.class.getResource(PCAS.class.getSimpleName() + ".class").toString();
    cp = cp.substring(0, cp.indexOf(PCAS.class.getPackage().getName())) 
                  +  "META-INF/MANIFEST.MF";
    Manifest mf = new Manifest((new URL(cp)).openStream());
    

    which I adapted from link text

    0 讨论(0)
  • 2020-12-28 17:11

    Just don't use the manifest. Create a foo.properties.original file, with a content such as version=@VERSION@

    And in ther same task you are jaring you can do a copy to copu foo.properties.original and then

    0 讨论(0)
  • 2020-12-28 17:17

    You can use a utility class Manifests from jcabi-manifests that automates finding and parsing of all MANIFEST.MF files available in classpath. Then, you read any attribute with a one liner:

    final String name = Manifests.read("Build-By");
    final String date = Manifests.read("Build-Date");
    

    Also, check this out: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

    0 讨论(0)
  • 2020-12-28 17:18

    ClassLoader.getResource(String) will load the first manifest it finds on the classpath, which may be the manifest for some other JAR file. Thus, you can either enumerate all the manifests to find the one you want or use some other mechanism, such as a properties file with a unique name.

    0 讨论(0)
  • 2020-12-28 17:21

    You can get the manifest for an arbitrary class in an arbitrary jar without parsing the class url (which could be brittle). Just locate a resource that you know is in the jar you want, and then cast the connection to JarURLConnection.

    If you want the code to work when the class is not bundled in a jar, add an instanceof check on the type of URL connection returned. Classes in an unpacked class hierarchy will return a internal Sun FileURLConnection instead of the JarUrlConnection. Then you can load the Manifest using one of the InputStream methods described in other answers.

    @Test
    public void testManifest() throws IOException {
        URL res = org.junit.Assert.class.getResource(org.junit.Assert.class.getSimpleName() + ".class");
        JarURLConnection conn = (JarURLConnection) res.openConnection();
        Manifest mf = conn.getManifest();
        Attributes atts = mf.getMainAttributes();
        for (Object v : atts.values()) {
            System.out.println(v);
        }
    }
    
    0 讨论(0)
提交回复
热议问题