I have a web application that reads content from a property file. When will this property file be loaded into memory. ie. Once I deploy the application with some content in the prop file, and after deployment , I change the contents of the prop file, will the changes be reflected or do I have to redeploy?
EDIT : An accessor class' static block reads content from the property file, which is a part of a deployed web application. Now after deployment, i change the property file contents. Will the accessor class read the changes or will it take up the old values?
EDIT2 : when the class is reloaded, will it surely take up the new modified file or rather take up the file cached during deployment(if at all it is cached)
Assuming that the property file is being loaded by the Properties class, then the property file will be loaded once when the Properties#load() method is called. It will not automatically be reloaded unless your application specifically supports reloading or if your web container restarts the web application during hot deployment.
update: Since the property file is loaded in a static initializer, then the property file will be reloaded when the class is reloaded (e.g. when the web app is hot deployed). If you want to debug this, a simple println() in the static initializer will show you when this happens.
It depends on the app server - generally, you'd have to redeploy. But some app servers, in certain configurations may monitor files and kick off a redeploy when they detect file changes. (as an example - I believe Tomcat will automatically redeploy when it detects file changes in exploded deployments.)
If this file is loaded by your class than I am pretty sure it won't reload it by it self.
If I were you I would have a separate thread that in given time intervals wakes up, checks whether the file modification date has changed and if it did than reloads it.
Apache Commons Configuration provides automatic reloading/saving of file-based configurations.
Related
Earlier I put my properties file within my classpath src/. Now I would like to put it within a folder called config/. This way the end users can actually modify the file by themselves.
However now my code below does not work anymore
ResourceBundle.getBundle("Messages", Locale.getDefault());
What I meant by the code doesn't work anymore is, after I deploy the application and I modify the Messages_en_US.properties the changes do not take place.
How can I achieve what I want ? Should I use getBundle at all ?
EDIT
I have added config folder into the classpath as well, but I am not sure if this is relevant. This is a plain Java application where I am not using Maven or any building tools.
By default, a ResourceBundle is only loaded when it is first requested, and reused for subsequent requests. You can throw away the cached ResourceBundles with ResourceBundle.clearCache();
Additionally, by default, ResourceBundles are loaded from the classpath. You must therefore ensure that the classloader in question does not cache the resource either. Or you can provide your own ResourceBundle.Control to load the properties file by whatever means you prefer.
Is there a way for a Servlet to do a hot re-deploy the webapp it is part of?
I know that I can configure Tomcat to do a hot re-deploy on changes to web.xml but I can't find any way to do the same from java code. I don't want tomcat to having to watch the web.xml for changes all the time.
I believe it can be done using JMX.
The Tomcat Manager is a web application that can be used interactively (via HTML GUI) or programmatically (via URL-based API) to deploy and manage web applications.
There is the link - http://tomcat.apache.org/tomcat-7.0-doc/deployer-howto.html
A Servlet has a life cycle that depends on the container. This is explained here
http://docs.oracle.com/javaee/5/tutorial/doc/bnafi.html
What this means is from the web.xml the container figures out a match depending on a request and if there is such a class that exists it loads it as a classloader resource. Once this has happened the instance stays loaded till the container is shutdown so replacing .class files wont actually achieve the "hot-deploy" unless you set the reloadable flag in the tomcat's context.xml
http://tomcat.apache.org/tomcat-5.5-doc/config/context.html#Common_Attributes
In any case, Tomcat or not, once a resource has been loaded by a ClassLoader changing the .class files wont exactly change the behaviour of the running jvm which you would probably know. So even deleting the class files from the file system also wont affect the running java process in ordinary situations.
However it may be possible that a servlet can start a background task that does a basic file copy of the new .class files you want to 'hot deploy' (if the context attribute 'reloadable' is true). This then forces these classes to be reloaded and so you achieve a hot deploy. So although this is out of the scope of what a servlet is designed to achieve the answer is yes.
Hope this helps.
I have multiple applications using log4j for their logging, each loading settings from separate log4j.properties loaded from the classpath (just a file on disk, not in a .jar or anything that would make it read-only). In each of these applications, I want to allow updating the log level through the regular UI.
I use a common utility class for this, which is shared between applications. I can do that for the lifetime of the app, but since the changes aren't persisted back out to the appropriate log4j.properties file, on next restart, it's reset to the specific level in the properties file.
Since it's just loaded from the classpath, I don't know the full path to the logfile in each application, and since it's a common class, I'd rather not hardcode paths. Is there a way to get log4j to write back its changes to its on-disk configuration?
I suggest you flip the problem on its head.
Always write changes to the log4j.properties file on disk, and then install the listener that checks for changes in that file and updates the appropriate log levels.
I have a java application. All I have with me is a set on class files. Iwant to replace one class file with a new one. Replacing the old class file with the new one and restrting tomcat is not reflecting the changes. How can I do this? I know its not a recommended way, but all I have is just one new class file.
I've done this the way you describe before, and Tomcat reflected the changes just fine after restart.
Perhaps your application's files are in multiple locations, and you aren't replacing the class file in the correct deployment? Make sure if Tomcat is auto-expanding the WAR that you are replacing it in the expanded folder of files. If you app is deployed somewhere besides webapps, double-check where your <Context> is pointing to for its doc base.
You can configure Tomcat and make your webapp "reloadable". To do so, add reloadable=true to the <Context> element of your webapp.
Set to true if you want Catalina to monitor classes in /WEB-INF/classes/ and /WEB-INF/lib for changes, and automatically reload the web application if a change is detected. You can use the Manager web application, however, to trigger reloads of deployed applications on demand.
I'm using jboss server and having all my classes inside a jar file.
Now if I change any of the java files, I need to replace the class file in the jar and have to restart the server.
Is there any way to dynamically load the newly created class file without the server restart?
Thanks in advance.
I've had great success with JRebel (http://www.zeroturnaround.com/jrebel/). This is a very good product that enables seamless class reloading for the vast majority of modifications you can make to a Java class. There is no restarting of the app sever or even the application required, classes simply reload behind the scenes.
It comes with a free 30 day trial so you can see if it works for you.
(Disclaimer: I'm in no way connected to Zero Turnaround)
It appears that you have to trick the server into reloading your application by modifying web.xml -- meaning you can open web.xml in an editor enter a space then delete and save the file or change the modification date on the file with a utility.
JBoss doesn't seem to have a handy feature like Tomcat's reloadable="true" flag in Tomcat's Server.xml file.
there are a number of solutions, none of them particularly clean or easy.
As stated, changing the web.xml will cause the context to reload and hence refresh the source code and this can be done without restarting the server. This works because "WEB-INF/web.xml" is configured as WatchedResource in the TOMCAT/conf/Context.xml file. That is every context inherits this setting and automatically watches this file. You can remove this behaviour but you can also provide WatchedResource values in your own web.xml to watch additional files. While I don't recommend it, you could add all of your class files to this and the context would reload when you change one file.
A better solution relies on the fact that a Class can be reloaded when you discard the ClassLoader that loaded the Class. Therefore if you manage your hot swappable code in your own ClassLoader then you can refresh your code without restarting the context if you refresh the ClassLoader. Easier said than done, unfortunately but it may get you started.