The Artima Developer Community
Sponsored Link

Java Buzz Forum
Recursive queries from a custom validator

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Chuck Hinson

Posts: 26
Nickname: chuckit
Registered: Mar, 2005

Chuck Hinson is a software developer
Recursive queries from a custom validator Posted: Feb 9, 2012 6:02 PM
Reply to this message Reply

This post originated from an RSS feed registered with Java Buzz by Chuck Hinson.
Original Post: Recursive queries from a custom validator
Feed Title: Chuck Hinson
Feed URL: http://chuckhinson.blogspot.com/atom.xml
Feed Description: Observations, questions and musings related to my life in the software industry.
Latest Java Buzz Posts
Latest Java Buzz Posts by Chuck Hinson
Latest Posts From Chuck Hinson

Advertisement
Just spent the morning tracking down a stack overflow while trying to implement a grails custom validator.

I have a domain class that has a parent/child relationship with itself (instance form a tree). When I update instances, I need to make sure that I haven't created a cycle (the instance has itself as its own parent/ancestor)

To do this, I created a custom validator to check that the object doesnt have itself as its own parent and that its parent is not also a child/descendent

class Afsc 
{
  String id
  String code
  Afsc parent

  def afscService
  def sessionFactory
  ...
  static constraints = {
    ...
    parent (nullable: true, validator: { val, obj ->
      if (obj.id && (val?.id == obj.id)
          || obj.afscService.getChild(obj, val.code)) {
        return 'AFSC.cannot.be.cyclic'
      }
    })
  }
...
}

The fun part is that getChild() does a recursive search checking to see that the instance doesnt have its parent as a child:

  def getChild(parent, targetCode) {
    def children = Afsc.findAllByParent(parent)
    def child = children.find {
      it.code == targetCode
    }
    if (!child) {
      children.each {
        child = child ?: getChild(it,targetCode)
      }
    }
    return child
  }


When I tried this, I started getting stack overflow exceptions.  Long story short, it turns out that using  findAllByParent() causes hibernate to flush changes before executing the query.  Well, guess what happens when changes are flushed?  That's right - the validator gets called.  Which calls getChild().  Which calls findAllByParent().  Which causes a flush.  Which gives us infinite recursion and a stack overflow.

Once I figured out what was going on, it wasnt too hard to find the solution - tell grails/hibernate not to automatically flush changes:

    parent (nullable: true, validator: { val, obj ->
      if (obj.id && val) {
        if (val.id == obj.id) {
          return 'AFSC.cannot.be.cyclic'
        }
        def originalFlushMode = obj.sessionFactory.currentSession.flushMode
        obj.sessionFactory.currentSession.flushMode = org.hibernate.FlushMode.MANUAL
        try {
          if (obj.afscService.getChild(obj, val.code)) {
            return 'AFSC.cannot.be.cyclic'
          }
        }
        catch(Exception e) {
          return e.getMessage()
        }
        finally {
          obj.sessionFactory.currentSession.flushMode = originalFlushMode
        }
       
      }
    })




Read: Recursive queries from a custom validator

Topic: Best Of The Week - 2012 - W05 Previous Topic   Next Topic Topic: Top 10 examples of find command in unix and linux

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use