Set value in message.properties file from grails service - grails

I want to set values to message.properties file.
I have already done it in java like the following:
Properties emailErrorMsgProp = new Properties();
emailErrorMsgProp.load(new FileInputStream("grails-app/i18n/messages.properties"));
emailErrorMsgProp.setProperty("ma_email_error",result.callStatusMsg.toString());
emailErrorMsgProp.store(new FileOutputStream("grails-app/i18n/messages.properties"), null);
I also want to make it language specific.i have language specific properties files.
I would like to do the same thing in grails Service, but how would I go about it?

Try this:
def writeToProps(key, value) {
new File("grails-app/i18n/messages.properties").withWriterAppend { out ->
out.writeLine "\n${key}=${value}"
}
}

You should take a look at ReloadableResourceBundleMessageSource.

Related

How to customize an existing Grails plugin functionality, modifying behavior of doWithSpring method

I am new to grails and while working with Spring Security LDAP plugin it was identified that it accepts the ldap server password in plain text only. The task in hand is to pass an encrypted password which is decrypted before it is consumed by the plugin during its initialization phase.
I have already searched for all possible blogs and stackoverflow questions but could not find a way to extend the main plugin class to simply override the doWithSpring() method so that i can simply add the required decryption logic for the Ldap server password. Any help here will be appreciated.
I have already seen and tried jasypt plugin but it also does not work well if the password is stored in some external file and not application yml. So I am looking for a solution to extend the Spring security plugin main class, add the required behavior and register the custom class.
EDIT
Adding the snippet from Grails LDAP Security plugin, which I am trying to override. So If i am successfully able to update the value of securityConfig object before the plugin loads, the purpose is solved.
Some snippet from the plugin:
def conf = SpringSecurityUtils.securityConfig
...
...
contextSource(DefaultSpringSecurityContextSource, conf.ldap.context.server) { // 'ldap://localhost:389'
authenticationSource = ref('ldapAuthenticationSource')
authenticationStrategy = ref('authenticationStrategy')
userDn = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**password = conf.ldap.context.managerPassword // 'secret'**
contextFactory = contextFactoryClass
dirObjectFactory = dirObjectFactoryClass
baseEnvironmentProperties = conf.ldap.context.baseEnvironmentProperties // none
cacheEnvironmentProperties = conf.ldap.context.cacheEnvironmentProperties // true
anonymousReadOnly = conf.ldap.context.anonymousReadOnly // false
referral = conf.ldap.context.referral // null
}
ldapAuthenticationSource(SimpleAuthenticationSource) {
principal = conf.ldap.context.managerDn // 'cn=admin,dc=example,dc=com'
**credentials = conf.ldap.context.managerPassword // 'secret'**
}
You don't need to override the doWithSpring() method in the existing plugin. You can provide your own plugin which loads after the one you want to affect and have your doWithSpring() add whatever you want to the context. If you add beans with the same name as the ones added by the other plugin, yours will replace the ones provided by the other plugin as long as you configure your plugin to load after the other one. Similarly, you could do the same think in resources.groovy of the app if you don't want to write a plugin for this.
You have other options too. You could write a bean post processor or bean definition post processor that affects the beans created by the other plugin. Depending on the particulars, that might be a better idea.
EDIT:
After seeing your comment below I created a simple example that shows how you might use a definition post processor. See the project at https://github.com/jeffbrown/postprocessordemo.
The interesting bits:
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomeBean.groovy
package demo
class SomeBean {
String someValue
}
https://github.com/jeffbrown/postprocessordemo/blob/master/src/main/groovy/demo/SomePostProcessor.groovy
package demo
import org.springframework.beans.BeansException
import org.springframework.beans.MutablePropertyValues
import org.springframework.beans.PropertyValue
import org.springframework.beans.factory.config.BeanDefinition
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.factory.support.BeanDefinitionRegistry
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
class SomePostProcessor implements BeanDefinitionRegistryPostProcessor{
#Override
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinition definition = registry.getBeanDefinition('someBean')
MutablePropertyValues values = definition.getPropertyValues()
PropertyValue value = values.getPropertyValue('someValue')
def originalValue = value.getValue()
// this is where you could do your decrypting...
values.addPropertyValue('someValue', "MODIFIED: ${originalValue}".toString())
}
#Override
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/conf/spring/resources.groovy
beans = {
someBean(demo.SomeBean) {
someValue = 'Some Value'
}
somePostProcessor demo.SomePostProcessor
}
https://github.com/jeffbrown/postprocessordemo/blob/master/grails-app/init/postprocessordemo/BootStrap.groovy
package postprocessordemo
import demo.SomeBean
class BootStrap {
SomeBean someBean
def init = { servletContext ->
log.info "The Value: ${someBean.someValue}"
}
def destroy = {
}
}
At application startup you will see log output that looks something like this...
2017-10-23 19:04:54.356 INFO --- [ main] postprocessordemo.BootStrap : The Value: MODIFIED: Some Value
The "MODIFIED" there is evidence that the bean definition post processor modified the property value in the bean. In my example I am simply prepending some text to the string. In your implementation you could decrypt a password or do whatever you want to do there.
I hope that helps.
After trying Jasypt plugin and BeanPostProcessor solutions unsuccessfully for my use case, I found below solution to work perfectly.
To describe again the problem statement here,
a) we had to keep the passwords in an encrypted format inside properties files
b) and given we were packaging as a war file so the properties must not be kept inside the war to allow automated deployment scripts update the encrypted passwords depending on the environment
Jasypt plugin was a perfect solution for the use case a), but it was not able to cover the b) scenario
Moreover, the Grails LDAP Security plugin was getting loaded quite early hence Bean Post processors were also not helping out here.
Solution:
Created a new class by implementing the interface SpringApplicationRunListener. Extended its methods and parsed the properties file using YamlPropertySourceLoader
Sample code:
YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
PropertySource<?> applicationYamlPropertySource = loader.load(
"application.yml", new ClassPathResource("application.yml"),"default");
return applicationYamlPropertySource;
Once the properties were loaded inside the MapPropertySource object, parsed them for the encrypted values and applied the decryption logic.
This whole implementation was executed before any plugins were initialized during Grails bootup process solving the purpose.
Hope it will help others.

