Enum constructor calls ara only allowed inside the enum class - grails

I'm working on a grails project. Right now I have a very disturbing problem. I have an enum called Status like this:
enum Status {
ENABLED("Habilitado"), DISABLED ("Desabilitado")
String type
private Status(String type) {
this.type = type
}
def String toString() {
return this.type
}
static list() {
[ENABLED, DISABLED]
}
}
I also have a controller called TesterController, which is where I keep getting errors saying "Enum constructor calls are only allowed inside the enum class" The thing is: I do not call the enum constructor from inside the controller class! Here it is:
class TesterController {
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def index() {
redirect(action: "list", params: params)
}
def list() {
def minElems = 10
if(params.max) minElems = params.int('max')
params.max = Math.min(minElems, 100)
[testers: Tester.list(params), testerTotal: Tester.count()]
}
def create() {
[tester: new Tester(params)]
}
def save() {
def tester = new Tester(params)
if (!tester.save(flush: true)) {
render(view: "create", model: [tester: tester])
return
}
flash.message = message(code: 'ateweb.created.message', args: [tester.name])
redirect(action: "show", id: tester.id)
}
def show() {
def tester = Tester.get(params.id)
if (!tester) {
flash.message = message(code: 'ateweb.not.found.message', args: [message(code: 'tester.label', default: 'Tester'), params.name])
redirect(action: "list")
return
}
[tester: tester]
}
def edit() {
def tester = Tester.get(params.id)
if (!tester) {
flash.message = message(code: 'ateweb.not.found.message', args: [message(code: 'tester.label', default: 'Tester'), params.name])
redirect(action: "list")
return
}
[tester: tester]
}
def update() {
def tester = Tester.get(params.id)
if (!tester) {
flash.message = message(code: 'ateweb.not.found.message', args: [message(code: 'tester.label', default: 'Tester'), params.name])
redirect(action: "list")
return
}
if (params.version) {
def version = params.version.toLong()
if (tester.version > version) {
tester.errors.rejectValue("version", "ateweb.optimistic.locking.failure",
[message(code: 'tester.label', default: 'Tester')] as Object[],
"Another user has updated this Tester while you were editing")
render(view: "edit", model: [tester: tester])
return
}
}
tester.properties = params
if (!tester.save(flush: true)) {
render(view: "edit", model: [tester: tester])
return
}
flash.message = message(code: 'ateweb.updated.message', args: [tester.name])
redirect(action: "show", id: tester.id)
}
}
Ok. So I am lost with this. Any help is appreciated.

There are a few issues with the definition of your Status class, though I don't know if these are the cause of your problem
enum Status {
ENABLED("Habilitado"), DISABLED ("Desabilitado")
String type
// delcaring the constructor private doesn't make much sense because
// enum constuctors can never be called outside the class
private Status(String type) {
this.type = type
}
// return type is declared as both def (Object) and String
def String toString() {
return this.type
}
// this is identical to the automatically-generated values() method
static list() {
[ENABLED, DISABLED]
}
}
Redefine this class as
enum Status {
ENABLED("Habilitado"), DISABLED ("Desabilitado")
String type
Status(String type) {
this.type = type
}
String toString() {
return this.type
}
}
and use values() instead of the deleted list() method, and maybe your problem will disappear

Related

Create form for domain object with multiselect Enum field fails with 'Property xxx is type-mismatched'

