new to groovy and stuck on this for quite some time.
Heres the method in question.
protected User currentUser() {
def user = springSecurityService.currentUser
println "In currentUser Method"
println "Is userId null?"
println user.id == null
println user.id instanceof Long
User.get(user.id)
}
And User.get is a method in the GORM package
D get(Serializable id) {
execute({ Session session ->
session.retrieve(persistentClass, id)
} as SessionCallback)
}
Im getting the error
No signature of method: User.get() is applicable for argument types: () values: []
What I dont understand is that through the println statements I verified that
user.id is not null
user.id is instanceof Long , which implements the Serializable interface.
Any idea whats happening here?
Thank you.
A possible solution could be that you have an invalid import statement. User is a very common class name so maybe you (or your IDE) have imported a different User class than you expect. The imported class might not have a get(id) method.
Related
I am trying to learn about creating the link using createLink from ApplicationTagLib called from the service.
Grails : 3.2.8
Code :
def applicationTag = new ApplicationTagLib()
def abc = application.Tag.createLink(controller:"accomodate", action:"menu", id:4)
Error :
org.grails.taglib.GrailsTagException: Tag [createLink] does not exist.
No corresponding tag library found.
I am very new to this version. I will be really thankful if you help me in finding out what sort of mistake is my code having.
try this:
import grails.core.support.GrailsApplicationAware
import grails.core.GrailsApplication
import grails.web.mapping.LinkGenerator
class MyService implements GrailsApplicationAware{
GrailsApplication grailsApplication
def config
LinkGenerator grailsLinkGenerator
def myMethod() {
def url = hostname+grailsLinkGenerator.link(controller: 'someController', action: 'something', params:[token:something], absolute: 'false')
}
void setGrailsApplication(GrailsApplication ga) {
config = ga.config
}
}
...
String hostname=grailsApplication.config.myApp?.hostName
def url=hostname+grailsLinkGenerator.link(controller: 'someController', action: 'something', params:[token:something], absolute: 'false')
or
def url=grailsLinkGenerator.link(controller: 'someController', action: 'something', params:[token:something], absolute: true)
ED2A
If you must
I have applicationTag lib working this way:
import grails.util.Holders
import org.grails.plugins.web.taglib.ApplicationTagLib
class SomeService {
def g = Holders.grailsApplication.mainContext.getBean(ApplicationTagLib)
def someMethod() {
def aa = g.createLink('something')
}
}
The problem with doing things this way is if you start hitting presentation layer references then you may get No thread-bound request found. Specially from quartz jobs and anything that is called outside of the scope of a real user. You can get around all of this using this example. But why go through all that when the grailsLinkGenerator example above won't hit any of the issues that may arise otherwise
I came here because I just wanted a link created in a regular service class, and V H's answer^ helped me; thank you! :D
But for those looking for the same thing I was, this is what is sufficient for us to work (Grails version 4.0.4):
import grails.web.mapping.LinkGenerator
and in the service method:
def link = grailsLinkGenerator.link(
controller: 'controlerName',
action: 'actionName',
params: [uuid: "uuidExample"]
)
Thank you once more, V H! :)
So I have done a bunch of research on using grailsApplication in services but none of them seem to work (2.4.4)
here's how i'm trying to use it
class AddressLookupService {
def grailsApplication
def addressLookup(address1, address2, city, state, zip){
def addressValidationErrors = verifyAddress(
grailsApplication.config.uspsUserId,
address1, address2, city, state, zip, '')
return addressValidationErrors.errDescription
}
}
and the error I'm getting
Cannot get property 'config' on null object
You can import Holders class in service as
import grails.util.Holders as H and then use this holder as
H.grailsApplication?.config?.uspsUserId
I recently created a new controller in a pretty big app, (note: we just upgraded from Grails 2.0.3 to 2.3.7) and the created tests have all been failing inexplicably. Most of my errors consist of the model being [:] after a controller call. And therefore any methods on that model being null. I get stuff like:
groovy.lang.MissingMethodException:
No signature of method:
TransitionController.save() is applicable for argument types: (Transition)
values: [null] Possible solutions: save(), wait(), show(), any(),
wait(long), raw(java.lang.Object) at TransitionControllerSpec.Test the
save action correctly persists an instance(TransitionControllerSpec.groovy:45)
I have tried explicitly assigning the model by doing:
def model = controller.delete()
def model = controller.update()
//....
But I get the same result, an empty model map and null values if I try to access it.
As per this article (https://jira.grails.org/browse/GRAILS-8462) I could also try accessing the model by doing:
def model = controller.modelAndView.model
But this did not work for me either, producing the same results.
Any ideas on what might be happening?
Edit: Here are the first couple of tests
package com.hey.how.are.ya
import grails.test.mixin.*
import spock.lang.*
import org.junit.*
#TestFor(TransitionController)
#Mock(Transition)
class TransitionControllerSpec extends Specification {
def populateValidParams(params) {
assert params != null
params['reason'] = 'just cuz'
}
void "Test the index action returns the correct model"() {
when:"The index action is executed"
controller.index()
then:"The model is correct"
!model.transitionInstanceList
model.transitionInstanceCount == 0
}
void "Test the create action returns the correct model"() {
when:"The create action is executed"
controller.create()
then:"The model is correctly created"
model.transitionInstance!= null
}
//...grails generated tests here
}
Edit: Here's an interesting case! If I do:
void "Test the create action returns the correct model"() {
when:"The create action is executed"
def model = controller.create()
def inst = new Transition()
println "${model}"
println "${model.transitionInstance}"
then:"The model is correctly created"
model.transitionInstance != null
}
Then I get this as output:
[transitionInstance:null]
null
But the test passes. This only happens with create. What is going on??
Edit: Adding code for create and save
def create() {
[transitionInstance: new Transition(params)]
}
def save() {
def transitionInstance = new Transition(params)
if (!transitionInstance.save(flush: true)) {
render(view: "create", model: transitionInstance: transitionInstance])
return
}
flash.message = message(code: 'default.created.message', args: [message(code: 'transition.label', default: 'Transition'), transitionInstance.id])
redirect(action: "show", id: transitionInstance.id)
}
Edit: I can't spend too much time on this, but I'm pretty sure the problem is discrepancies between the controller generated and the test created. For what it's worth I was running version 2.0.2 of the scaffolding plugin and grails 2.3.7. I'm gonna throw out the tests created by the command and start from scratch, thanks for the help!
I had the same issue but solved it like following:
Inside the controller method:
render view: "_myTemplate", model: [instance: myInstance]
So the controller, still renders the template and inside the test spec I can test
assert(model.instance = myExpectedInstance)
I have a Spock test case, in which the setup block looks like this :
setup: "set the required objects"
def company = new Company(shortName:"infyyy",fullName:"infoysys",
region:"tamilnadu" ,email:"a#ac.com" ,telphone:34343433,fax:34343433).save(failOnError:true)
def project = new Project(name:"testing")
def userInstance = new User(username:username,password:password,
company:company,project:project,pt:["dummy"]).save(failOnError:true)
def tasksInstance = new Tasks(title:"testingwork",startDate:(new Date()-4),endDate:(new Date().clearTime()-6),description:"blah blah",project:project,completed:true,user:userInstance).save(failOnError:true)
And more over, the Tasks domain class looks like this :
class Tasks {
static belongsTo = [ user : User, project: Project ]
//other code
}
And User class is like this :
class User {
static hasMany = [ holidays : Holiday, tasks : Tasks, pt:String, project: Project ]
//other code
}
But when I run my test and my test fails(not with an error message, but it fails in the then block of my Spock test) and I find a error in it. My setup doesn't create any relationship between User and Tasks, which makes my test to fail.
The controller code, which I'm trying to test is :
def todaysTasks() {
def user = User.get(springSecurityService.principal.id)
def choice = params.managersProject
params.max = Math.min(params.max ? params.int('max') : 10,100)
def search = Tasks.createCriteria().list(max: params.max as Integer, offset: params.offset as Integer, order: params.order as String, sort : params.sort) {
and {
project {
like('name',"${choice}")
}
eq('endDate', new Date().clearTime())
}
}
println "todays task selected project is " + search
[tasksInstanceList : search, tasksInstanceTotal: search.getTotalCount() ]
}
The println in the above test prints 0. Why does this happen even though I'm making the endDate in my test less than today's date?
Thanks in advance.
As far as I know, GORM does not auto-populate relationships, by following a belongsTo relationship.
I always do the following.
def u=new User(...)
u.addToTasks(
title:"testingwork",
startDate:(new Date()-4),
endDate:...
)
u.save()
Note that I have not created a task object. I have passed the Map of values directly to addToX... this emphasizes that the added object belongs to User and should be instantiated and saved by GORM.
You cannot (and you shouldn't) test criteria queries in your unit tests. Criteria queires are not supported in grails (and spock) unit tests. Read this question for possible solutions.
EDITED HEADER: more related with the actual problem
I'm trying to setup spring security for my test application
i installed the plugin , created User and Role classes ;
put this to UrlMappings.groovy;
"/login/$action?"(controller: "login")
"/logout/$action?"(controller: "logout")
then I put a user in the bootstrap as follows,
import org.project.auth.Role
import org.project.auth.User
import org.project.auth.UserRole;
class BootStrap {
def springSecurityService
def init = { servletContext ->
def userRole = Role.findByAuthority('ROLE_USER') ?: new Role(authority: 'ROLE_USER').save(failOnError: true,flush:true)
def adminRole = Role.findByAuthority('ROLE_ADMIN') ?: new Role(authority: 'ROLE_ADMIN').save(failOnError: true,flush:true)
def adminUser = User.findByUsername('admin') ?: new User(
username: 'admin',
password: springSecurityService.encodePassword('admin'),
enabled: true).save(failOnError: true,flush:true)
print User.count()
if (!adminUser.authorities.contains(adminRole)) {
print "TEST"
UserRole.create adminUser, adminRole,true
}
}
def destroy = {
}
}
this print User.count() returns 1 so i know the user is created , print "TEST" works as well so i know that it goes into the if block but when i run the server it fails with
Sorry, we were not able to find a user with that username and password.
I use Grails 2.0.0.M1 , do you think it might be the issue?
The User domain class in the 1.2 version of the plugin encrypts the password for you. So older code like this that uses the springSecurityService double-encodes. Change password: springSecurityService.encodePassword('admin') to password: 'admin' and it should work.
If not, turn up the debugging and you should see a message about why it's failing. Add this to Config.groovy in the log4j block:
debug 'org.springframework.security'
Also to be safe I'd change
if (!adminUser.authorities.contains(adminRole)) { to if (!UserRole.findByUserAndRole(adminUser, adminRole)) {
`
I ma facing the same problem but after some searching came across this. http://jira.grails.org/browse/GPSPRINGSECURITYUI-33
and http://jira.grails.org/browse/GPSPRINGSECURITYUI-27
Hope this helps. But i am unable to find the next stable version where this problem is fixed.