Grails Webflow - keeping things *out* of flow scope

不羁岁月 提交于 2019-12-10 10:06:16

问题


I'm missing something....

I have a Grails webflow that looks like this:-

def childFlow = {
        start {
            action {
                def targets = []
                Target.list().each {target ->
                    targets.add(new TargetCommand(name: target.name, id: target.id))
                }
                log.debug "targets are $targets"
                [children: targets]
            }
            on('success').to('selectChild')
        }
        ...

TargetCommand is serializable. but I get this error:-

Caused by: java.io.NotSerializableException: com.nerderg.groupie.donate.Target

For some reason the "target" object that is inside the Target.list().each {} closure is getting put into the flow scope, and I can't figure out how to mark it as transient.

I have some code in a Service that has objects placed in the flow scope when I don't want them to too.

How do I stop local transient variables in closures being put in the flow scope?


回答1:


Refining the above answer instead of clearing the persistenceContext we simply evict the instances as we finish with them, like so:

    Target.list().each {
        targets.add(new TargetCommand(name: it.name, id: it.id))
        flow.persistenceContext.evict(it)
    }

This is still a work-around for not being able to mark the closure variables as transient




回答2:


The answer to my question is:

the flow object is a map that contains a reference to the "persistenceContext" which is a org.hibernate.impl.SessionImpl so the flow tries to store the entire session, even if the objects are not changed (for context I suppose)

this incorrect example from grails 1.1.x doc gives us a clue what to do:

processPurchaseOrder  {
     action {
         def a =  flow.address
         def p = flow.person
         def pd = flow.paymentDetails
         def cartItems = flow.cartItems
         flow.clear()

    def o = new Order(person:p, shippingAddress:a, paymentDetails:pd) 
    o.invoiceNumber = new Random().nextInt(9999999) cartItems.each { o.addToItems(it) }
    o.save() 
    [order:o] } 
    on("error").to "confirmPurchase" 
    on(Exception).to "confirmPurchase" 
    on("success").to "displayInvoice" 
}

The flow.clear() clears the entire flow map including the persistenceContext or the session, which then makes the whole flow fail due to lack of a session.

so the intermediate "solution" is to use the persistenceContext and in this case clear it. So this works:-

def childFlow = {
        start {
            action {
                sponsorService.updateTargetsFromTaggedContent()
                def targets = []

                Target.list().each {
                    targets.add(new TargetCommand(name: it.name, id: it.id))
                }

                flow.persistenceContext.clear()
                [children: targets]
            }
            on('success').to('selectChild')
            on(Exception).to 'finish'
        }

The obvious problem with this is that the session is cleared completely, instead of just keeping out things I don't want in the flow.




回答3:


for want of a better way, here is a generalised solution that removes any non Serializable objects from the persistenceContext of the flow. This could be a service method given the flow:-

def remove = []
flow.persistenceContext.getPersistenceContext().getEntitiesByKey().values().each { entity ->
    if(!entity instanceof Serializable){
        remove.add(entity)
    }
}
remove.each {flow.persistenceContext.evict(it)}



回答4:


If like me you need to evict all maybe you like to do

flow.persistenceContext.flush()
flow.persistenceContext.persistenceContext.clear()


来源:https://stackoverflow.com/questions/1691853/grails-webflow-keeping-things-out-of-flow-scope

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!