Adding changes listeners in Grails' GORM - grails

I'm new to Grails and I'm using Grails 2.0.1. I want to add a persistence event listener for changes in objects for a domain class, so I tried the code in Bootstrap.groovy as given in the user guide:
def init = {
applicationContext.addApplicationListener(new FooBarListener())
}
And I get the following error message:
ERROR context.GrailsContextLoader - Error executing bootstraps: No such property: applicationContext for class: BootStrap
How can I get the applicacionContext property from inside the BootStrap class?
or Is the documentation outdated and there is a new/better way to add domain changes listeners?.
Thanks in advance.

The shortest way I know is
class BootStrap {
def grailsApplication
def init = { servletContext ->
def applicationContext = grailsApplication.mainContext
}
}

import org.codehaus.groovy.grails.commons.ApplicationAttributes
class BootStrap {
def init = {servletContext ->
def applicationContext = servletContext.getAttribute(ApplicationAttributes.APPLICATION_CONTEXT)
}
}

applicacionContext must be defined in BootStrap. Following should work
class BootStrap {
def applicacionContext
def init = {
applicationContext.addApplicationListener(new FooBarListener())
}
}

Related

Closures resolving strategy not working in trait context in Groovy 2.4.3

I've got the following code:
trait ContainingClosure {
def method() {
def delegateClass = new DelegateClass()
def closure = {
methodFromDelegate()
}
closure.delegate = delegateClass
closure.resolveStrategy = Closure.DELEGATE_FIRST
closure.call()
}
}
class DelegateClass {
def methodFromDelegate() {
println 'methodFromDelegate called'
}
}
class Main implements ContainingClosure {}
new Main().method()
The problem is that methodFromDelegate() cannot be found when I run call() method and the following exception is thrown:
groovy.lang.MissingMethodException: No signature of method: Main.methodFromDelegate() is applicable for argument types: () values: []
Is there any reasonable explanation why this snippet is not working in Grails 2.5.0 (Groovy 2.4.3)? It seems that the delegate of the closure is somehow ignored and method lookup is done in Main class scope not the delegate itself.
Changing trait into class and implementation of a trait into inheritance makes this code working again.
Found it, it's this bug
https://issues.apache.org/jira/browse/GROOVY-7456
Which is fixed in groovy 2.4.4, so an upgrade of grails should fix it :-)

Grails - Bootstrap - null pointers instead of services

