Is it possible to write on a properties file inside a .war? - java

I see a lot of how to read the file or locate it, but I've been trying to run Properties.store() and it simple does not modify the file.
I can read, get and set properties but store doesn't work. Should it work or is not meant to work?
If it doesn't work, how can I modify the file, so when the server restart those properties do not get lost?

No; it's inside a WAR.
Technically you could un-zip it, modify it, zip it back up. But don't.
Properties like that should be stored in a DB, in JNDI, or in a file outside of the war.

Property files bundled inside a JAR are not meant to change because they make part of the distribution.

I wouldn't mess with unzipping/rezipping a WAR file, just as a piece of advice. I have done that in the past and it did not work so well.

Related

Is this the best way to keep .properties file out of WAR file?

To externalize a .properties file, currently I am keeping it in a file system say
C:\test\UI\properties
and I have created a Environment variable $PROP_LOCATION which points to above file location. So whenever I need to change properties, just I go to that location edit properties and refresh the application. It works like a charm.
So is this the best way? Or is there any other way you professionals suggest me to keep properties file out of war file?
Note: The above thing works fine in both unix and windows environment as I have a "if" condition, if one of the environment variable not found I will check for another environment variable.
I agree that just packaging the properties file with your application makes the most sense. If you have some valid reason not to do that, your solution seems fine as long as in deployment the file is placed in a location that your application has access to and is not exposed to the Internet.
I am doing something somewhat analagous to you. In an application I'm running, there is a page of announcements and other messages that I want users to see, but to make it easier for me and others to edit these messages, they are loaded from another place on the server, not even in the Tomcat folder. I can then easily edit the messages without even re-deploying.
I usually reference external properties files by adding the directory to the classpath.
For example, if example.properties is in path C:\test\UI\properties directory, I call JVM as follows:
java -classpath C:\test\UI\properties MyJavaProgram
Inside the Java code, you can load the properties via the following mechanism:
Properties p = new Properties();
p.load(getClass().getClassLoader().getResourceAsStream("/example.properties"));
I suggest to use the ReloadableResourceBundleMessageSource of spring
Check it out: http://static.springsource.org/spring/docs/1.2.9/api/org/springframework/context/support/ReloadableResourceBundleMessageSource.html
And as for placing the properties files, I don't think keeping them outside application is good idea. You should package them in war anyway, as they are logically part of your application.
And since you are reloading the application, you can use maven task to build, deploy and reload the app on server everytime the properties change.

Self exploding and rejaring jar file during execution

I am currently working on a program to make sitting charts for my teacher's classroom. I have put all of the data files in the jar. These are read in and put in to a table. After running the main function of the program, it updates the files to match what the tables values are. I know I need to explode the jar and then rejar it during excution in order to edit the files, but I can't find any explination on how to rejar during excution. Does anyone have any ideas?
Short answer:
Put data files outside of the binary and ship together with JAR in a separate folder.
Long one:
It seems like you are approaching the problem from the wrong direction. JAR file is something like an executable (.exe) on Windows platform - a read only binary containing code.
You can (although it is a bad practice) put some resources like data files, multimedia, etc. inside JAR (like you can inside .exe). But a better solution would be to place these resources outside of the binary so you can switch them without recompiling/rebuilding.
If you need to modify the resources on-the-fly while the application is running, you basically have no choice. The data files have to be outside the binary. Once again, you'll never see a Windows .exe file modifying itself while running.
Tomasz is right that the following is bad practice, but it is possible.
The contents of the classpath are read into memory during bootstrapping, however the files are modifiable but their changes will not be reflected after initialisation. I would recommend putting the data into another file, separate to your class files, but if you insist on keeping them together, you could look at:
JarInputStream or ZipInputStream to read the contents of the JAR file
Get the JarEntry for the appropriate file
Read and modify the contents as you desire
JarOutputStream or ZipOutputStream to write the contents back out
Make sure you're not reading the resource through the classpath and that it's coming from a file on disk / network.

Store text files safely in JAR

Is there any way in Java to store external files (inside jar) safely? Java files are compiled to .class files and not readable.
I'm planning to use this meganism to store sql files, which hold queries, however i dont want those to be readable when one extracts the jar. External files are pre, cause we then have syntax highlighting while developping instead of putting them into a string.
A jar file is pretty much just a .zip file, so you can put whatever you want in them. There's no built-in encryption, so if you're trying to make the SQL files non-readable, you'll have to encrypt them (and then unencrypt in your code). I don't understand what you mean by "External files are pre, cause we then have syntax highlighting while developping instead of putting them into a string."
Yes, people do this all the time. Just add the files to the jar, and then access them with
getResourceAsStream. If you build with maven, you just plop them into src/main/resources to get them into the jar.
Of course you can put them in the Jar. Once there you can get at them by using the ClassLoader's getResourceAsStream method.
The challenge is to prevent other people extracting them. If your code can read them, so can someone else. What are your requirements here?