I am using Grails 4.0.4 w/ GORM 7.0.7.RELEASE
The database I am using is MongoDB
I can successfully run the application and navigate to the create form for the domain class. I can select the value for the singleton field someOtherEnum. I can multiselect values for the categories field. When I submit the form, however, I get this message: 'Property categories is type-mismatched'. I used this approach based on the answers to another question posted here, but it's not working for me. I am not using an embedded enum or hasMany collection like that user.
The controller and service were generated by the generate-all command.
How to add a multiple enum field to the create and edit forms in Grails 4?
I have an enum located in src/main/groovy/com/project/core/dsl I am using to populate a multiselect field for a domain class:
package com.project.core.dsl
import groovy.transform.CompileStatic
#CompileStatic
enum Category {
CATEGORY_ONE("Category One"),
CATEGORY_TWO("Category Two"),
CATEGORY_THREE("Category Three")
private final String id
private Category(String id) { this.id = id }
#Override
String toString() { id }
String getKey() { name() }
}
The domain class:
package com.project.core
import com.project.core.dsl.SomeOtherEnum
import com.project.core.dsl.Category
class DomainObject {
SomeOtherEnum someOtherEnum
Set<Category> categories
static constraints = {
}
static mapping = {
someOtherEnum index: true
}
#Override
String toString() {
return "DomainObject{" +
"someOtherEnum=" + someOtherEnum +
", categories=" + categories +
'}';
}
}
In the create.gsp view, I have this form:
<g:form resource="${this.domainObject}" method="POST">
<fieldset class="form">
<f:with bean="domainObject">
<f:field property="someOtherEnum"/>
<f:field property="categories">
<g:select
multiple="true"
name="${property}"
from="${Category}"
value="${domainObject?.categories}"
/>
</f:field>
</f:with>
</fieldset>
<fieldset class="buttons">
<g:submitButton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'Create')}" />
</fieldset>
</g:form>
The domain class Controller:
package com.project.core
import grails.validation.ValidationException
import static org.springframework.http.HttpStatus.*
class DomainObject {
DomainObjectService domainObjectService
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond domainObjectService.list(params), model:[domainObjectCount: domainObjectService.count()]
}
def show(Long id) {
respond domainObjectService.get(id)
}
def create() {
respond new DomainObject(params)
}
def save(DomainObject domainObject) {
if (domainObject == null) {
notFound()
return
}
try {
domainObjectService.save(domainObject)
} catch (ValidationException e) {
respond domainObject.errors, view:'create'
return
}
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'domainObject.label', default: 'DomainObject'), domainObject.id])
redirect domainObject
}
'*' { respond domainObject, [status: CREATED] }
}
}
def edit(Long id) {
respond domainObjectService.get(id)
}
def update(DomainObject domainObject) {
if (domainObject == null) {
notFound()
return
}
try {
domainObjectService.save(domainObject)
} catch (ValidationException e) {
respond domainObject.errors, view:'edit'
return
}
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'domainObject.label', default: 'DomainObject'), domainObject.id])
redirect domainObject
}
'*'{ respond domainObject, [status: OK] }
}
}
def delete(Long id) {
if (id == null) {
notFound()
return
}
domainObjectService.delete(id)
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message', args: [message(code: 'domainObject.label', default: 'DomainObject'), id])
redirect action:"index", method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}
protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'domainObject.label', default: 'DomainObject'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
}
The domain object service:
package com.project.core
import grails.gorm.services.Service
#Service(DomainObject)
interface DomainObjectService {
DomainObject get(Serializable id)
List<DomainObject> list(Map args)
Long count()
void delete(Serializable id)
DomainObject save(DomainObject domainObject)
}
I was able to get past my error by making the following changes. I added a hasMany statement in DomainObject
static hasMany = [categories: Category]
and I made these changes in the create.gsp file:
<f:field property="categories">
<g:select
multiple="true"
name="${property}"
from="${Category?.values()}"
optionKey="key"
value="${domainObject?.categories}"
/>
</f:field>

grails - Generated instance in View definition

generate-all in grails will Generate a Controller together with View (CRUD), I am trying to learn the impact of each generated block of code and now I can't seem to find the definition of {accountInstanceList} in the index.gsp.
/views/account/index.gsp
<g:each in="${accountInstanceList}" status="i" var="accountInstance">
<tr class="${(i % 2) == 0 ? 'even' : 'odd'}">
<td><g:link action="show" id="${accountInstance.id}">${fieldValue(bean: accountInstance, field: "firstname")}</g:link></td>
<td>${fieldValue(bean: accountInstance, field: "middlename")}</td>
<td>${fieldValue(bean: accountInstance, field: "lastname")}</td>
<td>${fieldValue(bean: accountInstance, field: "email")}</td>
<td>${fieldValue(bean: accountInstance, field: "role")}</td>
</tr>
</g:each>
From what I have learned the definition of the said instance should be included in Controller
/controller/.../AccountController.groovy
package ers
import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional
#Transactional(readOnly = true)
class AccountController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Account.list(params), model:[accountInstanceCount: Account.count()]
}
def show(Account accountInstance) {
respond accountInstance
}
def create() {
respond new Account(params)
}
#Transactional
def save(Account accountInstance) {
if (accountInstance == null) {
notFound()
return
}
if (accountInstance.hasErrors()) {
respond accountInstance.errors, view:'create'
return
}
accountInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'account.label', default: 'Account'), accountInstance.id])
redirect accountInstance
}
'*' { respond accountInstance, [status: CREATED] }
}
}
def edit(Account accountInstance) {
respond accountInstance
}
#Transactional
def update(Account accountInstance) {
if (accountInstance == null) {
notFound()
return
}
if (accountInstance.hasErrors()) {
respond accountInstance.errors, view:'edit'
return
}
accountInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'Account.label', default: 'Account'), accountInstance.id])
redirect accountInstance
}
'*'{ respond accountInstance, [status: OK] }
}
}
#Transactional
def delete(Account accountInstance) {
if (accountInstance == null) {
notFound()
return
}
accountInstance.delete flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message', args: [message(code: 'Account.label', default: 'Account'), accountInstance.id])
redirect action:"index", method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}
protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'account.label', default: 'Account'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
}
{accountInstanceList} is not in the index action in the controller, where is it defined? Is there hidden class that is also generated?
The render method figures out the type of 'thing' you're trying to pass to the view and creates a suitable name, in the case of a list of domain objects it's DomainNameInstanceList, see the class DefaultHtmlRenderer
Also see the scaffollding section of the docs
...the standard scaffold views expect model variables of the form
<propertyName>InstanceList for collections and <propertyName>Instance
for single instances

