change a config.properties file in a jar / war file in runtime and hotdeploy the changes ?
my requirement is something as follows, we have a "config.properties" in a jar/war file , i have to open the file through a webpage and after the user has made necessary changes to it, i have to update the "config.properties" in jar/war file and hot deploy it. can we achieve this feat ? if so can you please point me to relevant sites/documents so that i can jumpstart on this.
I will strongly recommend your architecht rethink this solution. What you describe should be done through JNDI or a similar technique, not through reloading properties.
Deployments should be considered static - that any given web container allows for magic trickery should not be depended on, and WILL break some day (most likely at the most inconvenient time).
You've got a couple of problems off the top of my head:
ensuring that nothing is holding static references to a java.util.Properties that has previously loaded your config.properties file.
most servlet engines will unpack your war to a working directory so the properties file you load won't be the one in the war, it will be the unpacked one. This means your changes
will be overwritten when you restart the servlet engine because this is typically one of the points the war is unpacked.
While these problems aren't insurmountable I've always found it much easier to implement this sort of behavior by storing the properties in JNDI (as Thorbjørn suggests) or a database (while being careful about the static references I mentioned in point 1).
The JNDI/database solution has the nice side effect of easing deployment into multiple environments because each typically has it's own registry/database.
Even that I agree with the comments explained before, I could suggest one solution:
Apache Commons Configuration extension gives you the posibility to do something like:
config.setReloadingStrategy(new FileChangedReloadingStrategy());
That could make the trick to change the configuration file on a runtime basis with no code at all.
However, like JNDI and other methods of web application configuration, the security is a concern. Be careful on which parameters you can/must be able to configure.
Related
I am trying to migrate from log4j1 to logj2.
I have a WLS server with two ear files. Ear1.ear and Ear2.ear. Both have similar code and for logging, they use the same logger name. In log4j1, there were two different config files loggingconfigEar1.xml and loggingconfigEar2.xml writing to ear1.log and ear2.log respectively.
I am trying to implement the same in log4j2, but not able to find an easy way out. Is it possible to have two different ears with same logger name have its own individual log files. Right now, I am initialising the config file through the System Property log4j.configurationFile and it does not work.
The only other option that I can think of is, have separate logger names for the two ears. But that would involve code change in quite a few places and I want to have it as a last resort option.
FYI, there was a lot of customisation done for log4j1 which I have avoided in the migration either by scrapping the functionality or by rewriting code. I am not sure how exactly this separate logging was achieved in log4j1.
In Grails 2 we used the "External configuration plugin", which included the method checkNow() for checking and refreshing values from an external config file.
Does it exist a simple approach for doing something similar in Grails 4+? I have seen references to Spring Cloud Config Server, but it seems a bit overkill for me. All I really want to do is be able to (now and then) update a config value in runtime. It could also be purely by a few lines of code, and does not have to originate from changes in the config file. This would avoid having to restart our server for minor changes in config. Thanks!
I'm replying to myself with a ridiculously simple answer: "just change it". Using the console plugin (or any other form of code execution), I can just assign grailsApplication.config.any.property a new value. It won't persist and it won't update any listeners or anything. But it is a glaringly obvious solution that I just assumed wouldn't work due to the getProperty() calls (I interpreted the name as reading from file) and googled discussions about Spring Cloud Config.
So, move on... nothing to see here. Just mild embarrassment :-P
Background
We have an existing webapp, built with Struts 2 and Freemarker, of which I’ve created a variation by copying some of the code and templates. Kludgy, but manageable. We will however soon be making quite a few other variants (which need to be individual WARs), making copying untenable. My thought is to instead put all the shared stuff into a jar included with each webapp: the common files could be maintained in one place, and even better a given webapp could override files from the classpath. So far I've been able to do this with the code, but the Convention plugin is making it difficult to do the same for the Freemarker templates.
Problem
Thus far our webapp has relied on Convention to find the Freemarker “action results” (i.e. templates) for actions at application start-up, saving us from having to tediously annotate each of them. If I've traced things correctly, the class DefaultResultMapBuilder is responsible for finding the actions results; in particular, the method createFromResources looks in the webapp and then on the classpath for template files matching our actions.
This is exactly what I want – except that we put our templates under /WEB-INF to protect them from outside access (using the struts.convention.result.path constant in our Struts configuration). This has worked fine until now, with ALL template files located under /WEB-INF, but it’s not working with files also on the classpath. DefaultResultMapBuilder can certainly find files on the classpath, but only when webapp templates are under the context root directly, as any classpath templates have to be in a package structure equivalent to the directory structure of templates under the context root. For action results to be found when “struts.convention.result.path" starts with “/WEB-INF/” would require a root package called “web-inf” – but of course hyphens are not allowed in package names.
(Note that this issue is independent of the TemplateLoader classes that are later used to actually grab the template files. The loading process is readily configurable to look in many places – but the app never gets that far if the ‘action results’ are not found at startup. It would be nice if both processes used the same configuration...)
Solutions?
So… I could move all our templates outside of /WEB-INF but really I’d rather not. Or I could provide specific annotations for each action class, and again I’d rather not (and indeed it might suffer from the same issue).
Or I could make my own implementation of ResultMapBuilder by copying and very slightly changing DefaultResultMapBuilder (every member in the latter is private, so I can't extend the class and change just the relevant parts – alas!), and then figure out how to override the "struts-plugin.xml" Struts config file (to change the org.apache.struts2.convention.ResultMapBuilder bean), and thus I could get Convention to ignore "/WEB-INF" when looking on the classpath. Or perhaps better, to always prefix the path with "/WEB-INF/" when looking in the ServletContext.
But maybe there's an easier way? Some undocumented bit of configuration magic?
I needed some templates to render some code for users to paste. I put these into
/project-dir/grails-app/resources/templates/quickInstallCode.html
Then I tried accessing them using their relative path (grails-app/resources/templates/quickInstallCode.html), and it worked great.
When we then deployed the application to a Tomcat Server, using a .war file, the paths began pointing to a wrong location.
ERROR call, Template file /var/lib/tomcat6/grails-app/resources/templates/quickInstallCode.html not found.
I assumed, that Grails, giving good defaults for everything would handle this mess for me, but it seems like it does not.
I also tried this call, and it seemed to work great, but when deployed, the BuildSettingsHolder did not contain build Settings, which resulted in a fatal error.
BuildSettingsHolder.settings.baseDir.toString()
http://grails.org/doc/latest/api/grails/util/BuildSettingsHolder.html
http://grails.org/doc/latest/api/grails/util/BuildSettings.html
I am pretty frustrated that I cannot get this easy task to work, but the reason that this is so complicated seems to be that all Files are encapsuled in a WAR and not unpacked on the Server.
So the Questions are:
Where in your Project would you put
Files like this?
How to get a
reliable and stable way to access
this files? I just need a stable path to a base directory, without having to hardcode something in the configuration ... This cannot be so hard.
I have 2 solution to propose for this situation:
Save the template in the database, in a setting table. This way guarantees that nothing can go wrong.
You can consider using the resource folder like Sachin & Nirmal has proposed. About security, I think you can configure SpringSecurity Plugin to protect the specific resources, so that it can only be accessed by the site user.
Take a look at this link and try to use the getResource that spring provides. Its way more flexible and configurable.
def filePath = "resources/file.txt"
def appHolder=ApplicationHolder.application.parentContext.getResource("classpath:$filePath")
By the way Conf is on the root of the classpath, you can stick the files in src/java or src/groovy.
I keep my static resources in web-app folder and access them like this
ApplicationHolder.application.parentContext.servletContext.getRealPath("quickInstallCode.html")
// quickInstallCode.html should be in web-app folder.
I'm investigating Grails vs. other Agile web frameworks, and one key use case I'm trying to support is the ability to modify controllers and install plugins post deployment. It appears that this isn't possible with Grails, but I want to make sure before I write it off.
As far as modifying controllers goes, it would be sufficient if the Groovlet behavior existed (compile-on-demand).
As far as plugin installs go, I understand this may be a long shot, but I thought I'd check to be sure.
For your information, I need this because I work on a product that requires a little site-specific customization, such as adding validation of simple meta-data, integrating with customer security environments, and maybe even including new controllers/pages quickly.
Out of the box, no, grails doesn't really support what you want. There may be ways to customize it but I've never looked into it. A PHP framework might be more of your ally since there is no real deployment process other than copying PHP files to a location.
That said, I personally would prefer a strict set of deployment policies. And honestly, deploying changes with Grails is as simple as running the 'grails war' command and copying that war to your servlet container. The site's downtime is negligible and if you have multiple web servers with a load-balancer, your customers should never see down time due to deployments.
Although it's not recommended for complex coding; You could execute groovy code from a string that you could store in database or a file on the fly at run time:
check out Groovy template engine:
http://groovy.codehaus.org/Groovy+Templates
but even then, you are still limited on what you can do or can't do let alone debugging will lack. you may want to consider an interpreted language; few to mention PHP/Perl/Coldfusion.