GroovyDynamicMethodsInterceptor - grails

is there anyway to use GroovyDynamicMethodsInterceptor in grails 3.0.17.
if not , what can I use instead?
this is part of my code ClinicianService.groovy :
package org.imedcom.server.provider
import org.codehaus.groovy.grails.web.metaclass.GroovyDynamicMethodsInterceptor
import org.codehaus.groovy.grails.web.metaclass.BindDynamicMethod
import grails.web.databinding.DataBinder
import org.imedcom.server.core.command.ClinicianCommand
import org.imedcom.server.core.command.CreateClinicianCommand
import org.imedcom.server.core.exception.ClinicianException
import org.imedcom.server.model.*
import org.springframework.transaction.annotation.Transactional
#Transactional
class ClinicianService {
def springSecurityService
def passwordService
ClinicianService() {
GroovyDynamicMethodsInterceptor i = new GroovyDynamicMethodsInterceptor(this)
i.addDynamicMethodInvocation(new BindDynamicMethod())
}
Clinician createClinician(CreateClinicianCommand command) {
def clinicianInstance = new Clinician(command.properties)
clinicianInstance.user = new User(command.properties)
clinicianInstance.user.enabled = true
if (!clinicianInstance.user.validate()) {
clinicianInstance.user.errors.fieldErrors.each {
clinicianInstance.errors.rejectValue("user.${it.field}", it.code, it.arguments, it.defaultMessage)
}
}
if (clinicianInstance.user.save(flush: true) && clinicianInstance.save(flush: true)) {
updateRoleLinks(command.roleIds, clinicianInstance)
updatePatientGroupLinks(command.groupIds, clinicianInstance)
}
return clinicianInstance
}
def updatePatientGroupLinks(List<Long> groupIds, Clinician clinician) {
def oldPatientGroups = Clinician2PatientGroup.findAllByClinician(clinician)*.patientGroup
def newPatientGroups = PatientGroup.findAllByIdInList(groupIds)
newPatientGroups.each { patientGroup ->
Clinician2PatientGroup.link(clinician, patientGroup)
}
def obsoletePatientGroups = oldPatientGroups - newPatientGroups
obsoletePatientGroups.each {
Clinician2PatientGroup.unlink(clinician, it)
}
}
def updateRoleLinks(List<Long> roleIds, Clinician clinician) {
UserRole.removeAll(clinician.user, true)
Role.findAllByIdInList(roleIds).each { role ->
def userRole = new UserRole(user: clinician.user, role: role)
if (!userRole.save()) {
throw new ClinicianException("clinician.could.not.assign.clinician.rights", userRole.errors)
}
}
}
}
and this is my ClinicianController.grroy where I also use
``def clinicianService```
import grails.plugin.springsecurity.annotation.Secured
import org.imedcom.server.core.command.CreateClinicianCommand
import org.imedcom.server.model.Clinician
import org.imedcom.server.model.Clinician2PatientGroup
import org.imedcom.server.core.command.ClinicianCommand
import org.imedcom.server.core.model.types.PermissionName
import org.springframework.dao.DataIntegrityViolationException
#Secured(PermissionName.NONE)
class ClinicianController {
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def clinicianService
def passwordService
def springSecurityService
def authenticationManager
#Secured(PermissionName.CLINICIAN_CREATE)
def create() {
if (!params.cleartextPassword) {
params.cleartextPassword = passwordService.generateTempPassword()
}
def command = new CreateClinicianCommand()
bindData(command, params, ["action", "controller"])
[cmd: command]
}
#Secured(PermissionName.CLINICIAN_CREATE)
def save(CreateClinicianCommand command) {
if (!command.validate()) {
render(view: "create", model: [cmd: command])
return;
}
def clinicianInstance = clinicianService.createClinician(command)
if (!clinicianInstance.hasErrors()) {
flash.message = message(code: 'default.created.message', args: [message(code: 'clinician.label'), clinicianInstance.firstName])
redirect(action: "show", id: clinicianInstance.id)
} else {
render(view: "create", model: [cmd: command])
}
}
}
and I am also using the clinicianService in other controllers too.
this all was in grails 2.4.4.

If what you want to do is invoke data binding from a Grails Service there are a few ways to do that. One is to implement DataBinder.
import grails.web.databinding.DataBinder
class SomeService implements DataBinder {
def serviceMethod(someMap) {
def obj = new SomeClass()
bindData obj, params
obj
}
}
Another option is to inject the data binder into your service:
import org.grails.databinding.SimpleMapDataBindingSource
class SomeService {
def grailsWebDataBinder
TestObject getNewTestObject(Map someMap) {
def obj = new SomeClass()
grailsWebDataBinder.bind obj, someMap as SimpleMapDataBindingSource
obj
}
}

Related

grails restful groovy can not resolve symbol

I am trying to learn grails by following the link: https://guides.grails.org/rest-hibernate/guide/index.html and after creating the controller ProductController as per the page's guidance I am getting the following error:
Unable to resolve class ProductService in ProductController
I new to groovy and trying to resolve the class reference by importing the necessary packages but the link does not show any imports to resolve this class. there is not explicit import statement for ProductService productService in ProductController.groovy. Here are the classes:
ProductController:
package hibernate.example
import groovy.transform.CompileStatic
import grails.rest.*
import grails.converters.*
#CompileStatic
class ProductController extends RestfulController {
static responseFormats = ['json', 'xml']
ProductController() {
super(Product)
}
ProductService productService
def search(String q, Integer max ) {
if (q) {
respond productService.findByNameLike("%${q}%".toString(), [max: Math.min( max ?: 10, 100)])
}
else {
respond([])
}
}
}
ProductControllerSpec:
package hibernate.example
import org.grails.testing.GrailsUnitTest
import spock.lang.Specification
#SuppressWarnings('MethodName')
class ProductControllerSpec extends HibernateSpec implements ControllerUnitTest<ProductController> {
def setup() {
}
def cleanup() {
}
static doWithSpring = {
jsonSmartViewResolver(JsonViewResolver)
}
void 'test the search action finds results'() {
given:
controller.productService = Stub(ProductService) {
findByNameLike(_, _) >> [new Product(name: 'Apple', price: 2.0)]
}
when: 'A query is executed that finds results'
controller.search('pp', 10)
then: 'The response is correct'
response.json.size() == 1
response.json[0].name == 'Apple'
}
}

How to write integration test for filter in grails

I have written one filter rule which I want to test using grails integration tests.
Filter is
invalidAccess(controller: "home") {
before = {
redirect(controller: "newHome", action: "index")
return false
}
}
I have followed this link to write the integration test
http://ldaley.com/post/392153102/integration-testing-grails-filters
It returns result as false But gives
null for redirectedUrl
instead of newHome & index method url.
What am I missing here?
import grails.util.GrailsWebUtil
class MyFilterTests extends GroovyTestCase {
def filterInterceptor
def grailsApplication
def grailsWebRequest
def request(Map params, controllerName, actionName) {
grailsWebRequest = GrailsWebUtil.bindMockWebRequest(grailsApplication.mainContext)
grailsWebRequest.params.putAll(params)
grailsWebRequest.controllerName = controllerName
grailsWebRequest.actionName = actionName
filterInterceptor.preHandle(grailsWebRequest.request, grailsWebRequest.response, null)
}
def getResponse() {
grailsWebRequest.currentResponse
}
def testFilterRedirects() {
def result = request( someParameter: "2", "home", "index")
assertFalse result
assertTrue response.redirectedUrl.endsWith(/* something */)
}
}
If you want to try unit testing and need to mock some services then you can mock like:
#TestFor(SomethingToTest)
#Mock([FirstService, SecondService])
class SomethingToTestSpec extends Specification {
and you want integration test then try following test
import grails.util.GrailsWebUtil
import org.junit.After
import org.junit.Before
import org.junit.Test
class MyFilterIntegrationTests {
def filterInterceptor
def grailsApplication
def grailsWebRequest
#Before
void setUp() {
}
#After
void tearDown() {
}
#Test
void testFilterRedirects() {
def result = request("person", "index", someParameter: "2")
assert !result
assert response.redirectedUrl.endsWith('/auth/index')
}
def getResponse() {
grailsWebRequest.currentResponse
}
def request(Map params, controllerName, actionName) {
grailsWebRequest = GrailsWebUtil.bindMockWebRequest(grailsApplication.mainContext)
grailsWebRequest.params.putAll(params)
grailsWebRequest.controllerName = controllerName
grailsWebRequest.actionName = actionName
filterInterceptor.preHandle(grailsWebRequest.request, grailsWebRequest.response, null)
}
}
Ref# Grails Integration Test Filter

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

How can I create a map with all i18n-messages in Grails

I need this to render a part of it in a controller like:
class MessageController {
def index = {
def messageMap = listAlli18nMessages() // the question
render (contentType: "text/xml") {
messageMap {key, message ->
..
}
}
}
}
Finally I found an answer - override the default Grails messageSource:
class ExtendedPluginAwareResourceBundleMessageSource extends PluginAwareResourceBundleMessageSource {
Map<String, String> listMessageCodes(Locale locale) {
Properties properties = getMergedProperties(locale).properties
Properties pluginProperties = getMergedPluginProperties(locale).properties
return properties.plus(pluginProperties)
}
}
In grails-app/conf/spring/resources.groovy:
beans = {
messageSource(ExtendedPluginAwareResourceBundleMessageSource) {
basenames = "WEB-INF/grails-app/i18n/messages"
}
}
Corresponding controller code:
class MessageController {
def messageSource
def index = {
def messageMap = messageSource.listMessageCodes(request.locale)
render (contentType: "text/xml") {
messageMap {key, message ->
..
}
}
}
}
The approach you are taking doesn't look to be possible based on the API docs for PluginAwareResourceBundleMessageSource. This will get you close to a solution
class MessageController {
def messageSource
def index = {
Locale locale = new Locale('en');
List codes = ['default.paginate.prev','default.paginate.next','default.boolean.true','default.boolean.false']
def messageMap = messagesForCodes(codes,locale)
render (contentType: "text/xml") {
messageMap {key, message ->
..
}
}
}
private def messagesForCodes(codes, locale){
Map messages = [:]
codes.each{code->
messages[code] = messageSource.getMessage(code,null,locale)
}
messages
}
}

idiom for save and update methods in grails

Are there in any idioms in grails which help us with saving domain objects ?
For example
i may want to do something like
if(candidate.hasErrors || !candidate.save)
{
candidate.errors.each {
log it
}
However i do not want to spread the logic across all the places i do domainObject.save.
I also do not want seperate class like say repo to which I pass this domainObject and put in this logic
Thanks
Sudarshan
Here's a service method that I've used to validate and save, but log resolved validation messages on failure. It's helpful to use this instead of just println error or log.warn error since the toString() for error objects is very verbose and you just want to see what would be displayed on the GSP:
class MyService {
def messageSource
def saveOrUpdate(bean, flush = false) {
return validate(bean) ? bean.save(flush: flush) : null
}
boolean validate(bean) {
bean.validate()
if (bean.hasErrors()) {
if (log.isEnabledFor(Level.WARN)) {
def message = new StringBuilder(
"problem ${bean.id ? 'updating' : 'creating'} ${bean.getClass().simpleName}: $bean")
def locale = Locale.getDefault()
for (fieldErrors in bean.errors) {
for (error in fieldErrors.allErrors) {
message.append("\n\t")
message.append(messageSource.getMessage(error, locale))
}
}
log.warn message
}
bean.discard()
return false
}
return true
}
And here's an example in a controller:
class MyController {
def myService
def actionName = {
def thing = new Thing(params)
if (myService.saveOrUpdate(thing)) {
redirect action: 'show', id: thing.id
}
else {
render view: 'create', model: [thing: thing]
}
}
}
Edit: It's also possible to add these methods to the MetaClass, e.g. in BootStrap.groovy:
class BootStrap {
def grailsApplication
def messageSource
def init = { servletContext ->
for (dc in grailsApplication.domainClasses) {
dc.metaClass.saveOrUpdate = { boolean flush = false ->
validateWithWarnings() ? delegate.save(flush: flush) : null
}
dc.metaClass.validateWithWarnings = { ->
delegate.validate()
if (delegate.hasErrors()) {
def message = new StringBuilder(
"problem ${delegate.id ? 'updating' : 'creating'} ${delegate.getClass().simpleName}: $delegate")
def locale = Locale.getDefault()
for (fieldErrors in delegate.errors) {
for (error in fieldErrors.allErrors) {
message.append("\n\t")
message.append(messageSource.getMessage(error, locale))
}
}
log.warn message
delegate.discard()
return false
}
return true
}
}
}
}
This depends on a 'log' variable being in scope, which will be true in any Grails artifact. This changes the controller usage slightly:
class MyController {
def actionName = {
def thing = new Thing(params)
if (thing.saveOrUpdate()) {
redirect action: 'show', id: thing.id
}
else {
render view: 'create', model: [thing: thing]
}
}
}
As a metaclass method it may make more sense to rename it, e.g. saveWithWarnings().

Resources