Setting default maxLength for Grails GORM Strings?

I know you can set default constraints via the grails.gorm.default.constraints config property by name by:
grails.gorm.default.constraints = {
'*'(nullable:true)
}
but is there a way to set it by type? I want to default all my strings to default to maxSize:2000 (primarily to force the default db mapping to not be to varchar(255))
I don't think there's any way to do this easily in Config.groovy. You can create a custom dialect for hibernate without too much trouble though. For example (using the Postgres dialect):
package mypackage;
import org.hibernate.dialect.PostgreSQLDialect;
import java.sql.Types;
public MyPostgresDialect extends PostgresSQLDialect {
public MyPostgresDialect() {
super();
registerColumnType(Types.VARCHAR, "text");
}
}
Then update DataSource.groovy to use the new dialect:
datasource {
...
dialect = mypackage.MyPostgresDialect
}
Just to provide an additional answer I received from a co-worker - which wasn't applicable in this case, but might help others...
if you can follow a naming convention in your properties, then you could do a:
'*_s': (maxSize:2000)
I personally don't like cross-tying prop names and datatypes - but wanted to include this as an approach (even though I like the dialect answer by ataylor more...)

How can I force Grails to use only one language?

I want to make my Grails application support only one language, that I can define somewhere, completely ignoring the client's headers or the "lang" parameter. Is there any way I can do so? Thanks.
Define a LocaleResolver bean in your config/spring/resources.groovy to set the default locale.
beans = {
localeResolver(org.springframework.web.servlet.i18n.SessionLocaleResolver) {
defaultLocale = new Locale("de","DE")
java.util.Locale.setDefault(defaultLocale)
}
}
This is useful if you don't have to deal with the lang parameter - otherwise it would get overridden. To even ignore the lang parameter value you can set the locale in a Filter upon each request:
import org.springframework.web.servlet.support.RequestContextUtils as RCU
...
def filters = {
all(controller:'*', action:'*') {
before = {
def locale = new Locale("sv","SV")
RCU.getLocaleResolver(request).setLocale(request, response, locale)
}
}
}
This approach seems a bit repetitive as Locale is re-set on every request. It would be more elegant to disable the browsers locale detection via an config option.
The default LocaleResolver of Grails is SessionLocaleResolver. If you want to always use de_DE you can change this to FixedLocaleResolver.
beans {
localeResolver(FixedLocaleResolver) {
locale = new Locale("de", "DE")
}
}
If you want to restrict to a set of locales, then you will need a filter, and use the SessionLocaleResolver#setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) method.
remove all messages_xx.properties files and keep only the messages.properties files.
This is the default message bundle to which the system will always fall back if it can't find the right message bundle.
This way you can still use messages (and thus keep the option to nationalize your app) but users will get always the same language.
This worked for me in order to override the default localResolver bean
beans = {
localeResolver(org.springframework.web.servlet.i18n.FixedLocaleResolver) {
setLocale(Locale.US)
}
}

Store and use application configuration settings in database for a Grails application?

