Kamil.H
Kamil.H

Reputation: 458

Grails, injecting/populating domain object with value from session

In my application many classes have common field 'company'. When application saves that objects, they must be filled with company (there is validation for that). Company is also kept in a session. Now, when I want to use domain class as a command object, company must be already filled or I get validation error. Is there any way to always fill company field, before any validation happens, so that I didn't have to do it manually every time. (I tried custom data binder, but it does not work when there is no parameter in a request)

Upvotes: 2

Views: 876

Answers (2)

Arthur Ronald
Arthur Ronald

Reputation: 33775

If you want to bind a property before the process of binding, You can create a custom BindEventListener and register in the grails-app/conf/spring/resources.groovy

First of all, create your custom BindEventListener

/src/groovy/SessionBinderEventListener.groovy

import org.springframework.beans.MutablePropertyValues
import org.springframework.beans.TypeConverter

class SessionBinderEventListener implements BindEVentListener {

    void doBind(Object wrapper, MutablePropertyValues mpv, TypeConverter converter) {
        def session = RequestContextHolder.currentRequestAttributes().getSession()
        mpv.addPropertyValue("company", session.company)
    }

}

Second of all, register your BindEventListener

grails-app/conf/spring/resources.groovy

beans = {
    sessionBinderEventListener(SessionBinderEventListener)
}

However, if your domain class does not hold a property called company, you will get InvalidPropertyException. To overcome this issue, create a list of classes which contain a property called company - See details bellow

/src/groovy/SessionBinderEventListener.groovy

import org.springframework.beans.MutablePropertyValues
import org.springframework.beans.TypeConverter

class SessionBinderEventListener implements BindEVentListener {

    private List<Class> allowedClasses = [Foo]

    void doBind(Object wrapper, MutablePropertyValues mpv, TypeConverter converter) {
        if(!(allowedClasses.contains(wrapper.class))) {
            return
        }

        def session = RequestContextHolder.currentRequestAttributes().getSession()
        mpv.addPropertyValue("company", session.company)
    }

}

Upvotes: 1

aiolos
aiolos

Reputation: 4697

You could set the property just before the object is saved, updated or validated using the GORM events beforeInsert, beforeUpdate or beforeValidate.

In your domain you need something like that:

import org.springframework.web.context.request.RequestContextHolder 
class Foo {
    String company
    ...
    def beforeInsert = {
        try {
            // add some more error checking (i.e. if there is is no request)
            def session = RequestContextHolder.currentRequestAttributes().getSession()
            if(session) {
                this.company = session.company
            }             
        } catch(Exception e) {
            log.error e
        }
    }
}

Upvotes: 1

Related Questions