I have read that files within a jar file are not supposed to be modified, and I think that explains why getting an outputStream is not as simple as getting an inputStream calling getClass().getResourceAsStream() to read a file. When using properties files values are going to be retrieved during execution, but what if those values are subject to change? It would be tedious to recompile the program.
In my case those values are IP address, username and a path to an external file. So I guess I could not move the external file even by accident because my properties file in the jar have a different path to that file. Is this the way is supposed to be or is there a more flexible way that I am not aware of?
Usually property files are located outside of jar somewhere on production system's classpath. Values are usually changed once in a while via provisioning scripts / manually and then only application restart is required, not a re-compile.
So, to sum it up, I'd suggest not having properties file inside the jar.
Related
I need to read in config.properties for some configuration.
I am open to any way of doing it, with requirements.
I want it outside my war file so that it can be changed easily, and does not require a rebuild.
I have searched everywhere but cannot find how to do it, I'm sure this is java 101, but I cant figure it.
I have tried classloader but that seems to only load resources from inside the war, and I cannot find how to get the location I loaded the war into my server from to read it from there.
I also cannot find a way to pass in an argument via command line parameter's as its a soap endpoint, which I can access anywhere in my code?
I saw this Where to place and how to read configuration resource files in servlet based application?
and i want to use the file system approach but I don't want a hard coded path for the config file.
I just want something simple and easy, I know there is something but I just cannot find it.
use this this is helpful your question . i think.
In one method abcd
public static String abcd(String one) {
properties = new Properties();
properties.load(<classNmae>.class.getClassLoader().getResourceAsStream("AppResources.properties"));
return properties.getProperty(one);
call this code
String fileLocation = abcd("internal property file");
Properties properties = new Properties();
FileInputStream fis = new FileInputStream(fileLocation );
properties.load(fis);
fis.close();
acd = (String)properties.get("acd");
Note:
AppResources.properties have external file location D:/aaa.properties file
then in second method you read properties of external file
I want it outside my war file so that it can be changed easily, and does not require a rebuild.
May not be how you want it, but just to answer this, we have a similar scenario where our web applications are deployed in web servers located in locations /apps/servers/webserver-1, /apps/servers/webserver-2. And we have properties placed in some other locations like /apps/my-web-app1/app.properties and /apps/my-web-app2/app.properties.
Now good thing about this structure is that if I need to update any property, I just do the edit in the relative property and restart my web server. A downside of this is that I have to pass in paths to these properties file as system arguments to my web-server startup scripts (in my case, these are the catalina.sh files, yes I am using tomcats).
So my catalina.sh has line somewhere lying around something like
export JAVA_ARGS `-Dpath.to.properties.of.my-web-app2=/apps/my-web-app2/app.properties` ....
To read these properties, I have a Property Utility function that gets called by the StartupServlets of each application. The purpose of this function is to simply open up this file by reading the system property path.to.properties.of.my-web-app2 and puts these properties in something like a cache (a HashMap in my case) from where I can access them easily throughout the application.
I am loading my properties file using the class loader as follows.
Properties prop = new Properties();
prop.load(MyClass.class.getResourseAsStream("/Property.properties"));
Now, using this method I am able to read the properties file. I want to write some data to the property file. I don't know the path of the property file. How do I store the data to the property file then ?
Update
I tried the following, but it doesn't give me the correct path:
File propFile = new File("Property.properties");
System.out.println(propFile.getAbsolutePath());
I don't think you can in a generic way that would always work, because your properties file could be bundled inside a jar, etc. You can get the URL via getResource(String) and then do something with that URL, for example if it's a file URL, you could get the file name there.
URL u=MyClass.class.getResource("/Property.properties");
if ("file".equals(u.getProtocol()){
File f=new File(u.toURI());
}
But that wouldn't work in all cases.
I would write the modified value to a file in a well known location, and use the bundled Properties as the default value, that are overriden by the values in the file.
There are two parts to your question.
First, the reading part. You said: "I am loading my properties file ..." using the code you provided. This code treats the file as a "resource" and loads it using the class loader. The class loader mechanism in the Java Runtime comes into picture here. Roughly speaking, this mechanism searches for it in your application's current classpath and makes the input stream associated with first matching resource available to your code. It may be fine in your case, however, you should realize that if there are multiple properties files by the same name in different parts of your classpath (e.g. different JAR files having the same config file), then you may not know which file is being read. The only way to ensure that you are reading the right file from the classpath is to ensure that you have that config file in a unique place in your application's classpath.
This seems to work for you. Reading from a file is easier, than, say writing to a file.
In the second part, you want to write to a file. It's important to note that you should know the exact whereabouts of the file you are writing to. If you rather unknowingly convert it to an output stream, then you might end up trying to write to a stream that you are not allowed to write to. So, here, you should try to find the location (path) of the actual, physical file, for example, on a computer's hard drive. That path is something you should know before you write and run this program. Remember that a file always exists in a folder or a directory.
Your attempt:
File propFile = new File("Property.properties");
System.out.println(propFile.getAbsolutePath());
to find the location or path of the file you want to write to fails because when you do new File("Property.properties");, Java tries to refer to a file (does not do anything yet with the operating system) that resides in the Java Runtime's current working directory. This refers to the location given by System.getProperty("user.dir"). So, your propFile refers to a (hypothetical) file in that folder and the call to getAbsolutePath() prints its path. This is not the file that you want because you are trying to write to a file whose path you don't know. So, you should find the path of the file and then use a BufferedWriter backed by a FileWriter or BufferedOutputStream backed by a FileOutputStream to write to this file. Make sure that the file you want to write to exists and you have permission to write to it.
Essentially get the resource as an OutputStream, then pass it to the store() method of your Properties object.
Details here:
http://www.drdobbs.com/jvm/readwrite-properties-files-in-java/231000005
Anyone plz let us know what to do when we have some configuration file which is basically xml.I want to for example give the path to save the image(for my java program) in a folder from some config file (xml in my case).In that case where should the config file be kept.Rt now every thing is converted to jar file when i create a java standalone package.But i want to give some setting from xml file.What to do in that case.How is it possible.This article only provides to create a single jar file for java project but talks nothing about the configuration settings that u can provide from some external source.
Regards
Sagar
I'm not sure I fully understand your question, but if it is where to put the XML file with configuration information, you can place your xml file in the same directory as your jar file, and then pass the XML file name and path into the Jar on the command line when calling the Jar. If you're running it in Windows, this is often done using a shortcut. Then you can get the full path string for the Jar from the main method's String[] arg array that accepts the command parameters.
Sagar,
The fact your java program is a standalone package (.jar file) has no bearing on where your configuration file is stored. Your java package is a program and that program can read any file from the file system that it so desires; it does not have to be part of the code inside the IDE i.e. you don't have to write it when you write the program. What you do need is some way, when you start the program, to find and read said configuration file.
Depending on how you expect the program to be configured, you might put that file in a number of locations. For example, /etc/yourimageprogram/config.xml or c:\program files\yourimageprogram\config.xml or perhaps c:\users\Sagar\Application Settings\yourimageprogram\config.xml. Which you choose of those options really depends on what the use case is and that I can't help with.
However, there are some main points to reading any file:
Does it exist?
Are we allowed to open it for reading?
Are we allowed to open it for writing? Might want to know if we want to update the config?
In Java, typically, you would test this with:
File configfile = new File("C:\test.xml");
if ( configfile.exists() && configfile.canRead() )
{
// read the file
}
else
{
// decide what to do if no config exists.
// might be first run of app.
}
The next stage is to parse the file. There are a number of parsers available for XML including sax and org.w3c.dom. What you need to do is to use these to extract the information you require and store that in a class. Probably a singleton class as you're unlikely to have multiple configuration instances per instance of the program.
I suggest you read about XML Parsers and File Handling under Java. Also look at the File object. See all your options for file io in java. These should give you some indication of how to proceed.
I have a java desktop app and the issue of config files is vexing me.
What I want is for my distributable application folder to look like this:
MyApp/Application.jar
MyApp/SpringConfig.xml
MyApp/OtherConfig.xml
MyApp/lib
But at the moment SpringConfig.xml is inside Application.jar and I can't even find OtherConfig.xml programmatically.
I don't care how I set up the various files in my compilation path, so long as they end up looking like the above.
So..
where do i put the files in my dev setup?
and how do i access them programmatically?
thanks
the spring config file is related to the code and wiring of your application, hence it'd better be inside the jar, and should be subject to change by the users
(new File(".")).getAbsolutePath(); returns the absolute path of your jar - then you can load the OtherConfig.xml by a simple FileInputStream
if the SpringConfig.xml contains configuration data like database credentials, put them in an external application.properties and use a custom PropertyPlaceholderConfigurer to load the external file.
Answering the question "where do I put the files in my dev setup" is not possible because we don't know your environment.
Actually, if you want to be able to edit the config yourself (and not necessarily end-users), you can open the jar with any zip software (WinRAR for instance) and edit the config file from within the jar.
Update: as it seems you can't make the config files to be places out of the jar. Well, for a start, you can do it manually - whenever the .jar is complete, just remove the config file from inside and place it outside.
I typically create a structure where I have a src/ directory and then other directories exist at the same level. Some of those directories include:
lib/ - External Libraries
config/ - Configuration Files
resources/ - Various resources I use (images, etc)
At that same level, I then create an Ant script to perform my build so that the appropriate config files, resources, lib, etc are copied into my JAR file upon build. It has worked great for me up to this point and is a fairly easy to understand organizational structure.
Update: Accessing my config files is done, typically, by knowing their location and opening them up and reading them in the code. Because I use Ant to build, I make sure that my config files are in a location that I expect. So, for example, in a recent application I created, when I compile, my JAR file is in the top level directory (relative to the application release structure). Then, there is a "main" config file at that same level. And there is a "theme" config file that is in a themes folder.
To read the various files, I just open them up as I would any other file and read them in and go from there. It's nothing particularly fancy but it works well and it makes it easy to manually change configurations if I need to do so.
In dev mode, put them in source dir and they will be copied to your classes folder, you can then access them using classloader.
Example:
URL url = ClassLoader.getSystemResource("test.properties");
Properties p = new Properties();
p.load(new FileInputStream(new File(url.getFile())));
In Prod mode, you can make them part of your jar.
I know that you can use java.util.Properties to read Java properties files.
See: Java equivalent to app.config?
Is there a standard place to put this file? In .NET we put application.exe.config in the same directory as application.exe. The application looks for it here by default.
Java can be made to look for a properties file in the class path but I am struggling to understand the filename/path structure to use and how to use either a standard .properties format or XML format file.
Assuming I have an API packaged in org_example_api.jar (the root package is org.example.api). I don't want to put the properties file inside the jar as it should be editable by the user. I want the user to be able to put the required configuration properties in either a .properties or .xml file somewhere relative to the classpath so I can find it without needing to know anything about the ir file system structure.
Will this work on all systems:
/classpath/org_example_api.jar
/classpath/org/example/api/config.properties OR
/classpath/org/example/api/config.xml
Code:
java.util.Properties = ? //NEED SOME HELP HERE
This purely depends on the type of application you are developing.
1) If it is a web application the best place is inside the WEB-INF/classes/ folder.
2) If you are developing a standalone application there are many approaches. From your example I think the following structure will work.
/<dist>/org_example_api.jar
/<dist>/config.xml
/<dist>/run.sh
In the run.sh you can start the java application providing the current directory also in the classpath. Something like this.
java -cp .:org_example_api.jar ClassToExecute
3) If it is an API distribution it is up to the end user. You can tell the user that they can provide the config.xml in the classpath which should follow some predefined structure. You can look at Log4J as an example in this case.
The world is wide open to you here. The only best practice is what works best for you:
Whatever program the user is running can require the path to the properties file as an argument
Your application can be configured to look in the current directory for config.properties.
If the file can't be found, you could maybe fall back to the user.home directory, or fall back to wherever your application is installed.
Personally I usually have my applications attempt to read properties files from the classpath - but I'm not in a world where I have end-users update/change the file.
Whatever option you choose, just make sure you clearly document it for your users so they know which file to edit and where it needs to be!
You can put the properties file in a directory or JAR in your CLASSPATH, and then use
InputStream is = getClass().getResourceAsStream("/path/goes/here");
Properties props = new Properties();
props.load(is);
(I noticed you mentioned this in your OP, but others may find the code useful.)