user771912
user771912

Reputation: 411

trouble binding parameters to an object and successfully save()

I have a somewhat basic Q/A application and I'm having problem changing the order of my answers. The answers are displayed through the Ordinal property which has a unique constraint.

answer domain

class Answer {

    DateTime dateCreated
    DateTime lastUpdated

    String body
    Integer ordinal
    String reason

    static belongsTo = [question: Question]

    static constraints = {
        body blank: false
        ordinal unique: 'question'
    }

    String toString() {
        "Answer: $body"
    }
}

question domain

class Question {

    DateTime dateCreated
    DateTime lastUpdated

    String body
    Answer correctAnswer
    Integer ordinal

    static belongsTo = [lesson: Lesson]
    static hasMany = [answers: Answer]

    static constraints = {
        body blank: false
        correctAnswer nullable: true,
                validator: { Answer val, Question obj ->                    
                val ? val.question == obj : true // TODO: Give this a proper error message
            }
        ordinal unique: 'lesson'
    }

    static mapping = {
        lesson lazy: true
        answers sort: 'ordinal'
    }
}

I update the ordinals through a form

form image

<g:each status="i" in="${questionInstance.answers}" var="answer">
    <input type="number" name="answers[${i}].ordinal" value="${answer?.ordinal}" />: ${answer}
</g:each>    

update action

the params binds to the questionInstance.answers object and updates the ordinal fields the each answer

def update(Long id, Long version) {

    def questionInstance = Question.get(id)

    questionInstance.properties = params

    if (!questionInstance.save(flush: true)) {
        render(view: "edit", model: [questionInstance: questionInstance])
        return
    }

    redirect(action: "index", id: questionInstance.id)
}

this is what my questionInstance.answers object looks like before I bind the params before

after the params are assigned. Notice that answers has changed from hibernate.collection.PersistentSet to grails.web.binding.ListOrderedSet

after

stacktrace

No signature of method: edu.example.work_department.website.Question$__clinit__closure1_closure3.doCall() is applicable for argument types: (edu.example.work_department.website.Answer, edu.example.work_department.website.Question) values: [Answer: Answer 2, edu.example.work_department.website.Question : 1]
Possible solutions: doCall(edu.example.work_department.website.Answer, edu.example.work_department.website.Question), call(), call([Ljava.lang.Object;), call(java.lang.Object), call(edu.example.work_department.website.Answer, edu.example.work_department.website.Question), findAll()
The following classes appear as argument class and as parameter class, but are defined by different class loader:
edu.example.work_department.website.Answer (defined by 'java.net.URLClassLoader@689319a1' and 'groovy.lang.GroovyClassLoader@8db6e40'), edu.example.work_department.website.Question (defined by 'java.net.URLClassLoader@689319a1' and 'groovy.lang.GroovyClassLoader@8db6e40')
If one of the method suggestions matches the method you wanted to call, 
then check your class loader setup.. Stacktrace follows:
'groovy.lang.MissingMethodException: No signature of method: edu.example.work_department.website.Question$__clinit__closure1_closure3.doCall() is applicable for argument types: (edu.example.work_department.website.Answer, edu.example.work_department.website.Question) values: [Answer: Answer 2, edu.example.work_department.website.Question : 1]
Possible solutions: doCall(edu.example.work_department.website.Answer, edu.example.work_department.website.Question), call(), call([Ljava.lang.Object;), call(java.lang.Object), call(edu.example.work_department.website.Answer, edu.example.work_department.website.Question), findAll()
The following classes appear as argument class and as parameter class, but are defined by different class loader:
edu.example.work_department.website.Answer (defined by 'java.net.URLClassLoader@689319a1' and 'groovy.lang.GroovyClassLoader@8db6e40'), edu.example.work_department.website.Question (defined by 'java.net.URLClassLoader@689319a1' and 'groovy.lang.GroovyClassLoader@8db6e40')
If one of the method suggestions matches the method you wanted to call, 

The error occurs when hitting the questionInstance.save() command. What am I doing wrong that it doesn't like my argument types?

Upvotes: 0

Views: 226

Answers (1)

JiniKJohny
JiniKJohny

Reputation: 1182

It is better to avoid data binding with

object.properties = params

Apart from this, you can use Command classes grails command class creation

And you can bind data using command class object.

For your Domain class Answer

create command class as :

Class AnswerCommand {      

    String body
    Integer ordinal
    String reason

    static constraints = {
        body blank: false
        ordinal unique: 'question'
    }
}

and read the params as command class object.

def update(Long id, Long version, AnswerCommand answerCmd) {

    def questionInstance = Question.get(id)

    //questionInstance.properties = params // use the below codes.

      questionInstance.body = answerCmd.body
      questionInstance.ordinal = answerCmd.ordinal
      questionInstance.reason = answerCmd.reason

    //here you can use bindData() also. But this is for making you a clear picture.


    if (!questionInstance.save(flush: true)) {
        render(view: "edit", model: [questionInstance: questionInstance])
        return
    }

    redirect(action: "index", id: questionInstance.id)
}

Upvotes: 3

Related Questions