Grails: can settings in Config.groovy be overridden programmatically at runtime? - grails

The mail plugin is documented to require its settings in Config.groovy. I want to have it stored in the database so it can be changed at runtime. And this is just one example.
I've read Does externalizing sensitive config variables into a .properties outside of Config.groovy provide a security advantage in Grails? but this is about using an external property file, I need to store the settings in the database (the app has an admin interface, with auditing and so on).
Thank you.

In Bootstrap.groovy you can read the property values from the database and replace those read from the config files by updating grailsApplication.config. For example, assume you want to replace the value of a config property named foo.bar
class BootStrap {
GrailsApplication grailsApplication
def init = { servletContext ->
def fooBarDB = // read the value of foo.bar from the database
grailsApplication.config.foo.bar = fooBarDB
}
}
Rather than writing this code yourself, you could instead use the Dynamic Config Plugin to achieve the same outcome.

Yes, you can do this. During the grails bootstrap process using Bootstrap.groovy, retrieve the properties from the database and override them. It's similar to a properties file override, you're just storing them in a database.
Also see Properties in the database

First way to change value dynamic:
grailsApplication.config.grails.mail.put("port",your database fetch value of port)
grailsApplication.config.grails.mail.put("username","your database fetch value of username")
grailsApplication.config.grails.mail.put("password","your database fetch value of username")
grailsApplication.config.grails.mail.put("props","your database fetch value of username")
second way to change value dynamic:
org.codehaus.groovy.grails.commons.DefaultGrailsApplication
DefaultGrailsApplication class provide the all the information about config. you can get email information using following code and change it dynamic.
def defaultGrailsApplication= new DefaultGrailsApplication()
// to get mails information from Config.groovy
defaultGrailsApplication?.config?.grails.mail?.get("host")
defaultGrailsApplication?.config?.grails.mail?.get("port")
defaultGrailsApplication?.config?.grails.mail?.get("username")
defaultGrailsApplication?.config?.grails.mail?.get("password")
defaultGrailsApplication?.config?.grails.mail?.get("props")
// to change mails information of Config.groovy
defaultGrailsApplication?.config?.grails.mail?.put("host","your database fetch value of host")
defaultGrailsApplication?.config?.grails.mail?.put("port",your database fetch value of port)
defaultGrailsApplication?.config?.grails.mail?.put("username","your database fetch value of username")
defaultGrailsApplication?.config?.grails.mail?.put("password","your database fetch value of username")
defaultGrailsApplication?.config?.grails.mail?.put("props","your database fetch value of username")
Now you need to assign this "defaultGrailsApplication" instance to inject value of application. just assume that we have one class service Temp.service having grailsApplication injected like:
Temp.service
class Temp{
def grailsApplication
def your method(){
please add above code for set value
grailsApplication = defaultGrailsApplication
}
}

Related

Where to store api client key in grails

I'd like to store api key in my grails application. Api key should be global and can be changed every several minutes or hours.
Where is the best place to store this key globally?
I don't want to store it in database, guess that config is the best place.
But I suppose that config is a good place to store constants, not changeable data.
So, where to store api key globally?
Update: maybe class with static fields like String apiKey will be enough?
Api key should be global and can be changed every several minutes or hours.
Why would an API key change so frequently?
guess that config is the best place. But I suppose that config is a good place to store constants, not changeable data.
Normally properties in Config.groovy are read-only, but there's nothing to prevent you modifying them, e.g.
class MyController {
def grailsApplication
def updateApiKey(String newKey) {
grailsApplication.config.apiKey = newKey
}
}

Is it possible to force Grails/Gorm to not include a column in an insert?

For instance, suppose I wanted to let that column be set to whatever the database defaults it to, without redefining that default in the domain class?
I can't find much through Google. There are hints that if I were working with Hibernate directly, I could set that particular column/property to private, and this might accomplish what I seek.
I can of course leave that column undefined, and GORM ignores it. But I need the values out of it whenever the Grails app does a select.
You can use the GORM property insertable as in doc or can read the value with a beforeInsert event:
class Book {
String title
String isbn
static mapping = {
isbn nullable: false
}
def beforeInsert {
title = queryFromDatabase...
}
}
I think you have to go the beforeInsert / Hibernate interceptor route since your requirement is to read default values from an existing database.
You can read the database default values for columns with JDBC's DatabaseMetaData.getColumns .
To find out the database table and column names, you can use something like this (this code is not tested)
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder
import org.codehaus.groovy.grails.orm.hibernate.cfg.Mapping
import org.codehaus.groovy.grails.commons.DomainClassArtefactHandler
def gdc=grailsApplication.getArtefact(DomainClassArtefactHandler.TYPE, someInstance.class.name)
Mapping mapping=GrailsDomainBinder.getMapping(gdc)
def tableName=mapping.tableName
def columnName=mapping.getPropertyConfig('someColumn').column
This is not a complete answer, but I hope this helps.

