I am trying to save many-many related objects. A SellingCompany can have many accounts, and an account can be associated with many SellingCompanies. Thus, there are many relationships between tables stored in SellingCompaniesAccount
My Account_Info domain is as follows:
class AccountInfo { static mapping ={ table 'AccountInfo' version false //id column:'accountInfoID' } String evi_pass_phrase String evi_username String security_key // to make sure fields show up in a particular order static constraints = { //accountInfoID(insert:false,update:false) evi_pass_phrase() evi_username() security_key() } static hasMany = [sellingcompaniesaccount:SellingCompaniesAccount] String toString() { return "${evi_username}" } }
My SellingComapanies domain is as follows:
class SellingCompanies { static mapping = { table 'SellingCompanies' version false } String name
The table that contains the Many-Many relationships is as follows:
class SellingCompaniesAccount { static constraints = {
The form in the create.gsp file contains code that actually iterates through all the different SellingCompanies and displays as a flag.
<g:form action="save" method="post"> <div class="dialog"> <table width="500px" border="0px" color="red"> <tbody> <tr class="prop"> <td valign="top" class="name"><label for="accountInfo"><g:message code="sellingCompaniesAccount.accountInfo.label" default="Account Info" /></label></td> <td valign="top" class="value ${hasErrors(bean: sellingCompaniesAccountInstance, field: 'accountInfo', 'errors')}"> <g:select name="accountInfo.id" from="${content_hub_admin.AccountInfo.list()}" optionKey="id" value="${sellingCompaniesAccountInstance?.accountInfo?.id}" /></td> </tr> <tr class="prop"> <td valign="top" class="name"><label for="sellingCompanies"><g:message code="sellingCompaniesAccount.sellingCompanies.label" default="Selling Companies" /></label></td> <td valign="top" class=""> <g:each in="${content_hub_admin.SellingCompanies.list()}" var="item" status="i"> ${++i}. ${item.name} <g:checkBox name="sellingcompanies_${++i-1}" optionKey="id" value="${item.id}" /> <br> </g:each> </td> </tr> <tr class="prop"> <td valign="top" class="name"><label for="code"><g:message code="sellingCompaniesAccount.code.label" default="Code" /></label></td> <td valign="top" class="value ${hasErrors(bean: sellingCompaniesAccountInstance, field: 'code', 'errors')}"> <g:textField name="code" value="${sellingCompaniesAccountInstance?.code}" /></td> </tr> <tr class="prop"> <td valign="top" class="name"><label for="agency_name"><g:message code="sellingCompaniesAccount.agency_name.label" default="Agencyname" /></label></td> <td valign="top" class="value ${hasErrors(bean: sellingCompaniesAccountInstance, field: 'agency_name', 'errors')}"> <g:textField name="agency_name" value="${sellingCompaniesAccountInstance?.agency_name}" /></td> </tr> <tr class="prop"> <td valign="top" class="name"><label for="isActive"><g:message code="sellingCompaniesAccount.isActive.label" default="Is Active" /></label> </td> <td valign="top" class="value ${hasErrors(bean: sellingCompaniesAccountInstance, field: 'isActive', 'errors')}"> <g:checkBox name="isActive" value="${sellingCompaniesAccountInstance?.isActive}" /></td> </tr> <tr class="prop"> <td valign="top" class="name"><label for="agency_id"><g:message code="sellingCompaniesAccount.agency_id.label" default="Agencyid" /></label> </td> <td valign="top" class="value ${hasErrors(bean: sellingCompaniesAccountInstance, field: 'agency_id', 'errors')}"> <g:textField name="agency_id" value="${fieldValue(bean: sellingCompaniesAccountInstance, field: 'agency_id')}" /> </td> </tr> <tr class="prop"> <td valign="top" class="name"><label for="iata"><g:message code="sellingCompaniesAccount.iata.label" default="Iata" /></label></td> <td valign="top" class="value ${hasErrors(bean: sellingCompaniesAccountInstance, field: 'iata', 'errors')}"> <g:textField name="iata" value="${sellingCompaniesAccountInstance?.iata}" /></td> </tr> <tr class="prop"> <td valign="top" class="name"><label for="consultant_id"><g:message code="sellingCompaniesAccount.consultant_id.label" default="Consultantid" /></label></td> <td valign="top" class="value ${hasErrors(bean: sellingCompaniesAccountInstance, field: 'consultant_id', 'errors')}"> <g:textField name="consultant_id" value="${sellingCompaniesAccountInstance?.consultant_id}" /></td> </tr> <tr class="prop"> <td valign="top" class="name"><label for="contactinfo"><g:message code="sellingCompaniesAccount.contactinfo.label" default="Contactinfo" /></label></td> <td valign="top" class="value ${hasErrors(bean: sellingCompaniesAccountInstance, field: 'contactinfo', 'errors')}"> <g:select name="contactinfo.id" from="${content_hub_admin.ContactInfo.list()}" optionKey="id" value="${sellingCompaniesAccountInstance?.contactinfo?.id}" /></td> </tr> </tbody> </table> </div> <div class="buttons"><span class="button"><g:submitButton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'Create')}" /></span> </div> </g:form>
Finally, a controller that handles the save and list functions.
class SellingCompaniesAccountController { private static Logger log = Logger.getLogger(SellingCompaniesAccountController.class) //def index = { } //def scaffold = true def index = { redirect(action:list,params:params) } //To limit access to controller actions based on the HTTP request method. def allowedMethods = [save:'POST'] //create.gsp exists def create = { render(view:"create") } //edit.gsp exists //def edit = {} //list.gsp exists def list = { [ sellingCompaniesAccountInstanceList: SellingCompaniesAccount.list( max:15) ] } //show.gsp exists //def show={} //save.gsp exists def save = { log.info "Saving: " + params.toString() println("Saving: " + params.toString()) def sellingCompaniesAccount = params.sellingCompaniesAccount println(sellingCompaniesAccount) def sellingCompanies = params.sellingCompanies log.info "sellingCompanies: " + sellingCompanies println(sellingCompanies) def sellingCompaniesAccountInstance = new SellingCompaniesAccount(name: params.name) println(params.name) params.each { if (it.key.contains("_sellingcompanies")) //sellingCompaniesAccountInstance.sellingCompaniesId << SellingCompanies.get((it.key - "sellingcompanies_") as Integer) if (it.key.contains("sellingcompanies_")) sellingCompaniesAccountInstance.sellingCompaniesId << SellingCompanies.get((it.key - "sellingcompanies_") as Integer) } log.info sellingCompaniesAccountInstance if (sellingCompaniesAccountInstance.save(flush: true)) { flash.message = "${message(code: 'default.created.message', args: [message(code: 'sellingCompaniesAccountInstance.label', default: 'sellingCompaniesAccountInstance'), sellingCompaniesAccountInstance.id])}" redirect(action: "show", id: sellingCompaniesAccountInstance.id) log.info sellingCompaniesAccountInstance } else { render(view: "create", model: [sellingCompaniesAccountInstance: sellingCompaniesAccountInstance]) } } }
Now I get the following error due to empty hidden values similar to _sellingcompanies_1, etc .:
Error Logs:
Saving: ["accountInfo.id":"1", "accountInfo":["id":"1"], "_sellingcompanies_5":"", "_isActive":"", "code":"test", "agency_name":"test", "sellingcompanies_4":"4", "sellingcompanies_5":"5", "create":"Create", "isActive":"on", "iata":"test", "agency_id":"test", "contactinfo.id":"1", "contactinfo":["id":"1"], "consultant_id":"test", "sellingcompanies_2":"2", "_sellingcompanies_1":"", "sellingcompanies_3":"3", "_sellingcompanies_2":"", "_sellingcompanies_3":"", "sellingcompanies_1":"1", "_sellingcompanies_4":"", "action":"save", "controller":"sellingCompaniesAccount"] null null null 2011-03-15 17:13:44,620 [http-8080-2] ERROR org.codehaus.groovy.grails.web.errors.GrailsExceptionResolver - For input string: "_5" java.lang.NumberFormatException: For input string: "_5" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Integer.parseInt(Integer.java:449) at java.lang.Integer.valueOf(Integer.java:554) at content_hub_admin.SellingCompaniesAccountController$_closure4_closure5.doCall(content_hub_admin.SellingCompaniesAccountController:70) at content_hub_admin.SellingCompaniesAccountController$_closure4.doCall(content_hub_admin.SellingCompaniesAccountController:66) at content_hub_admin.SellingCompaniesAccountController$_closure4.doCall(content_hub_admin.SellingCompaniesAccountController) at java.lang.Thread.run(Thread.java:680)
First of all, where do the hidden values come from, and this approach is suitable for capturing Many-Many relationship information in the SellingCompaniesAccount controller class. The best technique for this.
Creator create.gsp resolves this in the browser: 
Thanks in advance