I'd like to use data generator at init in my application. It works fine when create objects using .save() method, but it doesn't work when I want to use dedicated services, because of null pointers instead of injected services. That's my code:
I have defined DataGenerator bean inside conf/spring
beans = {
dataGenerator(DataGenerator)
}
My Bootstrap.groovy looks like:
class BootStrap {
def dataGenerator
def init = { servletContext ->
dataGenerator.generateData()
}
}
In `DataGenerator' I have:
class DataGenerator{
BookService bookService
def generateData() {
log.info("Generating books")
createBooks()
}
def createBooks(){
(1..40).each() {
CreateBookCommand command = new CreateBookCommand()
/* some command populate code*/
bookService.create(command);
}
}
}
The problem is, that I cannot invoke create() method, because bookService is always null
BookService is simple grails service with some dependencies, of course placed in grails-app/services
class BookService {
UserService userService
SpringSecurityService springSecurityService
def create(CreateBookCommand command){
Book book = new Book()
command.bindTo(book)
book.save(flush:true, failOnError:true)
}
/*some other methods*/
}
Could you tell me how to fix it?
Try this in resources.groovy
beans = {
dataGenerator(DataGenerator) { bean ->
bean.autowire = 'byName'
}
}
I assume DataGenrator being a class outside the grails artifact (that is: placed in src/groovy), you can refer the already available service class in the context as:
beans = {
dataGenerator(DataGenerator){
bookService = ref('bookService')
}
}
or try autowiring byName as mentioned by #sudhir.

Grails resources.groovy beans

Im having some problems trying to actually determine if my beans have been properly loaded.
Is there some log4j property which can show me in the log what beans that are properly loaded?.
After some trying i went off and tried another example from here
redefining my resources.groovy like follows:
import grails.spring.BeanBuilder
BeanBuilder bb = new BeanBuilder()
bb.beans = {
ldapUserDetailsMapper(example.CustomDetailsContextMapper) {
}
}
CustomDetailsContextMapper in its turn is defined as:
class CustomDetailsContextMapper implements UserDetailsContextMapper {
def springSecuritySource
#Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection authorities) {
This is the error im getting when using this kind of resource.groovy setup:
2012-10-12 12:52:31,663 [main] ERROR spring.GrailsRuntimeConfigurator - [RuntimeConfiguration] Unable to load beans from resources.groovy
org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack: No such property: beans for class: resources
Possible solutions: class
When not using beanbuilder i get no errors but i cant really verify that my beans are loaded, since they seem never to be called.
In the other case i get the below error.
Any suggestions?
in resource.groovy simply write
beans = {
ldapUserDetailsMapper(example.CustomDetailsContextMapper) {
}
The BeanBuilder is already defined for you
A bean is called when used... inside a controller try thi
VeryBeanController{
def ldapUserDetailsMapper
def index = {
render( ldapUserDetailsMapper )
}
}
And call the controller

Grails - access static config object in codec class

I am currently updating my Grails project in order not to use the deprecated ConfigurationHolder class.
This goes fine in most cases, but I am facing trouble in my custom codec classes, where I have been using the following approach until now:
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
class MyCodec {
static boolean myStaticConfigProperty=CH.config.myStaticConfigProperty
static encode = { something ->
if(myStaticConfigProperty)
...
}
}
Direct injection using
def grailsApplication
does not work in this case since this will be injected as a non-static object.
Instead I have tried to use the approach suggested in this post getting-grails-2-0-0m1-config-info-in-domain-object-and-static-scope, but I cannot make it work even after injecting the grailsApplication object into my codec metaclasses in the bootstrap:
class BootStrap {
def grailsApplication
def init = { servletContext ->
for (cc in grailsApplication.codecClasses) {
cc.clazz.metaClass.getGrailsApplication = { -> grailsApplication }
cc.clazz.metaClass.static.getGrailsApplication = { -> grailsApplication }
}
}
}
Could anyone suggest an approach that will allow me to access the config object in a static way inside codec classes?
I'd suggest something like this completely untested code:
class MyCodec {
static def grailsConfig
static boolean myStaticConfigProperty = grailsConfig.myStaticConfigProperty
static encode = { something ->
if(myStaticConfigProperty)
...
}
}
class BootStrap {
def grailsApplication
def init = { servletContext ->
for (cc in grailsApplication.codecClasses) {
cc.grailsConfig = grailsApplication.config
}
}
}
If all of your codec classes just need the same one configuration property, you could skip injecting the grailsApplication and/or the config object entirely, and just set the one static property from BootStrap.
it works for me in grails 2.2.3
import grails.util.Holders as holders;
class MyFileCodec {
static encode = {file ->
def configPath= holders.grailsApplication.config.share.contextPath
return "${configPath}/${file.name}"
}
}
grails.util.Holders has been introduced since grails 2.0, it's the way to access config object.

springSecurityService in resources.groovy grails file?

I'm having trouble accessing springSecurityService from resources.groovy file, I'm trying to load user locale setting and create LocaleResolver
import User
beans = {
localeResolver(org.springframework.web.servlet.i18n.SessionLocaleResolver) {
def user = User.get(springSecurityService.principal.id)
if (user?.settings?.locale) {
defaultLocale = new Locale(user?.settings?.locale)
java.util.Locale.setDefault(defaultLocale)
}
}
}
Thanks,
Mika
Your code above doesn't make a lot of sense. In resources.groovy you're supposed to define the implementation class of Spring beans and set their dependencies. It looks like you're trying to actually write the implementation class in resources.groovy.
Instead you should write your own LocaleResolver class
package org.example
class MyLocaleResolver extends AbstractLocaleResolver {
def springSecurityService
// implementation of methods omitted, because I haven't clue how you want to resolve Locales
}
Then in resources.groovy, define a bean of this type that replaces the default localeResolver bean
beans = {
localeResolver(org.example.MyLocaleResolver) {
springSecurityService = ref('springSecurityService')
}
}

Resources