Когда я пытаюсь привязать полезную нагрузку 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, но без него все выходит из строя.Я думаю, что привязка данных сможет справиться с этим, поскольку она отлично отображает остальные свойства, но, кажется, просто ужасно терпит неудачу для справки.
Наконец, причина, по которой я столкнулся с этим, заключается в том, чтопотому что я пытаюсь построить клиент Griffon на основе REST API, и кажется, что HTTPBuilder удаляет "class": "server.Session"
, когда он преобразует исходный ответ JSON в net.sf.json.JSONObject
, так как ответ по проводам имеетсвойство в нем, но дамп net.sf.json.JSONObject
этого не делает, и при этом полезная нагрузка последующих запросов JSON.
- Является ли это ошибкой в том, как Grails связывается с данными, когда нет «класса»свойство объекта JSON?
- Это ошибка в том, как HTTPBuilder анализирует ответ JSON?
- Это ошибка в том, как HTTPBuilder выводит JSON из net.sf.json.JSONObject?
- Я просто что-то делаю не так?
Обновление
Я нашел несколько дополнительных битов информации:
- Удаление уникального ограничения не меняет поведение
- Если поле
uploader
имеет значение ненулевое , а внутренний объект JSON пытается установить его на null
свойство не изменено (и не возникает ошибка).Но если свойство "class": "server.Session"
находится во внутренней полезной нагрузке JSON, оно изменяется на null
, как и ожидалось.