在Grails中发布嵌套资源的问题

时间:2014-07-25 18:04:49

标签: java rest grails groovy gorm

我在理解Grails Restful控制器如何工作方面遇到了问题。我正在尝试向嵌套资源发布帖子请求(见下文)。我不确定我是否理解我需要更改以使其工作,因为看起来GET请求与其父资源项构建Bid的关联,但是当我尝试POST时,我被警告该项不能为空。< / p>

感谢任何帮助!

Item.groovy

class Item {
    static hasMany = [bids:Bid]
}

Bid.groovy

class Bid {
    Integer ownerId
    Double amount

    static belongsTo = [item:Item]

    static constraints = {
        ownerId nullable: false
        amount nullable: false
    }
}

BidController.groovy

class BidController extends RestfulController<Bid> {
    static responseFormats = ['json', 'xml']
    BidController() {
        super(Bid)
    }
    @Override
    def getObjectToBind() {
        request.parameterMap.put('itemId', params.itemId)
        return request
    }
}

ItemController.groovy

class ItemController extends RestfulController<Item> {
    static responseFormats = ['json', 'xml']
    ItemController() {
        super(Item)
    }
}

UrlMappings.groovy

class UrlMappings {

    static mappings = {
        "/items"(resources:"item") {
            "/bids"(resources: "bid")
        }
    }
}

网址映射

Controller: item
 |   GET    | /items                                                    | Action: index            
 |   GET    | /items/create                                             | Action: create           
 |   POST   | /items                                                    | Action: save             
 |   GET    | /items/${id}                                              | Action: show             
 |   GET    | /items/${id}/edit                                         | Action: edit             
 |   PUT    | /items/${id}                                              | Action: update           
 |  PATCH   | /items/${id}                                              | Action: patch            
 |  DELETE  | /items/${id}                                              | Action: delete    
Controller: bid
 |   GET    | /items/${itemId}/bids                                     | Action: index            
 |   GET    | /items/${itemId}/bids/create                              | Action: create           
 |   POST   | /items/${itemId}/bids                                     | Action: save             
 |   GET    | /items/${itemId}/bids/${id}                               | Action: show             
 |   GET    | /items/${itemId}/bids/${id}/edit                          | Action: edit             
 |   PUT    | /items/${itemId}/bids/${id}                               | Action: update           
 |  PATCH   | /items/${itemId}/bids/${id}                               | Action: patch            
 |  DELETE  | /items/${itemId}/bids/${id}                               | Action: delete                    

发布请求

POST /AuctionService/items/1/bids HTTP/1.1
Content-Type: application/json
Host: localhost:8080
Connection: close
Content-Length: 34

{
    "ownerId": 1,
    "amount": 3.00
}

响应

HTTP/1.1 422 Unprocessable Entity
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 25 Jul 2014 17:44:03 GMT
Connection: close

{"errors":[{"object":"auctionservice.Bid","field":"item","rejected-value":null,"message":"Property [item] of class [class auctionservice.Bid] cannot be null"}]}

3 个答案:

答案 0 :(得分:1)

我认为您可以通过覆盖createResource()方法来完成您想要的任务。

@Override
protected Bid createResource() {

    Bid bid=super.createResource();
    bid.item=Item.get(params.itemId)
    return bid;
}

使用嵌套URL时,其他默认控制器操作可能无法按预期工作。 如果要确保只返回属于URL中项目的出价,您可能还想覆盖queryForResource和index

@Override
protected Stay queryForResource(Serializable id) {
    def itemId=params.itemId

    Bid.where {
        id==id &&  item.id == itemId
    }.find()

}

def index(Integer max) {
    params.max = Math.min(max ?: 10, 100)
    def itemId=params.itemId
    respond Bid.where {
        item.id==itemId
    }.list(params)
}

答案 1 :(得分:0)

RestfulController的实现有一个方法getObjectToBind(),它返回请求对象。我建议覆盖此方法并返回一个包含密钥itemId的映射,如此方法的注释中所述。

另一种选择可能是,在http json体中发送itemId。这有点多余,因为信息已经在网址中表示。但作为一种解决方法,这也可能是一个很好的解决方案。

答案 2 :(得分:0)

我建议使用@Resource注释Domain类,即使您实现自己的控制器也是如此。 Grails文档似乎表明你做了一个或另一个,注释域或编写自己的控制器扩展RestfulContoroller。

我发现没有域类注释,请求对象在createResource()方法中没有正确绑定。所有属性都为null。一旦我添加了域注释,就会按照我的预期重新绑定绑定。

在您的情况下,我希望/希望Grails能够处理所有关系,而无需您自己管理项目ID。所以,

@Resource(uri='items')
class Item {
    static hasMany = [bids:Bid]
}

和...

@Resource(uri='bids')
class Bid {
    Integer ownerId
    Double amount

    static belongsTo = [item:Item]

    static constraints = {
        ownerId nullable: false
        amount nullable: false
    }
}

希望您不再需要覆盖getObjectToBind()。

class BidController extends RestfulController<Bid> {
    static responseFormats = ['json', 'xml']
    BidController() {
        super(Bid)
    }
    //don't override the getObjectTobind
}

当我尝试将对象与一对一映射发布到另一个对象时,这对我有用。