we currently use configuration files to store application settings. I was wondering if it is possible to store these settings inside the database and if so how to achieve this?
Greetings
You can store whatever you want in the database and read it out using a Domain class. This is especially useful if you want to be able to make changes to things without having to redeploy new code. But realize that you will incur a database hit every time the property is accessed.
You can set up a ConfigurationService with:
ConfigurationService {
static def configurationValues
def getConfigurationValues() {
if(configurationValues == null) {
refreshConfigurationValues()
}
configurationValues
}
def refreshConfigurationValues() {
configurationValues = //go get the values out of the database
}
}
Then you can add a Controller/Action to force the refresh when necessary
ConfigurationController {
def configurationService
def refreshConfiguration = {
configurationService.refreshConfigurationValues()
render "Ahhh... That's refreshing :)"
}
}
Now you can refresh your config values by invoking: "http://yoururl/appName/configuration/refreshConfiguration"
This is can be done with BootStrap.groovy. So following Jarred's answer, create a domain class of the configuration data you would like to store and then inside the BootStrap.groovy file, put these values. What this does is if the configuration values does not exists, it will create it, if it exists will not do anything.
Then you can access your configuration values using the domain class. I'm assuming you want to do this because grailsApplication.config... can sometimes become unruly.
Domain-Class MyConfig.groovy:
class MyConfig {
String type
String name
String value
}
BootStrap.groovy:
def myConfig = MyConfig.findByName("path") ?: new MyConfig(
type: "Path"
name: "path"
value: "/var/tmp"
).save(failOnError: true)

Grails i18n from property files backed up by a DB?

i am trying to get a situation where i can use i18n property files which are backed up with a database?
So for some standard stuff i would like to use the property files, but some fields must be editable by the end-user so i was planning to use i18n in the database for that. So a real combination would be great. If the i18n code cannot be found in the property files then do a lookup in the DB.
Any idea how i can tackle this? I have seen the post Grails i18n From Database but Default Back To File
But there is no real answer to the problem, any other suggestions on how to tackle this?
Put a new domain class into your project:
class Message {
String code
Locale locale
String text
}
Add the following lines to your resources.groovy:
// Place your Spring DSL code here
beans = {
messageSource(DatabaseMessageSource) {
messageBundleMessageSource = ref("messageBundleMessageSource")
}
messageBundleMessageSource(org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource) {
basenames = "WEB-INF/grails-app/i18n/messages"
}
}
And add the following class to your src/groovy folder:
class DatabaseMessageSource extends AbstractMessageSource {
def messageBundleMessageSource
protected MessageFormat resolveCode(String code, Locale locale) {
Message msg = messageBundleMessageSource.resolveCode(code, locale)
def format
if(msg) {
format = new MessageFormat(msg.text, msg.locale)
}
else {
format = Message.findByCodeAndLocale(code, locale)
}
return format;
}
}
Now grails will try to resolve the message from the message bundle. If it is not available, it will look it up from database. You could add some error-handling, but this version works, if all messages are available at least in one place.
See http://graemerocher.blogspot.com/2010/04/reading-i18n-messages-from-database.html for some more details.
Some details on the changes done in resources.groovy:
In this file you can define injectable groovy classes, which can be included by just defining a variable having the same name as defined in the resources.groovy. E.g. in this file, there are messageSource and messageBundleMessageSource, which you can be include in any controller or service files. If this variable is defined, an instance of the class in the brackets is created.
In this case, we overwrite the general messageSource to use our custom implementation DatabaseMessageSource. So the I18n function message will now use our custom implementation.
Since our custom implementation requires to check the message.properties-files we keep the original message source in the second bean. By defining this instance in our custom implementation, we can still use the old implementation (and therefore looking up messages the usual way).
I'm not sure I know what you mean by
i18n property files which are backed up with a database
But if you simply mean that you want the message keys to be resolved using a database table (instead of a .properties file), then you can do this by writing your own implementation of the MessageSource interface
class DBMessageSource implements MessageSource {
String getMessage(MessageSourceResolvable resolvable, Locale locale) {
// IMPLEMENT ME
}
String getMessage(String code, Object[] args, Locale locale) {
// IMPLEMENT ME
}
String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
// IMPLEMENT ME
}
}
Then simply replace the default implementation of the messageSource bean with your implementation by adding the following to resources.groovy
messageSource(DBMessageSource)
In followup of the answer of #crudolf i implemented the following method to achieve my goal.
class DatabaseMessageSource extends AbstractMessageSource {
// the message bundle resource that holds all of the messages
def messageBundleMessageSource
// the default locale used when there is no correct results found
// if a visitor (x) comes along with an unknown locale in the DB
// then this locale will be used as fallback!
Locale fallbackLocale = new Locale("nl", "NL")
protected MessageFormat resolveCode(String code, Locale locale) {
// first try to find the message in the messagebundles
MessageFormat messageFormat = messageBundleMessageSource.resolveCode(code, locale)
if(!messageFormat) {
// no message found so lets find one in the database
def message = Message.findByCodeAndLocale(code, locale) ?: Message.findByCodeAndLocale(code, fallbackLocale)
if (message) {
// found one create a message format!
messageFormat = new MessageFormat(message.text, message.locale)
} else {
// not found! create a standard message format
messageFormat = new MessageFormat(code, locale)
}
}
return messageFormat
}
}
Take a look at https://github.com/goeh/grails-i18n-db and https://github.com/halfbaked/grails-localizations. Both offer also a gui to manage localizations.

Resources