首页 > 解决方案 > 资源注释域上集合属性的 Grails REST 更新不起作用

问题描述

我在带@Resource注释的域类和RestfulController为所述类自动生成的问题上遇到了一个非常奇怪的问题。具体来说,我的 Domain 实体在 type中Product有一个 CollectionhasMany属性,我正在尝试使用 PUT在实例中进行更新,但更新不起作用。partsPartpartsProduct

我的包含域实体Product定义如下:

package com.test

import grails.rest.Resource

@Resource(uri='/rest/product', formats=['json', 'xml'])
class Product
{
  Integer completed  // Completed quantity
  Set<Part> parts    // Each requested product has a list of requested parts

  static hasMany = [parts: Part]

  static constraints = {
    parts minSize: 1
  }
}

我的部分定义如下:

package com.test

import grails.rest.Resource

@Resource(uri='/rest/part', formats=['json', 'xml'])
class Part
{
  String identifier // Each part must have an identifier
  Double weight     // How much does each unit of this product part weigh
  Product product   // The product request that this part request belongs to

  static belongsTo = [product: Product]

  static constraints = {
  }
}

在我的 BootStrap.groovy 中,我已经为两个产品创建了两个部分(总共 4 个部分)。

package broken.put.array.property

import com.test.Product
import com.test.Part

class BootStrap {

    def init = { servletContext ->
      Product product = Product.findOrSaveWhere(completed: 4)
      product.addToParts(new Part(product: product, weight: 1237, identifier: "part1").save(failOnError: true, flush: true))
      product.addToParts(new Part(product: product, weight: 1236, identifier: "part2").save(failOnError: true, flush: true))
      product.save(failOnError: true, flush: true)
      Product product2 = Product.findOrSaveWhere(completed: 3)
      product2.addToParts(new Part(product: product2, weight: 1235, identifier: "part3").save(failOnError: true, flush: true))
      product2.addToParts(new Part(product: product2, weight: 1234, identifier: "part4").save(failOnError: true, flush: true))
      product2.save(failOnError: true, flush: true)
    }
    def destroy = {
    }
}

因此,在运行应用程序后,我执行以下操作:

$ curl -X PUT "http://localhost:8080/product/1" -H "Content-Type:application/json" -d '{"parts" : [{ "id": 1 }], "completed": 3}'

将 ID 为 1 的partsCollection 属性Product从具有 2 个部分更新为具有 1 个部分。出于某种原因,更新总是最终根本没有真正修改 parts 属性,如响应 JSON 中所示:

{"id":1,"parts":[{"id":2},{"id":1}],"completed":3}

所以我决定通过让我的@Resource注释包含一个superClass指向我自己的控制器的属性来调试它,我可以在其中做一些println. 我从默认的 RestfulController 中复制了update()方法的主体,并在其中添加了 println 语句以找出问题所在。经过一些实验,我了解到在设置instance.properties为之后getObjectToBind(),其中的partsCollection 仍然具有旧值(ID 为 1 和 2 的 Part 对象),而不是我在 PUT 的 JSON 正文中发送的值(具有 ID 的单个 Part 对象1)。

但是我发现还有一些非常令人惊讶的事情,如果我在设置为 的行之前放置了一个println打印输出的语句,那么更新会突然与我的预期行为一起工作。除了那个位置之外的任何东西都不会做。它必须打印.instance.propertiesgetObjectToBind()PUTinstance.properties

当我意识到这与巫毒教接壤时,我以已上传到TinyUpload的 zip 文件的形式创建了一个独立的测试用例项目。我的 grails 版本是 3.3.6。很想听听任何见过这种情况的人,或者谁能帮助我理解为什么会发生这种情况。您需要做的就是将 zip 文件解压缩到一个文件夹中,然后使用 grails dev run-app 运行它。代码的当前状态将该println行(第 42 行)注释掉了,src/main/groovy/com/test/ReactAdminRestfulController.groovy因此您可以看到我上面描述的内容。但是取消注释该行并重新运行应用程序将给出正确的行为。

标签: restgrailscontroller

解决方案


推荐阅读