Domanda

mi sfugge qualcosa....

Ho un flusso web Grails che assomiglia a questo: -

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 è serializzabile.ma ottengo questo errore: -

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

Per qualche motivo l'oggetto "target" che si trova all'interno della chiusura Target.list().each {} viene inserito nell'ambito del flusso e non riesco a capire come contrassegnarlo come transitorio.

Ho del codice in un servizio che ha oggetti inseriti nell'ambito del flusso quando non voglio che lo facciano anch'essi.

Come posso impedire che le variabili transitorie locali nelle chiusure vengano inserite nell'ambito del flusso?

È stato utile?

Soluzione

Raffinazione la risposta di cui sopra, invece di cancellare la PersistenceContext abbiamo semplicemente sfrattare le istanze finiamo con loro, in questo modo:

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

Questo è ancora un work-around per non essere in grado di marcare le variabili di chiusura come transitoria

Altri suggerimenti

La risposta alla mia domanda è:

l'oggetto flusso è una mappa che contiene un riferimento a "persistenceContext" che è un org.hibernate.impl.SessionImpl quindi il flusso tenta di memorizzare l'intera sessione, anche se gli oggetti non vengono modificati (per contesto suppongo)

Questo errato esempio dal documento Grails 1.1.x ci dà un indizio su cosa fare:

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() cancella l'intera mappa del flusso incluso il persistenceContext o la sessione, il che fa sì che l'intero flusso fallisca a causa della mancanza di una sessione.

quindi la "soluzione" intermedia è utilizzare persistenceContext e in questo caso cancellarlo.Quindi funziona: -

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

L'ovvio problema con questo è che la sessione viene completamente cancellata, invece di tenere semplicemente fuori le cose che non voglio nel flusso.

in mancanza di un modo migliore, ecco una soluzione generalizzata che rimuove tutti gli oggetti non Serializable dalla PersistenceContext del flusso. Questo potrebbe essere un metodo di servizio dato il flusso: -

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

Se come me avete bisogno di sfrattare tutti forse ti piace fare

flow.persistenceContext.flush()
flow.persistenceContext.persistenceContext.clear()
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top