2009-11-07 48 views
3

的我失去了一些東西....Grails的Webflow的 - 讓事情*出*流量範圍

我有一個Grails的Webflow,看起來像這樣: -

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是序列化的。但我得到這個錯誤: - 。

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

出於某種原因,「目標」對象,它是Target.list(內部)每個{}封閉是越來越投入流通範圍,我就想不通了解如何將其標記爲瞬態。

我有一些服務中的對象放置在流程範圍中的代碼,當我不希望他們也是。

如何在放入流量範圍的閉包中阻止本地瞬態變量?

+0

實際上Target.list()的作用就是目標ojects在會議中,因此流量。 – pmc 2009-11-07 10:29:49

回答

3

提煉上面的回答,而不是清除persistenceContext我們只是退出的情況下,我們與他們完成,像這樣:

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

這仍然是一個變通爲不能以紀念閉包變量as transient

2

回答我的問題是:

流對象是包含了「persistenceContext」,這是一個org.hibernate.impl.SessionImpl所以流動試圖存儲整個會話的參考圖,即使對象沒有改變(背景下,我想)

從Grails的1.1.x版本文檔此不正確例子給了我們一個線索做什麼:

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

的flow.clear()清除該包含persistenceContext或會話的整個流程圖,然後由於缺少會話而導致整個流程失敗。

所以中間的「解決方案」是使用persistenceContext,在這種情況下清除它。所以這個工程: -

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

與此明顯的問題是,這次會議被完全清除,而不是僅僅保持了事情,我不想在流動。

+0

謝謝。我浪費了一個驚訝的下午,直到我看到你的答案。非常奇怪的行爲...不知道爲什麼流應該默認持續整個hibernate會話,但清除它對我有用。 – 2010-10-25 09:10:51

+0

當天很晚,但這顯然是爲了確保對話正常進行。另一種解決方案是創建任何可以從Serializable流中訪問的域類。 – 2010-11-29 13:43:30

+0

我已經提出了一個問題,順便說一句:http://jira.codehaus.org/browse/GRAILS-6984 – 2010-11-30 16:56:36

0

想要更好的方法,下面是一個通用的解決方案,它從流的persistenceContext中刪除任何非Serializable對象。這可能是考慮到流動服務的方法: -

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

這是一切都很好,直到你在選擇一個域對象的視圖中使用標記。我正在考慮webflow是不是爲此或它是一個braindead impl – pmc 2009-11-07 10:45:12

+0

通過實現調用flowService.cleanUpSession(流)的新標記來修復標記問題 - 例如, pmc 2009-11-07 11:15:17

+0

請注意,這似乎只適用於第一個狀態操作。 似乎工作的其他事情是分離有問題的域對象。 如果所有elese失敗都實現可序列化: - / – pmc 2009-11-16 02:35:15

0

如果你像我一樣需要也許驅逐所有你喜歡做

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