Don Clerecudzio
Don Clerecudzio

Reputation: 86

How to get domain class value from groovy reflection(?)?

I want to show persistentProperties value invoked by doWithDynamicMethod on some plugin

with the following code, i managed to intercept save and update method on domain classes and see their output when they tried to save an object.

But i couldn't print the content of persistentProperties (maybe because i'm a noob on groovy and grails, therefore i didn't familiar with the syntax on groovy reflection.

Anyone could help ?

Following is my code :

def doWithDynamicMethods = { ctx ->
   // TODO Implement registering dynamic methods to classes (optional)

   application.domainClasses.each { gc ->

      def domainClass = gc.clazz
      domainClass.metaClass.invokeMethod = { name, args ->

         if (name == 'save' || name == 'update')
            delegate.log.info " ${delegate.class.name}.$name() args: $args"

         new DefaultGrailsDomainClass(delegate.class).persistentProperties.each{ property -> 

            delegate.log.info "printing properties => "+ property.name+ "  "
         }//end persistentProperties.each                   

      }//endmetaClass.invokeMethod 
   } //end domainClasses.each
}//end doWithDynamicMethod

Upvotes: 0

Views: 1578

Answers (1)

Phuong LeCong
Phuong LeCong

Reputation: 1854

If I understand what you're trying to do, your code is currently listing the persistentProperties which are associated with the domain class itself. To actually get the value of the property you need to pass the property name.

For instance, if you have the following domain class:

class Book {
    String title
    String lang
}

If you're saving a new Book like so:

def b = new Book(title: 'Hemingway', lang: 'en-us').save()

Your code should print out something like this:

printing properties => title  
printing properties => lang

If you want it to print something like this:

printing properties => Hemingway  
printing properties => en-us

Then you'll have to access the property from the obj itself:

def doWithDynamicMethods = { ctx ->
    application.domainClasses.each { gc ->
        def domainClass = gc.clazz
        domainClass.metaClass.invokeMethod = { name, args ->
            def domainObj = delegate

            if (name == 'save' || name == 'update') {
                new DefaultGrailsDomainClass(domainObj.class).persistentProperties.toList().each { property ->
                    domainObj.log.info "printing properties => " + domainObj[property.name]
                }
            }

            def called = domainClass.metaClass.getMetaMethod(name, args)
            called?.invoke(domainObj, args)
        }
    }
}

There are some other gotchas. The variable delegate is special to each closure. If you actually are running it you might not have seen the "printing properties..." log messages at all because in the call to delegate.log.info inside the each closure delegate refers to the closure enclosing class. Also if you're going to read the properties from the domainObj then you should make sure that it is inside the name if clause or else you'll make call into invokeMethod again.

Finally, you should get the metaMethod that was originally being called and invoke it or else it won't actually save/update.

Upvotes: 2

Related Questions