Is there a way to override at runtime the value of a property defined in a message bundle?
My grails application contains a property in the messages.properties file:
page1.para1.text=Some text to display to the user
My Config.groovy defines the following config location:
grails.config.locations = [ "file:${userHome}/.myApp/myApp-config.properties" ]
I currently use this approach to override Config.groovy properties (like db connections, etc), but it doesn't seen to apply to message bundle properties.
I was hoping/expecting to just make sure that the myApp-config.properties file contains my new property value, restart the Tomcat server where my app is deployed and it would get picked up and displayed on my page:
page1.para1.text=Some DIFFERENT text to display to the user
Grails docs on Internalization/Message bundles grails i18n doesn't suggest if this is possible or not.
Obviously, I'm trying to achieve this change without the need to recompile and redeliver my Grails application.
Any ideas?
Thanks in advance.
When you are already live and don't want to create a new .war file:
I'm not sure, but the .war file can be found unzipped on the server. You might try to replace the message files directly on the server, but a restart of the app might be necessary. But I wouldn't advice doing so.
If you need to often change the message bundles at runtime, I guess it would make sense to store them in the database. But that means that you have to change your code a little bit and redeploy it once. There is a blog entry which describes how to do it: http://graemerocher.blogspot.de/2010/04/reading-i18n-messages-from-database.html
Another SO question handles the case that you want to store changes to the messages in a DB but fall back to the files:
Grails i18n From Database but Default Back To File
hth
In theory you should be able to replace the messageSource bean with a ReloadableResourceBundleMessageSource inside Resources.groovy. This way you can not only point it to a new location but also declare how often they should be invalidated as cached values.
Related
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.
I have an EJB that plays the role of my web service class too. I use Oracle Weblogic 12.1.2 as JavaEE container.
Here is the code of that class:
#Stateless
#WebService(serviceName="MyService")
#Policy(uri = "Wssp1.2-2007-Https-UsernameToken-Plain.xml", attachToWsdl=true)
#XmlAccessorType(XmlAccessType.FIELD)
public class MyWebServiceBean{
// some web methods ...
}
The attached policy and its corresponding wsse tags is properly can be seen in generated WSDL file. However, there is a IncludeTimestamp tag in the generated file that forces clients to send Timestamp in their request. As in my environment clients may have different times, I perefer not to force them to send the time! Then I simply omit the IncludeTimestamp Tag from the server wsdl and everything goes well after that! But I do not want to handle it by hand. Is there any setting in weblogic 12.1.2 to configure existence of mentioned tag?
After a lot reading and searching for this matter i found that we should create Custom Policy. Firstly we should find the xml file of the desired policy. Flow this post to do so. Then we should edit it and copy the edited version in our classpath and for #Policy annotation we should use new address of our xml file! That's it.
What are the minimal properties that must be set inside a Grails (2.3.6) app's BuildConfig.groovy file?
According to the documentation:
Grails has a set of core settings that are worth knowing about. Their defaults are suitable for most projects, but it's important to understand what they do because you may need one or more of them later.
However this doesn't necessarily confirm that they all have defaults. So I ask: is there a minimal set of properties for this file?
You don't have to set anything in here. If your app uses the default database (H2), the default Grails plugins, and has no JAR dependencies other than those provided by Grails, you don't need to make any changes to it.
However, for most applications the above is not true.
I am new to Grails and I have inherited an existing application. I have a big file message.properties that I would like to prune, in order to remove keys that are no longer used.
In Django there is a command makemessages that goes through all codebase and collects all strings that need translation, adding them to the messages file and commenting out the entries that no longer exist. Is there a similar tool for Grails? If it helps, the project is based on verions 1.3.9.
There is no such tool, but you can create your own gant script. Take a look at getting a list of all i18n properties used in a Grails application and process this list.
I'm having some trouble merging the localization satellite assemblies into the plugin DLL for CRM2011.
Either that, or I don't know how to use the merged resources afterwards.
I create a few plugins and create a basic resource file (default - English) and one for a specific culture (at the time of writing it's for Polish localizations, but later I'll need to add French as well).
I make sure not to sign the assembly itself, as ILMerge will sign the finished assembly itself.
This is the command I use to merge the extra satellite assembly:
ilmerge /targetplatform:v4,C:\Windows\Microsoft.NET\Framework\v4.0.30319 /log:log.txt /keyfile:KeyFile.snk /out:Plugins.dll DynamicsCRM2011.Plugins.dll pl-PL\DynamicsCRM2011.Plugins.resources.dll
As you can see, the plugins are in .NET 4.0 and I've got the required .config file for ILMerge to use the required assemblies for merging.
The generated file appears fine, I can register it with CRM plugin-registrator, add new steps and so forth.
However, it will always use the default language. I've tried changing the System.Threading.Thread.CurrentThread.UICulture, but this didn't help. When I created a ResourceManager class and used GetString("ErrorMessage", new System.Globalization.CultureInfo("pl-PL")), I got an Exception that the specified ResourceManager doesn't know what to do with the specified culture.
I know of this question here. However, the posted solution seems to be an old one. The generated resource .cs files do not use a ComponentResourceManager. Also, parts of the code posted there have been marked as deprecated.
I'm not really sure what I'm am to do now, or how to further debug this, as I have very little experience when it comes to working with assemblies themselves. Please, help me get those satellite assemblies under control.
Update:
I've been working with sandbox plugins for a while now, and thus I no longer have access to things such as CurrentCulture (or at least I cannot change such things). I've tried tackling this problem once more: I've created a simple plugin which is fired when a new Account is saved. Nothing fancy. Here's the actual plugin code:
ResourceManager rm = new ResourceManager(typeof(Properties.Resources));
var s = rm.GetString("ErrorAlreadyPosted", new System.Globalization.CultureInfo("pl-PL"));
throw new InvalidPluginExecutionException(s);
The code no longer throws an exception about not being able to find the specified culture... also the code obviously throws an exception at the end, but the important thing is WHAT the exception message is. I'd expect it to be in Polish.
Alas, it is not. The string returned by GetString is still in English.
The command I used for ILmerge is the same as before, but with the /lib parameter specified so that I don't have to copy all the CRM SDK dlls...
Apparently it is not possible to read resources from with the context of a Plugin.
Read up on MSDN: http://msdn.microsoft.com/en-us/library/hh670609.aspx#BKMK_UseXMLWebResourcesAsLanguageResources
Quote: When a plug-in requires localized text, you can use an XML web resource to store the localized strings so the plug-in can access them when needed. The structure of the XML is your option, but you may want to follow the structure used by ASP.NET Resource (.resx) files to create separate XML web resources for each language. For example, the following is an XML web resource named localizedString.en_US that follows the pattern used by .resx files.
This is all I know so far - have yet to build my own solution for localization of a crm plugin.
If you use a reflector tool to look at the generated assembly, do you see your resource(s) embedded correctly? You may be experiencing the bug as outlined in the link you posted.
Try setting Thread.CurrentThread.CurrentUICulture and\or Thread.CurrentThread.CurrentCulture.
Also try hooking into the AppDomain.CurrentDomain.AssemblyLoad and\or AppDomain.CurrentDomain.AssemblyResolve to debug which assemblies are being attempted to load and from where. You might need to customize their behavior so that instead of loading an external assembly to load an internal resource instead.
You can try embedding project references as resources instead of using ilmerge as well.
See this: http://bartlomiej.net/dotnet/embeded-assembies-into-an-executable/
The way we eventually handled this is by adding the localization XML files (generated by Visual Studio) as CRM resources, and created a bit of custom code which seeks the appropriate resource and then seeks the localization text inside.
It's, obviously, not as simple as just using the generated C# localization class, and requires some prep work. However, with that prep-work in place and with using nameof it's now almost as simple as the aforementioned resource classes.