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

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)

Related

Grails - Command object, service method

I'm not a programming savvy person, so please bear with me.
I've read blog entries and docs about command object. I've never used it and was wondering if I should. (I probably should...)
My project requires parsing, sorting, calculating, and saving results into database when users upload files.
So according to one of the blog entries I read and its corresponding github code,
1) SERVICE should receive file uploads, parse uploaded files (mainly docs and pdfs), sort parsed data using RegEx, and calculate data,
2) COMMAND OBJECT should call SERVICE, collect results and send results back to controller, and save results into the database,
3) CONTROLLER should receive request from VIEW, get results from COMMAND OBJECT, and send results back to VIEW.
Did I understand correctly?
Thanks.
I found this to be the best setup. Here is an example that I use on production:
Command Object (to carry data and ensure their validity):
#grails.validation.Validateable
class SearchCommand implements Serializable {
// search query
String s
// page
Integer page
static constraints = {
s nullable: true
page nullable: true
}
}
Controller (directs a request to a Service and then gets a response back from the Service and directs this response to a view):
class SomeController {
//inject service
def someService
def search(SearchCommand cmd) {
def result = someService.search(cmd)
// can access result in .gsp as ${result} or in other forms
render(view: "someView", model: [result: result])
}
}
Service (handles business logic and grabs data from Domain(s)):
class SomeService {
def search(SearchCommand cmd) {
if(cmd.hasErrors()) {
// errors found in cmd.errors
return
}
// do some logic for example calc offset from cmd.page
def result = Stuff.searchAll(cmd.s, offset, max)
return result
}
}
Domain (all database queries are handled here):
class Stuff {
String name
static constraints = {
name nullable: false, blank: false, size: 1..30
}
static searchAll(String searchQuery, int offset, int max) {
return Stuff.executeQuery("select s.name from Stuff s where s.name = :searchQuery ", [searchQuery: searchQuery, offset: offset, max:max])
}
}
Yes, you understood it correctly except the one thing: command object shouldn't save the data to DB - let service to do that. The other advantage of command object is data binding and validation of data from the client. Read more about command objects here grails command object docs
You can also find helpful information regarding your question in this article
grails best practices
I guess not. Its not really related to whether the save is done in a service it should always attempt to carry out complex stuff and specifically db stuff in a service. so that is regardless. I tend to not use command object but have got hooked on helper classes aka beans that sit in src/main/groovy and do all of the validation and formatting. I just did a form and in it has feedback and reason.
Initially I thought I would get away with
def someAction(String feedback, String reason) {
someService.doSomething(feedback,reason)
}
But then I looked closed and my form was firstly a textarea then the selection objects were bytes so above was not working and to simply fix it without adding the complexity to my controller/service I did this:
packe some.package
import grails.validation.Validateable
class SomeBean implements Validateable {
User user
byte reason
String feedback
static constraints = {
user(nullable: true)
reason(nullable:true, inList:UsersRemoved.REASONS)
feedback(nullable:true)
}
void setReason(String t) {
reason=t as byte
}
void setFeedback(String t) {
feedback=t?.trim()
}
}
Now my controller
class SomeController {
def userService
def someService
def doSomething(SomeBean bean){
bean.user = userService.currentUser
if (!bean.validate()) {
flash.message=bean.errors.allErrors.collect{g.message([error : it])}
render view: '/someTemplate', model: [instance: bean,template:'/some/template']
return
}
someService.doSomeThing(bean)
}
}
Now my service
Class SomeService {
def doSomeThing(SomeBean bean) {
if (bean.user=='A') {
.....
}
}
All of that validation would have still had to have been done somewhere, you say no validation but in a good model you should do validation and set things to be stored in proper structures to reduce overloading your db over time. difficult to explain but in short i am talking about your domain class objects and ensuring you are not setting up String something string somethingelse and then not even defining their lenghts etc. be strict and validate
if you have a text area this will be stored in the back end - so you will need to trim it like above - you will need to ensure the input does not exceed the max character of the actual db structure which if not defined will probably be 255
and by doing
static constraints = {
user(nullable: true)
reason(min:1, max:255, nullable:true, inList:UsersRemoved.REASONS)
Has already invalidated it through the bean.validate() in the controller if the user exceeded somehow my front end checks and put in more than 255.
This stuff takes time be patient
Edited to finally add in that example byte - is one to be careful of -
When adding any String or what ever I have started to define the specific like this and in the case of byte if it is a boolean true false - fine if not then define it as a tinyint
static mapping = {
//since there is more than 1 type in this case
reason(sqlType:'tinyint(1)')
feedback(sqlType:'varchar(1000)')
// name(sqlType:'varchar(70)')
}
If you then look at your tables created in the db you should find they have been created as per definition rather than standard 255 varchar which I think is the default for a declared String.

Set value in message.properties file from grails service

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.

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.

Grails - how to pass Domain Objects and use services

I'm writing a service that shouldn't have to save anything. It gets some values. Looks up a few things in the database, and then coughs back a response. Is there anything I should do to make the service faster/less overhead? Also whats the best way to pass it something. I usually pass the id and get it again; is that good/bad/dumb?
example
class DoStuffController {
def ExampleProcessingService
def yesDoIt = {
def lookup = "findme"
def theObject = ExampleThing.findByLookie(lookup)
def lolMap = ExampleProcessingService.doYourThing(theObject.id)
if(lolMap["successBool"]){
theObject.imaString = "Stuff"
theObject.save()
}
[]
}
}
service
class ExampleProcessingService{
static transactional = true //???????? false? not-a?
def doYourThing = {theID ->
def returnMap = [:]
def myInstance = ExampleThing.get(theID)
if(myInstance.something)returnMap.put "successBool", true
else returnMap.put "successBool", false
return returnMap
}
}
domain object
class ExampleThing {
String imaString
String lookie
static constraints = {
imaString(nullable:true)
}
def getSomething() {
return true
}
}
bootstrap
import learngrails.*
class BootStrap {
def init = { servletContext ->
def newThing = new ExampleThing(lookie:"findme")
newThing.save()
}
def destroy = {
}
}
Is the an advantage, disadvantage or standard to passing ID and doing get vs. passing the object? Does this change given my case of not going to save anything in the service? Is there something I'm doing glaringly wrong? Do you have a better suggestion for the title?
You've asked a lot of questions, and should split this into several individual questions. But I'll address the overall issue - this approach is fine in general.
There's not a lot of overhead in starting and committing a transaction that doesn't do any database persistence, but it is wasteful, so you should add
static transactional = false
In this case you're using the class as an easily injected singleton helper class. It's convenient to do transactional work in services because they're automatically transactional, but it's far from a requirement.
One thing though - do not use closures in services. They're required in controllers and taglibs (until 2.0 anyway) but should always be avoided in services and other classes. If you're not using the fact that it's a closure - i.e. passing it as an object to a method as a parameter, or setting its delegate, etc. - then you're just being way too groovy. If you're calling it like a method, make it a method. The real downside to closures in services is that when you want them to be transactional, they cannot be. This is because Spring interceptors intercept method calls, not closure calls that Groovy pretends are method calls. So there won't be any interception for transactions, security, etc.

Setting Grails domain id in Bootstrap.groovy

Is it possible to explicitly set the id of a domain object in Grails' Bootstrap.groovy (or anywhere, for that matter)?
I've tried the following:
new Foo(id: 1234, name: "My Foo").save()
and:
def foo = new Foo()
foo.id = 1234
foo.name = "My Foo"
foo.save()
But in both cases, when I print out the results of Foo.list() at runtime, I see that my object has been given an id of 1, or whatever the next id in the sequence is.
Edit:
This is in Grails 1.0.3, and when I'm running my application in 'dev' with the built-in HSQL database.
Edit:
chanwit has provided one good solution below. However, I was actually looking for a way to set the id without changing my domain's id generation method. This is primarily for testing: I'd like to be able to set certain things to known id values either in my test bootstrap or setUp(), but still be able to use auto_increment or a sequence in production.
Yes, with manually GORM mapping:
class Foo {
String name
static mapping = {
id generator:'assigned'
}
}
and your second snippet (not the first one) will do the job (Id won't be assigned when passing it through constructor).
What I ended up using as a workaround was to not try and retrieve objects by their id. So for the example given in the question, I changed my domain object:
class Foo {
short code /* new field */
String name
static constraints = {
code(unique: true)
name()
}
}
I then used an enum to hold all of the possible values for code (which are static), and would retrieve Foo objects by doing a Foo.findByCode() with the appropriate enum value (instead of using Foo.get() with the id like I wanted to do previously).
It's not the most elegant solution, but it worked for me.
As an alternative, assuming that you're importing data or migrating data from an existing app, for test purposes you could use local maps within the Bootstrap file. Think of it like an import.sql with benefits ;-)
Using this approach:
you wouldn't need to change your domain constraints just for
testing,
you'll have a tested migration path from existing data, and
you'll have a good data slice (or full slice) for future integration tests
Cheers!
def init = { servletContext ->
addFoos()
addBars()
}
def foosByImportId = [:]
private addFoos(){
def pattern = ~/.*\{FooID=(.*), FooCode=(.*), FooName=(.*)}/
new File("import/Foos.txt").eachLine {
def matcher = pattern.matcher(it)
if (!matcher.matches()){
return;
}
String fooId = StringUtils.trimToNull(matcher.group(1))
String fooCode = StringUtils.trimToNull(matcher.group(2))
String fooName = StringUtils.trimToNull(matcher.group(3))
def foo = Foo.findByFooName(fooName) ?: new Foo(fooCode:fooCode,fooName:fooName).save(faileOnError:true)
foosByImportId.putAt(Long.valueOf(fooId), foo) // ids could differ
}
}
private addBars(){
...
String fooId = StringUtils.trimToNull(matcher.group(5))
def foo = foosByImportId[Long.valueOf(fooId)]
...
}

Resources