how to read config.properties j2ee - java

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.

Related

mule/java - reading a property file which is inside of jar dependency from java class

Here my requirement is, I have created one mule application which has java class. Some of the values which I don't want to keep it as a hard-coded so I am trying to externalize it. I kept this values in mule-app.properties file and used FileInputStream as below.
String propFileName = "src/main/app/mule-app.properties"
Properties property = new Properties();
property.load(new FileInputStream(propFileName));
But this code needs to be deployed on CloudHub; there its failing saying that file not found. I Tried with give path of the file name as
String propFileName = "target/classes/mule-app.properties"
for both the cases its running fine locally but gives same results on CloudHub as "File Not Found".
What could be the solution?
Another thing is I have a common code in which we are keeping all the properties related to different environment. Packaging of this common code is in the form of jar. So, can I keep properties which I am using in above code and read it from jar itself.
If Yes, then How?
If you want to deploy in cloudhub and externalize your properties file better use Cloudhub properties tab to externalize the values.
ref:- https://docs.mulesoft.com/runtime-manager/deploying-to-cloudhub#properties-tab
And in Java class you can pick the properties value using :- System.getProperty("yourpropertykey")
simple as that :)
Regarding keeping properties file in common jar app, you need to use <context:property-placeholder/> to pick up the properties file from the classpath of the common jar application and can use it in your host application mule flow
To achieve this we can do one thing. Using expression component set variable for each property you want to fetch.
<expression-component doc:name="setVariable"><![CDATA[flowVars.clientId="${poc.clientId}";]]></expression-component>
This flow Variable is accessible in Java class irrespective of where it is been kept i.e. mule-app.properties or on cloudhub run time properties.
In Java class, using below code we can read this Flow Variable.
String clientId = eventContext.getMessage().getInvocationProperty("clientId");
Use the below sample code it should work.
FileInputStream fi = new FileInputStream(System.getProperty("C:\Users\userName\
AnypointStudio\workspace\test\src\main\resources\my-app1.propertie");
Properties prop = new Properties();
prop.load(fi)

What if values in properties files are subject to change?

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.

System.getProperty("catalina.base") There can be scenario where client may use any other server

I am reading a properties file from the Tomcat\conf\somename.properties directory using
String demo = System.getProperty("catalina.base") +
File.separator + "conf" + File.separator + "somename.properties";
This is working perfectly fine with Tomcat. But, there can be scenario where client may use any other server like Glassfish or Websphere, in that case I won't be able to get System.getProperty("catalina.base").
How should I solve it properly? I'm able to do that using ResourceBundle but for that I have to keep my properties file in my build, which I don't want. I just want to read my properties file from outside my build.
There are basically two ways.
Just add its path to the runtime classpath so that you can get it from the classpath the usual way. In case of Tomcat, you can add external folders to the runtime classpath by specifying it in the shared.loader property of /conf/catalina.properties. E.g.
shared.loader = ${catalina.home}/conf
Or better, don't be server-specific
shared.loader = /path/to/folder
Other servers also supports adding external folders to the classpath, consult their documentation.
This way you'll be able to get an InputStream of it from the classpath as follows:
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("/config.properties");
Properties properties = new Properties();
properties.load(input);
// ...
Add another server-independent system property yourself, you can set as a VM argument.
-Dconfig.location=/path/to/folder
In case of Tomcat, you can set it as JAVA_OPTS environment variable, or edit the catalina.bat startup file or edit the Windows Service settings (when it's installed as Windows Service), etc. Other servers supports similar constructs as well.
This way you can obtain it as follows
File file = new File(System.getProperty("config.location"), "config.properties");
InputStream input = new FileInputStream(file);
Properties properties = new Properties();
properties.load(input);
// ...
Either way you choose, when distributing your application, you should document it properly so that the serveradmin can configure it accordingly.
Unrelated to the problem, the ResourceBundle is not the right way to read configuration properties files. It's intented for localized content for internationalization.
First use the ServletContext.getServerInfo() to determine the container. Then based on the container, use container specific ways of getting the information. For e.g. if the method returns "tomcat*" then you can use catalina.base thing, if it returns glassfish, then use some glassfish specific ways, and so on.
Simply put, don't rely on catalina.base, that is your first problem :)
Or, more precisely, the java servlet api gives you access to resources inside your web application, so your app is truly portable (not only between servers, but also you can put it anywhere on the file system, zipped as a war or exploded)
Say you put your file at <webapp-root>/WEB-INF/somename.properties, then this is what you do in your servlet, listener, or other web-aware classes:
getServletContext().getResourceAsStream("/WEB-INF/somename.properties");
See similar question here.
Another alternative is to use regular java api to search for files in your classpath, e.g. this.getClass().getResource("/somename.properties"). In the case of a web application, this will find such a file located under /WEB-INF/class/ or any jar under /WEB-INF/lib/.
Finally, if you can't put the file inside your web application, you can put it anywhere on the hard drive and use some config param (e.g. a system property, or a context parameter in web.xml) to refer to it.

Creating a standalone package in java and take some settings from the configuration file

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.

Simulate app.config for Java?

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.)

Categories