Grails Webflow - 흐름 범위를 *밖*으로 유지
-
18-09-2019 - |
문제
뭔가 빠졌네요....
다음과 같은 Grails 웹플로가 있습니다.
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().each {} 클로저 내부에 있는 "대상" 객체가 흐름 범위에 들어가고 있으며 이를 임시로 표시하는 방법을 알 수 없습니다.
원하지 않을 때 흐름 범위에 개체가 배치된 서비스에 일부 코드가 있습니다.
흐름 범위에 배치되는 클로저의 로컬 임시 변수를 어떻게 중지합니까?
해결책
persistenceContext를 지우는 대신 위의 답변을 구체화하여 다음과 같이 인스턴스를 완료할 때 간단히 인스턴스를 제거합니다.
Target.list().each {
targets.add(new TargetCommand(name: it.name, id: it.id))
flow.persistenceContext.evict(it)
}
이는 클로저 변수를 일시적인 것으로 표시할 수 없는 해결 방법입니다.
다른 팁
내 질문에 대한 답은 다음과 같습니다.
Flow 객체는 org.hibernate.impl.sessionimpl 인 "persistencecontext"에 대한 참조를 포함하는 맵입니다. 따라서 객체가 변경되지 않더라도 흐름이 전체 세션을 저장하려고합니다 (컨텍스트를 위해).
이것 잘못된 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'
}
이것의 명백한 문제는 흐름에서 원하지 않는 것들을 막는 대신 세션이 완전히 지워진다는 것입니다.
더 나은 방법을 원하기 위해, 여기에는 흐름의 영구 콘텍스트에서 직렬화 할 수없는 객체를 제거하는 일반화 된 솔루션이 있습니다. 이것은 흐름을 감안할 때 서비스 방법 일 수 있습니다.
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()