error appears when i add anything in my controller

i'm using Grails 2.5.1 on Windows 7 64 bit , After generating the controllers and the views using Grails command
generate-all "*"
When i add any new lines in my controllers i get the below error :
Compilation error: startup failed:
E:\Development\eclipse\TekDays\grails- app\controllers\com\tekdays\TekEventController.groovy:47: Ambiguous expression could be a parameterless closure expression, an isolated open code block, or it may continue a previous statement;solution: Add an explicit parameter list, e.g. {it -> ...}, or force it to be treated as an open block by giving it a label, e.g. L:{...}, and also either remove the previous newline, or add an explicit semicolon ';' # line 47, column 4.
{
^
1 error
here is my controller :
package com.tekdays
import static org.springframework.http.HttpStatus.*
#Transactional(readOnly = true)
class TekEventController
{
def taskService // this what i added
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max)
{
params.max = Math.min(max ?: 10, 100)
respond TekEvent.list(params), model:[tekEventInstanceCount: TekEvent.count()]
}
def show(TekEvent tekEventInstance)
{
respond tekEventInstance
}
def create()
{
respond new TekEvent(params)
}
#Transactional
def save(TekEvent tekEventInstance)
{
if (tekEventInstance == null)
{
notFound()
return
}
if (tekEventInstance.hasErrors())
{
respond tekEventInstance.errors, view:'create'
return
}
tekEventInstance.save flush:true
taskService.addDefaultTasks(tekEventInstance) // this what i added
request.withFormat
{
form multipartForm
{
flash.message = message(code: 'default.created.message', args: [message(code: 'tekEvent.label', default: 'TekEvent'), tekEventInstance.id])
redirect tekEventInstance
}
'*' { respond tekEventInstance, [status: CREATED] }
}
}
def edit(TekEvent tekEventInstance)
{
respond tekEventInstance
}
#Transactional
def update(TekEvent tekEventInstance)
{
if (tekEventInstance == null)
{
notFound()
return
}
if (tekEventInstance.hasErrors())
{
respond tekEventInstance.errors, view:'edit'
return
}
tekEventInstance.save flush:true
request.withFormat
{
form multipartForm
{
flash.message = message(code: 'default.updated.message', args: [message(code: 'TekEvent.label', default: 'TekEvent'), tekEventInstance.id])
redirect tekEventInstance
}
'*'
{
respond tekEventInstance, [status: OK]
}
}
}
#Transactional
def delete(TekEvent tekEventInstance)
{
if (tekEventInstance == null)
{
notFound()
return
}
tekEventInstance.delete flush:true
request.withFormat
{
form multipartForm
{
flash.message = message(code: 'default.deleted.message', args: [message(code: 'TekEvent.label', default: 'TekEvent'), tekEventInstance.id])
redirect action:"index", method:"GET"
}
'*'
{
render status: NO_CONTENT
}
}
}
protected void notFound()
{
request.withFormat
{
form multipartForm
{
flash.message = message(code: 'default.not.found.message', args: [message(code: 'tekEvent.label', default: 'TekEvent'), params.id])
redirect action: "index", method: "GET"
}
'*'
{
render status: NOT_FOUND
}
}
}
}
Any advice to solve this error ?
Thanks

Grails Static Mapping argument type mismatch when saving

