> thanx burt. this is exactly what i did. i passed the whole map to the
> service instead, and removed all GORM prior to service execution. a bit ugly
> though at the moment since i have to retrieve the Book instance, pass in the
> properties, then invoke a validate() so that my gsp's render proper error
> messages everytime there's a failure. have to go this route since it's all
> inside a "catch" (my services throw an exception to terminate the
> transaction)
>
> On Sat, Apr 11, 2009 at 11:24 PM, Burt Beckwith <
burt@...>wrote:
>
> > I've seen the same thing. I have a utility method in a service that saves a
> > domain instance, and if it's not valid it logs the validation errors and
> > calls discard(). The weird thing that I was seeing was that if there was a
> > validation error for a database constraint (e.g. nullable or unique), it
> > would save the instance and the constraint violation would throw an
> > exception. It never even hit my service method.
> >
> > I spent a lot of time in a debugger and haven't completely figured out
> > what's going on, but the call to getMetaClass() in the service ends the
> > transaction and triggers a flush. I'm not sure yet why that's happening.
> >
> > All methods of a transactional service become transactional, even the ones
> > added by Groovy, so a more fine-grained configuration like in traditional
> > Spring using annotations, or even just discovering the "real" methods and
> > making all of them transactional would avoid this.
> >
> > The core problem is that the instance was updated outside of the service,
> > so dirty checking causes a flush. I reworked everything so I make all
> > changes in a service (the utility method is in the base class that all
> > services extend) and save the instance there. For a few parameters I make an
> > explicit signature, e.g. "void updatePerson(person, username, password)" and
> > extract the parameters in the controller, but if there are several I punt
> > and pass in the whole params map, e.g. "void updatePerson(person, params)".
> >
> > Burt
> >
> > > hi all,
> > > i've moved a lot of GORM calls to services instead of controllers. this
> > is
> > > due to the fact i need transactions that spans more than one domain
> > class.
> > > unfortunately, when erroneous properties are set to the domain class,
> > they
> > > get retained or saved. to illustrate:
> > >
> > >
> > > *domain class:*
> > >
> > > class Book
> > > {
> > > String title
> > > static constraints = {
> > > title(blank: false)
> > > }
> > > }
> > >
> > > service:
> > >
> > > *service method:*
> > >
> > > def update(book)
> > > {
> > > if(!book.hasErrors() || book.save())
> > > {
> > > //do something
> > > }
> > > else
> > > {
> > > throw new RuntimeException()
> > > }
> > > ..
> > > ..
> > >
> > > }
> > >
> > > *controller method:*
> > >
> > > def update = {
> > > def book = Book.get(params['id'])
> > > book.properties = params
> > > if(!book.hasErrors() && bookService.update(book)
> > > {
> > > ....
> > > }
> > > else
> > >
> > > ...
> > > }
> > >
> > >
> > >
> > > if the "title" i pass is blank, and invoke the update action, when i go
> > to
> > > "show" or "browse" actions, i see that the book's title is now blank.
> > > although it did enter the "else" clause in the "update" action. but
> > somehow,
> > > the book retained the title property inserted to it.
> > >
> > >
> > > verified that without the service, and putting just "if(!book.hasErrors()
> > ||
> > > book.save())" to the controller, this behavior is not seen.
> > >
> > > am i doing anything wrong?
> > >
> > > regards,
> > > mykol
> > >
> >
>