当我尝试将 JSON 有效负载绑定到对另一个域对象具有可为空引用的现有域对象时,如果入站 JSON 指示引用为空,则绑定失败。这会导致持久性尝试失败并出现以下错误:
| Error 2011-12-21 10:21:24,202 ["http-bio-8080"-exec-3] ERROR hibernate.AssertionFailure - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
Message: null id in server.Uploader entry (don't flush the Session after an exception occurs)
Line | Method
->> 105 | update in server.SessionController
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 603 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run in java.lang.Thread
| Error 2011-12-21 10:21:24,206 ["http-bio-8080"-exec-3] ERROR errors.GrailsExceptionResolver - AssertionFailure occurred when processing request: [POST] /Server/session/2
null id in server.Uploader entry (don't flush the Session after an exception occurs). Stacktrace follows:
Message: null id in server.Uploader entry (don't flush the Session after an exception occurs)
Line | Method
->> 105 | update in server.SessionController
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 603 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run in java.lang.Thread
这是有问题的域对象:
class Session {
DateTime dateCreated
DateTime lastUpdated
String ip
String state
static hasOne = [uploader:Uploader]
static constraints = {
ip blank: false
state blank: false
uploader nullable: true, unique: true
}
}
class Uploader {
DateTime dateCreated
DateTime lastUpdated
Session session
String firstName
String lastName
String organization
String phoneNumber
String emailAddress
static constraints = {
firstName blank: false
lastName blank: false
organization blank: false
}
}
这是引发错误的控制器代码:
def update() {
def sessionInstance = Session.get(params.id)
if (!sessionInstance) {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'session.label', default: 'Session'), params.id])
redirect(action: "list")
return
}
if (params.version) {
def version = params.version.toLong()
if (sessionInstance.version > version) {
sessionInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
[message(code: 'session.label', default: 'Session')] as Object[],
"Another user has updated this Session while you were editing")
render(view: "edit", model: [sessionInstance: sessionInstance])
return
}
}
sessionInstance.properties = params
if (!sessionInstance.save(flush: true)) { // <---- Error thrown here
render(view: "edit", model: [sessionInstance: sessionInstance])
return
}
flash.message = message(code: 'default.updated.message', args: [message(code: 'session.label', default: 'Session'), sessionInstance.id])
redirect(action: "show", id: sessionInstance.id)
}
这是导致问题的 JSON 有效负载:
{
"id":2,
"dateCreated":"2011-12-21T09:33:33-06:00",
"ip":"127.0.0.1",
"lastUpdated":"2011-12-21T09:33:33-06:00",
"state":"closed",
"uploader":null
}
但是这个 JSON 有效负载工作得很好:
{
"class": "server.Session",
"id":2,
"dateCreated":"2011-12-21T09:33:33-06:00",
"ip":"127.0.0.1",
"lastUpdated":"2011-12-21T09:33:33-06:00",
"state":"closed",
"uploader":null
}
发生的情况是uploader
会话的属性被设置为"server.Uploader : null"
. 这是之后.dump()
的sessionInstance
对象sessionInstance.properties = params
:
<server.Session@713c6968 dateCreated=2011-12-21T09:33:33.000-06:00 lastUpdated=2011-12-21T09:33:33.000-06:00 ip=127.0.0.1 state=closed errors=grails.validation.ValidationErrors: 0 errors id=2 version=1 uploader=server.Uploader : null>
当"class": "server.Session"
属性在 JSON 有效负载中时,一切都正常工作,但没有它,一切都会崩溃。我认为数据绑定能够处理这个问题,因为它可以很好地映射其余属性,但似乎只是因为参考而失败了。
最后,我遇到此问题的原因是因为我正在尝试针对 REST API 构建 Griffon 客户端,并且似乎 HTTPBuilder在"class": "server.Session"
将原始 JSON 响应转换为时剥离了net.sf.json.JSONObject
response 中有属性,但转储net.sf.json.JSONObject
没有,后续的 JSON 请求有效负载也没有。
- 当 JSON 对象没有“类”属性时,这是 Grails 数据绑定方式的错误吗?
- 这是 HTTPBuilder 如何解析 JSON 响应的错误吗?
- HTTPBuilder 如何从 net.sf.json.JSONObject 输出 JSON 是否存在错误?
- 我只是在做完全错误的事情吗?
更新
我发现了一些额外的信息:
- 删除唯一约束不会改变行为
- 如果该
uploader
字段为非 null并且入站 JSON 对象尝试将其设置为null
,则该属性不会更改(并且不会发生错误)。但是,如果该"class": "server.Session"
属性在入站 JSON 有效负载中,它会null
按预期更改。