Search code examples
javagrailsgroovygrails-orm

Getting error in binding a set in command object


I am trying to bind request to a command object. I have to map a set in command object,but i am getting error "type mismatch,rejected value null". i am stuck here, how can i resolve this.

my command object is

@Validateable
public class CreateFundingCommand extends BaseCommand {
    Set<Causes> 
}

my domain class is

class CrowdFunding extends BaseEntity{

Set<Causes> 

}

my controller is

 def saveCreateFunding(CreateFundingCommand createFundingCommand){
        log.debug"hello"+params
        createFundingCommand.validate()
        if(createFundingCommand.hasErrors()){
            log.debugg"errors"+createFundingCommand.errors
        }else{
            crowdFundingService.saveCreateFunding(createFundingCommand.getCrowdFunding())
        }
    }

Causes class is

class Causes extends BaseEntity {
    String name
    String description
    String icon
}

My params are :

causes:{"name":"prabh","description":"ggg","icon":"deec"}

errrors are :

rejected value [{"name":"prabh","description":"ggg","icon":"deec"}]; codes [com.volcare.command.crowdFunding.CreateFundingCommand.causes.typeMismatch.error,com.volcare.command.crowdFunding.CreateFundingCommand.causes.typeMismatch,createFundingCommand.causes.typeMismatch.error,createFundingCommand.causes.typeMismatch,typeMismatch.com.volcare.command.crowdFunding.CreateFundingCommand.causes,typeMismatch.causes,typeMismatch.java.util.Set,typeMismatch]; arguments [causes]; default message [Could not find matching constructor for: com.volcare.domain.setting.Causes(java.lang.String)]

Solution

  • The problem is probably the following:

    causes:{"name":"prabh","description":"ggg","icon":"deec"}
    

    You probably want that to be something like this:

    causes:[{"name":"prabh","description":"ggg","icon":"deec"}]
    

    Notice that the value of causes should be a list of Map, not a Map.

    See https://github.com/jeffbrown/fundbinding. That project includes the following:

    src/groovy/demo/CreateFundingCommand.groovy

    package demo
    
    @grails.validation.Validateable
    class CreateFundingCommand extends BaseCommand {
        Set<Cause> causes
    }
    

    grails-app/controllers/demo/DemoController.groovy

    package demo
    
    class DemoController {
    
        def saveCreateFunding(CreateFundingCommand createFundingCommand){
            if(createFundingCommand.hasErrors()){
                render 'Errors were found'
            }else{
                render 'No errors were found'
            }
        }
    }
    

    test/unit/demo/DemoControllerSpec.groovy

    package demo
    
    import grails.test.mixin.TestFor
    import spock.lang.Specification
    
    @TestFor(DemoController)
    class DemoControllerSpec extends Specification {
    
        void "test valid command object"() {
            when:
            request.json = '{"causes":[{"name":"prabh","description":"ggg","icon":"deec"}]}'
            controller.saveCreateFunding()
    
            then:
            response.text == 'No errors were found'
        }
    
        void "test invalid command object"() {
            when:
            request.json = '{"causes":{"name":"prabh","description":"ggg","icon":"deec"}}'
            controller.saveCreateFunding()
    
            then:
            response.text == 'Errors were found'
        }
    }
    

    Also note that in your code you are calling createFundingCommand.validate() inside of you controller action which is not necessary. The instance will already have been validated before your code executes.

    I hope that helps.