0
votes

I have special case of domain classes structure where three classes presents and they are connected to chain: Event <- Room <- Projector. (All relation ships are one-to-one)

The implementation looks like:

class Event {
    Room room
    static constraints = {
        room(nullable:false)
    }
}
class Room {
    Projector projector = new Projector()
    static belongsTo = [event: Event]
    static constraints = {
        projector(nullable:false)
    }
}
class Projector {
    String something = "Something"
    static belongsTo = [room: Room]
    static constraints = {
        room(nullable:false)
    }
}

When I want to create Event with new Room I expect that the Projector will be created by default:

class TestController {
    def index() {
        Room room = new Room()
        Event event = new Event(room: room)
        event.save(flush: true, failOnError: true)
        render event
    }
}

I receive following exception

| Error 2012-07-11 16:09:12,541 [http-bio-8080-exec-3] ERROR errors.GrailsExceptionResolver  - TransientObjectException occurred when processing request: [GET] /Test/room/index
object references an unsaved transient instance - save the transient instance before flushing: Projector. Stacktrace follows:
Message: object references an unsaved transient instance - save the transient instance before flushing: Projector
    Line | Method
->>   46 | onApplicationEvent in org.grails.datastore.mapping.engine.event.AbstractPersistenceEventListener
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     18 | index              in RoomController
|   1110 | runWorker . . . .  in java.util.concurrent.ThreadPoolExecutor
|    603 | run                in java.util.concurrent.ThreadPoolExecutor$Worker
^    722 | run . . . . . . .  in java.lang.Thread

It seems that cascading over three classes doesn't save default values. Is there any solution for that? Or what am I doing wrong?

1
Just to troubleshoot... What happens if you change Projector projector = new Projector() to just Projector projector and change Room room = new Room() to Room room = new Room(projector:new Projector()) There are some methods that get meta-programmed onto domain classes. It could be that by directly assigning a value for Projector inside the domain class, you are bypassing the hook that handles cascading saves.proflux
Your recommendation works. Maybe my implementation bypasses the hooks but how should I implement this... I don't want to annoy other developers with creation of Projector when they want to create room and event.kuceram
Not 100% sure if this will work, but I would try adding a constructor to Room and putting the statement this.projector = new Projector() in the constructor.proflux
It doesn't work either. It seems to be a grails bug. I've risen an issue: jira.grails.org/browse/GRAILS-9262kuceram

1 Answers

0
votes

There is an open jira for your issue at http://jira.grails.org/browse/GRAILS-4613?attachmentOrder=desc

Personally I would handle the creation of objects in my controller instead of doing it in the domain. You need to be able to call projector.save(flush:true).