« Return to Thread: Domain object retains erroneous properties when in a Service

Re: Domain object retains erroneous properties when in a Service

by mykol :: Rate this Message:

Reply to Author | View in Thread

ah! so the setting of "properties" should happen inside the service, and not in the controller.

service:

def update(book, params)
{
  book.properties = params
  ...
}

thanx for the tip! will give this a shot

On Sun, Apr 12, 2009 at 12:03 AM, Burt Beckwith <burt@...> wrote:
I've found that you can load the domain instance in the controller (it makes sense to do this there so you can more easily display an appropriate message about missing id param, or existing param but instance not found, etc.), but changes and the call to save() need to be done in the service. The session is open the whole time due to the OpenSessionInView interceptor, but the transaction is what's triggering an early flush.

Burt

> 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
> > >
> >
>

 « Return to Thread: Domain object retains erroneous properties when in a Service