Grails, storing app own settings (singleton domain class?)

I'm developing an app using Grails and there are some app-wide configuration settings I'd like to store somewhere. The only way I've thought of is to create a domain class that stores the configuration values, and to use a service that queries that domain class. The problem I see is that there should be just one instance of that domain class, but I haven't found anything to enforce that restriction.
There may be other best practices to store app's own configuration that I may not be aware of, all suggestions are welcome.
Edit: the settings are supposed to be configurable from within the app.
There is special place: /grails-app/conf/Config.groovy. You can add values there like:
my.own.x=1
and read values by:
def x = grailsApplication.config.my.own.x
See docs for more details: http://grails.org/doc/latest/guide/conf.html#config
There is a plugin for that: Settings. It allows you to create named setting like my.own.x of different types (String, date, BigDecimal and integer), and provides you with the basic CRUD pages to manage them.
You can access the settings from either gsp:
<g:setting valueFor="my.own.x" default="50" encodeAs="HTML"/>
or controllers/services/domains
Setting.valueFor("my.own.x", 50)
I use it in several projects and think it works great.
You can enforce your single domain class db entry via custom validator:
// No more than one entry in DB
class MasterAccount {
boolean singleEntry = true
static constraints = {
singleEntry nullable: false, validator: { val, obj ->
if(val && obj.id != getMasterAccount()?.id && MasterAccount.count > 0){
return "Master account already exists in database"
}
}
}
MasterAccount static getMasterAccount(){
MasterAccount.list()?.first()
}
}
You can defer its configuration and persistence to Bootstrap.groovy, which would achieve the same effect as Config.groovy
If you're using 1.3.* you can try grails dynamic-config plugin (http://www.grails.org/plugin/dynamic-config). "This plugin gives your application the ability to change the config properties without restarting the application. The values in Config.groovy are persisted in database when application is run-for the first time after installing the plugin. "
I've never used it on a grails 2.0.* project.

Custom Insert and Update methods defeated by automatic Save

I am porting a Grails application from Oracle to MySQL database. The original Oracle version is a legacy database which uses a few complex Views leveraging Oracle's INSTEAD OF INSERT OR UPDATE feature which MySQL doesn't have. As a workaround I have implement Insert and Update methods on the Domain classes which point to these kinds of Views. For example,
class AdminUser {
//...
def update() {
if(this.validate()) {
Sql sql = Utils.getHibernateSql()
sql.execute(
"update table_x ...",
[...]
)
sql.execute(
"update table_y ...)",
[...]
)
sql.execute(
"update table_z ...",
[...]
)
return true
}
return false
}
//...
}
Here is a description of the problem I am running into at the moment:
Within a service method I load an instance of AdminUser using AdminUser.get
I modify the loaded instance and call update(), all appears well
Once the service method finishes executing an exception is thrown due to something calling save on the instance.
How can I prevent the magical save happening in step (3) (I recently read somewhere that Grails will automatically save a modified Domain class instance which hasn't yet been saved upon exiting a service method, but I can't seem to find the link to that resource right now)?
You're leaving the modified instance in the hibernate session with dirty fields. When the hibernate session gets flushed, it will try to save the object again with the usual save() method.
One solution would be to discard your object from the hibernate session after you've manually saved the changes. For example:
def update() {
if(this.validate()) {
Sql sql = Utils.getHibernateSql()
sql.execute(
"update table_z ...",
[...]
)
...
this.discard() // remove the object from the hibernate session
return true
}
In addition, you can add this to your Config.groovy to require that objects be saved explicitly:
hibernate.flush.mode="manual"
If you use read() instead of get(), then the object will not auto-persist changes. You can still call save() explicitly, but the standard behavior where the OpenSessionInView interceptor flushes all unsaved dirty instances will skip the instances loaded with read().

Not Saving Domain Object with Grails Searchable Plugin

Is it possible to use the Searchable Plugin to create an index of objects and never actually save the objects to the database?
I think so. If you never save the objects, then I think you can just call:
domainInstance.index()
But I've never tried it, so I'm not sure if it just indexes the one instance, or any instance of that class.
See here:
https://svn.codehaus.org/grails-plugins/grails-searchable/trunk/src/groovy/org/codehaus/groovy/grails/plugins/searchable/compass/domain/DynamicDomainMethodUtils.groovy
If you just want to save the object but just want to index manually, then set the following in your conf/Searchable.groovy config file:
mirrorChanges = false
bulkIndexOnStartup = false
See here: https://svn.codehaus.org/grails-plugins/grails-searchable/trunk/src/conf/Searchable.groovy

Resources