Save something into JAR

I have a java app, that needs to save and load user settings. I want to save them in a file located in the JAR file, how could I achieve this?
That's not possible. Rather consider using java.util.prefs.Preferences which is designed for exactly this purpose. See also this little guide.
This is not a sensible course of action.
A JAR file is basically just a ZIP file. To rewrite its contents you need to extract them in full, make changes as needed and then write them to a new file that replaces the old one.
If the program that is going to do this is the same one as that contained in the JAR file, this becomes impossible as the file is write protected during execution.
You'd be better advised to store your configuration elsewhere.
That is not the way to store preferences as others said.
If you has to do it that way then :
Locate the JAR from code: How to get the path of a running JAR file?
Unjar the contents to temp folder
Modify in the temp folder
Jar temp folder to the new JAR file.
To add to what Kris said, most security experts will tell you that it's generally a bad security practice to allow end-user applications to modify their own code. What you're asking for would require that.

What is the best place to store a configuration file in a Java web application (WAR)?

I create a web application (WAR) and deploy it on Tomcat. In the webapp there is a page with a form where an administrator can enter some configuration data. I don't want to store this data in an DBMS, but just in an XML file on the file system. Where to put it?
I would like to put the file somewhere in the directory tree where the application itself is deployed. Should my configuration file be in the WEB-INF directory? Or put it somewhere else?
And what is the Java code to use in a servlet to find the absolute path of the directory? Or can it be accessed with a relative path?
What we do is to put it in a separate directory on the server (you could use something like /config, /opt/config, /root/config, /home/username/config, or anything you want). When our servlets start up, they read the XML file, get a few things out of it (most importantly DB connection information), and that's it.
I asked about why we did this once.
It would be nice to store everything in the DB, but obviously you can't store DB connection information in the DB.
You could hardcode things in the code, but that's ugly for many reasons. If the info ever has to change you have to rebuild the code and redeploy. If someone gets a copy of your code or your WAR file they would then get that information.
Putting things in the WAR file seems nice, but if you want to change things much it could be a bad idea. The problem is that if you have to change the information, then next time you redeploy it will overwrite the file so anything you didn't remember to change in the version getting built into the WAR gets forgotten.
The file in a special place on the file system thing works quite well for us. It doesn't have any big downsides. You know where it is, it's stored seperatly, makes deploying to multiple machines easy if they all need different config values (since it's not part of the WAR).
The only other solution I can think of that would work well would be keeping everything in the DB except the DB login info. That would come from Java system properties that are retrieved through the JVM. This the Preferences API thing mentioned by Hans Doggen above. I don't think it was around when our application was first developed, if it was it wasn't used.
As for the path for accessing the configuration file, it's just a file on the filesystem. You don't need to worry about the web path. So when your servlet starts up it just opens the file at "/config/myapp/config.xml" (or whatever) and it will find the right thing. Just hardcodeing the path in for this one seems pretty harmless to me.
WEB-INF is a good place to put your config file. Here's some code to get the absolute path of the directory from a servlet.
public void init(ServletConfig servletConfig) throws ServletException{
super.init(servletConfig);
String path = servletConfig.getServletContext().getRealPath("/WEB-INF")
Putting it in WEB-INF will hide the XML file from users who try to access it directly through a URL, so yes, I'd say put it in WEB-INF.
I would not store it in the application folder, because that would override the configuration with a new deployment of the application.
I suggest you have a look at the Preferences API, or write something in the users folder (the user that is running Tomcat).
The answer to this depends on how you intend to read and write that config file.
For example, the Spring framework gives you the ability to use XML configuration files (or Java property files); these can be stored in your classpath (e.g., in the WEB-INF directory), anywhere else on the filesystem, or even in memory. If you were to use Spring for this, then the easiest place to store the config file is in your WEB-INF directory, and then use Spring's ClassPathXmlApplicationContext class to access your configuration file.
But again, it all depends on how you plan to access that file.
If it is your custom config WEB-INF is a good place for it. But some libraries may require configs to reside in WEB-INF/classes.

Categories

Resources