316
316

Reputation: 11

grails 3 mongodb: Method on class [] was used outside of a Grails application

I am using the following:

I have two domain objects that look like this:

class PhoneNumber {
    String country
    String numberString

    static constraints = {
        country nullable: false, size: 2..2
        numberString nullable: false, blank: false, size: 1..16
    }
}

and

class Contact {
    String name

    static hasMany = [phoneNumber: PhoneNumber]

    static embedded = ['phoneNumber']
    static constraints = { }
}

I have a controller that looks like this:

class ContactController extends RestfulController {
    static responseFormats = ['json', 'xml']

    ContactController() { super(Contact) }


    @Transactional
    def save(Contact contact) {
        println contact
        response.status = 201
        def result = [:]
        result.id = 1
        render result as JSON
    }
}

When I POST to the controller via:

curl -XPOST "http://localhost:8080/contact" -d "@contact.json"

I get a response of {"id":1}. However if I add the following line to my Contact and PhoneNumber domain objects:

static mapWith = 'mongo'

I get the following error:

ERROR org.grails.web.errors.GrailsExceptionResolver - IllegalStateException occurred when processing request: [POST] /contact - parameters:
{"id":null,"name":"Full Name","phoneNumber":[{"country":"ca","numberString":"18095551212"},{"country":"ca","numberString":"16135551212"}]}: 
Method on class [xxx.Contact] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.. Stacktrace follows:
    java.lang.IllegalStateException: Method on class [demo.Contact] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly.
at  grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:93) ~[grails-core-3.0.1.jar:3.0.1]
at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:90) ~[grails-core-3.0.1.jar:3.0.1]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_05]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_05]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]

What else needs to be done to get mongodb domain objects marshalled on a POST?

Upvotes: 0

Views: 413

Answers (1)

Dem Pilafian
Dem Pilafian

Reputation: 5976

Explicitly define the id field as an ObjectId when using MongoDB.

domain/com/example/Book.groovy

package com.example

import org.bson.types.ObjectId

class Book {

   ObjectId id
   String   title
   String   author

   static mapWith = "mongo"

}

BSON IDs are not simple long numbers — they contain four parts, including a timestamp. When converted to a String (example: book.id as String), the ID will be 24 characters long and look something like: "556a7299aa2437211f8e4e73"

See:
https://docs.mongodb.com/manual/reference/method/ObjectId

Upvotes: 1

Related Questions