how to load a properties file from the META-INF directory?

核能气质少年 提交于 2020-01-05 04:12:09

问题


Is it correct to say that properties files used in execution by a running JAR best belong in META-INF? The notion being to fit with the Standard Directory Layout specified by Maven.

Assuming that structure is desired, how is the properties file loaded from META-INF?

thufir@doge:~/NetBeansProjects/json_parser$ 
thufir@doge:~/NetBeansProjects/json_parser$ java -jar build/libs/json_parser-all.jarAug 18, 2017 6:44:24 AM net.bounceme.doge.json.Main main
INFO: starting
Aug 18, 2017 6:44:24 AM net.bounceme.doge.json.Main run
INFO: actually
Aug 18, 2017 6:44:24 AM net.bounceme.doge.json.PropertiesReader tryGetProps
INFO: properties
Aug 18, 2017 6:44:24 AM net.bounceme.doge.json.PropertiesReader getProps
INFO: properties
Exception in thread "main" java.lang.NullPointerException
    at java.util.Properties$LineReader.readLine(Properties.java:434)
    at java.util.Properties.load0(Properties.java:353)
    at java.util.Properties.load(Properties.java:341)
    at net.bounceme.doge.json.PropertiesReader.getProps(PropertiesReader.java:26)
    at net.bounceme.doge.json.PropertiesReader.tryGetProps(PropertiesReader.java:16)
    at net.bounceme.doge.json.Main.run(Main.java:18)
    at net.bounceme.doge.json.Main.main(Main.java:12)
thufir@doge:~/NetBeansProjects/json_parser$ 
thufir@doge:~/NetBeansProjects/json_parser$ jar tf build/libs/json_parser-all.jarMETA-INF/
META-INF/MANIFEST.MF
META-INF/maven/
META-INF/maven/javax.json/
META-INF/maven/javax.json/javax.json-api/
META-INF/maven/javax.json/javax.json-api/pom.properties
META-INF/maven/javax.json/javax.json-api/pom.xml
javax/
javax/json/
javax/json/Json.class
javax/json/JsonArray.class
javax/json/JsonArrayBuilder.class
javax/json/JsonBuilderFactory.class
javax/json/JsonException.class
javax/json/JsonMergePatch.class
javax/json/JsonNumber.class
javax/json/JsonObject.class
javax/json/JsonObjectBuilder.class
javax/json/JsonPatch$Operation.class
javax/json/JsonPatch.class
javax/json/JsonPatchBuilder.class
javax/json/JsonPointer.class
javax/json/JsonReader.class
javax/json/JsonReaderFactory.class
javax/json/JsonString.class
javax/json/JsonStructure.class
javax/json/JsonValue$ValueType.class
javax/json/JsonValue.class
javax/json/JsonValueImpl.class
javax/json/JsonWriter.class
javax/json/JsonWriterFactory.class
javax/json/spi/
javax/json/spi/JsonProvider.class
javax/json/stream/
javax/json/stream/JsonCollectors.class
javax/json/stream/JsonGenerationException.class
javax/json/stream/JsonGenerator.class
javax/json/stream/JsonGeneratorFactory.class
javax/json/stream/JsonLocation.class
javax/json/stream/JsonParser$Event.class
javax/json/stream/JsonParser.class
javax/json/stream/JsonParserFactory.class
javax/json/stream/JsonParsingException.class
module-info.class
net/
net/bounceme/
net/bounceme/doge/
net/bounceme/doge/json/
net/bounceme/doge/json/Main.class
net/bounceme/doge/json/Marshaller.class
net/bounceme/doge/json/PropertiesReader.class
net/bounceme/doge/json/JsonReader.class
json.json
properties.properties
META-INF/properties.properties
thufir@doge:~/NetBeansProjects/json_parser$ 
thufir@doge:~/NetBeansProjects/json_parser$ jar tf build/libs/json_parser-all.jar | grep properties.properties
properties.properties
META-INF/properties.properties
thufir@doge:~/NetBeansProjects/json_parser$ 

and the relevant code:

package net.bounceme.doge.json;

import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

public class PropertiesReader {

    private static final Logger log = Logger.getLogger(PropertiesReader.class.getName());

    public Properties tryGetProps(String propertiesFileName) {
        log.info(propertiesFileName);
        Properties properties = new Properties();
        try {
            properties = getProps(propertiesFileName);
        } catch (IOException ex) {
            Logger.getLogger(PropertiesReader.class.getName()).log(Level.SEVERE, null, ex);
        }
        return properties;
    }

    private Properties getProps(String propertiesFileName) throws IOException {
        log.info(propertiesFileName);
        Properties properties = new Properties();
        properties.load(PropertiesReader.class.getResourceAsStream("/META-INF/" + propertiesFileName));
        log.info(properties.toString());
        return properties;
    }
}

This is in relation to using init properly from gradle and based on general information.

I tried removing the leading / as suggested -- same result as above.


回答1:


You're not obliged to store your properties files in META-INF, indeed it's not even very common to do so (in my experience at least). In support of this contention the Java JAR Specification doesn't include properties files amongst the expected contents of META-INF.

The code below shows several approach to loading properties from a JAR, whether they are in META-INF or not.

Given a JAR file with this content:

jar -tvf properties.jar
   0 Fri Aug 18 15:35:52 IST 2017 META-INF/
  68 Fri Aug 18 15:35:52 IST 2017 META-INF/MANIFEST.MF
   4 Fri Aug 18 15:35:32 IST 2017 META-INF/bProps.properties
   4 Fri Aug 18 15:35:18 IST 2017 aProps.properties

You can load aProps.properties and bProps.properties like so:

@Test
public void canWriteAndRead() throws IOException {
    ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
    // this works
    loadProperties(systemClassLoader.getResource("aProps.properties"));
    // this works
    loadProperties(systemClassLoader.getResource("META-INF/bProps.properties"));
    // this does not work
    loadProperties(systemClassLoader.getResource("/aProps.properties"));
    // this does not work
    loadProperties(systemClassLoader.getResource("/META-INF/bProps.properties"));

    ClassLoader classLoader = getClass().getClassLoader();
    // this works
    loadProperties(classLoader.getResource("aProps.properties"));
    // this works
    loadProperties(classLoader.getResource("META-INF/bProps.properties"));
    // this does not work
    loadProperties(classLoader.getResource("/aProps.properties"));
    // this does not work
    loadProperties(classLoader.getResource("/META-INF/bProps.properties"));

    // this works
    loadProperties(getClass().getResourceAsStream("/aProps.properties"));
    // this works
    loadProperties(getClass().getResourceAsStream("/META-INF/bProps.properties"));
    // this does not work
    loadProperties(getClass().getResourceAsStream("aProps.properties"));
    // this does not work
    loadProperties(getClass().getResourceAsStream("META-INF/bProps.properties"));
}

private void loadProperties(InputStream incoming) throws IOException {
    if (incoming != null) {
        Properties properties = new Properties();
        properties.load(incoming);
        for (String s : properties.stringPropertyNames()) {
            System.out.println(s);
        }
    }
}

private void loadProperties(URL incoming) throws IOException {
    if (incoming != null) {
        Properties properties = new Properties();
        properties.load(incoming.openStream());
        for (String s : properties.stringPropertyNames()) {
            System.out.println(s);
        }
    }
}


来源:https://stackoverflow.com/questions/45758528/how-to-load-a-properties-file-from-the-meta-inf-directory

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!