Grails with MongoDB, Object id, and scaffold

旧时模样 提交于 2019-12-06 05:39:15

I believe this is happening because the show() method (that the Grails scaffolding functionality generates as an action) accepts an id parameter of type Long ie.

def show(Long id) {
    def suiteInstance = Suite.get(id)
    if (!suiteInstance) {
        flash.message = message(code: 'default.not.found.message', args: [message(code: 'suite.label', default: 'MyDomainClass'), id])
        redirect(action: "list")
        return
    }

    [suiteInstance: suiteInstance]
}

which binds the id parameter to the argument. Because the ObjectId can't be converted to a Long, it ends up being null, hence the call to MyDomainClass.get(id) fails with the error message.

You can get around this by overriding the show() action in your scaffolded controller so that it expects an ObjectId or String, but I would say the proper fix for this is to update the Grails scaffolding plugin so it is a little more liberal in the types of IDs it accepts.

I had this problem as well. You can keep the domain object id as an ObjectId and update the controller as follows:

domain Object:

import org.bson.types.ObjectId;

class DomainObject {
        ObjectId id
        // Add other member variables...
}

Controller:

def show(String id) {
    def domainObjectInstance = domainObject.get(new ObjectId(id))
    if (!domainObjectInstance) {
        flash.message = message(code: 'default.not.found.message', args: [message(code: 'domainObject.label', default: 'DomainObject'), id])
        redirect(action: "list")
        return
    }

    [domainObjectInstance: domainObjectInstance]
}

You would also need to update your other controller methods that use id as well such as edit, update etc.

Additionally, if you want the grails default controller generation to work like this for all your domain objects you can update the template as coderLMN suggests.

The get(params.id) call in show() method will NOT convert params.id String to an ObjectId object, so the domain instance will be null, then the following code takes you to list action with an error message:

if (!exampleInstance) {
    flash.message = message(code: 'default.not.found.message', args: [message(code: 'example.label', default: 'Example'), params.id])
    redirect(action: "list")
    return
}

Possible solutions:

  1. you can run "grails install-template" command, so that the scaffolding templates in src/templates/scaffolding/ directory can be modified. Then you have new scaffold ready to generate customized controllers, views, tests for all your Domain classes.

  2. A simpler solution is to define the id property as String instead of ObjectId. A String id will be equal to objectId.toString(), in this case your scaffold will work.

In domain classes keep you id type as ObjectId and keep scaffold = true for all respective controllers.

In Domain class :

ObjectId id

In respective controller :

static scaffold = true

Clear all existing collections from Mongo

I guess that's sufficient to have Grails-Mongo app up & running, considering you have correctly configured mongo-plugin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!