views:

354

answers:

1

I have a domain object on which I want to store a few things which only exist at runtime. I looked at the documentation and found the transients keyword, which, on the face of it was what I was looking for. Here is what my domain object looks like...

class Contact {

    def Seeker

    def beforeInsert() 
    {
       initiatedDate = new Date()
    }

    Date initiatedDate
    Date acceptedDate

    static transients = ['pal']
    Seeker pal
}

where Seeker is a groovy class which is not a domain object, but a placeholder for some properties.

So far all is fine and my Contact table does not have a pal field as expected. In my ContactController I query for a bunch of contacts, c, then look up their Seeker pals (details of how withheld) and set the pal field to a new object.

c.pal = new Seeker();
c.pal.name = otherObject.name
render c as JSON

This all seems to work fine except that the pal object is missing from the JSON returned.

Is this a valid use of transients? The docs mention that they are handy for function-based getters and setters, but in my case I want an actual object. Should I be writing a getPal() and setPal() method on my object?

Thanks

+4  A: 

Transients are indeed used to stop fields in domain objects from being persisted. (If you want to perform some init on the pal field without having to put it in your controller you could use the onLoad() event or write a getPal() method which would override the default property getter). You are also right to note that the default JSON marshaller only renders persisted fields.

When rendering my domain objects I've found it useful to create JSON object marshallers so that unwanted properties are not rendered, but it would also solve your transient issue too. You can do this using the JSON.registerObjectMarshaller method:

import grails.converters.JSON
...
class BootStrap {

    def init = {servletContext ->
        JSON.registerObjectMarshaller(Contact ) {
            def returnArray = [:]
            returnArray['id'] = it.id
            returnArray['initiatedDate'] = it.initiatedDate
            returnArray['acceptedDate'] = it.acceptedDate
            returnArray['pal'] = it.pal
            return returnArray
        }

        JSON.registerObjectMarshaller(Seeker) {
            ...
        }

If you add the marshallers in your BootStrap.groovy they will be available in your controllers.

HTH

(Also found this: http://old.nabble.com/Taggable-plugin-and-JSON-converter-ts24830987.html#a24832970)

Dave
tasty, thanks! I'll try it out
Simon
as a matter of interest, how would one put this in the bootstrap.groovy? Would I have to include the JSON marshalling from grails.converters?
Simon
Put it inside the init closure and import grails.converters.JSON (I've updated the example in the post to show this)
Dave