views:

609

answers:

2

Hi,

In my Grails app, I have defined the following (simplified) web flow

def registerFlow = {

    start {
        action {RegistrationCommand cmd ->                

            try {
                memberService.validateRegistrationCommandDTO(cmd)

            } catch (MemberException ex) {
                flow.regErrorCode = ex.errorCode
                throw ex
            }
        }

        on("success").to "survey"  // The 'survey' state has been omitted
        on(MemberException).to "handleRegMemberException"
        on(Exception).to "handleUnexpectedException"
    }

    handleRegMemberException {
        action {
            // Implementation omitted
        }
    }

    handleUnexpectedException {
        redirect(controller:'error', action:'serverError')
    }
}

If a MemberException is thrown by the "start" state, execution should proceed to the "handleRegMemberException" state, but it doesn't. Is there something wrong with my flow definition, or my understanding of how this should work?

Thanks, Don

A: 

I am still pretty new to Groovy and Grails, but I have a suggestion. Perhaps the issue has something to do with the difference in the way the Grails framework (and Groovy for that matter) handles checked vs. unchecked exceptions.

If MemberException is a checked exception (extends Exception), perhaps the 'throw' that is inside the closure behaves to bring execution the whole way out of the webflow. You and I both could do some RTFM'ing on this one... I see the Groovy book on my bookshelf from here. As a quick answer, I would say change MemberException to an unchecked exception (extends RuntimeException) and see if you get the same results. Or, you could wrap MemberException in a RuntimeException...

throw new RuntimeException(ex)

Greg
A: 

The flow should behave as you expect. Something might be wrong with your flow, for example some other error in service, but it is not clear from your question what is actually going on. You say how you expect flow to behave and then you say it doesn't behave the way you expected, but you don't say how it actually behaves.

I suggest adding some traces to your flow to see what is actually going on.

By the way, there are some known bugs with different versions of grails and webflows are broken in grails 1.2-M3: http://jira.codehaus.org/browse/GRAILS-5185

Here is my flow similar to what you have programmed:

class SomeController {

    def index = {     
     redirect(action:'someProcess')      
        }

def someProcessFlow = {

 start{
  action{
   dosome -> 
    println "-> inside start action closure"
   try{
    println "-> throwing IllegalArgumentException"
    throw new IllegalArgumentException()
   }catch(IllegalArgumentException ex){
    println "-> inside catch"
    throw ex
    }
   throw new Exception()
   "success"    
      }
  on("success").to "helloPage"
  on(IllegalArgumentException).to "illegal"
  on(Exception).to "handleException"
     }

 illegal{
  action{    
   println "-> illegal handled"
   "success"
   }
  on("success").to "helloPage"
  }

 handleException{
  action{    
   println "-> generic exception handled"
   "success"
   }
  on("success").to "helloPage"
 }

 helloPage()

    }
}

It behave as you expect and the output is:

-> inside start action closure
-> throwing IllegalArgumentException
-> inside catch
2009-11-03 11:55:00,364 [http-8080-1] ERROR builder.ClosureInvokingAction  
- Exception     occured invoking flow action: null
 java.lang.IllegalArgumentException
    at SomeController$_closure2_closure3_closure6.doCall(SomeController:18)
    at java.lang.Thread.run(Thread.java:619)
-> illegal handled
Dan