I can make a simple grails app in 2.4.4, but as soon as I add in static mapping that changes the name of the primary key it refuses to save. Here is the domain class I use.
class Liaison {
String first;
String last;
static constraints = {}
static mapping = {
id column:'liaisonId', type: 'integer'
}
}
here is the generated controller
import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional
#Transactional(readOnly = true)
class LiaisonController {
static allowedMethods = [save: "POST", update: "PUT", delete: "DELETE"]
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Liaison.list(params), model:[liaisonInstanceCount: Liaison.count()]
}
def show(Liaison liaisonInstance) {
respond liaisonInstance
}
def create() {
respond new Liaison(params)
}
#Transactional
def save(Liaison liaisonInstance) {
if (liaisonInstance == null) {
notFound()
return
}
if (liaisonInstance.hasErrors()) {
respond liaisonInstance.errors, view:'create'
return
}
liaisonInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.created.message', args: [message(code: 'liaison.label', default: 'Liaison'), liaisonInstance.id])
redirect liaisonInstance
}
'*' { respond liaisonInstance, [status: CREATED] }
}
}
def edit(Liaison liaisonInstance) {
respond liaisonInstance
}
#Transactional
def update(Liaison liaisonInstance) {
if (liaisonInstance == null) {
notFound()
return
}
if (liaisonInstance.hasErrors()) {
respond liaisonInstance.errors, view:'edit'
return
}
liaisonInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.updated.message', args: [message(code: 'Liaison.label', default: 'Liaison'), liaisonInstance.id])
redirect liaisonInstance
}
'*'{ respond liaisonInstance, [status: OK] }
}
}
#Transactional
def delete(Liaison liaisonInstance) {
if (liaisonInstance == null) {
notFound()
return
}
liaisonInstance.delete flush:true
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.deleted.message', args: [message(code: 'Liaison.label', default: 'Liaison'), liaisonInstance.id])
redirect action:"index", method:"GET"
}
'*'{ render status: NO_CONTENT }
}
}
protected void notFound() {
request.withFormat {
form multipartForm {
flash.message = message(code: 'default.not.found.message', args: [message(code: 'liaison.label', default: 'Liaison'), params.id])
redirect action: "index", method: "GET"
}
'*'{ render status: NOT_FOUND }
}
}
}
I get an error at liaisonInstance.save flush:true in the def save(), but I don't understand why. If I look in my change log the table looks to be fine. Is it some sort of hidden hash map? Any help would be great.
Omg I think I get it. I was over-thinking. The static mapping should be
static mapping = {
id column: 'liaisonId'
}
instead of
static mapping = {
id column: 'liaisonId', type: 'integer'
}
I think it has to do with the auto generated primary key is a bigInt. I think type is only for if you plan on using an id generator for primary key.

how to get contacts created by currently logged in user in grails

