Load properties file in JAR?
The problem is that you are using getSystemResourceAsStream
. Use simply getResourceAsStream
. System resources load from the system classloader, which is almost certainly not the class loader that your jar is loaded into when run as a webapp.
It works in Eclipse because when launching an application, the system classloader is configured with your jar as part of its classpath. (E.g. java -jar my.jar will load my.jar in the system class loader.) This is not the case with web applications - application servers use complex class loading to isolate webapplications from each other and from the internals of the application server. For example, see the tomcat classloader how-to, and the diagram of the classloader hierarchy used.
EDIT: Normally, you would call getClass().getResourceAsStream()
to retrieve a resource in the classpath, but as you are fetching the resource in a static initializer, you will need to explicitly name a class that is in the classloader you want to load from. The simplest approach is to use the class containing the static initializer,
e.g.
[public] class MyClass {
static
{
...
props.load(MyClass.class.getResourceAsStream("/someProps.properties"));
}
}
How to read properties file inside jar?
To obtain the stream you don't need FileInputStream at all. You can get the properties' file stream like this
InputStream is = VerifyFolderStructure.class.getResourceAsStream("/com/abc/properties/config.properties");
How to reload a properties file on a jar
For your first question: you should not do it. A common way woul be to use a builtin configuration in you executable jar with the option of passing a config file as argument. Storing changes of the configuration back into the jar is not a great idea because it means modifing the running binary.
Second question: a usual way to implement such a functionality would be to add a change listener to your config file. This can be done using the java.nio.file package
:
https://docs.oracle.com/javase/tutorial/essential/io/notification.html
Read specific property from a property file in a jar
Try something like (untested):
private static int getProductBuildNumber(Path artefactFilePath) throws IOException{
try(FileSystem zipFileSystem = FileSystems.newFileSystem(artefactFilePath, null)){
Path versionPropertiesPath = zipFileSystem.getPath("/version.properties");
Properties versionProperties = new Properties();
try (InputStream is = Files.newInputStream(versionPropertiesPath)){
versionProperties.load(is);
}
return Integer.parseInt(versionProperties.getProperty("product.build.number"));
}
}
Read properties file outside JAR file
So, you want to treat your .properties
file on the same folder as the main/runnable jar as a file rather than as a resource of the main/runnable jar. In that case, my own solution is as follows:
First thing first: your program file architecture shall be like this (assuming your main program is main.jar and its main properties file is main.properties):
./ - the root of your program
|__ main.jar
|__ main.properties
With this architecture, you can modify any property in the main.properties file using any text editor before or while your main.jar is running (depending on the current state of the program) since it is just a text-based file. For example, your main.properties file may contain:
app.version=1.0.0.0
app.name=Hello
So, when you run your main program from its root/base folder, normally you will run it like this:
java -jar ./main.jar
or, straight away:
java -jar main.jar
In your main.jar, you need to create a few utility methods for every property found in your main.properties file; let say the app.version
property will have getAppVersion()
method as follows:
/**
* Gets the app.version property value from
* the ./main.properties file of the base folder
*
* @return app.version string
* @throws IOException
*/
import java.util.Properties;
public static String getAppVersion() throws IOException{
String versionString = null;
//to load application's properties, we use this class
Properties mainProperties = new Properties();
FileInputStream file;
//the base folder is ./, the root of the main.properties file
String path = "./main.properties";
//load the file handle for main.properties
file = new FileInputStream(path);
//load all the properties from this file
mainProperties.load(file);
//we have loaded the properties, so close the file handle
file.close();
//retrieve the property we are intrested, the app.version
versionString = mainProperties.getProperty("app.version");
return versionString;
}
In any part of the main program that needs the app.version
value, we call its method as follows:
String version = null;
try{
version = getAppVersion();
}
catch (IOException ioe){
ioe.printStackTrace();
}
Read properties file from jar
So I found the solution.
I use this method to get the file's InputStream what is in your application's jar:
public InputStream getLanguageStream(String languageName) {
languageName = languageName.replace(".properties", "");
return MainClass.class.getResourceAsStream("/me/s3ns3iw00/resources/languages/" + languageName + ".properties");
}
Now you can load it to Properties:
properties.load(new InputStreamReader(getLanguageStream("ENG"), Charset.forName("UTF-8")));
And an extra:
I use this method to get files' name in jar path:
public List<String> getFileNamesInJarPath(String jarPath) {
List<String> fileNames = new ArrayList<>();
CodeSource src = MainClass.class.getProtectionDomain().getCodeSource();
try {
if (src != null) {
URL jar = src.getLocation();
ZipInputStream zip = new ZipInputStream(jar.openStream());
while (true) {
ZipEntry e = zip.getNextEntry();
if (e == null)
break;
String name = e.getName();
if (name.startsWith(jarPath)) {
String substringedName = name.substring(name.lastIndexOf("/") + 1);
if (!substringedName.equalsIgnoreCase("")) {
fileNames.add(substringedName);
}
}
}
} else {
/* Fail... */
}
} catch (IOException e) {
e.printStackTrace();
}
return fileNames;
}
You get a list of jarPath's directory content what is in your applications's jar.
Java properties file in .jar folder
To copy a file (config.properties) into target directory (dist/), you can modify your build.xml:
<target name="-post-compile">
<copy todir="${dist.dir}">
<fileset dir="" includes="config.properties"/>
</copy>
</target>
To package properties file in jar itself, you can just put the properties file into the same directory as your source files. In this case, you can use Class.getResouce() to read it at runtime, but one has to re-package jar to modify it. Source directories are listed under "Source package folders" in project -> properties -> sources.
Related Topics
Running Java in Package from Command Line
What Does Biginteger Having No Limit Mean
How to Read Xml Response from a Url in Java
Singleton Design Pattern: Pitfalls
How to Correctly Decode Unicode Parameters Passed to a Servlet
How to Find the Console Width with Java
Compare One String with Multiple Values in One Expression
Including Images with an Executable Jar
What Is the Purpose of Defining a Package in a Java File
How to Do a Soap Web Service Call from Java Class
Java 'File.Delete()' Is Not Deleting Specified File
Difference Between Getclass().Getclassloader().Getresource() and Getclass.Getresource()
Cannot Find Firefox Binary in Path. Make Sure Firefox Is Installed
"The Public Type <<Classname>> Must Be Defined in Its Own File" Error in Eclipse