Вопрос

Я что-то упускаю....

У меня есть 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", который находится внутри замыкания Target.list().each {}, помещается в область потока, и я не могу понять, как пометить его как переходный.

У меня есть некоторый код в Службе, в котором объекты помещаются в область потока, когда я этого тоже не хочу.

Как мне остановить размещение локальных переходных переменных в замыканиях в области потока?

Это было полезно?

Решение

Уточнение приведенного выше ответа вместо очистки PersistenceContext мы просто удаляем экземпляры по мере завершения работы с ними, вот так:

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

Это все еще обходной путь из-за невозможности пометить переменные замыкания как временные

Другие советы

Ответ на мой вопрос таков:

объект потока - это карта, которая содержит ссылку на "PersistenceContext", который является org.hibernate.impl.SessionImpl, поэтому поток пытается сохранить весь сеанс, даже если объекты не изменены (я полагаю, для контекста)

это неверный пример из grails 1.1.x doc дает нам подсказку, что делать:

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

Очевидная проблема с этим заключается в том, что сеанс очищается полностью, вместо того чтобы просто не допускать в поток то, что мне не нужно.

за неимением лучшего способа, вот обобщенное решение, которое удаляет любые несериализуемые объекты из PersistenceContext потока.Это может быть метод обслуживания, учитывая поток:-

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

Если вам, как и мне, нужно выселить всех, возможно, вам нравится это делать

flow.persistenceContext.flush()
flow.persistenceContext.persistenceContext.clear()
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top