I have implemented spring security service for user authentication in my grails application.
I have Subscriber.groovy(user table) and Contact.groovy domains. Once a subscriber(user) logs in, he/she can create contacts.There is hasMany relationship between Subscriber and Contact domain.
Problem: I have implemented search functionality for contacts created by currently logged user or subscriber on contact page. It works fine but it fetch all contacts in system but I want only contacts those are created by currently logged in subscriber(user).
How to search contacts those are created by currently logged in subscriber.
Method for searching contacts from contact table
def searchAJAX = {
def contacts = Contact.findAllByNameLike("%${params.query}%")
//Create XML response
render(contentType: "text/xml") {
results() {
contacts.each { contact ->
result(){
name(contact.name)
//Optional id which will be available in onItemSelect
id(contact.id)
}
}
}
}
}
ContactController.groovy
package com.vproc.member
import grails.converters.*
class ContactController {
def springSecurityService
def subscriberService
def imageUploadService
def searchableService
def autoCompleteService
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def index() {
redirect(action: "list", params: params)
}
def list() {
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
List<Contact>contactsList = new ArrayList<Contact>();
loggedinSubscriber?.contacts.each { it ->
contactsList.add(it)
}
[contactInstanceList:contactsList , contactInstanceTotal: contactsList.size() ]
}
def create() {
[contactInstance: new Contact(params)]
}
def save() {
// params.birthday = Date.parse( 'MM/dd/yyyy', params.birthday )
if (params.birthday){
params.birthday = (new SimpleDateFormat("MM/dd/yyyy")).parse(params.birthday)
}
def contactInstance = new Contact(params)
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
if (loggedinSubscriber == null)
System.out.println("not able to save")
else {
if (!loggedinSubscriber.contacts){
loggedinSubscriber.contacts = new ArrayList<Contact>();
}
loggedinSubscriber.contacts.add(contactInstance)
if (!loggedinSubscriber.save(flush: true)) {
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
render(view: "create", model: [contactInstance: contactInstance])
return
}
}
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
redirect(action: "list")
}
// enable search for contacts
def contact_search = {
def query = params.q
if(query){
def srchResults = searchableService.search(query)
render(view: "list",
model: [contactInstanceList: srchResults.results,
contactInstanceTotal:srchResults.total])
}
else{
render "not record found";
}
}
// fetch name from contact table for autocomplete on contact
def searchAJAX = {
def contacts = Contact.findAllByNameLike("%${params.query}%")
//Create XML response
render(contentType: "text/xml") {
results() {
contacts.each { contact ->
result(){
name(contact.name)
//Optional id which will be available in onItemSelect
id(contact.id)
}
}
}
}
}
}
Contact.groovy
package com.vproc.member
import java.util.Date;
import com.vproc.common.Tag;
import com.vproc.enquiry.ContactType;
import grails.converters.JSON;
class Contact {
String name
String phoneNumber
String emailAddress
Gender gender
String url
String note
byte[] image
String address
Date dateCreated
Date lastUpdated
ContactType contactType
Date birthday
static belongsTo = [Subscriber]
static hasMany = [tags:Tag , shares: SharedContact]
static constraints = {
image nullable: true
phoneNumber nullable: true
url nullable :true
address nullable :true
gender nullable :true
note nullable :true
contactType nullable :true
birthday nullable :true
}
static mapping = {
note(type: 'text')
}
//static searchable = [only: ['name', 'emailAddress']]
static searchable = true
static scaffold = true
//static searchable = true
}
Subscriber.groovy
package com.vproc.member
import java.util.Date;
import com.vproc.common.StatusEnum;
import com.vproc.enquiry.Discussion;
import com.vproc.enquiry.Enquiry;
import com.vproc.enquiry.Membership;
import com.vproc.enquiry.Notification;
import com.vproc.enquiry.SharedEnquiry;
import com.vproc.enquiry.Team;
import com.vproc.order.Seat;
class Subscriber extends PartyRole{
transient springSecurityService
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
StatusEnum status
Date dateCreated
Date lastUpdated
List<Contact> contacts ;
static belongsTo = [ customer: Customer]
static hasMany = [seats: Seat, ownedEnquiries: Enquiry,enquiresSharedWith: SharedEnquiry, enquiriesSharedBy: SharedEnquiry ,
managedTeams: Team , memberships: Membership, contacts: Contact , sharedByContacts: SharedContact, sharedWithContacts: SharedContact,
vContacts: VContact, partOf: VContact, sharedbyVContacts: SharedVcontact, sharedWithVcontacts: SharedVcontact,
notifications: Notification, discussions: Discussion]
static mappedBy = [ managedTeams : "manager" , enquiresSharedWith: "sharedWith" , enquiriesSharedBy: "sharedBy" ,
sharedByContacts : "sharedBy" , sharedWithContacts : "sharedWith" ,
vContacts: "forSubscriber" , partOf :"ofContact",
sharedbyVContacts: "sharedby" , sharedWithVcontacts :"sharedWith"
]
static constraints = {
username validator : { val , obj ->
if (obj.status != StatusEnum.Pending)
val!= null
}
username unique: true
password validator : { val , obj ->
if (obj.status != StatusEnum.Pending)
val != null
}
contacts nullable: true
notifications nullable : true
username nullable: true
password nullable: true
}
static mapping = {
password column: '`password`'
}
Set<Role> getAuthorities() {
SubscriberRole.findAllBySubscriber(this).collect { it.role } as Set
}
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService.encodePassword(password)
}
}
save action for Contact controller
def save() {
// params.birthday = Date.parse( 'MM/dd/yyyy', params.birthday )
if (params.birthday){
params.birthday = (new SimpleDateFormat("MM/dd/yyyy")).parse(params.birthday)
}
def contactInstance = new Contact(params)
Subscriber loggedinSubscriber = Subscriber.get( springSecurityService.principal.id )
if (loggedinSubscriber == null)
System.out.println("not able to save")
else {
if (!loggedinSubscriber.contacts){
loggedinSubscriber.contacts = new ArrayList<Contact>();
}
loggedinSubscriber.contacts.add(contactInstance)
if (!loggedinSubscriber.save(flush: true)) {
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
render(view: "create", model: [contactInstance: contactInstance])
return
}
}
flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'Contact'), contactInstance.id])
redirect(action: "list")
}
Note: while saving contacts,I have logged in subscriber in save action of Contact controller but I do not know how to use it below method which is searchAjax for searching contacts.
Assuming Subscriber has an association to Contact as,
class Subscriber {
static hasMany = [contacts: Contact]
}
then, to get all contacts for a subscriber user,
subscriberInstance.contacts
and to query among contacts of the same subscriber use,
subscriberInstance.findByContact('your_query_string')
For reference look up querying associations on the documentation http://grails.org/doc/latest/guide/GORM.html#querying

Resources